这一节主要了解一下Android输入事件源码,Android输入系统的工作原理概括来说,就是监控/dev/input/下的所有设备节点,当某个节点有数据可读时,将数据读出并进行一系列的加工,然后在所有的窗口中寻找合适的事件接收者,并派发给它。 整体含有几个关键因素:
Linux内核:接受输入设备的中断,并将原始事件的数据写入设备节点中。
设备节点:作为内核与IMS的桥梁,它将原始事件的数据暴露给用户空间,以便IMS可以从中读取事件。
EventHub:直接访问所有的设备节点。并且正如其名字所描述的,它通过一个名为getEvents()的函数将所有输入系统相关的待处理的底层事件返回给使用者。这些事件包括原始输入事件、设备节点的增删等。
InputReader,是IMS中的关键组件之一。它运行于一个独立的线程中,负责管理输入设备的列表与配置,以及进行输入事件的加工处理。它通过其线程循环不断地通过getEventsO)函数从EventHub 中将事件取出并进行处理。对于设备节点的增删事件,它会更新输入设备列表与配置。对于原始输入事件,InputReader对其进行翻译、组装、封装为包含更多信息、更具可读性的输人事件,然后交给 InputDispatcher 进行派发。
InputReaderPolicy:它为InputReader的事件加工处理提供一些策略配置,例如键盘布局信息等。
InputDispatcher:是IMS中的另一个关键组件。它也运行于一个独立的线程中。InputDispatcher中保管了来自WMS的所有窗口的信息,其收到来自InputReader的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口。
InputDispatcherPolicy:它为InputDispatcher的派发过程提供策略控制。例如截取某些特定的输入事件用作特殊用途,或者阻止将某些事件派发给目标窗口。一个典型的例子就是HOME键被InputDispatcherPolicy截取到PhoneWindowManager中进行处理,并阻止窗口收到HOME键按下的事件。
WMS:虽说不是输入系统中的一员,但是它却对InputDispatcher的正常工作起到了至关重要的作用。当新建窗口时,WMS为新窗口和IMS创建了事件传递所用的通道。另外,WMS还将所有窗口的信息,包括窗口的可点击区域、焦点窗口等信息,实时地更新到IMS的InputDispatcher 中,使得InputDispatcher 可以正确地将事件派发到指定的窗口。
ViewRootImpl:对某些窗口,如壁纸窗口、SurfaceView的窗口来说,窗口就是输入事件派发的终点。而对其他的如Activity、对话框等使用了Android 控件系统的窗口来说,输入事件的终点是控件(View)。ViewRootImpl将窗口所接收的输人事件沿着控件树将事件派发给感兴趣的控件。
frameworks/base/services/java/com/android/server/SystemServer.javapublic static void main(String[] args) {new SystemServer().run();}private void run() {TimingsTraceAndSlog t = new TimingsTraceAndSlog();try {t.traceBegin("InitBeforeStartServices");// Record the process start information in sys props.SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime); // The system server should never make non-oneway callsBinder.setWarnOnBlocking(true);// The system server should always load safe labelsPackageItemInfo.forceSafeLabels();// Default to FULL within the system server.SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;// Deactivate SQLiteCompatibilityWalFlags until settings provider is initializedSQLiteCompatibilityWalFlags.init(null);// Here we go!Slog.i(TAG, "Entered the Android system server!");final long uptimeMillis = SystemClock.elapsedRealtime();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);if (!mRuntimeRestart) {FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,uptimeMillis);}SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());// Mmmmmm... more memory!VMRuntime.getRuntime().clearGrowthLimit();// Some devices rely on runtime fingerprint generation, so make sure// we've defined it before booting further.Build.ensureFingerprintProperty();// Create the system service manager.mSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.start();// Attach JVMTI agent if this is a debuggable build and the system property is set....} finally {t.traceEnd(); // InitBeforeStartServices}// Setup the default WTF handlerRuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);// Start services.try {t.traceBegin("StartServices");// 启动引导服务startBootstrapServices(t);// 启动核心服务startCoreServices(t);// 启动其他服务 startOtherServices(t);} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}StrictMode.initVmDefaults(null);...// Diagnostic to ensure that the system is in a base healthy state. Done here as a common// non-zygote process.if (!VMRuntime.hasBootImageSpaces()) {Slog.wtf(TAG, "Runtime is not running with a boot image!");}// Loop forever.Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}private void startOtherServices(@NonNull TimingsTraceAndSlog t) {final Context context = mSystemContext;VibratorService vibrator = null;DynamicSystemService dynamicSystem = null;IStorageManager storageManager = null;NetworkManagementService networkManagement = null;IpSecService ipSecService = null;NetworkStatsService networkStats = null;NetworkPolicyManagerService networkPolicy = null;ConnectivityService connectivity = null;NsdService serviceDiscovery = null;WindowManagerService wm = null;SerialService serial = null;NetworkTimeUpdateService networkTimeUpdater = null;InputManagerService inputManager = null;TelephonyRegistry telephonyRegistry = null;ConsumerIrService consumerIr = null;MmsServiceBroker mmsService = null;HardwarePropertiesManagerService hardwarePropertiesService = null;try {t.traceBegin("StartInputManagerService");inputManager = new InputManagerService(context);wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());inputManager.start(); } catch (Throwable e) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting core service");throw e;} }
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.javapublic void start() {Slog.i(TAG, "Starting input manager");nativeStart(mPtr);// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);registerPointerSpeedSettingObserver();registerShowTouchesSettingObserver();registerAccessibilityLargePointerSettingObserver();registerLongPressTimeoutObserver();mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic 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");}
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cppstatic void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}}inline sp<InputManager> getInputManager() const { return mInputManager; }
用reinterpret_cast操作符将jlong类型的ptr强制转换为原类型(NativeInputManager指针类型)。
/frameworks/native/services/inputflinger/InputManager.cppstatus_t InputManager::start() {status_t result = mDispatcher->start();if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}result = mReader->start();if (result) {ALOGE("Could not start InputReader due to error %d.", result);mDispatcher->stop();return result;}return OK;
}
/frameworks/native/services/inputflinger/reader/InputReaderFactory.cppnamespace android {sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,const sp<InputListenerInterface>& listener) {return new InputReader(std::make_unique<EventHub>(), policy, listener);
}} // namespace android/frameworks/native/services/inputflinger/reader/InputReader.cppstatus_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });return OK;
}
/frameworks/native/services/inputflinger/InputThread.cppclass InputThreadImpl : public Thread {
public:explicit InputThreadImpl(std::function<void()> loop): Thread(/* canCallJava */ true), mThreadLoop(loop) {}~InputThreadImpl() {}private:std::function<void()> mThreadLoop;bool threadLoop() override {mThreadLoop();return true;}
};
InputManager的start函数运行了InputDispatcherThread和InputReaderThread线程;
InputDispatcher和InputReader是在哪创建的
/frameworks/native/services/inputflinger/InputManager.cppInputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {mDispatcher = createInputDispatcher(dispatcherPolicy);mClassifier = new InputClassifier(mDispatcher);mReader = createInputReader(readerPolicy, mClassifier);
}
可以看出InputDispatcher和InputReader是有关联的,InputDispatcher会作为一个参数传入到InputReader中;