Linux/Android——Input系統之frameworks層InputManag - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

您當前位置>首頁 » 新聞資(zī)訊 » 技術(shù)分享 >

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)知它有新的事沂攀來了

相關(guān)案例查看更多