Android R 激活Settings里面的息屏休眠, 最前台运行的Activity生命周期 ->onPause->onStop
adb shell dumpsys window policy //获取PhoneWindowManager的dump信息
...
bootCompleted=true
screenState=SCREEN_STATE_ON /SCREEN_STATE_OFF
interactiveState=INTERACTIVE_STATE_AWAKE /INTERACTIVE_STATE_SLEEP
...
case A.不使用屏保
当设备超过设定的时间后,进入SCREEN_STATE_OFF状态,最前台运行的Activity生命周期 ->onPause->onStop.
那到底是谁让Activity进入了onStop状态?
跟踪代码发现:
/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
// Called on the DisplayManager's DisplayPowerController thread.
@Override
public void screenTurnedOff() {
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
updateScreenOffSleepToken(true);
mDefaultDisplayPolicy.screenTurnedOff();
synchronized (mLock) {
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onScreenTurnedOff();
}
}
mDefaultDisplayRotation.updateOrientationListener();
reportScreenStateToVrManager(false);
}
// Called on the DisplayManager's DisplayPowerController thread.
@Override
public void screenTurningOn(final ScreenOnListener screenOnListener) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */);
updateScreenOffSleepToken(false);
mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
...
}
//SCREEN_STATE_OFF 时调用screenTurnedOff(..),这个函数里面有updateScreenOffSleepToken(true)
// TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
private void updateScreenOffSleepToken(boolean acquire) {
if (acquire) {
mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY);
} else {
mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY);
}
}
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
//SleepTokenAcquirer是ActivityTaskManagerService的内部类
final class SleepTokenAcquirerImpl implements ActivityTaskManagerInternal.SleepTokenAcquirer {
private final String mTag;
private final SparseArray<RootWindowContainer.SleepToken> mSleepTokens =
new SparseArray<>();
SleepTokenAcquirerImpl(@NonNull String tag) {
mTag = tag;
}
@Override
public void acquire(int displayId) {
synchronized (mGlobalLock) {
if (!mSleepTokens.contains(displayId)) {
mSleepTokens.append(displayId,
mRootWindowContainer.createSleepToken(mTag, displayId));
//调用ActivityTaskManagerService的updateSleepIfNeededLocked方法对resume的Activity进行pause
updateSleepIfNeededLocked();
}
}
}
@Override
public void release(int displayId) {
synchronized (mGlobalLock) {
final RootWindowContainer.SleepToken token = mSleepTokens.get(displayId);
if (token != null) {
mRootWindowContainer.removeSleepToken(token);
mSleepTokens.remove(displayId);
}
}
}
}
1.(息屏)在获取了SleepToken后,会将resume的Activity进入pause状态.如下:
SleepTokenAcquirerImpl::acquire()
--->
RootWindowContainer::createSleepToken()->ActivityTaskManagerService::updateSleepIfNeededLocked()
--->
ActivityStackSupervisor::goingToSleepLocked()
--->
ActivityStackSupervisor::checkReadyForSleepLocked()
--->
RootWindowContainer::putStacksToSleep()
--->
ActivityStack::goToSleepIfPossible()
--->
ActivityStack::startPausingLocked()
2.(亮屏)在释放了SleepToken后,如果此时没有SleepToken了,并且也没有keyguard,会对前台Activity进行resume.
SleepTokenAcquirerImpl::release()
--->
RootWindowContainer::removeSleepToken()
--->
ActivityTaskManagerService::updateSleepIfNeededLocked()
--->
RootWindowContainer::applySleepTokens()
--->
ActivityStack::resumeTopActivityUncheckedLocked()
如果不想设备当前Activity被pause,如下:
+++ b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4708,7 +4708,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void screenTurnedOff() {
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
- updateScreenOffSleepToken(true);
+ //updateScreenOffSleepToken(true);
mDefaultDisplayPolicy.screenTurnedOff();
synchronized (mLock) {
cast B.使用屏保(com.android.deskclock/android.service.dreams.DreamActivity)
前台Activity --->App A
com.android.deskclock/android.service.dreams.DreamActivity ---> App B
App A 被 App B 挤下去了,当前App A不在栈顶(前台)时,App A就会执行on Pause流程
SleepToken
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
//SleepToken是RootWindowContainer的内部类
static final class SleepToken {
private final String mTag;
private final long mAcquireTime;
private final int mDisplayId;
final int mHashKey;
SleepToken(String tag, int displayId) {
mTag = tag;
mDisplayId = displayId;
mAcquireTime = SystemClock.uptimeMillis();
mHashKey = makeSleepTokenKey(mTag, mDisplayId);
}
@Override
public String toString() {
return "{\"" + mTag + "\", display " + mDisplayId
+ ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
}
}