Android之Input子系统事件分发流程

Android创建窗口机制,请看如下转载:

http://blog.csdn.net/sfdev/article/details/9130527

一、Android4.2系统服务侧——与View关系

1.服务端channel注册过程

frameworks/base/core/java/android/view/ViewRootImpl.java

[cpp] view plain copy
  1. publicvoidsetView(Viewview,WindowManager.LayoutParamsattrs,ViewpanelParentView){
  2. mInputChannel=newInputChannel();//创建InputChannel
  3. res=mWindowSession.addToDisplay(mWindow,mSeq,mWindowAttributes,
  4. getHostVisibility(),mDisplay.getDisplayId(),
  5. mAttachInfo.mContentInsets,mInputChannel);//创建与上述InputChannel对应的通道至服务端
  6. /*
  7. mWindowSession=WindowManagerGlobal.getWindowSession(context.getMainLooper());
  8. frameworks/base/core/java/android/view/WindowManagerGlobal.java
  9. publicstaticIWindowSessiongetWindowSession(LoopermainLooper){
  10. IWindowManagerwindowManager=getWindowManagerService();
  11. sWindowSession=windowManager.openSession(
  12. imm.getClient(),imm.getInputContext());
  13. returnsWindowSession;
  14. }
  15. frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
  16. publicIWindowSessionopenSession(IInputMethodClientclient,
  17. IInputContextinputContext){
  18. if(client==null)thrownewIllegalArgumentException("nullclient");
  19. if(inputContext==null)thrownewIllegalArgumentException("nullinputContext");
  20. Sessionsession=newSession(this,client,inputContext);
  21. returnsession;
  22. }
  23. */
  24. mInputEventReceiver=newWindowInputEventReceiver(mInputChannel,
  25. Looper.myLooper());//将本通道注册进InputEventReceiver
  26. }
frameworks/base/services/java/com/android/server/wm/Session.java [cpp] view plain copy
  1. publicintaddToDisplay(IWindowwindow,intseq,WindowManager.LayoutParamsattrs,
  2. intviewVisibility,intdisplayId,RectoutContentInsets,
  3. InputChanneloutInputChannel){
  4. returnmService.addWindow(this,window,seq,attrs,viewVisibility,displayId,
  5. outContentInsets,outInputChannel);
  6. }
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java [cpp] view plain copy
  1. publicintaddWindow(Sessionsession,IWindowclient,intseq,
  2. WindowManager.LayoutParamsattrs,intviewVisibility,intdisplayId,
  3. RectoutContentInsets,InputChanneloutInputChannel){
  4. //以下包括了管道的创建(用于WMS与应用程序View通信)等
  5. Stringname=win.makeInputChannelName();
  6. InputChannel[]inputChannels=InputChannel.openInputChannelPair(name);
  7. win.setInputChannel(inputChannels[0]);
  8. inputChannels[1].transferTo(outInputChannel);
  9. //以下便是注册至server端过程
  10. //finalInputManagerServicemInputManager;
  11. mInputManager.registerInputChannel(win.mInputChannel,win.mInputWindowHandle);
  12. }
frameworks/base/service/java/com/android/server/input/InputManagerService.java [cpp] view plain copy
  1. publicvoidregisterInputChannel(InputChannelinputChannel,
  2. InputWindowHandleinputWindowHandle){
  3. nativeRegisterInputChannel(mPtr,inputChannel,inputWindowHandle,false);
  4. }
  5. privatestaticnativevoidnativeRegisterInputChannel(intptr,InputChannelinputChannel,
  6. InputWindowHandleinputWindowHandle,booleanmonitor);
frameworks/base/service/jni/com_android_server_input_InputManagerService.cpp [cpp] view plain copy
  1. staticvoidnativeRegisterInputChannel(JNIEnv*env,jclassclazz,
  2. jintptr,jobjectinputChannelObj,jobjectinputWindowHandleObj,jbooleanmonitor){
  3. NativeInputManager*im=reinterpret_cast<NativeInputManager*>(ptr);
  4. status_tstatus=im->registerInputChannel(
  5. env,inputChannel,inputWindowHandle,monitor);
  6. }
  7. status_tNativeInputManager::registerInputChannel(JNIEnv*env,
  8. constsp<InputChannel>&inputChannel,
  9. constsp<InputWindowHandle>&inputWindowHandle,boolmonitor){
  10. returnmInputManager->getDispatcher()->registerInputChannel(
  11. inputChannel,inputWindowHandle,monitor);
  12. //mInputManager=newInputManager(eventHub,this,this);
  13. /*
  14. frameworks/base/services/input/InputManager.cpp
  15. sp<InputDispatcherInterface>InputManager::getDispatcher(){
  16. returnmDispatcher;
  17. }
  18. mDispatcher=newInputDispatcher(dispatcherPolicy);
  19. */
  20. }

frameworks/base/services/input/InputDispatcher.cpp

[cpp] view plain copy
  1. status_tInputDispatcher::registerInputChannel(constsp<InputChannel>&inputChannel,
  2. constsp<InputWindowHandle>&inputWindowHandle,boolmonitor){
  3. intfd=inputChannel->getFd();
  4. mConnectionsByFd.add(fd,connection);
  5. //该fd监听对应的处理函数为handleReceiveCallback
  6. mLooper->addFd(fd,0,ALOOPER_EVENT_INPUT,handleReceiveCallback,this);
  7. }
2.服务端上报过程

2.1.InputReaderThread线程从驱动读取数据并处理,如实现鼠标右键上报back键即在此处完成、以下代码将会看到

Android之Input子系统事件分发流程_第1张图片

frameworks/base/services/input/InputReader.cpp

[cpp] view plain copy
  1. boolInputReaderThread::threadLoop(){
  2. mReader->loopOnce();
  3. returntrue;
  4. }
  5. voidInputReader::loopOnce(){
  6. size_tcount=mEventHub->getEvents(timeoutMillis,mEventBuffer,EVENT_BUFFER_SIZE);
  7. /*
  8. frameworks/base/services/input/EventHub.cpp
  9. size_tEventHub::getEvents(inttimeoutMillis,RawEvent*buffer,size_tbufferSize){
  10. int32_treadSize=read(device->fd,readBuffer,
  11. sizeof(structinput_event)*capacity);//从驱动读取事件
  12. }
  13. */
  14. processEventsLocked(mEventBuffer,count);
  15. }
  16. voidInputReader::processEventsLocked(constRawEvent*rawEvents,size_tcount){
  17. processEventsForDeviceLocked(deviceId,rawEvent,batchSize);
  18. }
  19. voidInputReader::processEventsForDeviceLocked(int32_tdeviceId,
  20. constRawEvent*rawEvents,size_tcount){
  21. device->process(rawEvents,count);
  22. }
  23. voidInputDevice::process(constRawEvent*rawEvents,size_tcount){
  24. //该设备的所有mapper进行处理;注意:这里使用了多态
  25. for(size_ti=0;i<numMappers;i++){
  26. InputMapper*mapper=mMappers[i];
  27. mapper->process(rawEvent);
  28. }
  29. }
  30. //以下就是各个mapper
  31. //CursorInput鼠标设备
  32. voidCursorInputMapper::process(constRawEvent*rawEvent){
  33. mCursorButtonAccumulator.process(rawEvent);
  34. mCursorMotionAccumulator.process(rawEvent);
  35. mCursorScrollAccumulator.process(rawEvent);
  36. if(rawEvent->type==EV_SYN&&rawEvent->code==SYN_REPORT){
  37. sync(rawEvent->when);
  38. }
  39. }
  40. //CursorButtonAccumulator::process(constRawEvent*rawEvent)
  41. //CursorMotionAccumulator::process(constRawEvent*rawEvent)
  42. //CursorScrollAccumulator::process(constRawEvent*rawEvent)
  43. voidCursorInputMapper::sync(nsecs_twhen){
  44. int32_tcurrentButtonState=mCursorButtonAccumulator.getButtonState();
  45. /*
  46. uint32_tCursorButtonAccumulator::getButtonState()const{
  47. if(mBtnRight){
  48. //Changedbytankformouseleftbuttontoback
  49. result|=AMOTION_EVENT_BUTTON_BACK;
  50. //result|=AMOTION_EVENT_BUTTON_SECONDARY;
  51. }
  52. if(mBtnMiddle){
  53. //changebytank@tcl.comformousemiddlebuttontomenu
  54. result|=AMOTION_EVENT_BUTTON_MENU;
  55. //result|=AMOTION_EVENT_BUTTON_TERTIARY;
  56. }
  57. }
  58. */
  59. getListener()->notifyMotion(&args);
  60. synthesizeButtonKeys(getContext(),AKEY_EVENT_ACTION_UP,when,getDeviceId(),mSource,
  61. policyFlags,lastButtonState,currentButtonState);
  62. /*
  63. staticvoidsynthesizeButtonKeys(InputReaderContext*context,int32_taction,
  64. nsecs_twhen,int32_tdeviceId,uint32_tsource,
  65. uint32_tpolicyFlags,int32_tlastButtonState,int32_tcurrentButtonState){
  66. synthesizeButtonKey(context,action,when,deviceId,source,policyFlags,
  67. lastButtonState,currentButtonState,
  68. AMOTION_EVENT_BUTTON_BACK,AKEYCODE_BACK);
  69. synthesizeButtonKey(context,action,when,deviceId,source,policyFlags,
  70. lastButtonState,currentButtonState,
  71. AMOTION_EVENT_BUTTON_FORWARD,AKEYCODE_FORWARD);
  72. //addbytankmousekeyeventmiddle->menu.
  73. synthesizeButtonKey(context,action,when,deviceId,source,policyFlags,
  74. lastButtonState,currentButtonState,
  75. AMOTION_EVENT_BUTTON_MENU,AKEYCODE_MENU);
  76. //endtank
  77. }
  78. staticvoidsynthesizeButtonKey(InputReaderContext*context,int32_taction,
  79. nsecs_twhen,int32_tdeviceId,uint32_tsource,
  80. uint32_tpolicyFlags,int32_tlastButtonState,int32_tcurrentButtonState,
  81. int32_tbuttonState,int32_tkeyCode){
  82. if((action==AKEY_EVENT_ACTION_DOWN&&!(lastButtonState&buttonState)
  83. &&(currentButtonState&buttonState))
  84. ||(action==AKEY_EVENT_ACTION_UP
  85. &&(lastButtonState&buttonState)
  86. &&!(currentButtonState&buttonState))){
  87. context->getListener()->notifyKey(&args);
  88. }
  89. }
  90. */
  91. }
  92. //TouchInput触摸板设备
  93. voidSingleTouchInputMapper::process(constRawEvent*rawEvent)
  94. TouchInputMapper::process(rawEvent);
  95. mSingleTouchMotionAccumulator.process(rawEvent);
  96. }
  97. //SingleTouchMotionAccumulator::process(constRawEvent*rawEvent)
  98. voidMultiTouchInputMapper::process(constRawEvent*rawEvent){
  99. TouchInputMapper::process(rawEvent);
  100. mMultiTouchMotionAccumulator.process(rawEvent);
  101. }
  102. //MultiTouchMotionAccumulator::process(constRawEvent*rawEvent)
  103. voidTouchInputMapper::process(constRawEvent*rawEvent){
  104. mCursorButtonAccumulator.process(rawEvent);
  105. mCursorScrollAccumulator.process(rawEvent);
  106. mTouchButtonAccumulator.process(rawEvent);
  107. if(rawEvent->type==EV_SYN&&rawEvent->code==SYN_REPORT){
  108. sync(rawEvent->when);
  109. }
  110. }
  111. //TouchButtonAccumulator::process(constRawEvent*rawEvent)
  112. voidTouchInputMapper::sync(nsecs_twhen){
  113. dispatchTouches(when,policyFlags);
  114. }
  115. voidTouchInputMapper::dispatchTouches(nsecs_twhen,uint32_tpolicyFlags){
  116. dispatchMotion(when,policyFlags,mSource,
  117. AMOTION_EVENT_ACTION_MOVE,0,metaState,buttonState,
  118. AMOTION_EVENT_EDGE_FLAG_NONE,
  119. mCurrentCookedPointerData.pointerProperties,
  120. mCurrentCookedPointerData.pointerCoords,
  121. mCurrentCookedPointerData.idToIndex,
  122. currentIdBits,-1,
  123. mOrientedXPrecision,mOrientedYPrecision,mDownTime);
  124. }
  125. voidTouchInputMapper::dispatchMotion(nsecs_twhen,uint32_tpolicyFlags,uint32_tsource,
  126. int32_taction,int32_tflags,int32_tmetaState,int32_tbuttonState,int32_tedgeFlags,
  127. constPointerProperties*properties,constPointerCoords*coords,
  128. constuint32_t*idToIndex,BitSet32idBits,
  129. int32_tchangedId,floatxPrecision,floatyPrecision,nsecs_tdownTime){
  130. getListener()->notifyMotion(&args);
  131. }
  132. //SwitchInput设备
  133. voidSwitchInputMapper::process(constRawEvent*rawEvent){
  134. sync(rawEvent->when);
  135. }
  136. voidSwitchInputMapper::sync(nsecs_twhen){
  137. getListener()->notifySwitch(&args);
  138. }
  139. //JoystickInput游戏手柄设备
  140. voidJoystickInputMapper::process(constRawEvent*rawEvent){
  141. sync(rawEvent->when,false/*force*/);
  142. }
  143. voidJoystickInputMapper::sync(nsecs_twhen,boolforce){
  144. getListener()->notifyMotion(&args);
  145. }
  146. //KeyboardInput按键设备
  147. voidKeyboardInputMapper::process(constRawEvent*rawEvent){
  148. processKey(rawEvent->when,rawEvent->value!=0,keyCode,scanCode,flags);
  149. }
  150. voidKeyboardInputMapper::processKey(nsecs_twhen,booldown,int32_tkeyCode,
  151. int32_tscanCode,uint32_tpolicyFlags){
  152. getListener()->notifyKey(&args);
  153. }

2.2.InputReaderThread线程对系统层按键做处理(比较重要的是POWER键,最终在PhoneWindowManager中的interceptKeyBeforeQueueing和interceptMotionBeforeQueueingWhenScreenOff)后分发给InputDispatcherThread线程,以下分析将看到之前一个鼠标操作过程中无法待机的问题解决

以下几种情况都会唤醒InputDispatcherThread线程,即调用mLooper->wake()唤醒正在awoken()中的InputReaderThread线程:

frameworks/base/services/input/InputDispatcher.cpp

[cpp] view plain copy
  1. //有新输入设备注册等
  2. voidInputDispatcher::notifyConfigurationChanged(constNotifyConfigurationChangedArgs*args){
  3. ConfigurationChangedEntry*newEntry=newConfigurationChangedEntry(args->eventTime);
  4. needWake=enqueueInboundEventLocked(newEntry);
  5. if(needWake){
  6. mLooper->wake();
  7. }
  8. }
  9. //分发按键事件
  10. voidInputDispatcher::notifyKey(constNotifyKeyArgs*args){
  11. //说明:PhoneWindowManager.java中policyFlags位决定系统按键(如HOME等是否需要由系统处理)
  12. mPolicy->interceptKeyBeforeQueueing(&event,policyFlags);
  13. //以下分析将看到,该调用实际是在PhoneWindowManager.java中实现
  14. /*
  15. frameworks/base/services/input/InputManager.cpp
  16. InputManager::InputManager(
  17. constsp<EventHubInterface>&eventHub,
  18. constsp<InputReaderPolicyInterface>&readerPolicy,
  19. constsp<InputDispatcherPolicyInterface>&dispatcherPolicy){
  20. mDispatcher=newInputDispatcher(dispatcherPolicy);
  21. mReader=newInputReader(eventHub,readerPolicy,mDispatcher);
  22. }
  23. frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
  24. NativeInputManager::NativeInputManager(jobjectcontextObj,
  25. jobjectserviceObj,constsp<Looper>&looper):
  26. mLooper(looper){
  27. mInputManager=newInputManager(eventHub,this,this);
  28. }
  29. voidNativeInputManager::interceptKeyBeforeQueueing(constKeyEvent*keyEvent,
  30. uint32_t&policyFlags){
  31. wmActions=env->CallIntMethod(mServiceObj,
  32. gServiceClassInfo.interceptKeyBeforeQueueing,
  33. keyEventObj,policyFlags,isScreenOn);
  34. //如下函数中将有待机和开机的处理
  35. handleInterceptActions(wmActions,when,policyFlags);
  36. }
  37. frameworks/base/service/java/com/android/server/input/InputManagerService.java
  38. privateintinterceptKeyBeforeQueueing(KeyEventevent,intpolicyFlags,booleanisScreenOn){
  39. returnmWindowManagerCallbacks.interceptKeyBeforeQueueing(
  40. event,policyFlags,isScreenOn);
  41. }
  42. frameworks/base/service/java/com/android/server/SystemServer.java
  43. inputManager=newInputManagerService(context,wmHandler);
  44. wm=WindowManagerService.main(context,power,display,inputManager,
  45. uiHandler,wmHandler,
  46. factoryTest!=SystemServer.FACTORY_TEST_LOW_LEVEL,
  47. !firstBoot,onlyCore);
  48. inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
  49. frameworks/base/service/java/com/android/server/wm/WindowManagerService.java
  50. publicInputMonitorgetInputMonitor(){
  51. returnmInputMonitor;
  52. }
  53. frameworks/base/service/java/com/android/server/wm/InputMonitor.java
  54. publicintinterceptKeyBeforeQueueing(
  55. KeyEventevent,intpolicyFlags,booleanisScreenOn){
  56. returnmService.mPolicy.interceptKeyBeforeQueueing(event,policyFlags,isScreenOn);
  57. }
  58. publicInputMonitor(WindowManagerServiceservice){
  59. mService=service;
  60. }
  61. frameworks/base/service/java/com/android/server/wm/WindowManagerService.java
  62. finalWindowManagerPolicymPolicy=PolicyManager.makeNewWindowManager();
  63. frameworks/base/core/java/com/android/internal/policy/PolicyManager.java
  64. publicstaticWindowManagerPolicymakeNewWindowManager(){
  65. returnsPolicy.makeNewWindowManager();
  66. }
  67. privatestaticfinalStringPOLICY_IMPL_CLASS_NAME=
  68. "com.android.internal.policy.impl.Policy";
  69. ClasspolicyClass=Class.forName(POLICY_IMPL_CLASS_NAME);
  70. sPolicy=(IPolicy)policyClass.newInstance();
  71. frameworks/base/core/java/com/android/internal/policy/Policy.java
  72. packagecom.android.internal.policy.impl;
  73. publicclassPolicyimplementsIPolicy{
  74. publicWindowManagerPolicymakeNewWindowManager(){
  75. returnnewPhoneWindowManager();
  76. }
  77. }
  78. frameworks/base/core/java/com/android/internal/policy/PhoneWindowManager.java
  79. publicintinterceptKeyBeforeQueueing(KeyEventevent,intpolicyFlags,booleanisScreenOn){
  80. caseKeyEvent.KEYCODE_POWER:{
  81. result=(result&~ACTION_WAKE_UP)|ACTION_GO_TO_SLEEP;
  82. }
  83. }
  84. */
  85. KeyEntry*newEntry=newKeyEntry(args->eventTime,
  86. args->deviceId,args->source,policyFlags,
  87. args->action,flags,args->keyCode,args->scanCode,
  88. metaState,repeatCount,args->downTime);
  89. needWake=enqueueInboundEventLocked(newEntry);
  90. if(needWake){
  91. mLooper->wake();
  92. }
  93. }
  94. //分发Motion事件
  95. voidInputDispatcher::notifyMotion(constNotifyMotionArgs*args){
  96. mPolicy->interceptMotionBeforeQueueing(args->eventTime,/*byref*/policyFlags);
  97. /*
  98. 如上分析,不再累赘;该接口是:
  99. frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
  100. voidNativeInputManager::interceptMotionBeforeQueueing(nsecs_twhen,uint32_t&policyFlags){
  101. jintwmActions=env->CallIntMethod(mServiceObj,
  102. gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
  103. policyFlags);
  104. handleInterceptActions(wmActions,when,policyFlags);
  105. }
  106. 如上interceptMotionBeforeQueueingWhenScreenOff在PhoneWindowManager中实现;分析同上,不再累赘:
  107. frameworks/base/core/java/com/android/internal/policy/PhoneWindowManager.java
  108. publicintinterceptMotionBeforeQueueingWhenScreenOff(intpolicyFlags){
  109. //result|=ACTION_WAKE_UP;
  110. //addbytank
  111. result=result&(~ACTION_WAKE_UP);
  112. //endtank
  113. returnresult;
  114. }
  115. 看看handleInterceptActions函数:
  116. voidNativeInputManager::handleInterceptActions(jintwmActions,nsecs_twhen,
  117. uint32_t&policyFlags){
  118. //接上边PhoneWindowManager中interceptKeyBeforeQueueing对于power键的返回值可知,系统将待机
  119. if(wmActions&WM_ACTION_GO_TO_SLEEP){
  120. #ifDEBUG_INPUT_DISPATCHER_POLICY
  121. ALOGD("handleInterceptActions:Goingtosleep.");
  122. #endif
  123. android_server_PowerManagerService_goToSleep(when);
  124. }
  125. //以下说明PhoneWindowManager中interceptMotionBeforeQueueingWhenScreenOff返回值WM_ACTION_WAKE_UP将会导致唤醒
  126. //当然,是可是收到motion事件的前提下
  127. if(wmActions&WM_ACTION_WAKE_UP){
  128. #ifDEBUG_INPUT_DISPATCHER_POLICY
  129. ALOGD("handleInterceptActions:Wakingup.");
  130. #endif
  131. android_server_PowerManagerService_wakeUp(when);
  132. }
  133. //以下是可以上报给系统的
  134. if(wmActions&WM_ACTION_PASS_TO_USER){
  135. policyFlags|=POLICY_FLAG_PASS_TO_USER;
  136. }
  137. }
  138. */
  139. MotionEntry*newEntry=newMotionEntry(args->eventTime,
  140. args->deviceId,args->source,policyFlags,
  141. args->action,args->flags,args->metaState,args->buttonState,
  142. args->edgeFlags,args->xPrecision,args->yPrecision,args->downTime,
  143. args->displayId,
  144. args->pointerCount,args->pointerProperties,args->pointerCoords);
  145. needWake=enqueueInboundEventLocked(newEntry);
  146. if(needWake){
  147. mLooper->wake();
  148. }
  149. }
  150. //设备重置
  151. voidInputDispatcher::notifyDeviceReset(constNotifyDeviceResetArgs*args){
  152. DeviceResetEntry*newEntry=newDeviceResetEntry(args->eventTime,args->deviceId);
  153. needWake=enqueueInboundEventLocked(newEntry);
  154. if(needWake){
  155. mLooper->wake();
  156. }
  157. }
  158. //C层的按键注入接口
  159. int32_tInputDispatcher::injectInputEvent(constInputEvent*event,
  160. int32_tinjectorPid,int32_tinjectorUid,int32_tsyncMode,int32_ttimeoutMillis,
  161. uint32_tpolicyFlags){
  162. needWake|=enqueueInboundEventLocked(entry);
  163. if(needWake){
  164. mLooper->wake();
  165. }
  166. }
  167. //setInputWindows
  168. //setFocusedApplication
  169. //setInputDispatchMode
  170. //setInputFilterEnabled
  171. //transferTouchFocus
  172. //registerInputChannel
  173. //unregisterInputChannel
  174. //monitor

2.3.InputDispatcherThread线程处理,根据PhoneWindowManager中的interceptKeyBeforeDispatching决定是否丢弃按键

Android之Input子系统事件分发流程_第2张图片

InputDispatcherThread线程被唤醒

[cpp] view plain copy
  1. boolInputDispatcherThread::threadLoop(){
  2. mDispatcher->dispatchOnce();
  3. returntrue;
  4. }
  5. voidInputDispatcher::dispatchOnce(){
  6. dispatchOnceInnerLocked(&nextWakeupTime);
  7. mLooper->pollOnce(timeoutMillis);
  8. }
  9. voidInputDispatcher::dispatchOnceInnerLocked(nsecs_t*nextWakeupTime){
  10. if(!mPolicy->isKeyRepeatEnabled()){
  11. resetKeyRepeatLocked();
  12. }
  13. switch(mPendingEvent->type){
  14. caseEventEntry::TYPE_CONFIGURATION_CHANGED:{
  15. done=dispatchConfigurationChangedLocked(currentTime,typedEntry);
  16. }
  17. caseEventEntry::TYPE_DEVICE_RESET:{
  18. done=dispatchDeviceResetLocked(currentTime,typedEntry);
  19. }
  20. caseEventEntry::TYPE_KEY:{
  21. done=dispatchKeyLocked(currentTime,typedEntry,&dropReason,nextWakeupTime);
  22. }
  23. caseEventEntry::TYPE_MOTION:{
  24. done=dispatchMotionLocked(currentTime,typedEntry,
  25. &dropReason,nextWakeupTime);
  26. }
  27. }
  28. dropInboundEventLocked(mPendingEvent,dropReason);//丢弃的事件!!!!
  29. }
  30. boolInputDispatcher::dispatchKeyLocked(nsecs_tcurrentTime,KeyEntry*entry,
  31. DropReason*dropReason,nsecs_t*nextWakeupTime){
  32. CommandEntry*commandEntry=postCommandLocked(
  33. &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
  34. /*
  35. voidInputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
  36. CommandEntry*commandEntry){
  37. //说明:PhoneWindowManager.java中可以截断事件而不上报,即返回-1、将被丢弃
  38. nsecs_tdelay=mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
  39. &event,entry->policyFlags);
  40. if(delay<0){
  41. entry->interceptKeyResult=KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
  42. }elseif(!delay){
  43. entry->interceptKeyResult=KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
  44. }else{
  45. entry->interceptKeyResult=KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
  46. entry->interceptKeyWakeupTime=now()+delay;
  47. }
  48. }
  49. */
  50. elseif(entry->interceptKeyResult==KeyEntry::INTERCEPT_KEY_RESULT_SKIP){
  51. if(*dropReason==DROP_REASON_NOT_DROPPED){
  52. *dropReason=DROP_REASON_POLICY;//dropReason是因为策略丢弃
  53. }
  54. }
  55. if(*dropReason!=DROP_REASON_NOT_DROPPED){
  56. setInjectionResultLocked(entry,*dropReason==DROP_REASON_POLICY
  57. ?INPUT_EVENT_INJECTION_SUCCEEDED:INPUT_EVENT_INJECTION_FAILED);
  58. returntrue;
  59. }
  60. dispatchEventLocked(currentTime,entry,inputTargets);
  61. }
  62. boolInputDispatcher::dispatchMotionLocked(
  63. nsecs_tcurrentTime,MotionEntry*entry,DropReason*dropReason,nsecs_t*nextWakeupTime){
  64. dispatchEventLocked(currentTime,entry,inputTargets);
  65. }

2.4.InputDispatcherThread线程分发给应用程序进程

在这里解决了up事件上报两次的问题!!!!!!

frameworks/base/services/input/InputDispatcher.cpp

[cpp] view plain copy
  1. voidInputDispatcher::dispatchEventLocked(nsecs_tcurrentTime,
  2. EventEntry*eventEntry,constVector<InputTarget>&inputTargets){
  3. pokeUserActivityLocked(eventEntry);//和Activity相关,后边三中有设备删除的分析;基本同下
  4. ssize_tconnectionIndex=getConnectionIndexLocked(inputTarget.inputChannel);
  5. sp<Connection>connection=mConnectionsByFd.valueAt(connectionIndex);
  6. prepareDispatchCycleLocked(currentTime,connection,eventEntry,&inputTarget);
  7. }
  8. voidInputDispatcher::prepareDispatchCycleLocked(nsecs_tcurrentTime,
  9. constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget){
  10. enqueueDispatchEntriesLocked(currentTime,connection,eventEntry,inputTarget);
  11. }
  12. voidInputDispatcher::enqueueDispatchEntriesLocked(nsecs_tcurrentTime,
  13. constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget){
  14. enqueueDispatchEntryLocked(connection,eventEntry,inputTarget,
  15. InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);//将按键注入队列
  16. /*
  17. voidInputDispatcher::enqueueDispatchEntryLocked(
  18. constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget,
  19. int32_tdispatchMode){
  20. DispatchEntry*dispatchEntry=newDispatchEntry(eventEntry,//incrementsref
  21. inputTargetFlags,inputTarget->xOffset,inputTarget->yOffset,
  22. inputTarget->scaleFactor);
  23. if(!connection->inputState.trackKey(keyEntry,
  24. dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags)||(dispatchEntry->resolvedFlags==0x28)){
  25. //addbytankai0x28
  26. deletedispatchEntry;
  27. return;
  28. }
  29. }
  30. */
  31. //dropInboundEventLocked
  32. //synthesizeCancelationEventsForAllConnectionsLocked->
  33. //synthesizeCancelationEventsForConnectionLocked->
  34. /*
  35. voidInputDispatcher::synthesizeCancelationEventsForConnectionLocked(
  36. constsp<Connection>&connection,constCancelationOptions&options){
  37. Vector<EventEntry*>cancelationEvents;
  38. connection->inputState.synthesizeCancelationEvents(currentTime,
  39. cancelationEvents,options);
  40. //关键在这里,mKeyMementos;在enqueueDispatchEntryLocked时调用trackKey由addKeyMemento注入!!!!!!
  41. if(!cancelationEvents.isEmpty()){
  42. enqueueDispatchEntryLocked(connection,cancelationEventEntry,//incrementsref
  43. &target,InputTarget::FLAG_DISPATCH_AS_IS);
  44. }
  45. }
  46. */
  47. //enqueueDispatchEntriesLocked,注入了0x28标志的按键
  48. startDispatchCycleLocked(currentTime,connection);
  49. }
  50. voidInputDispatcher::startDispatchCycleLocked(nsecs_tcurrentTime,
  51. constsp<Connection>&connection){
  52. switch(eventEntry->type){
  53. caseEventEntry::TYPE_KEY:{
  54. status=connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
  55. keyEntry->deviceId,keyEntry->source,
  56. dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags,
  57. keyEntry->keyCode,keyEntry->scanCode,
  58. keyEntry->metaState,keyEntry->repeatCount,keyEntry->downTime,
  59. keyEntry->eventTime);
  60. }
  61. caseEventEntry::TYPE_MOTION:{
  62. status=connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
  63. motionEntry->deviceId,motionEntry->source,
  64. dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags,
  65. motionEntry->edgeFlags,motionEntry->metaState,motionEntry->buttonState,
  66. xOffset,yOffset,
  67. motionEntry->xPrecision,motionEntry->yPrecision,
  68. motionEntry->downTime,motionEntry->eventTime,
  69. motionEntry->pointerCount,motionEntry->pointerProperties,
  70. usingCoords);
  71. }
  72. }
  73. }
frameworks/base/libs/androidfw/InputTransport.cpp
[cpp] view plain copy
  1. status_tInputPublisher::publishKeyEvent(
  2. uint32_tseq,
  3. int32_tdeviceId,
  4. int32_tsource,
  5. int32_taction,
  6. int32_tflags,
  7. int32_tkeyCode,
  8. int32_tscanCode,
  9. int32_tmetaState,
  10. int32_trepeatCount,
  11. nsecs_tdownTime,
  12. nsecs_teventTime){
  13. returnmChannel->sendMessage(&msg);
  14. }
  15. status_tInputChannel::sendMessage(constInputMessage*msg){
  16. do{
  17. nWrite=::send(mFd,msg,msgLength,MSG_DONTWAIT|MSG_NOSIGNAL);
  18. }while(nWrite==-1&&errno==EINTR);
  19. }

二、Android4.2系统应用程序侧——与View关系

Android之Input子系统事件分发流程_第3张图片

InputManagerService也就是InputDispatcher与应用程序通信是靠looper。

说明:

InputReader从设备文件中读取的是RawEvent,在交给InputDispatcher进行分发之前,它需要先把RawEvent进行转化分类,拆分成KeyEvent、MotionEvent、TrackEvent各种类型等。

InputDispatcher获得按键事件后,根据当前设备的状况来优先消化事件(该过程交由PhoneWindowManager.java来处理);最后,剩余事件分发给ViewRoot;ViewRoot再分发给IME输入法或View、Activity。

1.应用程序View中channel注册过程

frameworks/base/core/java/android/view/ViewRootImpl.java

[cpp] view plain copy
  1. publicvoidsetView(Viewview,WindowManager.LayoutParamsattrs,ViewpanelParentView){
  2. mInputChannel=newInputChannel();//创建InputChannel
  3. res=mWindowSession.addToDisplay(mWindow,mSeq,mWindowAttributes,
  4. getHostVisibility(),mDisplay.getDisplayId(),
  5. mAttachInfo.mContentInsets,mInputChannel);//创建与上述InputChannel对应的通道至服务端
  6. mInputEventReceiver=newWindowInputEventReceiver(mInputChannel,
  7. Looper.myLooper());//将本通道注册进InputEventReceiver
  8. }
  9. finalclassWindowInputEventReceiverextendsInputEventReceiver{
  10. publicWindowInputEventReceiver(InputChannelinputChannel,Looperlooper){
  11. super(inputChannel,looper);
  12. }
  13. @Override
  14. publicvoidonInputEvent(InputEventevent){
  15. enqueueInputEvent(event,this,0,true);
  16. }
  17. }

frameworks/base/core/java/android/view/InputEventReceiver.java

[cpp] view plain copy
  1. publicInputEventReceiver(InputChannelinputChannel,Looperlooper){
  2. mReceiverPtr=nativeInit(this,inputChannel,mMessageQueue);
  3. }
  4. privatestaticnativeintnativeInit(InputEventReceiverreceiver,
  5. InputChannelinputChannel,MessageQueuemessageQueue);

frameworks/base/core/jni/android_view_InputEventReceiver.cpp

[cpp] view plain copy
  1. staticjintnativeInit(JNIEnv*env,jclassclazz,jobjectreceiverObj,
  2. jobjectinputChannelObj,jobjectmessageQueueObj){
  3. sp<NativeInputEventReceiver>receiver=newNativeInputEventReceiver(env,
  4. receiverObj,inputChannel,messageQueue);
  5. status_tstatus=receiver->initialize();
  6. }
  7. status_tNativeInputEventReceiver::initialize(){
  8. intreceiveFd=mInputConsumer.getChannel()->getFd();
  9. mMessageQueue->getLooper()->addFd(receiveFd,0,ALOOPER_EVENT_INPUT,this,NULL);
  10. returnOK;
  11. }

frameworks/native/libs/utils/Looper.cpp

[cpp] view plain copy
  1. intLooper::addFd(intfd,intident,intevents,constsp<LooperCallback>&callback,void*data){
  2. request.callback=callback;
  3. }

2.应用程序View响应过程

frameworks/native/libs/utils/Looper.cpp

[cpp] view plain copy
  1. intLooper::pollInner(inttimeoutMillis){
  2. awoken();//阻塞,等待
  3. intcallbackResult=response.request.callback->handleEvent(fd,events,data);
  4. }

frameworks/base/core/jni/android_view_InputEventReceiver.cpp

[cpp] view plain copy
  1. intNativeInputEventReceiver::handleEvent(intreceiveFd,intevents,void*data){
  2. status_tstatus=consumeEvents(env,false/*consumeBatches*/,-1);
  3. }
  4. status_tNativeInputEventReceiver::consumeEvents(JNIEnv*env,
  5. boolconsumeBatches,nsecs_tframeTime){
  6. env->CallVoidMethod(mReceiverObjGlobal,
  7. gInputEventReceiverClassInfo.dispatchInputEvent,seq,inputEventObj);
  8. }
frameworks/base/core/java/android/view/InputEventReceiver.java [cpp] view plain copy
  1. privatevoiddispatchInputEvent(intseq,InputEventevent){
  2. mSeqMap.put(event.getSequenceNumber(),seq);
  3. onInputEvent(event);
  4. }
frameworks/base/core/java/android/view/ViewRootImpl.java [cpp] view plain copy
  1. finalclassWindowInputEventReceiverextendsInputEventReceiver{
  2. publicWindowInputEventReceiver(InputChannelinputChannel,Looperlooper){
  3. super(inputChannel,looper);
  4. }
  5. @Override
  6. publicvoidonInputEvent(InputEventevent){
  7. enqueueInputEvent(event,this,0,true);
  8. }
  9. }
  10. voidenqueueInputEvent(InputEventevent,
  11. InputEventReceiverreceiver,intflags,booleanprocessImmediately){
  12. scheduleProcessInputEvents();
  13. }

/////////////////////////////////////////////////////////////

有关handler机制请看下文:

http://blog.csdn.net/itachi85/article/details/8035333

[cpp] view plain copy
  1. finalViewRootHandlermHandler=newViewRootHandler();
  2. privatevoidscheduleProcessInputEvents(){
  3. Messagemsg=mHandler.obtainMessage(MSG_PROCESS_INPUT_EVENTS);
  4. mHandler.sendMessage(msg);
  5. }
  6. publicvoidhandleMessage(Messagemsg){
  7. switch(msg.what){
  8. caseMSG_PROCESS_INPUT_EVENTS:
  9. doProcessInputEvents();
  10. }
  11. }

///////////////////////////////////////////////////////

[cpp] view plain copy
  1. voiddoProcessInputEvents(){
  2. deliverInputEvent(q);
  3. }
  4. privatevoiddeliverInputEvent(QueuedInputEventq){
  5. deliverKeyEvent(q);
  6. deliverPointerEvent(q);
  7. deliverTrackballEvent(q);
  8. deliverGenericMotionEvent(q);
  9. }
  10. privatevoiddeliverKeyEvent(QueuedInputEventq){
  11. imm.dispatchKeyEvent(mView.getContext(),seq,event,mInputMethodCallback);//分发给输入法
  12. deliverKeyEventPostIme(q);//分发给View
  13. /*
  14. privatevoiddeliverKeyEventPostIme(QueuedInputEventq){
  15. mView.dispatchKeyEvent(event)
  16. }
  17. */
  18. }
  19. privatevoiddeliverPointerEvent(QueuedInputEventq){
  20. booleanhandled=mView.dispatchPointerEvent(event);//分发给View
  21. }
  22. privatevoiddeliverTrackballEvent(QueuedInputEventq){
  23. imm.dispatchTrackballEvent(mView.getContext(),seq,event,
  24. mInputMethodCallback);//分发给输入法
  25. deliverTrackballEventPostIme(q);//分发给View
  26. /*
  27. privatevoiddeliverTrackballEventPostIme(QueuedInputEventq){
  28. mView.dispatchTrackballEvent(event)
  29. }
  30. */
  31. }
  32. privatevoiddeliverGenericMotionEvent(QueuedInputEventq){
  33. imm.dispatchGenericMotionEvent(mView.getContext(),seq,event,
  34. mInputMethodCallback);//分发给输入法
  35. deliverGenericMotionEventPostIme(q);//分发给View
  36. /*
  37. privatevoiddeliverGenericMotionEventPostIme(QueuedInputEventq){
  38. updateJoystickDirection(event,false);//游戏手柄的摇杆就是在这处理
  39. mView.dispatchGenericMotionEvent(event)
  40. }
  41. */
  42. }

分发给应用程序Activity:

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java

[java] view plain copy
  1. privatefinalclassDecorViewextendsFrameLayoutimplementsRootViewSurfaceTaker{
  2. publicbooleandispatchKeyEvent(KeyEventevent){
  3. finalCallbackcb=getCallback();
  4. //cb为应用程序MainActivity
  5. finalbooleanhandled=cb!=null&&mFeatureId<0?cb.dispatchKeyEvent(event):super.dispatchKeyEvent(event);
  6. //给应用程序Activity的dispatchKeyEvent处理或交给View的dispatchKeyEvent
  7. }
  8. }

而上述应用程序中的dispatchKeyEvent一般会调用其父类的该方法,例如:

packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

[java] view plain copy
  1. publicbooleandispatchKeyEvent(KeyEventevent){
  2. returnsuper.dispatchKeyEvent(event);
  3. }

应用程序Activity在分发给与之关联的某个View,如果这个View没有处理、最终交给该Activity自己处理。

应用程序有关View的设置:

[java] view plain copy
  1. privateDialogmMenuWin;
  2. mMenuWin=newDialog(aActivity,R.style.CameraDialog);
  3. mMenuWin.setContentView(mMenuLayout);
  4. mMenuWin.setOnClickListener();//鼠标单击
  5. mMenuWin.setOnLongClickListener();//
  6. mMenuWin.setOnTouchListener();//触摸板
  7. mMenuWin.setOnKeyListener(newOnKeyListener(){
  8. publicbooleanonKey();//按键
  9. publicvoidonClick(Viewv);//鼠标单击
  10. }

frameworks/base/core/java/android/app/Activity.java

[java] view plain copy
  1. publicbooleandispatchKeyEvent(KeyEventevent){
  2. onUserInteraction();
  3. Windowwin=getWindow();
  4. if(win.superDispatchKeyEvent(event)){//首先由Window消化,即如果View消化了、则Activity将不在回调onKeyDown
  5. returntrue;
  6. }
  7. Viewdecor=mDecor;//如果没被消化,会调用Activity的onKeyDown
  8. if(decor==null)decor=win.getDecorView();
  9. returnevent.dispatch(this,decor!=null?decor.getKeyDispatcherState():null,this);
  10. }
  11. }
我们重点分析win.superDispatchKeyEvent,也就是View的处理流程:

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java

[java] view plain copy
  1. publicclassPhoneWindowextendsWindowimplementsMenuBuilder.Callback{
  2. publicbooleansuperDispatchKeyEvent(KeyEventevent){
  3. returnmDecor.superDispatchKeyEvent(event);
  4. }
  5. }
  6. privatefinalclassDecorViewextendsFrameLayoutimplementsRootViewSurfaceTaker{
  7. publicbooleansuperDispatchKeyEvent(KeyEventevent){
  8. super.dispatchKeyEvent(event)
  9. }
  10. }
frameworks/base/core/java/android/view/ViewGroup.java //分发给View的关键部分!!! [java] view plain copy
  1. publicbooleandispatchKeyEvent(KeyEventevent){
  2. mInputEventConsistencyVerifier.onKeyEvent(event,1);
  3. super.dispatchKeyEvent(event)
  4. }

frameworks/base/core/java/android/view/View.java

[java] view plain copy
  1. publicbooleandispatchKeyEvent(KeyEventevent){
  2. li.mOnKeyListener.onKey(this,event.getKeyCode(),event);//回调应用程序View相应方法
  3. event.dispatch(this,mAttachInfo!=null?mAttachInfo.mKeyDispatchState:null,this)
  4. /*
  5. frameworks/base/core/java/android/view/KeyEvent.java
  6. publicfinalbooleandispatch(Callbackreceiver,DispatcherStatestate,
  7. Objecttarget){
  8. //按键响应
  9. booleanres=receiver.onKeyDown(mKeyCode,this);//应用程序回调函数
  10. }
  11. */
  12. }
  13. publicfinalbooleandispatchPointerEvent(MotionEventevent){
  14. if(event.isTouchEvent()){
  15. returndispatchTouchEvent(event);
  16. }else{
  17. returndispatchGenericMotionEvent(event);
  18. }
  19. }
  20. publicbooleandispatchTouchEvent(MotionEventevent){
  21. //触摸板响应
  22. li.mOnTouchListener.onTouch(this,event)//应用程序继承OnTouchListener,实现的回调接口
  23. //鼠标左键响应
  24. onTouchEvent(event)
  25. /*
  26. publicbooleanonTouchEvent(MotionEventevent){
  27. performClick();
  28. //该接口调用li.mOnClickListener.onClick(this);为应用程序继承OnClickListener的回调函数
  29. }
  30. */
  31. }
以下不再做分析
dispatchGenericMotionEvent

dispatchTrackballEvent

dispatchConfigurationChanged //添加或删除键盘设备Activity重启,见http://blog.csdn.net/tankai19880619/article/details/16805401

三、Input设备与Activity关系

1.InputReaderThread线程检测到设备插入删除

frameworks/base/service/input/InputReader.cpp

[cpp] view plain copy
  1. voidInputReader::loopOnce(){
  2. size_tcount=mEventHub->getEvents(timeoutMillis,mEventBuffer,EVENT_BUFFER_SIZE);
  3. /*
  4. frameworks/base/services/input/EventHub.cpp
  5. size_tEventHub::getEvents(inttimeoutMillis,RawEvent*buffer,size_tbufferSize){
  6. int32_treadSize=read(device->fd,readBuffer,
  7. sizeof(structinput_event)*capacity);//从驱动读取事件
  8. }
  9. */
  10. processEventsLocked(mEventBuffer,count);
  11. }
  12. voidInputReader::processEventsLocked(constRawEvent*rawEvents,size_tcount){
  13. caseEventHubInterface::FINISHED_DEVICE_SCAN:
  14. handleConfigurationChangedLocked(rawEvent->when);
  15. }
  16. voidInputReader::handleConfigurationChangedLocked(nsecs_twhen){
  17. updateGlobalMetaStateLocked();
  18. //Enqueueconfigurationchanged.
  19. NotifyConfigurationChangedArgsargs(when);
  20. mQueuedListener->notifyConfigurationChanged(&args);
  21. }

说明:有的平台需要在接入硬件键盘时Activity不需要刷新;可以在上处做屏蔽:

[cpp] view plain copy
  1. //addbytank
  2. //donotsendconfigurationchange
  3. //NotifyConfigurationChangedArgsargs(when);
  4. //mQueuedListener->notifyConfigurationChanged(&args);
  5. //endtank

2.InputReaderThread线程分发给InputDispatcherThread线程

frameworks/base/service/input/InputDispatcher.cpp

[cpp] view plain copy
  1. voidInputDispatcher::notifyConfigurationChanged(constNotifyConfigurationChangedArgs*args){
  2. needWake=enqueueInboundEventLocked(newEntry);
  3. if(needWake){
  4. mLooper->wake();
  5. }
  6. }
3.InputReaderThread线程收到消息并处理

frameworks/base/service/input/InputDispatcher.cpp

[cpp] view plain copy
  1. boolInputDispatcherThread::threadLoop(){
  2. mDispatcher->dispatchOnce();
  3. returntrue;
  4. }
  5. voidInputDispatcher::dispatchOnce(){
  6. dispatchOnceInnerLocked(&nextWakeupTime);
  7. }
  8. voidInputDispatcher::dispatchOnceInnerLocked(nsecs_t*nextWakeupTime){
  9. caseEventEntry::TYPE_CONFIGURATION_CHANGED:{
  10. ConfigurationChangedEntry*typedEntry=
  11. static_cast<ConfigurationChangedEntry*>(mPendingEvent);
  12. done=dispatchConfigurationChangedLocked(currentTime,typedEntry);
  13. }
  14. }
  15. boolInputDispatcher::dispatchConfigurationChangedLocked(
  16. nsecs_tcurrentTime,ConfigurationChangedEntry*entry){
  17. CommandEntry*commandEntry=postCommandLocked(
  18. &InputDispatcher::doNotifyConfigurationChangedInterruptible);
  19. }
  20. voidInputDispatcher::doNotifyConfigurationChangedInterruptible(
  21. CommandEntry*commandEntry){
  22. mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
  23. }
如上,不再做分析:

frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp

[cpp] view plain copy
  1. voidNativeInputManager::notifyConfigurationChanged(nsecs_twhen){
  2. env->CallVoidMethod(mServiceObj,gServiceClassInfo.notifyConfigurationChanged,when);
  3. }
frameworks/base/services/java/com/android/server/input/InputManagerService.cpp [cpp] view plain copy
  1. privatevoidnotifyConfigurationChanged(longwhenNanos){
  2. mWindowManagerCallbacks.notifyConfigurationChanged();
  3. }
如上,不再做分析:

frameworks/base/service/java/com/android/server/wm/InputMonitor.java

[cpp] view plain copy
  1. publicvoidnotifyConfigurationChanged(){
  2. mService.sendNewConfiguration();
  3. }
frameworks/base/service/java/com/android/server/wm/WindowManagerService.java [cpp] view plain copy
  1. voidsendNewConfiguration(){
  2. mActivityManager.updateConfiguration(null);
  3. /*
  4. mActivityManager=ActivityManagerNative.getDefault();
  5. frameworks/base/core/java/android/app/ActivityManagerNative.java
  6. staticpublicIActivityManagergetDefault(){
  7. returngDefault.get();
  8. }
  9. privatestaticfinalSingleton<IActivityManager>gDefault=newSingleton<IActivityManager>(){
  10. IBinderb=ServiceManager.getService("activity");
  11. IActivityManageram=asInterface(b);
  12. returnam;
  13. }
  14. frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
  15. publicstaticvoidsetSystemProcess(){
  16. ActivityManagerServicem=mSelf;
  17. ServiceManager.addService("activity",m,true);
  18. }
  19. */
  20. }
4.交由ActivityManagerService进程处理

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

[cpp] view plain copy
  1. publicvoidupdateConfiguration(Configurationvalues){
  2. updateConfigurationLocked(values,null,false,false);
  3. }
  4. booleanupdateConfigurationLocked(Configurationvalues,
  5. ActivityRecordstarting,booleanpersistent,booleaninitLocale){
  6. kept=mMainStack.ensureActivityConfigurationLocked(starting,changes);
  7. publicvoidsetWindowManager(WindowManagerServicewm){
  8. mWindowManager=wm;
  9. }
  10. }
frameworks/base/services/java/com/android/server/am/ActivityStack.java [cpp] view plain copy
  1. finalbooleanensureActivityConfigurationLocked(ActivityRecordr,
  2. intglobalChanges){
  3. //一般会重启Activity
  4. if((changes&(~r.info.getRealConfigChanged()))!=0||r.forceNewConfig){
  5. relaunchActivityLocked(r,r.configChangeFlags,false);
  6. returnfalse;
  7. }
  8. //应用程序AndroidMenifest中写标记将不会重启
  9. r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
  10. }
frameworks/base/core/java/android/app/ActivityThread.java [cpp] view plain copy
  1. publicvoidscheduleActivityConfigurationChanged(IBindertoken){
  2. queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED,token);
  3. }
  4. //消息循环同上,不再分析
  5. publicvoidhandleMessage(Messagemsg){
  6. caseACTIVITY_CONFIGURATION_CHANGED:
  7. handleActivityConfigurationChanged((IBinder)msg.obj);
  8. }
  9. finalvoidhandleActivityConfigurationChanged(IBindertoken){
  10. performConfigurationChanged(r.activity,mCompatConfiguration);
  11. }
  12. privatestaticvoidperformConfigurationChanged(ComponentCallbacks2cb,Configurationconfig){
  13. cb.onConfigurationChanged(config);//回调Activity类的onConfigurationChanged方法
  14. }

四、项目问题

1.resumeTopActivity时的Activity重启。

http://blog.csdn.net/jivin_shen/article/details/6839175

操作逻辑:打开Launcher界面下的一个应用(比如播放器),完后接入USB键盘;之后退出该应用,也就是resumeTopActivity到Launcher时也引发了config配置更新导致的Activity重启。

原理以及解决部分:

frameworks/base/services/java/com/android/server/am/ActivityStack.java

[cpp] view plain copy
  1. finalbooleanresumeTopActivityLocked(ActivityRecordprev){
  2. returnresumeTopActivityLocked(prev,null);
  3. }
  4. finalbooleanresumeTopActivityLocked(ActivityRecordprev,Bundleoptions){
  5. Configurationconfig=mService.mWindowManager.updateOrientationFromAppTokens(
  6. mService.mConfiguration,
  7. next.mayFreezeScreenLocked(next.app)?next.appToken:null);
  8. }

frameworks/base/services/java/com/android/server/wm/WindowManagerService.java

[cpp] view plain copy
  1. publicConfigurationupdateOrientationFromAppTokens(
  2. ConfigurationcurrentConfig,IBinderfreezeThisOneIfNeeded){
  3. config=updateOrientationFromAppTokensLocked(currentConfig,
  4. freezeThisOneIfNeeded);
  5. }
  6. privateConfigurationupdateOrientationFromAppTokensLocked(
  7. ConfigurationcurrentConfig,IBinderfreezeThisOneIfNeeded){
  8. computeScreenConfigurationLocked(mTempConfiguration)
  9. }
  10. booleancomputeScreenConfigurationLocked(Configurationconfig){
  11. if((sources&InputDevice.SOURCE_TOUCHSCREEN)==InputDevice.SOURCE_TOUCHSCREEN){
  12. //changebytank
  13. config.touchscreen=Configuration.TOUCHSCREEN_NOTOUCH;
  14. //config.touchscreen=Configuration.TOUCHSCREEN_FINGER;
  15. //endtank
  16. }
  17. elseif((sources&InputDevice.SOURCE_DPAD)==InputDevice.SOURCE_DPAD
  18. &&config.navigation==Configuration.NAVIGATION_NONAV){
  19. //changebytank
  20. //config.navigation=Configuration.NAVIGATION_DPAD;
  21. //navigationPresence|=presenceFlag;
  22. //endtank
  23. }
  24. if(device.getKeyboardType()==InputDevice.KEYBOARD_TYPE_ALPHABETIC){
  25. //changebytank
  26. //config.keyboard=Configuration.KEYBOARD_QWERTY;
  27. //keyboardPresence|=presenceFlag;
  28. //endtank
  29. }
  30. }

2.面板设备与虚拟驱动导致的up上报两次:

drop类按键

down或up:

dispatchOnceInnerLocked>

dropInboundEventLocked>synthesizeCancelationEventsForAllConnectionsLocked-synthesizeCancelationEventsForConnectionLocked>inputState.synthesizeCancelationEvents->mKeyMementos.itemAt(i),最后上报系统(synthesizeCancelationEventsForConnectionLocked调用enqueueDispatchEntryLocked)

非drop类按键

down:

dispatchOnceInnerLocked->

dispatchKeyLocked->dispatchEventLocked->prepareDispatchCycleLocked->enqueueDispatchEntriesLocked->enqueueDispatchEntryLocked->InputState::trackKey->addKeyMemento //只在down时保存对up的处理

问题:

面板down->drop

虚拟down->非drop,保存up

面板down->drop,将虚拟保存的up送上去

虚拟up->非drop,直接上报

结果——两个虚拟的up

修改方法:

frameworks/base/service/input/InputDispatcher.cpp

[cpp] view plain copy
  1. voidInputDispatcher::enqueueDispatchEntryLocked(
  2. constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget,
  3. int32_tdispatchMode)
  4. {
  5. if(!connection->inputState.trackKey(keyEntry,
  6. dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags)/*addbytank@tcl.comend*/||(dispatchEntry->resolvedFlags==0x28))
  7. {
  8. #ifDEBUG_DISPATCH_CYCLE
  9. ALOGD("channel'%s'~enqueueDispatchEntryLocked:skippinginconsistentkeyevent",
  10. connection->getInputChannelName());
  11. #endif
  12. deletedispatchEntry;
  13. return;//skiptheinconsistentevent
  14. }
  15. /*
  16. //addbytankai
  17. if(dispatchEntry->resolvedFlags==0x28&&keyEntry->deviceId==3){
  18. ALOGD("TK--------->>>deletesimKeyMementosup\n");
  19. deletedispatchEntry;
  20. return;//skiptheinconsistentevent
  21. }
  22. //endtankai
  23. */
  24. }

3.焦点request错误导致不能响应按键

正确调用:setFocusable(true)和requestFocus()重新获取焦点

错误调用:setFocusable(false)和requestFocus()

系统侧为该应用tv.huan.deezer强制修改:

frameworks/base/core/java/android/view/View.java

[java] view plain copy
  1. publicfinalbooleanrequestFocus(){
  2. Log.d("TKTK","TK---->>>View.java>>>>requestFocus()");//addbytank
  3. if(SystemProperties.get("sys.user.camera",null).equals("tv.huan.deezer"))
  4. {
  5. setFocusable(true);
  6. }
  7. //endtank
  8. returnrequestFocus(View.FOCUS_DOWN);
  9. }

更多相关文章

  1. Google Android 应用程序结构
  2. android应用程序跳转到系统的各个设置页面
  3. 如何以编程方式退出android应用程序
  4. Android Application Fundamentals——Android应用程序基础知识
  5. Android 应用程序只运行一个实例
  6. android4.2上获取应用程序大小的变更点
  7. android按键灯流程分析
  8. Android 拦截 HOME 按键
  9. Android 之应用程序重启

随机推荐

  1. 了解Android
  2. android标题栏的选择与使用,AppCompatActi
  3. Android下 使用百度地图sdk
  4. Android即时消息介绍
  5. 在eclipse中查看android SDK的源代码
  6. Android(安卓)模拟器创建参数说明
  7. Android(安卓)Studio初探:不只是一个简单
  8. 开发Android应用 提升性能的小技巧
  9. 如何在Android和iOS设备上录制游戏?
  10. 记录一下八款开源 Android(安卓)游戏引擎