Android R input 之 InputManagerService 的建立
Posted pecuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android R input 之 InputManagerService 的建立相关的知识,希望对你有一定的参考价值。
文章托管在gitee上 Android Notes , 同步csdn
InputManagerService 介绍
InputManagerService是重要的系统服务,负责android输入系统的管理,职责包括但不限于:
- 输入设备的管理
- 输入事件的加工m
- 输入事件的派发与反馈
- 输入事件的派发ANR的检测
常见的输入设备是触摸屏/按键,其他支持的设备还有键盘,鼠标等. 当有新输入设备可用时,Linux内核会在/dev/input/下创建对应的名称类似eventX(X>=0)的设备节点。当输入设备不可用时,对应的节点也会被移除。通过 getevent 命令可以获取设备信息
# getevent
add device 1: /dev/input/event6
name: "msm8xx2-snd-card-mtp Button Jack"
add device 2: /dev/input/event5
name: "msm8xx2-snd-card-mtp Headset Jack"
add device 3: /dev/input/event0
name: "qpnp_pon"
add device 4: /dev/input/event2
name: "ts"
add device 5: /dev/input/event1
name: "soc:matrix_keypad"
add device 6: /dev/input/event3
name: "hall_sensor"
add device 7: /dev/input/event4
name: "gpio_keys"
当用户操作输入设备时(如手指在屏幕上滑动或按power键),会触发相应的硬件中断,Linux内核将相关信息加工成原始的输入事件数据,然后写入其对应的设备节点中.在用户空间,EventHub通过read()系统调用函数将事件数据读出,然后进行相关加工处理。
引用输入理解Android 卷三的一句来描述整体过程:
Android输入系统的工作原理概括来说,就是监控/dev/input/下的所有设备节点,当某个节点有数据可读时,将数据读出并进行一系列的翻译加工,然后在所有的窗口中寻找合适的事件接收者,并派发给它。
InputManagerService 的创建
InputManagerService 如大多数系统服务一样,也是在SystemServer中创建. 具体工作可以总结如下:
- 创建InputManagerService, 同时初始java和native
- 注册InputManagerService到ServiceManager
- 设置WindowManagerCallback,通知WMS一下感兴趣的事情
- 调用InputManagerService的start方法,启动工作线程,注册一下监听等
- 调用InputManagerService的systemRunning方法做一下初始工作
/// @frameworks/base/services/java/com/android/server/SystemServer.java
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context); // 创建InputManagerService
t.traceEnd();
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// 注册WMS
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
// 将 InputManagerService 注册到sm
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();
...
mActivityManagerService.setWindowManager(wm);
wm.onInitReady();
t.traceBegin("StartInputManager");
// 设置 input callback, 通知wms一下input相关的事件,如anr
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start(); // ims 启动
t.traceEnd();
...
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
mActivityManagerService.systemReady(() -> {
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
mSystemServiceManager.startBootPhase(t,SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
...
t.traceBegin("MakeInputManagerServiceReady");
try {
// TODO(BT) Pass parameter to input manager
if (inputManagerF != null) {
inputManagerF.systemRunning(); // 回调 systemRunning
}
} catch (Throwable e) {
reportWtf("Notifying InputManagerService running", e);
}
...
}
}
接下来分析具体的流程
创建 InputManagerService
/// @frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputManagerService(Context context) {
this.mContext = context;
// 创建InputManagerHandler, 消息将在DisplayThread处理
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mStaticAssociations = loadStaticInputPortAssociations();
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
// 重点关注 , 初始化native , mPtr保存NativeInputManager地址
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
String doubleTouchGestureEnablePath = context.getResources().getString(
R.string.config_doubleTouchGestureEnableFile);
mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
new File(doubleTouchGestureEnablePath);
// 注册 LocalService , 只能在SystemServer使用
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
IMS JNI函数注册表
InputManagerService的native 实现在frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp , 下面的注册表描述了java native方法与相关jni函数的对应关系
static const JNINativeMethod gInputManagerMethods[] = {
/* name, signature, funcPtr */
{"nativeInit",
"(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/"
"MessageQueue;)J",
(void*)nativeInit},
{"nativeStart", "(J)V", (void*)nativeStart},
{"nativeSetDisplayViewports", "(J[Landroid/hardware/display/DisplayViewport;)V",
(void*)nativeSetDisplayViewports},
{"nativeGetScanCodeState", "(JIII)I", (void*)nativeGetScanCodeState},
{"nativeGetKeyCodeState", "(JIII)I", (void*)nativeGetKeyCodeState},
{"nativeGetSwitchState", "(JIII)I", (void*)nativeGetSwitchState},
{"nativeHasKeys", "(JII[I[Z)Z", (void*)nativeHasKeys},
{"nativeRegisterInputChannel", "(JLandroid/view/InputChannel;)V",
(void*)nativeRegisterInputChannel},
{"nativeRegisterInputMonitor", "(JLandroid/view/InputChannel;IZ)V",
(void*)nativeRegisterInputMonitor},
{"nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
(void*)nativeUnregisterInputChannel},
{"nativePilferPointers", "(JLandroid/os/IBinder;)V", (void*)nativePilferPointers},
{"nativeSetInputFilterEnabled", "(JZ)V", (void*)nativeSetInputFilterEnabled},
{"nativeSetInTouchMode", "(JZ)V", (void*)nativeSetInTouchMode},
{"nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIII)I",
(void*)nativeInjectInputEvent},
{"nativeVerifyInputEvent", "(JLandroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;",
(void*)nativeVerifyInputEvent},
{"nativeToggleCapsLock", "(JI)V", (void*)nativeToggleCapsLock},
{"nativeDisplayRemoved", "(JI)V", (void*)nativeDisplayRemoved},
{"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
(void*)nativeSetFocusedApplication},
{"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
{"nativeSetPointerCapture", "(JZ)V", (void*)nativeSetPointerCapture},
{"nativeSetInputDispatchMode", "(JZZ)V", (void*)nativeSetInputDispatchMode},
{"nativeSetSystemUiVisibility", "(JI)V", (void*)nativeSetSystemUiVisibility},
{"nativeTransferTouchFocus", "(JLandroid/os/IBinder;Landroid/os/IBinder;)Z",
(void*)nativeTransferTouchFocus},
{"nativeSetPointerSpeed", "(JI)V", (void*)nativeSetPointerSpeed},
{"nativeSetShowTouches", "(JZ)V", (void*)nativeSetShowTouches},
{"nativeSetInteractive", "(JZ)V", (void*)nativeSetInteractive},
{"nativeReloadCalibration", "(J)V", (void*)nativeReloadCalibration},
{"nativeVibrate", "(JI[JII)V", (void*)nativeVibrate},
{"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
{"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
{"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases},
{"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump},
{"nativeMonitor", "(J)V", (void*)nativeMonitor},
{"nativeIsInputDeviceEnabled", "(JI)Z", (void*)nativeIsInputDeviceEnabled},
{"nativeEnableInputDevice", "(JI)V", (void*)nativeEnableInputDevice},
{"nativeDisableInputDevice", "(JI)V", (void*)nativeDisableInputDevice},
{"nativeSetPointerIconType", "(JI)V", (void*)nativeSetPointerIconType},
{"nativeReloadPointerIcons", "(J)V", (void*)nativeReloadPointerIcons},
{"nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
(void*)nativeSetCustomPointerIcon},
{"nativeCanDispatchToDisplay", "(JII)Z", (void*)nativeCanDispatchToDisplay},
{"nativeNotifyPortAssociationsChanged", "(J)V", (void*)nativeNotifyPortAssociationsChanged},
{"nativeSetMotionClassifierEnabled", "(JZ)V", (void*)nativeSetMotionClassifierEnabled},
};
nativeInit
java的nativeInit方法对应着同名的jni函数
/// @frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// 获取C++ 的MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 创建jni层的NativeInputManager, 用于InputManagerService与C++ InputManager 通信
// serviceObj是InputManagerService, 因此NativeInputManager持有了IMS的引用
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
NativeInputManager 构造
/// @frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
// 持有IMS的强引用
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
mLocked.pointerCapture = false;
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
// 创建InputManager, 注意两个this,都是指代 NativeInputManager,它是相关策略的实现类
mInputManager = new InputManager(this, this);
// 注册InputManager到sm, 名称是inputflinger
defaultServiceManager()->addService(String16("inputflinger"),
mInputManager, false);
}
从NativeInputManager的继承体系来看,它是InputReaderPolicyInterface,InputDispatcherPolicyInterface等策略的实现类
/// @frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface {...
创建InputManager
从继承结构上看,InputManager是binder service的Bn端,对外提供服务, 通过名称inputflinger获取
/// @frameworks/native/services/inputflinger/InputManager.h
class InputManager : public InputManagerInterface, public BnInputFlinger {
private:
sp<InputReaderInterface> mReader;
sp<InputClassifierInterface> mClassifier;
sp<InputDispatcherInterface> mDispatcher;
InputManager构造函数 , 此处的readerPolicy和dispatcherPolicy实际上都是NativeInputManager
/// @frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = createInputDispatcher(dispatcherPolicy); // 使用工厂创建InputDispatcher
mClassifier = new InputClassifier(mDispatcher); // 创建InputClassifier,持有mDispatcher
mReader = createInputReader(readerPolicy, mClassifier); // 使用工厂创建InputReader,注意mClassifier参数
}
以上工厂方法对应的头文件如下, 实现在对应的cpp文件
#include "InputDispatcherFactory.h"
#include "InputReaderFactory.h"
createInputDispatcher
/// @frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
sp<InputDispatcherInterface> createInputDispatcher(
const sp<InputDispatcherPolicyInterface>& policy) {
return new android::inputdispatcher::InputDispatcher(policy);
}
创建 InputDispatcher
/// @frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
// mInTouchMode will be initialized by the WindowManager to the default device config.
// To avoid leaking stack in case that call never comes, and for tests,
// initialize it here anyways.
mInTouchMode(true), // 默认touch mode
mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
mLooper = new Looper(false); // 创建 Looper
mReporter = createInputReporter();
mKeyRepeatState.lastKeyEntry = nullptr;
policy->getDispatcherConfiguration(&mConfig);
}
创建 InputClassifier
由上可知,mListener的值实际上是mDispatcher. InputClassifier代表输入事件的一个处理阶段,对于motion events会交由MotionClassifier处理,其他事件则是直通的,也就是直接交于mListener进行处理.
/// @frameworks/native/services/inputflinger/InputClassifier.cpp
/*
* Implementation of the InputClassifierInterface.
* Represents a separate stage of input processing. All of the input events go through this stage.
* Acts as a passthrough for all input events except for motion events.
* The events of motion type are sent to MotionClassifier.
*/
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
: mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
createInputReader
此处的listener就是上面创建的InputClassifier, 而它持有InputDispatcher的引用, 因此InputReader间接持有InputDispatcher的引用, 另外注意此处创建了EventHub, 用于加工处理原始事件
/// @frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) {
return new InputReader(std::make_unique<EventHub>(), policy, listener);
}
创建 InputReader
/// @frameworks/native/services/inputflinger/reader/InputReader.cpp
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
//queues up and defers dispatch of decoded events until flushed.
mQueuedListener = new QueuedInputListener(listener); // 间接持有InputDispatcher的引用
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
QueuedInputListener
它用于向Dispatcher发送事件,实现事件排队并推迟派发事件直到调用flush
/// @frameworks/native/services/inputflinger/include/InputListener.h
/*
* An implementation of the listener interface that queues up and defers dispatch
* of decoded events until flushed.
*/
class QueuedInputListener : public InputListenerInterface {
protected:
virtual ~QueuedInputListener();
public:
explicit QueuedInputListener(const sp<InputListenerInterface>& innerListener);
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
virtual void notifyKey(const NotifyKeyArgs* args); // key 事件
virtual void notifyMotion(const NotifyMotionArgs* args); // motion 事件
virtual void notifySwitch(const NotifySwitchArgs* args);
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
void flush();
private:
sp<InputListenerInterface> mInnerListener;
std::vector<NotifyArgs*> mArgsQueue;
};
} // namespace android
InputManagerService#start
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr); // 调用 nativeStart
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this); // 添加到watchdog监听
// 注册一些监听
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
registerLongPressTimeoutObserver();
mContext.registerReceiver(new BroadcastReceiver() { // 注册 ACTION_USER_SWITCHED
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("user switched");
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
// 更新配置
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("just booted");
}
nativeStart
nativeStart 对应同名的jni函数
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
// 取出在nativeInit创建的NativeInputManager
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
InputManager#start()
status_t InputManager::start() {
status_t result = mDispatcher->start(); // 启动 dispatcher 线程
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReader->start(); // 启动 reader 线程
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
InputDispatcher::start
status_t InputDispatcher::start() {
if (mThread) { // 已经创建
return ALREADY_EXISTS;
}
// 创建InputDispatcher线程, 线程执行会调用dispatchOnce
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake();/* wake函数*/ });
return OK;
}
dispatcher 线程会不断调用dispatchOnce去分发事件
InputReader::start
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
// 创建InputReader线程, 线程执行会调用loopOnce
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake();/* wake函数*/ });
return OK;
}
reader线程会不断调用loopOnce去获取底层的事件, 然后将事件传递给dispatcher线程
InputThread
这个是一个线程封装类, 用于持续处理事件, 直到退出
/* A thread that loops continuously until destructed to process input events.
*
* Creating the InputThread starts it immediately. The thread begins looping the loop
* function until the InputThread is destroyed. The wake function is used to wake anything
* that sleeps in the loop when it is time for the thread to be destroyed.
*/
class InputThread {
public:
explicit InputThread(std::string name, std::function<void()> loop, // 线程循环函数
std::function<void()> wake = nullptr /* 要销毁时调用,唤醒Loop中的sleep*/);
virtual ~InputThread();
bool isCallingThread();
private:
std::string mName;
std::function<void()> mThreadWake;
sp<Thread> mThread;
};
} // namespace android
InputThread构造
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
: mName(name), mThreadWake(wake) {
mThread = new InputThreadImpl(loop); // 真正创建一个线程
// 启动线程,执行threadLoop
mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
通过InputThread构造的构造方法可知,在其中创建了真正的Thread实现类InputThreadImpl,并执行其run方法启动了线程. 因此reader和dispatcher中创建InputThread,实际上已经启动了内部创建的线程.
InputThreadImpl
线程的真正实现类
// Implementation of Thread from libutils.
class InputThreadImpl : public Thread {
public:
explicit InputThreadImpl(std::function<void()> loop)
: Thread(/* canCallJava */ true), mThreadLoop(loop) {}
~InputThreadImpl() {}
private:
std::function<void()> mThreadLoop; // loop 函数
bool threadLoop() override {
mThreadLoop(); // threadLoop 函数中执行 mThreadLoop函数
return true; // 返回true表示线程不退出,继续循环
}
};
IMS#systemRunning
这个方法用于通知System ready, 然后做一些注册和其他工作
public void systemRunning() {
if (DEBUG) {
Slog.d(TAG, "System ready.");
}
mNotificationManager = (NotificationManager)mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
mSystemReady = true; // ready 标志
// 监听ACTION_PACKAGE_ADDED, 用于更新keyboard布局
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateKeyboardLayouts();
}
}, filter, null, mHandler);
// 监听ACTION_ALIAS_CHANGED
filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
reloadDeviceAliases();
}
}, filter, null, mHandler);
// 更新相关信息
mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
if (mWiredAccessoryCallbacks != null) {
mWiredAccessoryCallbacks.systemReady();
}
}
更新设备信息
更新操作, 都是调用的native方法.
private void reloadKeyboardLayouts() {
if (DEBUG) {
Slog.d(TAG, "Reloading keyboard layouts.");
}
nativeReloadKeyboardLayouts(mPtr);
}
private void reloadDeviceAliases() {
if (DEBUG) {
Slog.d(TAG, "Reloading device names.");
}
nativeReloadDeviceAliases(mPtr);
}
对应的jni函数如下 , 都是调用的InputReader
static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->getInputManager()->getReader()->requestRefreshConfiguration(
InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS);
}
static void nativeReloadDeviceAliases(JNIEnv* /* env */,
jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->getInputManager()->getReader()->requestRefreshConfiguration(
InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
}
InputReader::requestRefreshConfiguration
InputReader 会更新mConfigurationChangesToRefresh, 然后唤醒线程
void InputReader::requestRefreshConfiguration(uint32_t changes) {
AutoMutex _l(mLock);
if (changes) {
bool needWake = !mConfigurationChangesToRefresh;
mConfigurationChangesToRefresh |= changes;
if (needWake) {
mEventHub->wake();
}
}
}
reader线程被唤醒后会执行loopOnce方法
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
{ // acquire lock
AutoMutex _l(mLock);
...
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes); // 更新配置
} else if (mNextTimeout != LLONG_MAX) {...
} // release lock
...
refreshConfigurationLocked
具体更新
void InputReader::refreshConfigurationLocked(uint32_t changes) {
mPolicy->getReaderConfiguration(&mConfig);
mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
if (changes) {
ALOGI("Reconfiguring input devices, changes=%s",
InputReaderConfiguration::changesToString(changes).c_str());
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) {
updatePointerDisplayLocked();
}
if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
mEventHub->requestReopenDevices();
} else {
for (auto& devicePair : mDevices) {
std::shared_ptr<InputDevice>& device = devicePair.second;
device->configure(now, &mConfig, changes);
}
}
}
}
总结
本篇主要介绍了InputManagerService的启动流程,它的实现包含java和native两个部分. native的部分才是真正的实现,而java层的通常是相关功能的封装. 在native层创建了两个线程, reader线程不断的从EventHub从获取事件,然后将事件交给dispatcher线程进行分发. dispatcher会找到合适的window, 然后将事件派发给它.对应的window处理完相关事件后,向ims发送处理完毕的反馈,然后ims做一些收尾工作,此次事件派发循环才算完整结束.
以上是关于Android R input 之 InputManagerService 的建立的主要内容,如果未能解决你的问题,请参考以下文章
Android R input 之 InputChannel之发送事件处理反馈
Android R input 之 InputDispatcher 工作流程
Android R input 之 InputDispatcher 工作流程
Android R input 之 InputManagerService 的建立