Android输入子系统之启动过程分析
发布日期:2021-06-29 14:51:09 浏览次数:3 分类:技术文章

本文共 6404 字,大约阅读时间需要 21 分钟。

Android输入子系统之启动过程分析

Android的输入子系统是在InputManagerService中启动的,而InputManagerService是在system_server中启动的。

我们先看下整个启动过程的序列图,然后根据序列图来一步步分析。

在这里插入图片描述

Step 1. SystemServer.startOtherServices

函数定义在frameworks/base/services/java/com/android/server/SystemServer.java中

//启动核心服务private void startCoreServices() {
}//启动其他的服务private void startOtherServices() {
//初始化一个InputManagerService对象 inputManager = new InputManagerService(context); wm = WindowManagerService.main(context, inputManager, mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore); //将WindowManagerService加入到ServiceManager中 ServiceManager.addService(Context.WINDOW_SERVICE, wm); //将InputManagerService加入到ServiceManager中 ServiceManager.addService(Context.INPUT_SERVICE, inputManager); inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start();}

在SystemServer中先构造了一个InputManagerService对象和一个WindowManagerService对象,

然后将InputManagerService对象传给WindowManagerService对象,
WindowManagerService中初始化了一个InputMonitor对象,
调用InputManagerService.setWindowManagerCallbacks 函数将 InputMonitor 传进去,后面native层回调时会调用到该InputMonitor对象。

Step 2. InputManagerService.init

InputManagerService.java的构造函数定义在

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public class InputManagerService {
public InputManagerService(Context context) {
this.mContext = context; this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); //调用nativeInit来执行C++层的初始化操作 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); LocalServices.addService(InputManagerInternal.class, new LocalService()); }}

构造函数调用nativeInit来执行C++层的初始化操作

Step 3. InputManagerService.nativeInit

该函数定义在frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp
messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); //构造一个NativeInputManagera对象 NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); im->incStrong(0); return reinterpret_cast
(im);}

这个函数主要作用是创建一个NativeInputManager实例,并将其作为返回值保存在InputManagerService.java中的mPtr字段中。

Step 4. NativeInputManager.init

NativeInputManager 构造函数定义在 frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp 文件中

NativeInputManager::NativeInputManager(jobject contextObj,        jobject serviceObj, const sp
& looper) : mLooper(looper), mInteractive(true) {
//构造一个EventHub对象,最原始的输入事件都是通过它收集并且粗加工然后给到InputReader对象 sp
eventHub = new EventHub(); //构造一个InputManager对象 mInputManager = new InputManager(eventHub, this, this);}

NativeInputManager构造函数中创建了一个EventHub实例,

并且将这个实例作为参数来创建一个InputManager对象,这个对象会做一些初始化的操作。

Step 5. InputManager.init

InputManager的构造函数定义在

frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(        const sp
& eventHub, const sp
& readerPolicy, const sp
& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); initialize();}

这里创建了InputDispatcher对象用于分发按键给当前focus的窗口的,同时创建了一个InputReader用于从EventHub中读取键盘事件。

Step 6. InputManager.initialize

void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher);}

这里创建了一个InputReaderThread和InputDispatcherThread对象,

前面构造函数中创建的InputReader实际上是通过InputReaderThread来读取键盘事件,
而InputDispatcher实际通过InputDispatcherThread来分发键盘事件

Step 7. InputManagerService.start

InputManagerService.java中start函数定义在

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public void start() {
Slog.i(TAG, "Starting input manager"); nativeStart(mPtr); ...}

该函数主要调用了nativeStart进入native层启动

Step 8. InputManagerService.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
(ptr); status_t result = im->getInputManager()->start();}

实际调用了InputManager的start函数

Step 9. InputManager.start

start函数定义在

frameworks/native/services/inputflinger/InputManager.cpp

status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); return OK; }

Step 10. InputDispatcherThread.threadLoop

该函数定义在frameworks/native/services/inputflinger/InputDispatcher.cpp 中

status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); return OK; }

这里调用前面在Step 5中创建的实例InputDispatcher的dispatchOnce函数进行一次按键分发

Step 11. InputDispatcher.dispatchOnce

这个函数定义在frameworks/native/services/inputflinger/InputDispatcher.cpp 中

void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX; {
// acquire lock AutoMutex _l(mLock); mDispatcherIsAliveCondition.broadcast(); // 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; } } // 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);}

上述函数主要是调用dispatchOnceInnerLocked来进行一次按键分发,

当没有按键消息时会走到mLooper->pollOnce(timeoutMillis); 这个函数会进入睡眠状态,
当有按键消息发生时该函数会返回,然后走到dispatchOnceInnerLocked函数。

这里mLooper->pollOnce为何会睡眠涉及到Android的Handler机制,后续再研究

————————————————

原文链接:https://blog.csdn.net/chenweiaiyanyan/article/details/72910734

转载地址:https://ciellee.blog.csdn.net/article/details/104900703 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【输入子系统01】USB触摸屏驱动
下一篇:Input Subsystem 底层框架浅析

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月20日 20时59分41秒