Android Input 体系中,大致有两种类型的事件:实体按键 key 事件,屏幕点击触摸事件。
如果根据事件类型的不同我们还能细分为基础实体按键的 key(power,volume up/down,recents,back,home),实体键盘按键,屏幕点击 (多点,单点),屏幕滑动等等的事件。
在 Android 整个 Input 体系中有三个格外重要的成员:Eventhub,InputReader,InputDispatcher。
它们分别担负着各自不同的职责,Eventhub 负责监听 / dev/input 产生 Input 事件,InputReader 负责从 Eventhub 读取事件,并将读取的事件发给 InputDispatcher,InputDispatcher 则根据实际的需要具体分发给当前手机获得焦点实际的 Window。
inputmanagerservice启动原理
inpu子系统是运行在system 系统进程的
/frameworks/base/services/java/com/android/server/SystemServer.java
1325 private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
1326 t.traceBegin("startOtherServices");
。。。。。。
1471 t.traceBegin("StartInputManagerService");
// 1)创建 InputManagerService 对象
1472 inputManager = new InputManagerService(context);// 2)将其作为参数传入到wms 中
1488 wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
1489 new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// 增加这个input service,给客户端使用
1490 ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
1491 DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
1492 ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
1493 /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);// 3)启动 InputManagerService
1520 t.traceBegin("StartInputManager");
1521 inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
1522 inputManager.start();
1)创建 InputManagerService 对象
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
424 public InputManagerService(Context context) {
425 this.mContext = context;// 创建handler,在 DisplayThread 线程中处理
426 this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
427
428 mStaticAssociations = loadStaticInputPortAssociations();
429 mUseDevInputEventForAudioJack =
430 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);// system 系统进程input,会打印下列的日志
431 Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
432 + mUseDevInputEventForAudioJack);// 调用native 层的方法去初始化
433 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
434
435 String doubleTouchGestureEnablePath = context.getResources().getString(
436 R.string.config_doubleTouchGestureEnableFile);
437 mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
438 new File(doubleTouchGestureEnablePath);
439
440 LocalServices.addService(InputManagerInternal.class, new LocalService());
441 }
// 调用native 层的方法去初始化,looper 是 DisplayThread 线程
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
1488 static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
1489 jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
1490 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
1491 if (messageQueue == nullptr) {
1492 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1493 return 0;
1494 }
1495 // 创建NativeInputManager 对象,looper 是DisplayThread 线程【再次说明】
1496 NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
1497 messageQueue->getLooper());
1498 im->incStrong(0);
1499 return reinterpret_cast<jlong>(im);
1500 }
创建NativeInputManager 对象
407 NativeInputManager::NativeInputManager(jobject contextObj,
408 jobject serviceObj, const sp<Looper>& looper) :// 缓存 mLooper
409 mLooper(looper), mInteractive(true) {
410 JNIEnv* env = jniEnv();
411
412 mServiceObj = env->NewGlobalRef(serviceObj);
413
414 {
415 AutoMutex _l(mLock);
416 mLocked.systemUiLightsOut = false;
417 mLocked.pointerSpeed = 0;
418 mLocked.pointerGesturesEnabled = true;
419 mLocked.showTouches = false;
420 mLocked.pointerCapture = false;
421 mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
422 }
423 mInteractive = true;
424 // 创建对象 InputManager,2个参数都是this
425 InputManager* im = new InputManager(this, this);
426 mInputManager = im;// 将其保存到 "inputflinger",给native 层调用
427 defaultServiceManager()->addService(String16("inputflinger"), im);
428 }
创建对象 InputManager,2个参数都是this
/frameworks/native/services/inputflinger/InputManager.cpp
53 InputManager::InputManager(
54 const sp<InputReaderPolicyInterface>& readerPolicy,
55 const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {// 1-1)创建 InputDispatcher对象
56 mDispatcher = createInputDispatcher(dispatcherPolicy);// 1-2)创建 InputClassifier 对象
57 mClassifier = new InputClassifier(mDispatcher);// 1-3)创建 InputReader 对象,传入了 InputClassifier对象
58 mReader = createInputReader(readerPolicy, mClassifier);
59 }
60
// 1-1)创建 InputDispatcher对象
frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
22 sp<InputDispatcherInterface> createInputDispatcher(
23 const sp<InputDispatcherPolicyInterface>& policy) {
24 return new android::inputdispatcher::InputDispatcher(policy);
25 }
/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
509 InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)//mPolicy 是 NativeInputManager,可以通过此从native层传消息给java 层,比如通知没有焦点窗口510 : mPolicy(policy),
511 mPendingEvent(nullptr),
512 mLastDropReason(DropReason::NOT_DROPPED),
513 mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
514 mAppSwitchSawKeyDown(false),
515 mAppSwitchDueTime(LONG_LONG_MAX),
516 mNextUnblockedEvent(nullptr),
517 mDispatchEnabled(false),
518 mDispatchFrozen(false),
519 mInputFilterEnabled(false),
520 // mInTouchMode will be initialized by the WindowManager to the default device config.
521 // To avoid leaking stack in case that call never comes, and for tests,
522 // initialize it here anyways.
523 mInTouchMode(true),
524 mMaximumObscuringOpacityForTouch(1.0f),
525 mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
526 mFocusedWindowRequestedPointerCapture(false),
527 mWindowTokenWithPointerCapture(nullptr),
528 mLatencyAggregator(),
529 mLatencyTracker(&mLatencyAggregator),
530 mCompatService(getCompatService()) {
531 mLooper = new Looper(false);
532 mReporter = createInputReporter();
533
534 mKeyRepeatState.lastKeyEntry = nullptr;
535
536 policy->getDispatcherConfiguration(&mConfig);
537 }
// 1-2)创建 InputClassifier 对象
/frameworks/native/services/inputflinger/InputClassifier.cpp
构造函数中传入的参数 mListener 是inputdispatcher。而 InputClassifier也作为参数传入给 InputReader。相当于 InputClassifier 是 沟通 InputReader和 inputdispatcher 的桥梁
348 InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
349 : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
350
// 1-3)创建 InputReader 对象,传入了 InputClassifier对象
/frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
23 sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
24 const sp<InputListenerInterface>& listener) {// 这里还创建了 EventHub,负责读取驱动的事件
25 return new InputReader(std::make_unique<EventHub>(), policy, listener);
26 }
InputReader 构造方法
/frameworks/native/services/inputflinger/reader/InputReader.cpp
43 InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
44 const sp<InputReaderPolicyInterface>& policy,
45 const sp<InputListenerInterface>& listener)
46 : mContext(this),
47 mEventHub(eventHub),
48 mPolicy(policy),
49 mGlobalMetaState(0),
50 mLedMetaState(AMETA_NUM_LOCK_ON),
51 mGeneration(1),
52 mNextInputDeviceId(END_RESERVED_ID),
53 mDisableVirtualKeysTimeout(LLONG_MIN),
54 mNextTimeout(LLONG_MAX),
55 mConfigurationChangesToRefresh(0) {// 创建 QueuedInputListener 对象,listener 是 InputClassifier.cpp
56 mQueuedListener = new QueuedInputListener(listener);
57
58 { // acquire lock
59 std::scoped_lock _l(mLock);
60
61 refreshConfigurationLocked(0);
62 updateGlobalMetaStateLocked();
63 } // release lock
64 }
/frameworks/native/services/inputflinger/InputListener.cpp
在调用 flush 后,可以将信息传递给 inputDispatcher
315 QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
316 mInnerListener(innerListener) {
317 }367 void QueuedInputListener::flush() {
368 size_t count = mArgsQueue.size();
369 for (size_t i = 0; i < count; i++) {
370 NotifyArgs* args = mArgsQueue[i];
371 args->notify(mInnerListener);
372 delete args;
373 }
374 mArgsQueue.clear();
375 }
2)将其作为参数传入到wms 中
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
1204 private WindowManagerService(Context context, InputManagerService inputManager,
1205 boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
1206 ActivityTaskManagerService atm, DisplayWindowSettingsProvider
1207 displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
1208 Supplier<Surface> surfaceFactory,
1209 Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
1210 installLock(this, INDEX_WINDOW);
1211 mGlobalLock = atm.getGlobalLock();
1212 mAtmService = atm;
1213 mContext = context;
1214 mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
1215 mAllowBootMessages = showBootMsgs;
1216 mOnlyCore = onlyCore;
1217 mLimitedAlphaCompositing = context.getResources().getBoolean(
1218 com.android.internal.R.bool.config_sf_limitedAlpha);
1219 mHasPermanentDpad = context.getResources().getBoolean(
1220 com.android.internal.R.bool.config_hasPermanentDpad);
1221 mInTouchMode = context.getResources().getBoolean(
1222 com.android.internal.R.bool.config_defaultInTouchMode);
1223 inputManager.setInTouchMode(mInTouchMode);
1224 mDrawLockTimeoutMillis = context.getResources().getInteger(
1225 com.android.internal.R.integer.config_drawLockTimeoutMillis);
1226 mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
1227 com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
1228 mMaxUiWidth = context.getResources().getInteger(
1229 com.android.internal.R.integer.config_maxUiWidth);
1230 mDisableTransitionAnimation = context.getResources().getBoolean(
1231 com.android.internal.R.bool.config_disableTransitionAnimation);
1232 mPerDisplayFocusEnabled = context.getResources().getBoolean(
1233 com.android.internal.R.bool.config_perDisplayFocusEnabled);
1234 mAssistantOnTopOfDream = context.getResources().getBoolean(
1235 com.android.internal.R.bool.config_assistantOnTopOfDream);
1236
1237 mLetterboxConfiguration = new LetterboxConfiguration(context);
1238 // 缓存了 inputManager
1239 mInputManager = inputManager; // Must be before createDisplayContentLocked.
3)启动 InputManagerService
InputManager 类继承自 InputManagerInterface 接口,是系统处理输入事件的核心。 InputManager 包含两个线程:
- InputReader Thread(称为“ InputReader”)读取并预处理原始输入事件EventHub->getEvents,应用策略
- InputDispatcher Thread(称为“ InputDispatcher”)线程在队列上等待新事件,然 后异步将其分配给应用程序。
首先InputManagerService 设置callback: setWindowManagerCallbacks
该callback是:
4746 final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
/frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java
public InputManagerCallback(WindowManagerService service) {mService = service;}// 看起来是和回调通知消息给 wms相关public void notifyNoFocusedWindowAnr(@NonNull InputApplicationHandle applicationHandle) {mService.mAnrController.notifyAppUnresponsive(applicationHandle, "Application does not have a focused window");}
设置callback: setWindowManagerCallbacks
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {// 保证只有一个 callbackif (mWindowManagerCallbacks != null) {unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);}
// 缓存这个callbackmWindowManagerCallbacks = callbacks;registerLidSwitchCallbackInternal(mWindowManagerCallbacks);}
启动 InputManagerService
public void start() {Slog.i(TAG, "Starting input manager");// native 去启动startnativeStart(mPtr);// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);registerPointerSpeedSettingObserver();registerShowTouchesSettingObserver();.........
nativeStart
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);// 获取到 InputManager 对象,调用其start 的方法status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}
}
/frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {// 调用InputDispatcher 的start 方法status_t result = mDispatcher->start();if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}// 调用InputReader 的start 方法result = mReader->start();if (result) {ALOGE("Could not start InputReader due to error %d.", result);mDispatcher->stop();return result;}return OK;
}
// 调用InputDispatcher 的start 方法
/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::start() {if (mThread) {return ALREADY_EXISTS;}// 再系统进程中创建线程,名字为 "InputDispatcher"
// 创建 InputThread 线程,传入lambda循环函数dispatchOncemThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });return OK;
}=============/frameworks/native/services/inputflinger/InputThread.cpp// 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;// 会调用 threadLoop,执行loop方法bool threadLoop() override {mThreadLoop();return true;}
};} // namespace// 创建 InputThread
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake): mName(name), mThreadWake(wake) {// 创建InputThreadImpl对象,传入 loop函数mThread = new InputThreadImpl(loop);
// 开启线程循环。mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
执行loop 方法
void InputDispatcher::dispatchOnce() {nsecs_t nextWakeupTime = LONG_LONG_MAX;{ // acquire lockstd::scoped_lock _l(mLock);mDispatcherIsAlive.notify_all();// Run a dispatch loop if there are no pending commands.// The dispatch loop might enqueue commands to run afterwards.if (!haveCommandsLocked()) {dispatchOnceInnerLocked(&nextWakeupTime);}// Run all pending commands if there are any.// If any commands were run then force the next poll to wake up immediately.if (runCommandsLockedInterruptible()) {nextWakeupTime = LONG_LONG_MIN;}// If we are still waiting for ack on some events,// we might have to wake up earlier to check if an app is anr'ing.const nsecs_t nextAnrCheck = processAnrsLocked();nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);// We are about to enter an infinitely long sleep, because we have no commands or// pending or queued eventsif (nextWakeupTime == LONG_LONG_MAX) {mDispatcherEnteredIdle.notify_all();}} // release lock// Wait for callback or timeout or wake. (make sure we round up, not down)nsecs_t currentTime = now();int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);mLooper->pollOnce(timeoutMillis);
}
// 调用InputReader 的start 方法
/frameworks/native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}// 同理,也是在系统进程中创建一个线程,名字为 InputReader
// 执行方法 loopOnce()mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });return OK;
}============
void InputReader::loopOnce() {int32_t oldGeneration;int32_t timeoutMillis;bool inputDevicesChanged = false;std::vector<InputDeviceInfo> inputDevices;{ // acquire lockstd::scoped_lock _l(mLock);oldGeneration = mGeneration;timeoutMillis = -1;uint32_t changes = mConfigurationChangesToRefresh;if (changes) {mConfigurationChangesToRefresh = 0;timeoutMillis = 0;refreshConfigurationLocked(changes);} else if (mNextTimeout != LLONG_MAX) {nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);}} // release lock// 去从驱动中读取input 事件size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lockstd::scoped_lock _l(mLock);mReaderIsAliveCondition.notify_all();if (count) {processEventsLocked(mEventBuffer, count);}