Linux/Android——Input系統之(zhī)frameworks層InputManag - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

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

知識

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

您當前位置>首頁 » 新聞資訊 » 技術分享 >

Linux/Android——Input系統之(zhī)frameworks層InputManag

發表時(shí)間:2020-10-19

發布人(rén):融晨科技

浏覽次數:52


      上(shàng)一篇Linux/Android——input體系之(zhī) kernel層 與 frameworks層交互 (五)  中有介紹kernel層一下以(yǐ)及與android這(zhè)邊frameworks層之(zhī)間的(de)接洽,算是(shì)打通android 應用層與 kernel驅動層,半數個(gè)input體系的(de)進修是(shì)至關重要(yào / yāo)的(de),個(gè)中frameworks層隻是(shì)簡單記錄了(le/liǎo)幾個(gè)接入點,這(zhè)裏開端分析frameworks層的(de)細節部分。
                                            撰寫不(bù)易,轉載需注明出(chū)處:http://blog.csdn.net/jscese/article/details/42392311

input辦事的(de)啓動:


 android啓動的(de)時(shí)刻會啓動很多個(gè)service,這(zhè)個(gè)可以(yǐ)參考SystemServer.java ,會啓動InputManagerService這(zhè)個(gè)辦事:
   Slog.i(TAG, "Input Manager");
            inputManager = new InputManagerService(context, wmHandler);

...

            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

直接看InputManagerService.java中的(de)start函數:
    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);   //調用了(le/liǎo)本處所法,JNI對應的(de)cpp 在(zài)server下的(de)jni目次下

...

}

這(zhè)個(gè)牽扯到(dào)android的(de)server的(de)jni,最開端是(shì)在(zài)SystemServer中加載android_server這(zhè)個(gè)動态庫,
至于(yú)這(zhè)個(gè)動态庫的(de)編譯可參考/frameworks/base/services/jni/Android.mk中的(de)内容
所以(yǐ)在(zài)調用這(zhè)個(gè)nativeStart辦法時(shí),相幹的(de)動态庫已經加載到(dào)SystemServer的(de)過程中。
先看下這(zhè)個(gè)start函數在(zài)jni文件中的(de)實現,frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp中:
static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  //這(zhè)個(gè)NativeInputManager 是(shì)在(zài)膳绫擎InputMangerService構造的(de)時(shí)刻調用nativeInit時(shí)new出(chū)來(lái)的(de)

    status_t result = im->getInputManager()->start(); //這(zhè)裏是(shì)調用了(le/liǎo)NativeInputManager中的(de)InputManager中的(de)start辦法,同樣這(zhè)個(gè)InputManager是(shì)NativeInputManager構造的(de)時(shí)刻new出(chū)來(lái)的(de)
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

其實熟悉JNI的(de)話,我分析到(dào)這(zhè)裏,就(jiù)應當差不(bù)多了(le/liǎo)。。對于(yú)JNI 不(bù)是(shì)很懂得的(de)話可以(yǐ)參考我之(zhī)前的(de)博客:Andorid——ubuntu下的(de) NDK / JNI



看下NativeInputManager構造函數中的(de):
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);

這(zhè)裏的(de)JNI部分就(jiù)不(bù)多說(shuō)了(le/liǎo),如今就(jiù)看這(zhè)個(gè)InputManager的(de)start辦法,膳绫擎提到(dào)到(dào)Android.mk,可以(yǐ)看到(dào)include了(le/liǎo)一個(gè)libinput的(de)動态庫,
而(ér)這(zhè)個(gè)動态庫的(de)路徑是(shì)在(zài)/frameworks/base/services/input下,這(zhè)就(jiù)清楚明潦攀啦.此目次下有InputManager.cpp . EventHub.cpp等
直接看start:
status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  //這(zhè)個(gè)mDispatcherThread是(shì)在(zài)InputManager構造函數裏調用initialize初始化,這(zhè)裏很明顯啓動了(le/liǎo)這(zhè)個(gè)名爲(wéi / wèi)InputDispatcher的(de)線程
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); //同上(shàng),開啓線程
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);

        mDispatcherThread->requestExit();
        return result;
    }

    return OK;
}


到(dào)這(zhè)裏算是(shì)看到(dào)真面貌的(de)感到(dào),看這(zhè)兩個(gè)線程,字面意思,一個(gè)是(shì)分發給input事宜給當前的(de)activity的(de),一個(gè)是(shì)攫取大(dà)年夜基層發上(shàng)來(lái)的(de)input事宜的(de)

InputDispatcher分發:


 大(dà)年夜膳绫擎的(de)線程啓動分析:
bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}
調用分發一次的(de)函數:
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()) {           //如不(bù)雅有緩存的(de)敕令就(jiù)調用下面的(de)runCommand去履行,沒有的(de)話這(zhè)裏去檢查是(shì)否有新的(de)input事宜,這(zhè)裏定義一個(gè)喚醒時(shí)光┞菲握
            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);  //履行膳绫擎一次分發之(zhī)後,就(jiù)進入了(le/liǎo)loop,這(zhè)個(gè)loop會持續的(de)檢測對應的(de)管道(dào)中是(shì)否有内容可讀,而(ér)别的(de)一個(gè)線程InputReader 攫取到(dào)input事宜之(zhī)後就(jiù)會往這(zhè)個(gè)管道(dào)寫入
}

這(zhè)個(gè)是(shì)處理input事宜的(de),後續分析,先看怎麽攫取事宜.

InputReader攫取:


  源碼位于(yú)frameworks/base/libs/ui/InputReader.cpp ,開啓線程如下:
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

這(zhè)裏看這(zhè)個(gè)loopOnce:
void InputReader::loopOnce() {

...

   size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  //這(zhè)裏去獲取event事宜

...

        if (count) {
            processEventsLocked(mEventBuffer, count); //如不(bù)雅獲取到(dào)事宜,就(jiù)處理
        }

...

}

可以(yǐ)看到(dào)這(zhè)裏就(jiù)到(dào)了(le/liǎo)獲取event事宜了(le/liǎo)。上(shàng)一篇中有提到(dào)!
getEvent中會一向read,直到(dào)get到(dào)event之(zhī)後,經由過程precessevent處理,最終會喚醒膳绫擎介紹到(dào)的(de)InputDispatcherThread,通知它有新的(de)事沂攀來(lái)了(le/liǎo)

相關案例查看更多