Android CM12.1(android5.1) 关机流程
一、总关机流程图
之前查资料时从网上找的,觉得很正确。就借用一下别人的劳动成果吧~
二、长按电源键准备关机
长按电源键是进入/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java进行处理。
按电源键时,被interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)截获
//特殊处理主要是针对在锁屏或者屏幕不亮的情况的下收到特殊的键值,
//如音量键或者wake键。wake键是指能够点亮屏幕的键时的操作
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;//policyFlags位决定系统按键(如HOME等是否需要由系统处理)
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
final int scanCode = event.getScanCode();
if (SystemProperties.getInt("sys.quickboot.enable", 0) == 1) {// quickboot模式,长按电源键不会关机,进入low-power状态??
//现在手里没有真机,等拿到测试机试试!!!!!
if (keyCode == KeyEvent.KEYCODE_POWER && !interactive) {//!interactive表示屏幕没有唤醒
if(down){
acquireQuickBootWakeLock();//唤醒手机屏幕
mHandler.postDelayed(mQuickBootPowerLongPress, mLongPressPoweronTime);
//mLongPressPoweronTime的时间后,调用mQuickBootPowerLongPress这个线程
} else {
releaseQuickBootWakeLock();//释放手机屏幕
mHandler.removeCallbacks(mQuickBootPowerLongPress);
}
}
// ignore this event
return 0;
}
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
//...............
// Basic policy based on interactive state.
int result;
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();//该变量与屏幕唤醒有关系
//...............
// Handle special keys.
switch (keyCode) {
//如果是音量down,音量up,和菜单键
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
//.............
}
case KeyEvent.KEYCODE_HOME:
if (down && !interactive && mHomeWakeScreen) {
isWakeKey = true;//isWakeKey按home键时唤醒屏幕
}
break;
//.............
case <span style="background-color: rgb(255, 255, 102);">KeyEvent.KEYCODE_POWER</span>: {//按电源键,进入这里
if (mTopFullscreenOpaqueWindowState != null &&
(mTopFullscreenOpaqueWindowState.getAttrs().privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0
&& mScreenOnFully){
return result;
}
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
<span style="background-color: rgb(255, 255, 51);">interceptPowerKeyDown</span>(event, interactive);//进入这个函数!
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
//.............
if (isWakeKey) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
}
return result;
}
通过判断KeyEvent.KEYCODE_POWER,进入interceptPowerKeyDown(event, interactive)这个函数。
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
if (!mPowerKeyWakeLock.isHeld()) {//如果屏幕是黑的,唤醒屏幕
mPowerKeyWakeLock.acquire();
}
// Cancel multi-press detection timeout.
if (mPowerKeyPressCounter != 0) {
mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);//MSG_POWER_DELAYED_PRESS里面有finishPowerKeyPress()的mPowerKeyPressCounter = 0;
}
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
if (panic && !WindowManagerPolicyControl.isImmersiveFiltersActive()) {
mHandler.post(mRequestTransientNav);//暂时的显示导航栏--返回之类的浮在界面底部的按钮,
//这些按钮一般是消失了,只有在滑动的时候出来
//找个测试机试试
}
// Latch power key state to detect screenshot chord.
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordPowerKeyTriggered = true;
mScreenshotChordPowerKeyTime = event.getDownTime();
interceptScreenshotChord();//可进入触发截屏的函数
}
// Stop ringing or end call if configured to do so when power is pressed.
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();//在通话中,如果电源键挂断电话的设置是真,
//那么按电源键就挂断电话
}
}
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
|| mScreenshotChordVolumeUpKeyTriggered;//貌似音量up或者音量down都能截屏,测试测试
if (!mPowerKeyHandled) {//如果电源键没有被处理
if (interactive)