Android应用程序键盘(Keyboard)消息处理机制分析(15)
Step 7.KeyboardInputMapper.processKey 这个函数定义在frameworks/base/libs/ui/InputReader.cpp文件中: voidKeyboardInputMapper::processKey(nsecs_twhen,booldown,int32_tkeyCode, int32_tscanCode,uint32_tpolicyFlags){ int32_tnewMetaState; nsecs_tdownTime; boolmetaStateChanged=false; {//acquirelock AutoMutex_l(mLock); if(down){ //Rotatekeycodesaccordingtoorientationifneeded. //Note:getDisplayInfoisnon-reentrantsowecancontinueholdingthelock. if(mAssociatedDisplayId>=0){ int32_torientation; if(!getPolicy()->getDisplayInfo(mAssociatedDisplayId,NULL,NULL,&orientation)){ return; } keyCode=rotateKeyCode(keyCode,orientation); } //Addkeydown. ssize_tkeyDownIndex=findKeyDownLocked(scanCode); if(keyDownIndex>=0){ //keyrepeat,besuretousesamekeycodeasbeforeincaseofrotation keyCode=mLocked.keyDowns.itemAt(keyDownIndex).keyCode; }else{ //keydown if((policyFlags&POLICY_FLAG_VIRTUAL) &&mContext->shouldDropVirtualKey(when,getDevice(),keyCode,scanCode)){ return; } mLocked.keyDowns.push(); KeyDown&keyDown=mLocked.keyDowns.editTop(); keyDown.keyCode=keyCode; keyDown.scanCode=scanCode; } mLocked.downTime=when; }else{ //Removekeydown. ssize_tkeyDownIndex=findKeyDownLocked(scanCode); if(keyDownIndex>=0){ //keyup,besuretousesamekeycodeasbeforeincaseofrotation keyCode=mLocked.keyDowns.itemAt(keyDownIndex).keyCode; mLocked.keyDowns.removeAt(size_t(keyDownIndex)); }else{ //keywasnotactuallydown LOGI("Droppingkeyupfromdevice%sbecausethekeywasnotdown." "keyCode=%d,scanCode=%d", getDeviceName().string(),keyCode,scanCode); return; } } int32_toldMetaState=mLocked.metaState; newMetaState=updateMetaState(keyCode,down,oldMetaState); if(oldMetaState!=newMetaState){ mLocked.metaState=newMetaState; metaStateChanged=true; } downTime=mLocked.downTime; }//releaselock if(metaStateChanged){ getContext()->updateGlobalMetaState(); } getDispatcher()->notifyKey(when,getDeviceId(),AINPUT_SOURCE_KEYBOARD,policyFlags, down?AKEY_EVENT_ACTION_DOWN:AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM,keyCode,scanCode,newMetaState,downTime); } 这个函数首先对对按键作一些处理,例如,当某一个DPAD键被按下时,根据当时屏幕方向的不同,它所表示的意义也不同,因此,这里需要根据当时屏幕的方向来调整键盘码: //Rotatekeycodesaccordingtoorientationifneeded. //Note:getDisplayInfoisnon-reentrantsowecancontinueholdingthelock. if(mAssociatedDisplayId>=0){ int32_torientation; if(!getPolicy()->getDisplayInfo(mAssociatedDisplayId,NULL,NULL,&orientation)){ return; } keyCode=rotateKeyCode(keyCode,orientation); } 如果这个键是一直按着不放的,不管屏幕的方向如何,必须保证后面的键盘码和前面的一样: //Addkeydown. ssize_tkeyDownIndex=findKeyDownLocked(scanCode); if(keyDownIndex>=0){ //keyrepeat,besuretousesamekeycodeasbeforeincaseofrotation keyCode=mLocked.keyDowns.itemAt(keyDownIndex).keyCode; }else{ //keydown if((policyFlags&POLICY_FLAG_VIRTUAL) &&mContext->shouldDropVirtualKey(when,getDevice(),keyCode,scanCode)){ return; } mLocked.keyDowns.push(); KeyDown&keyDown=mLocked.keyDowns.editTop(); keyDown.keyCode=keyCode; keyDown.scanCode=scanCode; } 如果是第一次按下某个键,还必须把它保存在mLocked.keyDowns里面,就是为了处理上面讲的当这个键盘一直按着不放的时候屏幕方向发生改变的情况。 如果是松开键盘上的某个键,就把它从mLocked.keyDowns里面删除: //Removekeydown. ssize_tkeyDownIndex=findKeyDownLocked(scanCode); if(keyDownIndex>=0){ //keyup,besuretousesamekeycodeasbeforeincaseofrotation keyCode=mLocked.keyDowns.itemAt(keyDownIndex).keyCode; mLocked.keyDowns.removeAt(size_t(keyDownIndex)); }else{ //keywasnotactuallydown LOGI("Droppingkeyupfromdevice%sbecausethekeywasnotdown." "keyCode=%d,scanCode=%d", getDeviceName().string(),keyCode,scanCode); return; } 当然,对键盘事件的这些处理不是本文的重点,本文的重点是分析从键盘事件到当前激活的Activity窗口接收到这个键盘消息的过程。 最后,KeyboardInputMappger函数通知InputDispatcher,有键盘事件发生了: getDispatcher()->notifyKey(when,getDeviceId(),AINPUT_SOURCE_KEYBOARD,policyFlags, down?AKEY_EVENT_ACTION_DOWN:AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM,keyCode,scanCode,newMetaState,downTime); 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966633,如需转载请自行联系原作者