本文是基于android 5.0的源码来分析的:
当长按power键来进行关机操作时,按键信息会被分发到PhoneWindowManager.java的interceptKeyBeforeQueueing来进行处理:
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
……
case KeyEvent.KEYCODE_POWER:{
result &= ~ACTION_PASS_TO_USER;
if (down) {
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
if (panic) {
mHandler.post(mRequestTransientNav);
}
if (interactive && !mPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mPowerKeyTriggered = true;
mPowerKeyTime = event.getDownTime();
interceptScreenshotChord();//抓屏
}
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
telecomManager.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
&& telecomManager.isInCall() && interactive) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
hungUp = telecomManager.endCall();
}
}
mIsScreenOn = isScreenOn();
Log.d(TAG,"interceptPowerKeyDown:" + !interactive + ":" + hungUp + ":" +
mVolumeDownKeyTriggered + ":" + mVolumeUpKeyTriggered);
interceptPowerKeyDown(!interactive || hungUp
|| mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
} else {
mPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
// added for can't suspend issue
Log.d(TAG, "interceptPowerKeyUp:" + canceled + ":" + mPendingPowerKeyUpCanceled);
if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
if (mScreenOnEarly && !mScreenOnFully) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
} else {
powerShortPress(event.getEventTime());
}
isWakeKey = false;
}
mPendingPowerKeyUpCanceled = false;
}
break;
}
……
}
interceptKeyBeforeQueueing方法主要做一些对特殊按键的处理,上面的代码包行了长按电源键时间的处理,如静默来电铃声,屏幕截图,系统将根据电源键按下的时间长短和相关按键的使用情况来恰当的处理当前的用户操作这里可以看到当电源键按下时做一些处理,当电源键按下且没有截屏操作触发时interceptPowerKeyDown将会被调用,这时其他的按键响应(其他按键响应指interceptKeyBeforeQueueing的cases)将不会被触发。
private void interceptPowerKeyDown(boolean handled) {
mPowerKeyHandled = handled;
if (!handled) {
mOnlyShowFlashlight = false;
mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
} else if (!mIsScreenOn) {
mPowerKeyHandled = mIsScreenOn;
mOnlyShowFlashlight = true;
Log.d("FlashLight",
"PhoneWindowManager........interceptePowerKeyDown, we will run mPowerLongPress");
mHandler.postDelayed(mPowerLongPress, 1500);
}
}
interceptPowerKeyDown函数将注册一个回调函数,在500ms超时事件ViewConfiguration.getGlobalActionKeyTimeout()