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

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

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

1.服务端channel注册过程

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

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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键即在此处完成、以下代码将会看到


frameworks/base/services/input/InputReader.cpp

[cpp] view plaincopy

  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 plaincopy

  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决定是否丢弃按键


InputDispatcherThread线程被唤醒

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  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关系


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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  1. privatevoiddispatchInputEvent(intseq,InputEventevent){

  2. mSeqMap.put(event.getSequenceNumber(),seq);

  3. onInputEvent(event);

  4. }

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

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  1. publicbooleandispatchKeyEvent(KeyEventevent){

  2. returnsuper.dispatchKeyEvent(event);

  3. }

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

应用程序有关View的设置:

[java] view plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  1. publicbooleandispatchKeyEvent(KeyEventevent){

  2. mInputEventConsistencyVerifier.onKeyEvent(event,1);

  3. super.dispatchKeyEvent(event)

  4. }

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

[java] view plaincopy

  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 plaincopy

  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 plaincopy

  1. //addbytank

  2. //donotsendconfigurationchange

  3. //NotifyConfigurationChangedArgsargs(when);

  4. //mQueuedListener->notifyConfigurationChanged(&args);

  5. //endtank

2.InputReaderThread线程分发给InputDispatcherThread线程

frameworks/base/service/input/InputDispatcher.cpp

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  1. privatevoidnotifyConfigurationChanged(longwhenNanos){

  2. mWindowManagerCallbacks.notifyConfigurationChanged();

  3. }

如上,不再做分析:

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

[cpp] view plaincopy

  1. publicvoidnotifyConfigurationChanged(){

  2. mService.sendNewConfiguration();

  3. }

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

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  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 plaincopy

  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. }

四、项目问题

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 plaincopy

  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 plaincopy

  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. }

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

1.drop类按键

down或up:

dispatchOnceInnerLocked>

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

2.非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 plaincopy

  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. }


更多相关文章

  1. FregServer进程,发送BC_TRANSACTION,唤醒ServiceManager进程,返回BR
  2. Android(安卓)图片阴影处理分析!
  3. Android在WebView上构建Web应用程序
  4. Android应用程序常见编译问题解决
  5. Android应用程序显示欢迎画面并开机自启动
  6. Android:UI更新方法四:在Worker Thread中runOnUiThread直接刷新U
  7. Android图像处理相关文章
  8. 几个通用的类,迷你型的Android下载框架
  9. 在Android中使用Timer,并创建一个应用程序

随机推荐

  1. 如何培养数据分析的思维?
  2. 新手如何学习SQL
  3. 2019年终总结
  4. Python数据结构:字典那些事儿
  5. 你真的了解参数估计和假设检验吗?
  6. Python数据结构:神奇的序列
  7. 遇到喷子,请先别急于反驳!
  8. 一份电商数据分析案例
  9. 怎样绘制漂亮的统计图表|不一样的折线图
  10. C#基础入门第十三天(多态接口)