按键的处理主要由InputManagerService负责,属于Android输入系统的流程。在这篇博客里,我们只关注与Power键相关的内容。InputManagerService处理的按键事件,最终将会传递到PhoneWindowManager的interceptKeyBeforeQueueing函数。
我们就从这个函数开始,逐步进行分析。
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
return 0;
}
//表示屏幕是否点亮
final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
//按键对应的编码
final int keyCode = event.getKeyCode();
.................
switch (keyCode) {
...........
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
//处理按下Power键
interceptPowerKeyDown(event, interactive);
} else {
//处理松开Power键
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
}
..............
if (isWakeKey) {
//按power键时,isWakeKey置为false,于是不会调用wakeUp函数
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
接下来,我们分别看一下interceptPowerKeyDown和interceptPowerKeyUp函数。
一、interceptPowerKeyDown
interceptPowerKeyDown用于处理按下Power键(还未松手释放)对应的事件。
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
// mPowerKeyWakeLock为PARTIAL_WAKE_LOCK级别的锁
if (!mPowerKeyWakeLock.isHeld()) {
//将调用到PMS的acquire WakeLock流程
mPowerKeyWakeLock.acquire();
}
// Cancel multi-press detection timeout.
//处理多次按power键的场景
//每次power up时,发送MSG_POWER_DELAYED_PRESS的延迟消息
//如果延迟消息被处理,说明一次完整的Power键处理结束(按下去,弹起来)
//在延迟消息被处理前,再次按power键,就检测到多次点击了
//实际上,原生终端不支持该场景
if (mPowerKeyPressCounter != 0) {
mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
}
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
// 从注释来看及mHiddenNavPanic的代码,觉得像是处理“误触”的
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
if (panic) {
mHandler.post(mHiddenNavPanic);
}
// Latch power key state to detect screenshot chord.
// 如果当前是亮屏状态,且满足触发截屏的条件,触发截屏功能
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBA