1. 輸入按鍵

我們知道Android系統(tǒng)的按鍵分為三類:(1)Global Key;(2)System Key;(3)User Key

  • Global Key:按下一個(gè)按鍵,啟動(dòng)某個(gè)APP。 具體使用哪個(gè)按鍵啟動(dòng)哪個(gè)APP可以自己指定,修改\frameworks\base\core\res\res\xml\Global_keys.xml,接下來(lái)有一篇博文具實(shí)現(xiàn),假設(shè)它是AKEYCODE_TV

  • System Key:比如音量鍵(AKEYCODE_VOLUME_DOWN)

  • User Key:其他按鍵,比如ABCD(AKEYCODE_A)

2. 回顧

2.1 概述

Reader線程把驅(qū)動(dòng)上報(bào)的scancode根據(jù).kl文件轉(zhuǎn)化為keycode,Dispatch線程根據(jù)所獲得keycode進(jìn)行處理。Android Dispatch線程對(duì)這三類按鍵的處理

* Global Key* System Key* User Key
2.2 具體處理流程
  1. Reader線程將輸入事件稍作處理

  2. Reader線程會(huì)將輸入事件放入mInBoundQueue隊(duì)列中

  3. Dispatch線程將從mInBoundQueue隊(duì)列中取出輸入事件,稍作處理

  4. 再將處理后的輸入事件放入mOutBoundQueue隊(duì)列

  5. 最后再?gòu)膍OutBoundQueue隊(duì)列中取出來(lái),發(fā)給目的應(yīng)用

3. 閱讀源碼分析三種按鍵的處理過(guò)程

之前已經(jīng)分析了Reader線程從驅(qū)動(dòng)程序得到掃描碼之后,根據(jù).KL文件,得到對(duì)應(yīng)的按鍵碼,然后構(gòu)造args參數(shù),接著使用NotifiyKey將該參數(shù)告訴Reader線程的Listener,而Reader線程的監(jiān)聽(tīng)者肯定為Dispatch線程,要想驗(yàn)證,可以通過(guò)源代碼分析得出。

3.1 Golbal Key分析

1. Reader線程獲得他的Listener,調(diào)用notifykey做進(jìn)一步的處理
InputReader.cpp
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
        down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
        AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
getListener()->notifyKey(&args);
}
2. 放入隊(duì)列之前,稍作處理

2.1 調(diào)用Java里面PhoneWindowManager的同名函數(shù)
2.2 根據(jù)返回值設(shè)置policeFlags,對(duì)于global按鍵直接返回Pass_To_User

InputDispatch.cpp
//policyFlasgs接收函數(shù)的輸出結(jié)果,根據(jù)policyFlags構(gòu)造newEntry,將newEntry放入隊(duì)列中mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
3. 放入mInboundQueue隊(duì)列
InputDispatch.cpp
needWake = enqueueInboundEventLocked(newEntry);
4. 必要時(shí)候喚醒Dispatch線程
InputDispatch.cpp
if (needWake) {
    mLooper->wake();
}

3.2 System Key分析

1. Reader線程獲得他的Listener,調(diào)用notifykey做進(jìn)一步的處理
InputReader.cpp
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
        down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
        AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
getListener()->notifyKey(&args);
}
2. 放入隊(duì)列之前,稍作處理

2.1 調(diào)用Java里面PhoneWindowManager的同名函數(shù),分類處理

  • 可以處理的緊急事件,處理他,設(shè)置返回值為:!Pass_to_user

  • 返回pass_to_user

InputDispatch.cpp
//policyFlasgs接收函數(shù)的輸出結(jié)果,根據(jù)policyFlags構(gòu)造newEntry,將newEntry放入隊(duì)列中mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
3. 放入mInboundQueue隊(duì)列
InputDispatch.cpp
needWake = enqueueInboundEventLocked(newEntry);
4. 必要時(shí)候喚醒Dispatch線程
InputDispatch.cpp
if (needWake) {
    mLooper->wake();
}

3.3 User Key分析

1. Reader線程獲得他的Listener,調(diào)用notifykey做進(jìn)一步的處理
InputReader.cpp
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
        down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
        AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
getListener()->notifyKey(&args);
}
2. 放入隊(duì)列之前,稍作處理

2.1 調(diào)用Java里面PhoneWindowManager的同名函數(shù)
2.2 根據(jù)返回值設(shè)置policyFlags,對(duì)于用戶按鍵直接返回Pass_To_User

InputDispatch.cpp
//policyFlasgs接收函數(shù)的輸出結(jié)果,根據(jù)policyFlags構(gòu)造newEntry,將newEntry放入隊(duì)列中mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
3. 放入mInboundQueue隊(duì)列
InputDispatch.cpp
needWake = enqueueInboundEventLocked(newEntry);
4. 必要時(shí)候喚醒Dispatch線程
InputDispatch.cpp
if (needWake) {
    mLooper->wake();
}

4. DIspatch流程修訂圖

從上文分析可知,不論是否Pass_to_user,最終都要放入到隊(duì)列mInboundQueue當(dāng)中去,上篇博客總結(jié)的流程圖有點(diǎn)錯(cuò)誤,故進(jìn)行修改,具體如下圖。
大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團(tuán)訓(xùn)

分類: Android底層驅(qū)動(dòng)學(xué)習(xí)--韋東山視頻學(xué)習(xí)

http://www.cnblogs.com/lkq1220/p/7156771.html