Android输入子系统之启动过程分析
- Step 1. SystemServer.startOtherServices
- Step 2. InputManagerService.init
- Step 3. InputManagerService.nativeInit
- Step 4. NativeInputManager.init
- Step 5. InputManager.init
- Step 6. InputManager.initialize
- Step 7. InputManagerService.start
- Step 8. InputManagerService.nativeStart
- Step 9. InputManager.start
- Step 10. InputDispatcherThread.threadLoop
- Step 11. InputDispatcher.dispatchOnce
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> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
//构造一个NativeInputManagera对象
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(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>& looper) : mLooper(looper), mInteractive(true)
{
//构造一个EventHub对象,最原始的输入事件都是通过它收集并且粗加工然后给到InputReader对象
sp<EventHub> 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<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& 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<NativeInputManager*>(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