Android之Input子系統事件分發流程

From :  http://blog.csdn.net/tankai19880619/article/details/17019085

一、Android4.2系統服務側——與View關係

1.服務端channel註冊過程

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

  1. public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {  
  2.   mInputChannel = new InputChannel(); //創建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.   public static IWindowSession getWindowSession(Looper mainLooper) { 
  10.     IWindowManager windowManager = getWindowManagerService(); 
  11.     sWindowSession = windowManager.openSession( 
  12.                             imm.getClient(), imm.getInputContext()); 
  13.     return sWindowSession; 
  14.   } 
  15.   frameworks/base/services/java/com/android/server/wm/WindowManagerService.java 
  16.   public IWindowSession openSession(IInputMethodClient client, 
  17.             IInputContext inputContext) { 
  18.     if (client == null) throw new IllegalArgumentException("null client"); 
  19.     if (inputContext == null) throw new IllegalArgumentException("null inputContext"); 
  20.     Session session = new Session(this, client, inputContext); 
  21.     return session; 
  22.   } 
  23.   */  
  24.   mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,   
  25.     Looper.myLooper());  //將本通道註冊進InputEventReceiver  
  26. }  
frameworks/base/services/java/com/android/server/wm/Session.java
  1. public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,  
  2.             int viewVisibility, int displayId, Rect outContentInsets,  
  3.             InputChannel outInputChannel) {  
  4.   return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,  
  5.                 outContentInsets, outInputChannel);  
  6. }  
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
  1. public int addWindow(Session session, IWindow client, int seq,  
  2.             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,  
  3.             Rect outContentInsets, InputChannel outInputChannel) {  
  4.   //以下包括了管道的創建(用於WMS與應用程序View通信)等  
  5.   String name = win.makeInputChannelName();  
  6.   InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);  
  7.   win.setInputChannel(inputChannels[0]);  
  8.   inputChannels[1].transferTo(outInputChannel);  
  9.   //以下便是註冊至server端過程  
  10.   //final InputManagerService mInputManager;  
  11.   mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);  
  12. }  
frameworks/base/service/java/com/android/server/input/InputManagerService.java
  1. public void registerInputChannel(InputChannel inputChannel,  
  2.             InputWindowHandle inputWindowHandle) {  
  3.   nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);  
  4. }  
  5. private static native void nativeRegisterInputChannel(int ptr, InputChannel inputChannel,  
  6.             InputWindowHandle inputWindowHandle, boolean monitor);  
frameworks/base/service/jni/com_android_server_input_InputManagerService.cpp
  1. static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,  
  2.         jint ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {  
  3.   NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  
  4.   status_t status = im->registerInputChannel(  
  5.             env, inputChannel, inputWindowHandle, monitor);  
  6. }  
  7. status_t NativeInputManager::registerInputChannel(JNIEnv* env,  
  8.         const sp<InputChannel>& inputChannel,  
  9.         const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {  
  10.   return mInputManager->getDispatcher()->registerInputChannel(  
  11.             inputChannel, inputWindowHandle, monitor);  
  12.   //mInputManager = new InputManager(eventHub, this, this);  
  13.   /* 
  14.   frameworks/base/services/input/InputManager.cpp 
  15.   sp<InputDispatcherInterface> InputManager::getDispatcher() { 
  16.     return mDispatcher; 
  17.   } 
  18.   mDispatcher = new InputDispatcher(dispatcherPolicy); 
  19.   */  
  20. }  

frameworks/base/services/input/InputDispatcher.cpp

  1. status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,  
  2.         const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {  
  3.   int fd = 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

  1. bool InputReaderThread::threadLoop() {  
  2.   mReader->loopOnce();  
  3.   return true;  
  4. }  
  5. void InputReader::loopOnce() {  
  6.   size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
  7.   /* 
  8.   frameworks/base/services/input/EventHub.cpp 
  9.   size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { 
  10.     int32_t readSize = read(device->fd, readBuffer, 
  11.       sizeof(struct input_event) * capacity);//從驅動讀取事件 
  12.   } 
  13.   */  
  14.   processEventsLocked(mEventBuffer, count);  
  15. }  
  16. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {  
  17.   processEventsForDeviceLocked(deviceId, rawEvent, batchSize);  
  18. }  
  19. void InputReader::processEventsForDeviceLocked(int32_t deviceId,  
  20.          const RawEvent* rawEvents, size_t count) {  
  21.   device->process(rawEvents, count);  
  22. }  
  23. void InputDevice::process(const RawEvent* rawEvents, size_t count) {  
  24.   //該設備的所有mapper進行處理;注意:這裏使用了多態  
  25.   for (size_t i = 0; i < numMappers; i++) {  
  26.     InputMapper* mapper = mMappers[i];  
  27.     mapper->process(rawEvent);  
  28.   }  
  29. }  
  30. //以下就是各個mapper  
  31. //CursorInput鼠標設備  
  32. void CursorInputMapper::process(const RawEvent* 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(const RawEvent* rawEvent)  
  41. //CursorMotionAccumulator::process(const RawEvent* rawEvent)  
  42. //CursorScrollAccumulator::process(const RawEvent* rawEvent)  
  43. void CursorInputMapper::sync(nsecs_t when) {  
  44.   int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();  
  45.   /* 
  46.   uint32_t CursorButtonAccumulator::getButtonState() const { 
  47.     if (mBtnRight) { 
  48.       //Changed by tank for mouse left button to back   
  49.       result |= AMOTION_EVENT_BUTTON_BACK; 
  50.       //  result |= AMOTION_EVENT_BUTTON_SECONDARY; 
  51.     } 
  52.     if (mBtnMiddle) { 
  53.       //change by [email protected] for mouse middle button to menu 
  54.       result |= AMOTION_EVENT_BUTTON_MENU; 
  55.       //result |= AMOTION_EVENT_BUTTON_TERTIARY; 
  56.     } 
  57.   } 
  58.   */  
  59.   
  60.   getListener()->notifyMotion(&args);  
  61.   
  62.   synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,  
  63.       policyFlags, lastButtonState, currentButtonState);    
  64.   /* 
  65.   static void synthesizeButtonKeys(InputReaderContext* context, int32_t action, 
  66.       nsecs_t when, int32_t deviceId, uint32_t source, 
  67.       uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) { 
  68.     synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, 
  69.               lastButtonState, currentButtonState, 
  70.               AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK); 
  71.     synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, 
  72.               lastButtonState, currentButtonState, 
  73.               AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD); 
  74.     //add by tank  mouse key event middle->menu. 
  75.     synthesizeButtonKey(context, action, when, deviceId, source, policyFlags, 
  76.               lastButtonState, currentButtonState, 
  77.               AMOTION_EVENT_BUTTON_MENU, AKEYCODE_MENU); 
  78.     //end tank 
  79.   } 
  80.   static void synthesizeButtonKey(InputReaderContext* context, int32_t action, 
  81.           nsecs_t when, int32_t deviceId, uint32_t source, 
  82.           uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState, 
  83.           int32_t buttonState, int32_t keyCode) { 
  84.     if ((action == AKEY_EVENT_ACTION_DOWN && !(lastButtonState & buttonState) 
  85.     && (currentButtonState & buttonState)) 
  86.     || (action == AKEY_EVENT_ACTION_UP 
  87.     && (lastButtonState & buttonState) 
  88.     && !(currentButtonState & buttonState))) { 
  89.       context->getListener()->notifyKey(&args); 
  90.     } 
  91.   } 
  92.   */  
  93. }  
  94. //TouchInput觸摸板設備  
  95. void SingleTouchInputMapper::process(const RawEvent* rawEvent)   
  96.   TouchInputMapper::process(rawEvent);  
  97.   mSingleTouchMotionAccumulator.process(rawEvent);  
  98. }  
  99. //SingleTouchMotionAccumulator::process(const RawEvent* rawEvent)   
  100. void MultiTouchInputMapper::process(const RawEvent* rawEvent) {  
  101.   TouchInputMapper::process(rawEvent);  
  102.   mMultiTouchMotionAccumulator.process(rawEvent);  
  103. }  
  104. //MultiTouchMotionAccumulator::process(const RawEvent* rawEvent)   
  105. void TouchInputMapper::process(const RawEvent* rawEvent) {  
  106.   mCursorButtonAccumulator.process(rawEvent);  
  107.   mCursorScrollAccumulator.process(rawEvent);  
  108.   mTouchButtonAccumulator.process(rawEvent);  
  109.   if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  110.     sync(rawEvent->when);  
  111.   }  
  112. }  
  113. //TouchButtonAccumulator::process(const RawEvent* rawEvent)   
  114. void TouchInputMapper::sync(nsecs_t when) {  
  115.   dispatchTouches(when, policyFlags);  
  116. }  
  117. void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {  
  118.   dispatchMotion(when, policyFlags, mSource,  
  119.     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,  
  120.     AMOTION_EVENT_EDGE_FLAG_NONE,  
  121.     mCurrentCookedPointerData.pointerProperties,  
  122.     mCurrentCookedPointerData.pointerCoords,  
  123.     mCurrentCookedPointerData.idToIndex,  
  124.     currentIdBits, -1,  
  125.     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  126. }  
  127. void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,  
  128.     int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,  
  129.     const PointerProperties* properties, const PointerCoords* coords,  
  130.     const uint32_t* idToIndex, BitSet32 idBits,  
  131.     int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {  
  132.   getListener()->notifyMotion(&args);  
  133. }  
  134. //SwitchInput設備  
  135. void SwitchInputMapper::process(const RawEvent* rawEvent) {  
  136.   sync(rawEvent->when);  
  137. }  
  138. void SwitchInputMapper::sync(nsecs_t when) {  
  139.   getListener()->notifySwitch(&args);  
  140. }  
  141. //JoystickInput遊戲手柄設備  
  142. void JoystickInputMapper::process(const RawEvent* rawEvent) {  
  143.   sync(rawEvent->when, false /*force*/);  
  144. }  
  145. void JoystickInputMapper::sync(nsecs_t when, bool force) {  
  146.   getListener()->notifyMotion(&args);  
  147. }  
  148. //KeyboardInput按鍵設備  
  149. void KeyboardInputMapper::process(const RawEvent* rawEvent) {  
  150.   processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);  
  151. }  
  152. void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,  
  153.          int32_t scanCode, uint32_t policyFlags) {  
  154.   getListener()->notifyKey(&args);  
  155. }  

2.2.InputReaderThread線程對系統層按鍵做處理(比較重要的是POWER鍵,最終在PhoneWindowManager中的interceptKeyBeforeQueueing和interceptMotionBeforeQueueingWhenScreenOff)後分發給InputDispatcherThread線程,以下分析將看到之前一個鼠標操作過程中無法待機的問題解決

以下幾種情況都會喚醒InputDispatcherThread線程,即調用mLooper->wake()喚醒正在awoken()中的InputReaderThread線程:

frameworks/base/services/input/InputDispatcher.cpp

  1. //有新輸入設備註冊等  
  2. void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {  
  3.   ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);  
  4.   needWake = enqueueInboundEventLocked(newEntry);  
  5.   if (needWake) {  
  6.     mLooper->wake();  
  7.   }  
  8. }  
  9. //分發按鍵事件  
  10. void InputDispatcher::notifyKey(const NotifyKeyArgs* 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.         const sp<EventHubInterface>& eventHub, 
  18.         const sp<InputReaderPolicyInterface>& readerPolicy, 
  19.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { 
  20.     mDispatcher = new InputDispatcher(dispatcherPolicy); 
  21.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher); 
  22.   } 
  23.   frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp 
  24.   NativeInputManager::NativeInputManager(jobject contextObj, 
  25.         jobject serviceObj, const sp<Looper>& looper) : 
  26.         mLooper(looper) { 
  27.     mInputManager = new InputManager(eventHub, this, this); 
  28.   } 
  29.   void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* 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.   private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { 
  39.     return mWindowManagerCallbacks.interceptKeyBeforeQueueing( 
  40.                 event, policyFlags, isScreenOn); 
  41.   } 
  42.   frameworks/base/service/java/com/android/server/SystemServer.java 
  43.   inputManager = new InputManagerService(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.   public InputMonitor getInputMonitor() { 
  51.     return mInputMonitor; 
  52.   } 
  53.   frameworks/base/service/java/com/android/server/wm/InputMonitor.java 
  54.   public int interceptKeyBeforeQueueing( 
  55.             KeyEvent event, int policyFlags, boolean isScreenOn) { 
  56.     return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn); 
  57.   } 
  58.   public InputMonitor(WindowManagerService service) { 
  59.     mService = service; 
  60.   } 
  61.   frameworks/base/service/java/com/android/server/wm/WindowManagerService.java 
  62.   final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); 
  63.   frameworks/base/core/java/com/android/internal/policy/PolicyManager.java 
  64.   public static WindowManagerPolicy makeNewWindowManager() { 
  65.     return sPolicy.makeNewWindowManager(); 
  66.   } 
  67.   private static final String POLICY_IMPL_CLASS_NAME = 
  68.         "com.android.internal.policy.impl.Policy"; 
  69.   Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME); 
  70.   sPolicy = (IPolicy)policyClass.newInstance(); 
  71.   frameworks/base/core/java/com/android/internal/policy/Policy.java 
  72.   package com.android.internal.policy.impl; 
  73.   public class Policy implements IPolicy { 
  74.     public WindowManagerPolicy makeNewWindowManager() { 
  75.       return new PhoneWindowManager(); 
  76.     } 
  77.   } 
  78.   frameworks/base/core/java/com/android/internal/policy/PhoneWindowManager.java 
  79.   public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { 
  80.     case KeyEvent.KEYCODE_POWER: { 
  81.       result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; 
  82.     } 
  83.   } 
  84.   */  
  85.   KeyEntry* newEntry = new KeyEntry(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. void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {  
  96.   mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);  
  97.   /* 
  98.   如上分析,不再累贅;該接口是: 
  99.   frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp 
  100.   void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { 
  101.     jint wmActions = 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.   public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { 
  109.     //result |= ACTION_WAKE_UP; 
  110.     //add by tank 
  111.     result = result & (~ACTION_WAKE_UP); 
  112.     //end tank 
  113.     return result; 
  114.   } 
  115.   看看handleInterceptActions函數: 
  116.   void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, 
  117.         uint32_t& policyFlags) { 
  118.     //接上邊PhoneWindowManager中interceptKeyBeforeQueueing對於power鍵的返回值可知,系統將待機 
  119.     if (wmActions & WM_ACTION_GO_TO_SLEEP) { 
  120.       #if DEBUG_INPUT_DISPATCHER_POLICY 
  121.       ALOGD("handleInterceptActions: Going to sleep."); 
  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.       #if DEBUG_INPUT_DISPATCHER_POLICY 
  129.       ALOGD("handleInterceptActions: Waking up."); 
  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 = new MotionEntry(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. void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {  
  152.   DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId);  
  153.   needWake = enqueueInboundEventLocked(newEntry);  
  154.   if (needWake) {  
  155.     mLooper->wake();  
  156.   }  
  157. }  
  158. //C層的按鍵注入接口  
  159. int32_t InputDispatcher::injectInputEvent(const InputEvent* event,  
  160.         int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,  
  161.         uint32_t policyFlags) {  
  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線程被喚醒

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

2.4.InputDispatcherThread線程分發給應用程序進程

在這裏解決了up事件上報兩次的問題!!!!!!

frameworks/base/services/input/InputDispatcher.cpp

  1. void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,  
  2.         EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {  
  3.   pokeUserActivityLocked(eventEntry);  //和Activity相關,後邊三中有設備刪除的分析;基本同下  
  4.   ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);  
  5.   sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);  
  6.   prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);  
  7. }  
  8. void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,  
  9.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {  
  10.   enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);  
  11. }  
  12. void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,  
  13.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {  
  14.    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  15.             InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT); //將按鍵注入隊列  
  16.    /* 
  17.    void InputDispatcher::enqueueDispatchEntryLocked( 
  18.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget, 
  19.         int32_t dispatchMode) { 
  20.      DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref 
  21.             inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset, 
  22.             inputTarget->scaleFactor); 
  23.      if (!connection->inputState.trackKey(keyEntry, 
  24.                 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags) || (dispatchEntry->resolvedFlags == 0x28)){ 
  25.        //add by tankai 0x28 
  26.        delete dispatchEntry; 
  27.        return; 
  28.      } 
  29.    } 
  30.    */  
  31.    //dropInboundEventLocked  
  32.    //synthesizeCancelationEventsForAllConnectionsLocked->  
  33.    //synthesizeCancelationEventsForConnectionLocked->  
  34.    /* 
  35.    void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( 
  36.         const sp<Connection>& connection, const CancelationOptions& 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, // increments ref 
  43.                     &target, InputTarget::FLAG_DISPATCH_AS_IS); 
  44.      } 
  45.    } 
  46.    */  
  47.    //enqueueDispatchEntriesLocked,注入了0x28標誌的按鍵  
  48.    startDispatchCycleLocked(currentTime, connection);  
  49. }  
  50. void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,  
  51.         const sp<Connection>& connection) {  
  52.   switch (eventEntry->type) {  
  53.     case EventEntry::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.     case EventEntry::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
  1. status_t InputPublisher::publishKeyEvent(  
  2.         uint32_t seq,  
  3.         int32_t deviceId,  
  4.         int32_t source,  
  5.         int32_t action,  
  6.         int32_t flags,  
  7.         int32_t keyCode,  
  8.         int32_t scanCode,  
  9.         int32_t metaState,  
  10.         int32_t repeatCount,  
  11.         nsecs_t downTime,  
  12.         nsecs_t eventTime) {  
  13.   return mChannel->sendMessage(&msg);  
  14. }  
  15. status_t InputChannel::sendMessage(const InputMessage* 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

  1. public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {  
  2.   mInputChannel = new InputChannel(); //創建InputChannel  
  3.   res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,  
  4.     getHostVisibility(), mDisplay.getDisplayId(),  
  5.     mAttachInfo.mContentInsets, mInputChannel);  //創建與上述InputChannel對應的通道至服務端  
  6.   mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,   
  7.     Looper.myLooper());  //將本通道註冊進InputEventReceiver  
  8. }  
  9. final class WindowInputEventReceiver extends InputEventReceiver {  
  10.   public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {  
  11.     super(inputChannel, looper);  
  12.   }  
  13.   @Override  
  14.   public void onInputEvent(InputEvent event) {  
  15.     enqueueInputEvent(event, this, 0, true);  
  16.   }  
  17. }  

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

  1. public InputEventReceiver(InputChannel inputChannel, Looper looper) {  
  2.   mReceiverPtr = nativeInit(this, inputChannel, mMessageQueue);  
  3. }  
  4. private static native int nativeInit(InputEventReceiver receiver,  
  5.             InputChannel inputChannel, MessageQueue messageQueue);  

frameworks/base/core/jni/android_view_InputEventReceiver.cpp

  1. static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,  
  2.         jobject inputChannelObj, jobject messageQueueObj) {  
  3.   sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,  
  4.             receiverObj, inputChannel, messageQueue);  
  5.   status_t status = receiver->initialize();  
  6. }  
  7. status_t NativeInputEventReceiver::initialize() {  
  8.   int receiveFd = mInputConsumer.getChannel()->getFd();  
  9.   mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL);  
  10.   return OK;  
  11. }  

frameworks/native/libs/utils/Looper.cpp

  1. int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {  
  2.   request.callback = callback;  
  3. }  

2.應用程序View響應過程

frameworks/native/libs/utils/Looper.cpp

  1. int Looper::pollInner(int timeoutMillis) {  
  2.   awoken(); //阻塞,等待  
  3.   int callbackResult = response.request.callback->handleEvent(fd, events, data);  
  4. }  

frameworks/base/core/jni/android_view_InputEventReceiver.cpp

  1. int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {  
  2.   status_t status = consumeEvents(env, false /*consumeBatches*/, -1);  
  3. }  
  4. status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,  
  5.         bool consumeBatches, nsecs_t frameTime) {  
  6.   env->CallVoidMethod(mReceiverObjGlobal,  
  7.                         gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);  
  8. }  
frameworks/base/core/java/android/view/InputEventReceiver.java
  1. private void dispatchInputEvent(int seq, InputEvent event) {  
  2.         mSeqMap.put(event.getSequenceNumber(), seq);  
  3.         onInputEvent(event);  
  4. }  
frameworks/base/core/java/android/view/ViewRootImpl.java
  1. final class WindowInputEventReceiver extends InputEventReceiver {  
  2.   public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {  
  3.     super(inputChannel, looper);  
  4.   }  
  5.   @Override  
  6.   public void onInputEvent(InputEvent event) {  
  7.     enqueueInputEvent(event, this, 0, true);  
  8.   }  
  9. }  
  10. void enqueueInputEvent(InputEvent event,  
  11.     InputEventReceiver receiver, int flags, boolean processImmediately) {  
  12.   scheduleProcessInputEvents();  
  13. }  

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

有關handler機制請看下文:

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

  1. final ViewRootHandler mHandler = new ViewRootHandler();  
  2. private void scheduleProcessInputEvents() {  
  3.   Message msg = mHandler.obtainMessage(MSG_PROCESS_INPUT_EVENTS);  
  4.   mHandler.sendMessage(msg);  
  5. }  
  6. public void handleMessage(Message msg) {  
  7.   switch (msg.what) {  
  8.     case MSG_PROCESS_INPUT_EVENTS:  
  9.       doProcessInputEvents();  
  10.   }  
  11. }  

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

  1. void doProcessInputEvents() {  
  2.   deliverInputEvent(q);  
  3. }  
  4. private void deliverInputEvent(QueuedInputEvent q) {  
  5.   deliverKeyEvent(q);  
  6.   deliverPointerEvent(q);  
  7.   deliverTrackballEvent(q);  
  8.   deliverGenericMotionEvent(q);  
  9. }  
  10. private void deliverKeyEvent(QueuedInputEvent q) {  
  11.   imm.dispatchKeyEvent(mView.getContext(), seq, event, mInputMethodCallback); //分發給輸入法  
  12.   deliverKeyEventPostIme(q);//分發給View  
  13.   /* 
  14.   private void deliverKeyEventPostIme(QueuedInputEvent q) { 
  15.     mView.dispatchKeyEvent(event)  
  16.   } 
  17.   */  
  18. }  
  19. private void deliverPointerEvent(QueuedInputEvent q) {  
  20.   boolean handled = mView.dispatchPointerEvent(event); //分發給View  
  21. }  
  22. private void deliverTrackballEvent(QueuedInputEvent q) {  
  23.   imm.dispatchTrackballEvent(mView.getContext(), seq, event,  
  24.     mInputMethodCallback);  //分發給輸入法  
  25.   deliverTrackballEventPostIme(q);  //分發給View  
  26.   /* 
  27.   private void deliverTrackballEventPostIme(QueuedInputEvent q) { 
  28.     mView.dispatchTrackballEvent(event) 
  29.   } 
  30.   */  
  31. }  
  32. private void deliverGenericMotionEvent(QueuedInputEvent q) {  
  33.   imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,  
  34.     mInputMethodCallback);  //分發給輸入法  
  35.   deliverGenericMotionEventPostIme(q); //分發給View  
  36.   /* 
  37.   private void deliverGenericMotionEventPostIme(QueuedInputEvent q) { 
  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在CODE上查看代碼片派生到我的代碼片
  1. private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {  
  2.   public boolean dispatchKeyEvent(KeyEvent event) {  
  3.     final Callback cb = getCallback();  
  4.     //cb爲應用程序MainActivity  
  5.     final boolean handled = 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在CODE上查看代碼片派生到我的代碼片
  1. public boolean dispatchKeyEvent(KeyEvent event) {   
  2.   return super.dispatchKeyEvent(event);  
  3. }  

應用程序Activity在分發給與之關聯的某個View,如果這個View沒有處理、最終交給該Activity自己處理。

應用程序有關View的設置:

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. private Dialog mMenuWin;  
  2. mMenuWin = new Dialog(aActivity, R.style.CameraDialog);  
  3. mMenuWin.setContentView(mMenuLayout);  
  4. mMenuWin.setOnClickListener();  //鼠標單擊  
  5. mMenuWin.setOnLongClickListener();  //  
  6. mMenuWin.setOnTouchListener(); //觸摸板  
  7. mMenuWin.setOnKeyListener(new OnKeyListener() {  
  8.   public boolean onKey();  //按鍵  
  9.   public void onClick(View v); //鼠標單擊  
  10. }  

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

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public boolean dispatchKeyEvent(KeyEvent event) {  
  2.   onUserInteraction();  
  3.   Window win = getWindow();  
  4.   if (win.superDispatchKeyEvent(event)) { //首先由Window消化,即如果View消化了、則Activity將不在回調onKeyDown  
  5.     return true;  
  6.   }  
  7.   View decor = mDecor; //如果沒被消化,會調用Activity的onKeyDown  
  8.   if (decor == null) decor = win.getDecorView();  
  9.     return event.dispatch(this, decor != null ? decor.getKeyDispatcherState() : nullthis);  
  10.   }  
  11. }  

我們重點分析win.superDispatchKeyEvent,也就是View的處理流程:

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

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public class PhoneWindow extends Window implements MenuBuilder.Callback {  
  2.   public boolean superDispatchKeyEvent(KeyEvent event) {  
  3.     return mDecor.superDispatchKeyEvent(event);  
  4.   }  
  5. }  
  6. private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {  
  7.   public boolean superDispatchKeyEvent(KeyEvent event) {        
  8.     super.dispatchKeyEvent(event)  
  9.   }  
  10. }  
frameworks/base/core/java/android/view/ViewGroup.java  //分發給View的關鍵部分!!!
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public boolean dispatchKeyEvent(KeyEvent event) {  
  2.   mInputEventConsistencyVerifier.onKeyEvent(event, 1);  
  3.   super.dispatchKeyEvent(event)  
  4. }  

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

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public boolean dispatchKeyEvent(KeyEvent event) {  
  2.   li.mOnKeyListener.onKey(this, event.getKeyCode(), event); //回調應用程序View相應方法  
  3.   event.dispatch(this, mAttachInfo != null ? mAttachInfo.mKeyDispatchState : nullthis)  
  4.   /* 
  5.   frameworks/base/core/java/android/view/KeyEvent.java 
  6.   public final boolean dispatch(Callback receiver, DispatcherState state, 
  7.     Object target) {   
  8.     //按鍵響應 
  9.     boolean res = receiver.onKeyDown(mKeyCode, this); //應用程序回調函數 
  10.   } 
  11.   */  
  12. }  
  13. public final boolean dispatchPointerEvent(MotionEvent event) {  
  14.   if (event.isTouchEvent()) {  
  15.     return dispatchTouchEvent(event);  
  16.   } else {  
  17.     return dispatchGenericMotionEvent(event);  
  18.   }  
  19. }  
  20. public boolean dispatchTouchEvent(MotionEvent event) {  
  21.   //觸摸板響應  
  22.   li.mOnTouchListener.onTouch(this, event) //應用程序繼承OnTouchListener,實現的回調接口  
  23.   //鼠標左鍵響應  
  24.   onTouchEvent(event)  
  25.   /* 
  26.   public boolean onTouchEvent(MotionEvent event) { 
  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

  1. void InputReader::loopOnce() {  
  2.   size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
  3.   /* 
  4.   frameworks/base/services/input/EventHub.cpp 
  5.   size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { 
  6.     int32_t readSize = read(device->fd, readBuffer, 
  7.       sizeof(struct input_event) * capacity);//從驅動讀取事件 
  8.   } 
  9.   */  
  10.   processEventsLocked(mEventBuffer, count);  
  11. }  
  12. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {  
  13.   case EventHubInterface::FINISHED_DEVICE_SCAN:  
  14.     handleConfigurationChangedLocked(rawEvent->when);  
  15. }  
  16. void InputReader::handleConfigurationChangedLocked(nsecs_t when) {  
  17.   updateGlobalMetaStateLocked();  
  18.   // Enqueue configuration changed.  
  19.   NotifyConfigurationChangedArgs args(when);  
  20.   mQueuedListener->notifyConfigurationChanged(&args);  
  21. }  

說明:有的平臺需要在接入硬件鍵盤時Activity不需要刷新;可以在上處做屏蔽:

  1. // add by tank  
  2. // do not send configuration change  
  3. //NotifyConfigurationChangedArgs args(when);  
  4. //mQueuedListener->notifyConfigurationChanged(&args);  
  5. // end tank  

2.InputReaderThread線程分發給InputDispatcherThread線程

frameworks/base/service/input/InputDispatcher.cpp

  1. void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {  
  2.   needWake = enqueueInboundEventLocked(newEntry);  
  3.   if (needWake) {  
  4.     mLooper->wake();  
  5.   }  
  6. }  
3.InputReaderThread線程收到消息並處理

frameworks/base/service/input/InputDispatcher.cpp

  1. bool InputDispatcherThread::threadLoop() {  
  2.   mDispatcher->dispatchOnce();  
  3.   return true;  
  4. }  
  5. void InputDispatcher::dispatchOnce() {  
  6.   dispatchOnceInnerLocked(&nextWakeupTime);  
  7. }  
  8. void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {  
  9.   case EventEntry::TYPE_CONFIGURATION_CHANGED: {  
  10.     ConfigurationChangedEntry* typedEntry =  
  11.                 static_cast<ConfigurationChangedEntry*>(mPendingEvent);  
  12.   done = dispatchConfigurationChangedLocked(currentTime, typedEntry);  
  13.   }  
  14. }  
  15. bool InputDispatcher::dispatchConfigurationChangedLocked(  
  16.         nsecs_t currentTime, ConfigurationChangedEntry* entry) {  
  17.   CommandEntry* commandEntry = postCommandLocked(  
  18.             & InputDispatcher::doNotifyConfigurationChangedInterruptible);  
  19. }  
  20. void InputDispatcher::doNotifyConfigurationChangedInterruptible(  
  21.         CommandEntry* commandEntry) {  
  22.   mPolicy->notifyConfigurationChanged(commandEntry->eventTime);  
  23. }  
如上,不再做分析:

frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp

  1. void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {  
  2.   env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConfigurationChanged, when);  
  3. }  
frameworks/base/services/java/com/android/server/input/InputManagerService.cpp
  1. private void notifyConfigurationChanged(long whenNanos) {  
  2.   mWindowManagerCallbacks.notifyConfigurationChanged();  
  3. }  
如上,不再做分析:

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

  1. public void notifyConfigurationChanged() {  
  2.   mService.sendNewConfiguration();  
  3. }  
frameworks/base/service/java/com/android/server/wm/WindowManagerService.java
  1. void sendNewConfiguration() {  
  2.   mActivityManager.updateConfiguration(null);  
  3.   /* 
  4.   mActivityManager = ActivityManagerNative.getDefault(); 
  5.   frameworks/base/core/java/android/app/ActivityManagerNative.java 
  6.   static public IActivityManager getDefault() { 
  7.     return gDefault.get(); 
  8.   } 
  9.   private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { 
  10.     IBinder b = ServiceManager.getService("activity"); 
  11.     IActivityManager am = asInterface(b); 
  12.     return am; 
  13.   } 
  14.   frameworks/base/services/java/com/android/server/am/ActivityManagerService.java 
  15.   public static void setSystemProcess() { 
  16.     ActivityManagerService m = mSelf; 
  17.     ServiceManager.addService("activity", m, true); 
  18.   } 
  19.   */  
  20. }  
4.交由ActivityManagerService進程處理

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

  1. public void updateConfiguration(Configuration values) {  
  2.   updateConfigurationLocked(values, null, falsefalse);  
  3. }  
  4. boolean updateConfigurationLocked(Configuration values,  
  5.             ActivityRecord starting, boolean persistent, boolean initLocale) {  
  6.   kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);  
  7.   public void setWindowManager(WindowManagerService wm) {  
  8.     mWindowManager = wm;  
  9.   }  
  10. }  
frameworks/base/services/java/com/android/server/am/ActivityStack.java
  1. final boolean ensureActivityConfigurationLocked(ActivityRecord r,  
  2.             int globalChanges) {  
  3.   //一般會重啓Activity  
  4.   if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {  
  5.     relaunchActivityLocked(r, r.configChangeFlags, false);  
  6.     return false;  
  7.   }  
  8.   //應用程序AndroidMenifest中寫標記將不會重啓  
  9.   r.app.thread.scheduleActivityConfigurationChanged(r.appToken);  
  10. }  
frameworks/base/core/java/android/app/ActivityThread.java
  1. public void scheduleActivityConfigurationChanged(IBinder token) {  
  2.   queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);  
  3. }  
  4. //消息循環同上,不再分析  
  5. public void handleMessage(Message msg) {  
  6.   case ACTIVITY_CONFIGURATION_CHANGED:  
  7.     handleActivityConfigurationChanged((IBinder)msg.obj);  
  8. }  
  9. final void handleActivityConfigurationChanged(IBinder token) {  
  10.   performConfigurationChanged(r.activity, mCompatConfiguration);  
  11. }  
  12. private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {  
  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

  1. final boolean resumeTopActivityLocked(ActivityRecord prev) {  
  2.   return resumeTopActivityLocked(prev, null);  
  3. }  
  4. final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {  
  5.   Configuration config = 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

  1. public Configuration updateOrientationFromAppTokens(  
  2.             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {  
  3.   config = updateOrientationFromAppTokensLocked(currentConfig,  
  4.                     freezeThisOneIfNeeded);  
  5. }  
  6. private Configuration updateOrientationFromAppTokensLocked(  
  7.             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {  
  8.   computeScreenConfigurationLocked(mTempConfiguration)  
  9. }  
  10. boolean computeScreenConfigurationLocked(Configuration config) {  
  11.   if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) {  
  12.     //change by tank  
  13.     config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;  
  14.     //config.touchscreen = Configuration.TOUCHSCREEN_FINGER;  
  15.     //end tank  
  16.   }  
  17.   else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD  
  18.                              && config.navigation == Configuration.NAVIGATION_NONAV) {  
  19.     //change by tank  
  20.     //config.navigation = Configuration.NAVIGATION_DPAD;  
  21.     //navigationPresence |= presenceFlag;  
  22.     //end tank  
  23.   }  
  24.   if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {  
  25.     //change by tank  
  26.     //config.keyboard = Configuration.KEYBOARD_QWERTY;  
  27.     //keyboardPresence |= presenceFlag;  
  28.     //end tank  
  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

  1. void InputDispatcher::enqueueDispatchEntryLocked(  
  2.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,  
  3.         int32_t dispatchMode)   
  4. {  
  5.   if (!connection->inputState.trackKey(keyEntry,  
  6.                 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)/*add by [email protected] end */ || (dispatchEntry->resolvedFlags == 0x28))     
  7.   {  
  8.     #if DEBUG_DISPATCH_CYCLE  
  9.     ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",  
  10.                     connection->getInputChannelName());  
  11.     #endif  
  12.     delete dispatchEntry;  
  13.     return// skip the inconsistent event  
  14.   }  
  15.   /* 
  16.   //add by tankai 
  17.   if(dispatchEntry->resolvedFlags == 0x28 && keyEntry->deviceId == 3){ 
  18.     ALOGD("TK--------->>>delete sim KeyMementos up\n"); 
  19.     delete dispatchEntry; 
  20.     return; // skip the inconsistent event 
  21.   } 
  22.   //end tankai 
  23.   */  
  24. }  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章