生活随笔
收集整理的這篇文章主要介紹了
Android应用程序键盘(Keyboard)消息处理机制分析(14)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?3.?InputManager分發鍵盤消息給應用程序的過程分析
?? ? ? ?在分析InputManager分發鍵盤消息給應用程序的過程之前,我們先假設現在沒有鍵盤事件發生,因此,InputManager中的InputReader正在睡眠等待鍵盤事件的發生,而InputManager中的InputDispatcher正在等待InputReader從睡眠中醒過來并且喚醒它,而應用程序也正在消息循環中等待InputDispatcher從睡眠中醒過來并且喚醒它。這時候,用戶按下鍵盤中的一個鍵,于是,一系列喚醒的事件就依次發生了,一直到應用程序中正在顯示的Activity得到通知,有鍵盤事件發生了。我們先來看這個過程的序列圖,然后再詳細分析每一個步驟:
? ? ? ? Step 1. InputReader.pollOnce
?? ? ? ?Step 2. EventHub.getEvent
?? ? ? ?這兩個函數分別定義在frameworks/base/libs/ui/InputReader.cpp和frameworks/base/libs/ui/EventHub.cpp文件中,前面我們在分析InputManager的啟動過程的Step 17和Step 18時,已經看到過這兩個函數了。InputReaderThread線程會不民地循環調用InputReader.pollOnce函數來讀入鍵盤事件,而實際的鍵盤事件讀入操作是由EventHub.getEvent函數來進行的。如果當前沒有鍵盤事件發生,InputReaderThread線程就會睡眠在EventHub.getEvent函數上,而當鍵盤事件發生后,就會把這個事件封裝成一個RawEvent對象,然后返回到pollOnce函數中,執行process函數進一步處理:
void?InputReader::loopOnce()?{??????RawEvent?rawEvent;??????mEventHub->getEvent(&?rawEvent);????????......????????process(&?rawEvent);??}?? ?? ? ? ?Step 3. InputReader.process ?
?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputReader.cpp文件中:
void?InputReader::process(const?RawEvent*?rawEvent)?{??????switch?(rawEvent->type)?{??????case?EventHubInterface::DEVICE_ADDED:??????????addDevice(rawEvent->deviceId);??????????break;????????case?EventHubInterface::DEVICE_REMOVED:??????????removeDevice(rawEvent->deviceId);??????????break;????????case?EventHubInterface::FINISHED_DEVICE_SCAN:??????????handleConfigurationChanged(rawEvent->when);??????????break;????????default:??????????consumeEvent(rawEvent);??????????break;??????}??}?? ?? ? ? ?當鍵盤事件發生時,rawEvent->type的值為EV_KEY,這是一個宏定義,具體可以參考bionic/libc/kernel/common/linux/input.h文件:
#define?EV_KEY?0x01?? ?? ? ? ?因此,接下來會調用consumeEvent函數進一步處理。 ?
?? ? ? ?Step 4.?InputReader.consumeEvent
?? ? ? ?這個函數定義在frameworks/base/libs/ui/InputReader.cpp文件中:
void?InputReader::consumeEvent(const?RawEvent*?rawEvent)?{??????int32_t?deviceId?=?rawEvent->deviceId;????????{???????????RWLock::AutoRLock?_rl(mDeviceRegistryLock);????????????ssize_t?deviceIndex?=?mDevices.indexOfKey(deviceId);??????????if?(deviceIndex?<?0)?{??????????????LOGW("Discarding?event?for?unknown?deviceId?%d.",?deviceId);??????????????return;??????????}????????????InputDevice*?device?=?mDevices.valueAt(deviceIndex);??????????if?(device->isIgnored())?{????????????????????????????return;??????????}????????????device->process(rawEvent);??????}???}?? ?? ? ? ? 首先從rawEvent中取得觸發鍵盤事件設備對象device,然后調用它的process函數進行處理。 ?
?? ? ? ? Step 5. InputDevice.process
?? ? ? ? 這個函數定義在frameworks/base/libs/ui/InputReader.cpp文件中:
void?InputDevice::process(const?RawEvent*?rawEvent)?{??????size_t?numMappers?=?mMappers.size();??????for?(size_t?i?=?0;?i?<?numMappers;?i++)?{??????????InputMapper*?mapper?=?mMappers[i];??????????mapper->process(rawEvent);??????}??}?? ?? ? ? ? 這里的mMapper成員變量保存了一系列輸入設備事件處理象,例如負責處理鍵盤事件的KeyboardKeyMapper對象、負責處理軌跡球事件的TrackballInputMapper對象以及負責處理觸摸屏事件的TouchInputMapper對象, 它們是在InputReader類的成員函數createDevice中創建的。這里查詢每一個InputMapper對象是否要對當前發生的事件進行處理。由于發生的是鍵盤事件,真正會對該事件進行處理的只有KeyboardKeyMapper對象。 ?
?? ? ? ? Step 6.?KeyboardInputMapper.process
?? ? ? ??這個函數定義在frameworks/base/libs/ui/InputReader.cpp文件中:
void?KeyboardInputMapper::process(const?RawEvent*?rawEvent)?{??????switch?(rawEvent->type)?{??????case?EV_KEY:?{??????????int32_t?scanCode?=?rawEvent->scanCode;??????????if?(isKeyboardOrGamepadKey(scanCode))?{??????????????processKey(rawEvent->when,?rawEvent->value?!=?0,?rawEvent->keyCode,?scanCode,??????????????????????rawEvent->flags);??????????}??????????break;??????}??????}??}?? ?? ? ? ?這個函數首先會檢查一下鍵盤掃描碼是否正確,如果正確的話,就會調用processKey函數進一步處理。 ?
?
?
轉載于:https://blog.51cto.com/shyluo/966632
總結
以上是生活随笔為你收集整理的Android应用程序键盘(Keyboard)消息处理机制分析(14)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。