interceptKeyBeforeQueueing
Framework任何按键的上报都在PhoneWindowManager 中 interceptKeyBeforeQueueing 这里开始,power 键也是如此,而且interceptKeyBeforeQueueing的 会对一些特殊的按键进行处理,其中就有power 键
先看下这函数的一些官方注解,在
frameworks\base\services\core\java\com\android\server\wm\InputMonitor.java
/* Provides an opportunity for the window manager policy to intercept early key
* processing as soon as the key has been read from the device. */
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
/* Provides an opportunity for the window manager policy to intercept early motion event
* processing when the device is in a non-interactive state since these events are normally
* dropped. */
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
whenNanos, policyFlags);
}
/* Provides an opportunity for the window manager policy to process a key before
* ordinary dispatch. */
@Override
public long interceptKeyBeforeDispatching(
InputWindowHandle focus, KeyEvent event, int policyFlags) {
WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
}
/* Provides an opportunity for the window manager policy to process a key that
* the application did not handle. */
@Override
public KeyEvent dispatchUnhandledKey(
InputWindowHandle focus, KeyEvent event, int policyFlags) {
WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
}
另外需要注意到这个函数中interceptKeyBeforeQueueing 的 result = ACTION_PASS_TO_USER;
/**
* Pass this event to the user / app. To be returned from
* {@link #interceptKeyBeforeQueueing}.
*/
public final static int ACTION_PASS_TO_USER = 0x00000001;
这个标志位标识是否将按键进一步往上传递到 interceptKeyBeforeDispatching 等等…,之前有一次调试的时候在这里拦截power 键后没有操作这个flag 导致往上interceptKeyBeforeDispatching 还能收到案件消息
回到 interceptKeyBeforeQueueing 这里面对power 键会调用
private void interceptPowerKeyDown(KeyEvent event, boolean interactive)
和 interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled)
interceptPowerKeyDown
有个逻辑是判断是否进入长按流程
if ((hasLongPressOnPowerBehavior() ....)) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
通过 MSG_POWER_LONG_PRESS 这个hanlder msg 的调用时走到 powerLongPress();
而 powerLongPress(); 中会根据配置的对应长按模式进行对应的处理
private void powerLongPress() {
final int behavior = getResolvedLongPressOnPowerBehavior();
switch (behavior) {
case LONG_PRESS_POWER_NOTHING:
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
performAuditoryFeedbackForAccessibilityIfNeed();
}
showGlobalActionsInternal();
break;
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
break;
}
}
interceptPowerKeyUp
主要是调用
powerPress(eventTime, interactive, mPowerKeyPressCounter);
// Done. Reset our state.
finishPowerKeyPress();
而power press 中会根据配置的对应短按模式进行相应的处理
switch (mShortPressOnPowerBehavior) {
case SHORT_PRESS_POWER_NOTHING:
break;
case SHORT_PRESS_POWER_GO_TO_SLEEP:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
launchHomeFromHotKey();
那么如何修改这些配置呢
其配置流程是在PhoneWindowManager init函数的时候配置的
mShortPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shortPressOnPowerBehavior);
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
这些config的修改是在
frameworks/base/core/res/res/values/config.xml
以Android 7.1 为例,其配置值对应的模式为
static final int SHORT_PRESS_POWER_NOTHING = 0;
static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
static final int SHORT_PRESS_POWER_GO_HOME = 4;
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;