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

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

1.服务端channel注册过程

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

[cpp]

  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

[cpp]

  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

[cpp]

  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

[cpp]

  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

[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

[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

[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 tank@tcl.com 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

[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线程被唤醒

[cpp]

  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

[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

[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

[cpp]

  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

[cpp]

  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

[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

[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

[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

[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

[cpp]

  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

[cpp]

  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机制请看下文:

[cpp]

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

///

[cpp]

  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]

  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]

  1. public boolean dispatchKeyEvent(KeyEvent event) {   

  2.   return super.dispatchKeyEvent(event);  

  3. }  

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

应用程序有关View的设置:

[java]

  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]

  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]

  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]

  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]

  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重启,见

三、Input设备与Activity关系

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

frameworks/base/service/input/InputReader.cpp

[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不需要刷新;可以在上处做屏蔽:

[cpp]

  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

[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

[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

[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

[cpp]

  1. private void notifyConfigurationChanged(long whenNanos) {  

  2.   mWindowManagerCallbacks.notifyConfigurationChanged();  

  3. }  

如上,不再做分析:

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

[cpp]

  1. public void notifyConfigurationChanged() {  

  2.   mService.sendNewConfiguration();  

  3. }  

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

[cpp]

  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

[cpp]

  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

[cpp]

  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

[cpp]

  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重启。

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

  原理以及解决部分:

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

[cpp]

  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

[cpp]

  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

[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 tank@tcl.com 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.   */