Linux/Android——Input系統之frameworks層InputManag
發表時間:2020-10-19
發布人:葵宇科技
浏覽次數:38
上一篇Linux/Android——input體系之 kernel層 與 frameworks層交互 (五) 中(zhōng)有介紹kernel層一下(xià)以及與android這邊frameworks層之間的接洽,算是打通(tōng)android 應用層與 kernel驅動(dòng)層,半數個(gè)input體系的進修是至關(guān)重要的,個(gè)中(zhōng)frameworks層隻是簡單記錄了幾個(gè)接入點,這裡開端分析frameworks層的細節部分。
撰寫不易,轉載需注明出處:http://blog.csdn.net/jscese/article/details/42392311
input辦事的啟動(dòng):
android啟動(dòng)的時刻會啟動(dòng)很多個(gè)service,這個(gè)可(kě)以參考SystemServer.java ,會啟動(dòng)InputManagerService這個(gè)辦事:
Slog.i(TAG, "Input Manager"); inputManager = new InputManagerService(context, wmHandler); ... ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
直接看InputManagerService.java中(zhōng)的start函數:
public void start() { Slog.i(TAG, "Starting input manager"); nativeStart(mPtr); //調用了本處所法,JNI對應的cpp 在server下(xià)的jni目次下(xià) ... }
這個(gè)牽扯到android的server的jni,最開端是在SystemServer中(zhōng)加載android_server這個(gè)動(dòng)态庫,
至于這個(gè)動(dòng)态庫的編譯可(kě)參考/frameworks/base/services/jni/Android.mk中(zhōng)的内容
所以在調用這個(gè)nativeStart辦法時,相幹的動(dòng)态庫已經加載到SystemServer的過程中(zhōng)。
先看下(xià)這個(gè)start函數在jni文(wén)件中(zhōng)的實現,frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp中(zhōng):
static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); //這個(gè)NativeInputManager 是在膳绫擎InputMangerService構造的時刻調用nativeInit時new出來的 status_t result = im->getInputManager()->start(); //這裡是調用了NativeInputManager中(zhōng)的InputManager中(zhōng)的start辦法,同樣這個(gè)InputManager是NativeInputManager構造的時刻new出來的 if (result) { jniThrowRuntimeException(env, "Input manager could not be started."); } }
其實熟悉JNI的話,我分析到這裡,就應當差不多了。。對于JNI 不是很懂得的話可(kě)以參考我之前的博客:Andorid——ubuntu下(xià)的 NDK / JNI
看下(xià)NativeInputManager構造函數中(zhōng)的:
sp<EventHub> eventHub = new EventHub(); mInputManager = new InputManager(eventHub, this, this);
這裡的JNI部分就不多說了,如(rú)今就看這個(gè)InputManager的start辦法,膳绫擎提到到Android.mk,可(kě)以看到include了一個(gè)libinput的動(dòng)态庫,
而這個(gè)動(dòng)态庫的路(lù)徑是在/frameworks/base/services/input下(xià),這就清楚明潦攀啦.此目次下(xià)有InputManager.cpp . EventHub.cpp等
直接看start:
status_t InputManager::start() { status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); //這個(gè)mDispatcherThread是在InputManager構造函數裡調用initialize初始化,這裡很明顯啟動(dòng)了這個(gè)名為InputDispatcher的線程 if (result) { ALOGE("Could not start InputDispatcher thread due to error %d.", result); return result; } result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); //同上,開啟線程 if (result) { ALOGE("Could not start InputReader thread due to error %d.", result); mDispatcherThread->requestExit(); return result; } return OK; }
到這裡算是看到真面貌的感到,看這兩個(gè)線程,字面意思,一個(gè)是分發給input事宜給當前的activity的,一個(gè)是攫取大年夜基層發上來的input事宜的
InputDispatcher分發:
大年夜膳绫擎的線程啟動(dòng)分析:
bool InputDispatcherThread::threadLoop() { mDispatcher->dispatchOnce(); return true; }調用分發一次的函數:
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()) { //如(rú)不雅有緩存的敕令就調用下(xià)面的runCommand去履行,沒有的話這裡去檢查是否有新的input事宜,這裡定義一個(gè)喚醒時光┞菲握 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); //履行膳绫擎一次分發之後,就進入了loop,這個(gè)loop會持續的檢測對應的管道中(zhōng)是否有内容可(kě)讀,而别的一個(gè)線程InputReader 攫取到input事宜之後就會往這個(gè)管道寫入 }
這個(gè)是處理input事宜的,後續分析,先看怎麼攫取事宜.
InputReader攫取:
源碼位于frameworks/base/libs/ui/InputReader.cpp ,開啟線程如(rú)下(xià):
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true; }
這裡看這個(gè)loopOnce:
void InputReader::loopOnce() { ... size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); //這裡去獲取event事宜 ... if (count) { processEventsLocked(mEventBuffer, count); //如(rú)不雅獲取到事宜,就處理 } ... }
可(kě)以看到這裡就到了獲取event事宜了。上一篇中(zhōng)有提到!
getEvent中(zhōng)會一向read,直到get到event之後,經由過程precessevent處理,最終會喚醒膳绫擎介紹到的InputDispatcherThread,通(tōng)知它有新的事沂攀來了