相关文章:
[Android Framework] 8.1 PowerManagerService分析(一)——PMS的启动
[Android Framework] 8.1 PowerManagerService分析(二) ——updatePowerStateLocked()方法
[Android Framework] 8.1 PowerManagerService分析(三)——WakeLock机制
[Android Framework] 8.1 PowerManagerService分析(四)——亮屏流程分析
前言
在之前的PMS文章分析中知道,PMS中定义了四种屏幕状态:
- Awake状态:表示唤醒状态
- Dream状态:表示处于屏保状态
- Doze状态:表示处于Doze状态
- Asleep状态:表示处于休眠状态
Power键灭屏
当power键灭屏时,会在PhoneWindowManager中处理按键事件后,调用到PMS的gotoSleep()
进行灭屏处理,下面直接看看PhoneWindowManger中对Power键灭屏的处理以及和PMS的交互。
在按power后,PWS中如下:
case KeyEvent.KEYCODE_POWER: {
// Any activity on the power button stops the accessibility shortcut
cancelPendingAccessibilityShortcutAction();
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
//按下时
//处理按下事件
interceptPowerKeyDown(event, interactive);
} else //抬起时
//处理抬起事件
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
在处理Power键抬起事件时,开始了灭屏流程:
private void powerPress(long eventTime, boolean interactive, int count) {
if (mScreenOnEarly && !mScreenOnFully) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
return;
}
if (count == 2) {
......
} else if (interactive && !mBeganFromNonInteractive) {
switch (mShortPressOnPowerBehavior) {
//灭屏
case SHORT_PRESS_POWER_GO_TO_SLEEP:
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
break;
//灭屏,直接跳过Doze状态
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
break;
} else {
shortPressPowerGoHome();
}
break;
}
}
}
}
在这里调用了goToSleep()
方法,该方法如下:
private void goToSleep(long eventTime, int reason, int flags) {
mRequestedOrGoingToSleep = true;
mPowerManager.goToSleep(eventTime, reason, flags);
}
最终,PhoneWindowManager中调用了PowerManager的goToSleep()
方法来灭屏。
现在我们进入到PowerManager.goToSleep()方法:
public void goToSleep(long time, int reason, int flags) {
try {
mService.goToSleep(time, reason, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
可以看到,在PowerManger中开始向下调用到了PoweManagerService(以下简称PMS)中的goToSleep()
中。
我们进入PMS中,就需要详细分析其中的方法了,先来看看goToSleep()方法:
/**
* @param eventTime 时间
* @param reason 原因,Power键灭屏则是owerManager.GO_TO_SLEEP_REASON_POWER_BUTTON
* @param flags 目前只有两个值:0和1(GO_TO_SLEEP_FLAG_NO_DOZE)
*/
@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
//检查权限
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
//调用gotToSleepInternal
goToSleepInternal(eventTime, reason, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
这个方法的参数和PowerManager,PhoneWindowManager中的同名方法对应,需要注意的是第二个参数和第三个参数;
第二个参数:表示灭屏原因,在PowerManager中定义了一些常量值来表示;
第三个参数:是一个标识,用来表示是否直接进入灭屏,一般的灭屏流程,都会先进入Doze状态,然后才会进入Sleep状态,如果将flag设置为1,则将会直接进入Sleep状态,这部分会在下文中逐渐分析到。
在goToSleep()方法中,检查权限之后,开始调用了goToSleepInternal()方法,该方法如下:
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
synchronized (mLock) {
if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
updatePowerStateLocked();
}
}
}
这个方法逻辑很简单,首先是调用了goToSleepNoUpdateLocked()
方法,并根据该方法返回值来决定是否调用updatePowerStateLocked()
方法。
一般来说,goToSleepNoUpdateLocked()都会返回true,现在看看该方法:
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime