Android4.1中会被系统拦截的InputEent

来源:互联网 发布:淘宝上活动技巧 编辑:程序博客网 时间:2024/06/05 09:33

http://blog.csdn.net/siobhan/article/details/8132663


1. InputDispatcher::notifyKey

     如果系统发现一个Event是KeyEvent, 会调用nofityKey去通知收到一个KeyEvent. 在notifyKey中会查看policy的策略。 

     mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);  //mPolicy实际上就是 NativeInputManager。  当这个函数执行后会把对应的policy也设置到poicyFlags里面。

    

2. NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) 

     NativeInputManager是一个JNI类,自己不做什么工作,只是通过env->CallIntMethod(mServiceObj, gServiceClassInfo.interceptKeyBeforeQueueing, keyEventObj, policyFlags, isScreenOn); 去调用Java的interceptKeyBeforeQueueing方法。 实际上就是调用 InputManagerService.interceptKeyBeforeQueueing()


3. InputManagerService.interceptKeyBeforeQueueing()

[java] view plaincopy
  1. // Native callback.  
  2. private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {  
  3.     return mCallbacks.interceptKeyBeforeQueueing(  
  4.             event, policyFlags, isScreenOn);  
  5. }  
   可以看到里面只是调用了回到函数而已,而mCallbacks就是InputMoniter.java

4. InputMoniter.interceptKeyBeforeQueueing()

[java] view plaincopy
  1. /* Provides an opportunity for the window manager policy to intercept early key 
  2.  * processing as soon as the key has been read from the device. */  
  3. public int interceptKeyBeforeQueueing(  
  4.         KeyEvent event, int policyFlags, boolean isScreenOn) {  
  5.         Slog.d("InputMonitor.java""interceptKeyBeforeQueueing !!!!!!");  
  6.         return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);  
  7. }  

5. mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);

[java] view plaincopy
  1. // Native callback.  
  2. private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {  
  3.     Slog.d("InputManagerService.java""interceptKeyBeforeQueueing !!!!!!!!!!!!!!");  
  4.     return mCallbacks.interceptKeyBeforeQueueing(  
  5.             event, policyFlags, isScreenOn);  
  6. }  
    InputMoniter.interceptKeyBeforeQueueing()中就是直接调了mService.mPolicy.interceptKeyBeforeQueueing, mService是WindowManagerService, mPolicy是PhoneWindowManager. 简而言之就是会去直走到PhoneWindowManager中。


6. PhoneWindowManager.interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) 

    

     代码很长,需要慢慢分析。


7.  InputDispatcher::dispatchKeyLocked

     当InputDispatcher::notifyKey 完成之后,InputDispatcher就会调用dispatchKeyLocked去做进一步的分配。

      一个Event过来都是通过InputDispatcher进行分发的,在dispatchKeyLocked中会调用 InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible 去

     

[cpp] view plaincopy
  1. bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,  
  2.         DropReason* dropReason, nsecs_t* nextWakeupTime) {  
  3.     // Preprocessing.  
  4.     // Give the policy a chance to intercept the key.  
  5.     if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {  
  6.         if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {  
  7.             CommandEntry* commandEntry = postCommandLocked(  
  8.                     & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);  
  9.         ... ...  
  10.         } else {  
  11.             entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;  
  12.         }  
  13.     } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {  
  14.         ... ...  
  15.     }  
  16.   
  17.   
  18.     // Dispatch the key.  
  19.     dispatchEventLocked(currentTime, entry, inputTargets);  
  20.     return true;  
  21. }  

8. InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible

    在这个函数中哦你依旧还是通过mPolicy(NativeInputManager)去通过JNI调用InputManagerService. 

[cpp] view plaincopy
  1. void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(  
  2.         CommandEntry* commandEntry) {  
  3.     ... ...  
  4.     nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,  
  5.             &event, entry->policyFlags);  
  6.   
  7.     mLock.lock();  
  8.   
  9.     if (delay < 0) {  
  10.         entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;  
  11.     } else if (!delay) {  
  12.         entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;  
  13.     } else {  
  14.         entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;  
  15.         entry->interceptKeyWakeupTime = now() + delay;  
  16.     }  
  17.     entry->release();  
  18. }  

 9. NativeInputManager::interceptKeyBeforeDispatching

[cpp] view plaincopy
  1. nsecs_t NativeInputManager::interceptKeyBeforeDispatching(  
  2.         const sp<InputWindowHandle>& inputWindowHandle,  
  3.         const KeyEvent* keyEvent, uint32_t policyFlags) {  
  4.     // Policy:  
  5.     // - Ignore untrusted events and pass them along.  
  6.     // - Filter normal events and trusted injected events through the window manager policy to  
  7.     //   handle the HOME key and the like.  
  8.     nsecs_t result = 0;  
  9.     if (policyFlags & POLICY_FLAG_TRUSTED) {  
  10.     
  11.         jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);  
  12.         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);  
  13.         if (keyEventObj) {  
  14.             jlong delayMillis = env->CallLongMethod(mServiceObj,  
  15.                     gServiceClassInfo.interceptKeyBeforeDispatching,  
  16.                     inputWindowHandleObj, keyEventObj, policyFlags);  
  17.               
  18.         }   
  19.         env->DeleteLocalRef(inputWindowHandleObj);  
  20.     }  
  21.     return result;  
  22. }  

 10. InputManagerService.intercepKeyBeforeDispatching()
[java] view plaincopy
  1. // Native callback.  
  2. private long interceptKeyBeforeDispatching(InputWindowHandle focus,  
  3.         KeyEvent event, int policyFlags) {  
  4.     return mCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);  
  5. }  

11. InputMonitor.interceptKeyBeforeDispatching()

[java] view plaincopy
  1. /* Provides an opportunity for the window manager policy to process a key before 
  2.  * ordinary dispatch. */  
  3. public long interceptKeyBeforeDispatching(  
  4.         InputWindowHandle focus, KeyEvent event, int policyFlags) {  
  5.     Log.d("InputMonitor.java","interceptKeyBeforeDispatching !!!!!!");  
  6.     WindowState windowState = focus != null ? (WindowState) focus.windowState : null;  
  7.     return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);  
  8. }  


12. PhoneWondowManager.interceptKeyBeforeDispatching()
[java] view plaincopy
  1. public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {  
  2.      final boolean keyguardOn = keyguardOn();  
  3.      final int keyCode = event.getKeyCode();  
  4.      final int repeatCount = event.getRepeatCount();  
  5.      final int metaState = event.getMetaState();  
  6.      final int flags = event.getFlags();  
  7.      final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;  
  8.      final boolean canceled = event.isCanceled();  
  9.   
  10.      if (DEBUG_INPUT) {  
  11.          Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="  
  12.                  + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed  
  13.                  + " canceled=" + canceled);  
  14.      }  
  15.   
  16.      // If we think we might have a volume down & power key chord on the way  
  17.      // but we're not sure, then tell the dispatcher to wait a little while and  
  18.      // try again later before dispatching.  
  19.      if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {  
  20.          if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {  
  21.              final long now = SystemClock.uptimeMillis();  
  22.              final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;  
  23.              if (now < timeoutTime) {  
  24.                  return timeoutTime - now;  
  25.              }  
  26.          }  
  27.          if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN  
  28.                  && mVolumeDownKeyConsumedByScreenshotChord) {  
  29.              if (!down) {  
  30.                  mVolumeDownKeyConsumedByScreenshotChord = false;  
  31.              }  
  32.              return -1;  
  33.          }  
  34.      }  
  35.   
  36.      // First we always handle the home key here, so applications  
  37.      // can never break it, although if keyguard is on, we do let  
  38.      // it handle it, because that gives us the correct 5 second  
  39.      // timeout.  
  40.      if (keyCode == KeyEvent.KEYCODE_HOME) {  
  41.   
  42.          // If we have released the home key, and didn't do anything else  
  43.          // while it was pressed, then it is time to go home!  
  44.          if (!down) {  
  45.              final boolean homeWasLongPressed = mHomeLongPressed;  
  46.              mHomePressed = false;  
  47.              mHomeLongPressed = false;  
  48.              if (!homeWasLongPressed) {  
  49.                  try {  
  50.                      IStatusBarService statusbar = getStatusBarService();  
  51.                      if (statusbar != null) {  
  52.                          statusbar.cancelPreloadRecentApps();  
  53.                      }  
  54.                  } catch (RemoteException e) {  
  55.                      Slog.e(TAG, "RemoteException when showing recent apps", e);  
  56.                      // re-acquire status bar service next time it is needed.  
  57.                      mStatusBarService = null;  
  58.                  }  
  59.   
  60.                  mHomePressed = false;  
  61.                  if (!canceled) {  
  62.                      // If an incoming call is ringing, HOME is totally disabled.  
  63.                      // (The user is already on the InCallScreen at this point,  
  64.                      // and his ONLY options are to answer or reject the call.)  
  65.                      boolean incomingRinging = false;  
  66.                      try {  
  67.                          ITelephony telephonyService = getTelephonyService();  
  68.                          if (telephonyService != null) {  
  69.                              incomingRinging = telephonyService.isRinging();  
  70.                          }  
  71.                      } catch (RemoteException ex) {  
  72.                          Log.w(TAG, "RemoteException from getPhoneInterface()", ex);  
  73.                      }  
  74.   
  75.                      if (incomingRinging) {  
  76.                          Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");  
  77.                      } else {  
  78.                          launchHomeFromHotKey();  //launch home  
  79.                      }  
  80.                  } else {  
  81.                      Log.i(TAG, "Ignoring HOME; event canceled.");  
  82.                  }  
  83.                  return -1;  
  84.              }  
  85.          }  
  86.   
  87.          // If a system window has focus, then it doesn't make sense  
  88.          // right now to interact with applications.  
  89.          WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;  
  90.          if (attrs != null) {  
  91.              final int type = attrs.type;  
  92.              if (type == WindowManager.LayoutParams.TYPE_KEYGUARD  
  93.                      || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {  
  94.                  // the "app" is keyguard, so give it the key  
  95.                  return 0;  
  96.              }  
  97.              final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;  
  98.              for (int i=0; i<typeCount; i++) {  
  99.                  if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {  
  100.                      // don't do anything, but also don't pass it to the app  
  101.                      return -1;  
  102.                  }  
  103.              }  
  104.          }  
  105.          if (down) {  
  106.              if (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {  
  107.                  try {  
  108.                      IStatusBarService statusbar = getStatusBarService();  
  109.                      if (statusbar != null) {  
  110.                          statusbar.preloadRecentApps();  
  111.                      }  
  112.                  } catch (RemoteException e) {  
  113.                      Slog.e(TAG, "RemoteException when preloading recent apps", e);  
  114.                      // re-acquire status bar service next time it is needed.  
  115.                      mStatusBarService = null;  
  116.                  }  
  117.              }  
  118.              if (repeatCount == 0) {  
  119.                  mHomePressed = true;  
  120.              } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {  
  121.                  if (!keyguardOn) {  
  122.                      handleLongPressOnHome();  
  123.                  }  
  124.              }  
  125.          }  
  126.          return -1;  
  127.      } else if (keyCode == KeyEvent.KEYCODE_MENU) {  
  128.          // Hijack modified menu keys for debugging features  
  129.          final int chordBug = KeyEvent.META_SHIFT_ON;  
  130.   
  131.          if (down && repeatCount == 0) {  
  132.              if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {  
  133.                  Intent intent = new Intent(Intent.ACTION_BUG_REPORT);  
  134.                  mContext.sendOrderedBroadcast(intent, null);  
  135.                  return -1;  
  136.              } else if (SHOW_PROCESSES_ON_ALT_MENU &&  
  137.                      (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {  
  138.                  Intent service = new Intent();  
  139.                  service.setClassName(mContext, "com.android.server.LoadAverageService");  
  140.                  ContentResolver res = mContext.getContentResolver();  
  141.                  boolean shown = Settings.System.getInt(  
  142.                          res, Settings.System.SHOW_PROCESSES, 0) != 0;  
  143.                  if (!shown) {  
  144.                      mContext.startService(service);  
  145.                  } else {  
  146.                      mContext.stopService(service);  
  147.                  }  
  148.                  Settings.System.putInt(  
  149.                          res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);  
  150.                  return -1;  
  151.              }  
  152.          }  
  153.      } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {  
  154.          if (down) {  
  155.              if (repeatCount == 0) {  
  156.                  mSearchKeyShortcutPending = true;  
  157.                  mConsumeSearchKeyUp = false;  
  158.              }  
  159.          } else {  
  160.              mSearchKeyShortcutPending = false;  
  161.              if (mConsumeSearchKeyUp) {  
  162.                  mConsumeSearchKeyUp = false;  
  163.                  return -1;  
  164.              }  
  165.          }  
  166.          return 0;  
  167.      } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {  
  168.          if (down && repeatCount == 0 && !keyguardOn) {  
  169.              showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);  
  170.          }  
  171.          return -1;  
  172.      } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {  
  173.          if (down) {  
  174.              if (repeatCount == 0) {  
  175.                  mAssistKeyLongPressed = false;  
  176.              } else if (repeatCount == 1) {  
  177.                  mAssistKeyLongPressed = true;  
  178.                  if (!keyguardOn) {  
  179.                       launchAssistLongPressAction();  
  180.                  }  
  181.              }  
  182.          } else {  
  183.              if (mAssistKeyLongPressed) {  
  184.                  mAssistKeyLongPressed = false;  
  185.              } else {  
  186.                  if (!keyguardOn) {  
  187.                      launchAssistAction();  
  188.                  }  
  189.              }  
  190.          }  
  191.          return -1;  
  192.      }  
  193.   
  194.      // Shortcuts are invoked through Search+key, so intercept those here  
  195.      // Any printing key that is chorded with Search should be consumed  
  196.      // even if no shortcut was invoked.  This prevents text from being  
  197.      // inadvertently inserted when using a keyboard that has built-in macro  
  198.      // shortcut keys (that emit Search+x) and some of them are not registered.  
  199.      if (mSearchKeyShortcutPending) {  
  200.          final KeyCharacterMap kcm = event.getKeyCharacterMap();  
  201.          if (kcm.isPrintingKey(keyCode)) {  
  202.              mConsumeSearchKeyUp = true;  
  203.              mSearchKeyShortcutPending = false;  
  204.              if (down && repeatCount == 0 && !keyguardOn) {  
  205.                  Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);  
  206.                  if (shortcutIntent != null) {  
  207.                      shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  208.                      try {  
  209.                          mContext.startActivity(shortcutIntent);  
  210.                      } catch (ActivityNotFoundException ex) {  
  211.                          Slog.w(TAG, "Dropping shortcut key combination because "  
  212.                                  + "the activity to which it is registered was not found: "  
  213.                                  + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);  
  214.                      }  
  215.                  } else {  
  216.                      Slog.i(TAG, "Dropping unregistered shortcut key combination: "  
  217.                              + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));  
  218.                  }  
  219.              }  
  220.              return -1;  
  221.          }  
  222.      }  
  223.   
  224.      // Invoke shortcuts using Meta.  
  225.      if (down && repeatCount == 0 && !keyguardOn  
  226.              && (metaState & KeyEvent.META_META_ON) != 0) {  
  227.          final KeyCharacterMap kcm = event.getKeyCharacterMap();  
  228.          if (kcm.isPrintingKey(keyCode)) {  
  229.              Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,  
  230.                      metaState & ~(KeyEvent.META_META_ON  
  231.                              | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));  
  232.              if (shortcutIntent != null) {  
  233.                  shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  234.                  try {  
  235.                      mContext.startActivity(shortcutIntent);  
  236.                  } catch (ActivityNotFoundException ex) {  
  237.                      Slog.w(TAG, "Dropping shortcut key combination because "  
  238.                              + "the activity to which it is registered was not found: "  
  239.                              + "META+" + KeyEvent.keyCodeToString(keyCode), ex);  
  240.                  }  
  241.                  return -1;  
  242.              }  
  243.          }  
  244.      }  
  245.   
  246.      // Handle application launch keys.  
  247.      if (down && repeatCount == 0 && !keyguardOn) {  
  248.          String category = sApplicationLaunchKeyCategories.get(keyCode);  
  249.          if (category != null) {  
  250.              Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);  
  251.              intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  252.              try {  
  253.                  mContext.startActivity(intent);  
  254.              } catch (ActivityNotFoundException ex) {  
  255.                  Slog.w(TAG, "Dropping application launch key because "  
  256.                          + "the activity to which it is registered was not found: "  
  257.                          + "keyCode=" + keyCode + ", category=" + category, ex);  
  258.              }  
  259.              return -1;  
  260.          }  
  261.      }  
  262.   
  263.      // Display task switcher for ALT-TAB or Meta-TAB.  
  264.      if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {  
  265.          if (mRecentAppsDialogHeldModifiers == 0 && !keyguardOn) {  
  266.              final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;  
  267.              if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)  
  268.                      || KeyEvent.metaStateHasModifiers(  
  269.                              shiftlessModifiers, KeyEvent.META_META_ON)) {  
  270.                  mRecentAppsDialogHeldModifiers = shiftlessModifiers;  
  271.                  showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);  
  272.                  return -1;  
  273.              }  
  274.          }  
  275.      } else if (!down && mRecentAppsDialogHeldModifiers != 0  
  276.              && (metaState & mRecentAppsDialogHeldModifiers) == 0) {  
  277.          mRecentAppsDialogHeldModifiers = 0;  
  278.          showOrHideRecentAppsDialog(keyguardOn ? RECENT_APPS_BEHAVIOR_DISMISS :  
  279.                  RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);  
  280.      }  
  281.   
  282.      // Handle keyboard language switching.  
  283.      if (down && repeatCount == 0  
  284.              && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH  
  285.                      || (keyCode == KeyEvent.KEYCODE_SPACE  
  286.                              && (metaState & KeyEvent.META_CTRL_MASK) != 0))) {  
  287.          int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;  
  288.          mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);  
  289.          return -1;  
  290.      }  
  291.      if (mLanguageSwitchKeyPressed && !down  
  292.              && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH  
  293.                      || keyCode == KeyEvent.KEYCODE_SPACE)) {  
  294.          mLanguageSwitchKeyPressed = false;  
  295.          return -1;  
  296.      }  
  297.   
  298.      // Let the application handle the key.  
  299.      return 0;  
  300.  } 

原创粉丝点击