Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +57 −4 Original line number Diff line number Diff line Loading @@ -653,16 +653,25 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ volatile int mTopProcessState = ActivityManager.PROCESS_STATE_TOP; /** Whether to keep higher priority to launch app while device is sleeping. */ private volatile boolean mRetainPowerModeAndTopProcessState; /** The timeout to restore power mode if {@link #mRetainPowerModeAndTopProcessState} is set. */ private static final long POWER_MODE_UNKNOWN_VISIBILITY_TIMEOUT_MS = 1000; @Retention(RetentionPolicy.SOURCE) @IntDef({ POWER_MODE_REASON_START_ACTIVITY, POWER_MODE_REASON_FREEZE_DISPLAY, POWER_MODE_REASON_UNKNOWN_VISIBILITY, POWER_MODE_REASON_ALL, }) @interface PowerModeReason {} static final int POWER_MODE_REASON_START_ACTIVITY = 1 << 0; static final int POWER_MODE_REASON_FREEZE_DISPLAY = 1 << 1; /** @see UnknownAppVisibilityController */ static final int POWER_MODE_REASON_UNKNOWN_VISIBILITY = 1 << 2; /** This can only be used by {@link #endLaunchPowerMode(int)}.*/ static final int POWER_MODE_REASON_ALL = (1 << 2) - 1; Loading Loading @@ -4248,15 +4257,39 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } void startLaunchPowerMode(@PowerModeReason int reason) { if (mPowerManagerInternal == null) return; if (mPowerManagerInternal != null) { mPowerManagerInternal.setPowerMode(Mode.LAUNCH, true); } mLaunchPowerModeReasons |= reason; if ((reason & POWER_MODE_REASON_UNKNOWN_VISIBILITY) != 0) { if (mRetainPowerModeAndTopProcessState) { mH.removeMessages(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG); } mRetainPowerModeAndTopProcessState = true; mH.sendEmptyMessageDelayed(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG, POWER_MODE_UNKNOWN_VISIBILITY_TIMEOUT_MS); Slog.d(TAG, "Temporarily retain top process state for launching app"); } } void endLaunchPowerMode(@PowerModeReason int reason) { if (mPowerManagerInternal == null || mLaunchPowerModeReasons == 0) return; if (mLaunchPowerModeReasons == 0) return; mLaunchPowerModeReasons &= ~reason; if (mLaunchPowerModeReasons == 0) { if ((mLaunchPowerModeReasons & POWER_MODE_REASON_UNKNOWN_VISIBILITY) != 0) { boolean allResolved = true; for (int i = mRootWindowContainer.getChildCount() - 1; i >= 0; i--) { allResolved &= mRootWindowContainer.getChildAt(i).mUnknownAppVisibilityController .allResolved(); } if (allResolved) { mLaunchPowerModeReasons &= ~POWER_MODE_REASON_UNKNOWN_VISIBILITY; mRetainPowerModeAndTopProcessState = false; mH.removeMessages(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG); } } if (mLaunchPowerModeReasons == 0 && mPowerManagerInternal != null) { mPowerManagerInternal.setPowerMode(Mode.LAUNCH, false); } } Loading Loading @@ -5123,6 +5156,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final class H extends Handler { static final int REPORT_TIME_TRACKER_MSG = 1; static final int UPDATE_PROCESS_ANIMATING_STATE = 2; static final int END_POWER_MODE_UNKNOWN_VISIBILITY_MSG = 3; static final int FIRST_ACTIVITY_TASK_MSG = 100; static final int FIRST_SUPERVISOR_TASK_MSG = 200; Loading @@ -5146,6 +5180,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } break; case END_POWER_MODE_UNKNOWN_VISIBILITY_MSG: { synchronized (mGlobalLock) { mRetainPowerModeAndTopProcessState = false; endLaunchPowerMode(POWER_MODE_REASON_UNKNOWN_VISIBILITY); if (mTopApp != null && mTopProcessState == ActivityManager.PROCESS_STATE_TOP_SLEEPING) { // Restore the scheduling group for sleeping. mTopApp.updateProcessInfo(false /* updateServiceConnection */, false /* activityChange */, true /* updateOomAdj */, false /* addPendingTopUid */); } } } break; } } } Loading Loading @@ -5464,6 +5512,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @HotPath(caller = HotPath.OOM_ADJUSTMENT) @Override public int getTopProcessState() { if (mRetainPowerModeAndTopProcessState) { // There is a launching app while device may be sleeping, force the top state so // the launching process can have top-app scheduling group. return ActivityManager.PROCESS_STATE_TOP; } return mTopProcessState; } Loading services/core/java/com/android/server/wm/RootWindowContainer.java +20 −12 Original line number Diff line number Diff line Loading @@ -3545,14 +3545,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void startPowerModeLaunchIfNeeded(boolean forceSend, ActivityRecord targetActivity) { final boolean sendPowerModeLaunch; if (forceSend) { sendPowerModeLaunch = true; } else if (targetActivity == null || targetActivity.app == null) { // Set power mode if we don't know what we're launching yet. sendPowerModeLaunch = true; } else { if (!forceSend && targetActivity != null && targetActivity.app != null) { // Set power mode when the activity's process is different than the current top resumed // activity on all display areas, or if there are no resumed activities in the system. boolean[] noResumedActivities = {true}; Loading @@ -3568,13 +3561,28 @@ class RootWindowContainer extends WindowContainer<DisplayContent> !resumedActivityProcess.equals(targetActivity.app); } }); sendPowerModeLaunch = noResumedActivities[0] || allFocusedProcessesDiffer[0]; if (!noResumedActivities[0] && !allFocusedProcessesDiffer[0]) { // All focused activities are resumed and the process of the target activity is // the same as them, e.g. delivering new intent to the current top. return; } } if (sendPowerModeLaunch) { mService.startLaunchPowerMode( ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY); int reason = ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY; // If the activity is launching while keyguard is locked (including occluded), the activity // may be visible until its first relayout is done (e.g. apply show-when-lock flag). To // avoid power mode from being cleared before that, add a special reason to consider whether // the unknown visibility is resolved. The case from SystemUI is excluded because it should // rely on keyguard-going-away. if (mService.mKeyguardController.isKeyguardLocked() && targetActivity != null && !targetActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_SYSTEMUI)) { final ActivityOptions opts = targetActivity.getOptions(); if (opts == null || opts.getSourceInfo() == null || opts.getSourceInfo().type != ActivityOptions.SourceInfo.TYPE_LOCKSCREEN) { reason |= ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY; } } mService.startLaunchPowerMode(reason); } // TODO(b/191434136): handle this properly when we add multi-window support on secondary Loading services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +9 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,15 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { // The top app should not change while sleeping. assertEquals(topActivity.app, mAtm.mInternal.getTopApp()); mAtm.startLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY | ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY); assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState()); // Because there is no unknown visibility record, the state will be restored if other // reasons are all done. mAtm.endLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY); assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING, mAtm.mInternal.getTopProcessState()); // If all activities are stopped, the sleep wake lock must be released. final Task topRootTask = topActivity.getRootTask(); doReturn(true).when(rootHomeTask).goToSleepIfPossible(anyBoolean()); Loading Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +57 −4 Original line number Diff line number Diff line Loading @@ -653,16 +653,25 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ volatile int mTopProcessState = ActivityManager.PROCESS_STATE_TOP; /** Whether to keep higher priority to launch app while device is sleeping. */ private volatile boolean mRetainPowerModeAndTopProcessState; /** The timeout to restore power mode if {@link #mRetainPowerModeAndTopProcessState} is set. */ private static final long POWER_MODE_UNKNOWN_VISIBILITY_TIMEOUT_MS = 1000; @Retention(RetentionPolicy.SOURCE) @IntDef({ POWER_MODE_REASON_START_ACTIVITY, POWER_MODE_REASON_FREEZE_DISPLAY, POWER_MODE_REASON_UNKNOWN_VISIBILITY, POWER_MODE_REASON_ALL, }) @interface PowerModeReason {} static final int POWER_MODE_REASON_START_ACTIVITY = 1 << 0; static final int POWER_MODE_REASON_FREEZE_DISPLAY = 1 << 1; /** @see UnknownAppVisibilityController */ static final int POWER_MODE_REASON_UNKNOWN_VISIBILITY = 1 << 2; /** This can only be used by {@link #endLaunchPowerMode(int)}.*/ static final int POWER_MODE_REASON_ALL = (1 << 2) - 1; Loading Loading @@ -4248,15 +4257,39 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } void startLaunchPowerMode(@PowerModeReason int reason) { if (mPowerManagerInternal == null) return; if (mPowerManagerInternal != null) { mPowerManagerInternal.setPowerMode(Mode.LAUNCH, true); } mLaunchPowerModeReasons |= reason; if ((reason & POWER_MODE_REASON_UNKNOWN_VISIBILITY) != 0) { if (mRetainPowerModeAndTopProcessState) { mH.removeMessages(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG); } mRetainPowerModeAndTopProcessState = true; mH.sendEmptyMessageDelayed(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG, POWER_MODE_UNKNOWN_VISIBILITY_TIMEOUT_MS); Slog.d(TAG, "Temporarily retain top process state for launching app"); } } void endLaunchPowerMode(@PowerModeReason int reason) { if (mPowerManagerInternal == null || mLaunchPowerModeReasons == 0) return; if (mLaunchPowerModeReasons == 0) return; mLaunchPowerModeReasons &= ~reason; if (mLaunchPowerModeReasons == 0) { if ((mLaunchPowerModeReasons & POWER_MODE_REASON_UNKNOWN_VISIBILITY) != 0) { boolean allResolved = true; for (int i = mRootWindowContainer.getChildCount() - 1; i >= 0; i--) { allResolved &= mRootWindowContainer.getChildAt(i).mUnknownAppVisibilityController .allResolved(); } if (allResolved) { mLaunchPowerModeReasons &= ~POWER_MODE_REASON_UNKNOWN_VISIBILITY; mRetainPowerModeAndTopProcessState = false; mH.removeMessages(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG); } } if (mLaunchPowerModeReasons == 0 && mPowerManagerInternal != null) { mPowerManagerInternal.setPowerMode(Mode.LAUNCH, false); } } Loading Loading @@ -5123,6 +5156,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final class H extends Handler { static final int REPORT_TIME_TRACKER_MSG = 1; static final int UPDATE_PROCESS_ANIMATING_STATE = 2; static final int END_POWER_MODE_UNKNOWN_VISIBILITY_MSG = 3; static final int FIRST_ACTIVITY_TASK_MSG = 100; static final int FIRST_SUPERVISOR_TASK_MSG = 200; Loading @@ -5146,6 +5180,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } break; case END_POWER_MODE_UNKNOWN_VISIBILITY_MSG: { synchronized (mGlobalLock) { mRetainPowerModeAndTopProcessState = false; endLaunchPowerMode(POWER_MODE_REASON_UNKNOWN_VISIBILITY); if (mTopApp != null && mTopProcessState == ActivityManager.PROCESS_STATE_TOP_SLEEPING) { // Restore the scheduling group for sleeping. mTopApp.updateProcessInfo(false /* updateServiceConnection */, false /* activityChange */, true /* updateOomAdj */, false /* addPendingTopUid */); } } } break; } } } Loading Loading @@ -5464,6 +5512,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @HotPath(caller = HotPath.OOM_ADJUSTMENT) @Override public int getTopProcessState() { if (mRetainPowerModeAndTopProcessState) { // There is a launching app while device may be sleeping, force the top state so // the launching process can have top-app scheduling group. return ActivityManager.PROCESS_STATE_TOP; } return mTopProcessState; } Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +20 −12 Original line number Diff line number Diff line Loading @@ -3545,14 +3545,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void startPowerModeLaunchIfNeeded(boolean forceSend, ActivityRecord targetActivity) { final boolean sendPowerModeLaunch; if (forceSend) { sendPowerModeLaunch = true; } else if (targetActivity == null || targetActivity.app == null) { // Set power mode if we don't know what we're launching yet. sendPowerModeLaunch = true; } else { if (!forceSend && targetActivity != null && targetActivity.app != null) { // Set power mode when the activity's process is different than the current top resumed // activity on all display areas, or if there are no resumed activities in the system. boolean[] noResumedActivities = {true}; Loading @@ -3568,13 +3561,28 @@ class RootWindowContainer extends WindowContainer<DisplayContent> !resumedActivityProcess.equals(targetActivity.app); } }); sendPowerModeLaunch = noResumedActivities[0] || allFocusedProcessesDiffer[0]; if (!noResumedActivities[0] && !allFocusedProcessesDiffer[0]) { // All focused activities are resumed and the process of the target activity is // the same as them, e.g. delivering new intent to the current top. return; } } if (sendPowerModeLaunch) { mService.startLaunchPowerMode( ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY); int reason = ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY; // If the activity is launching while keyguard is locked (including occluded), the activity // may be visible until its first relayout is done (e.g. apply show-when-lock flag). To // avoid power mode from being cleared before that, add a special reason to consider whether // the unknown visibility is resolved. The case from SystemUI is excluded because it should // rely on keyguard-going-away. if (mService.mKeyguardController.isKeyguardLocked() && targetActivity != null && !targetActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_SYSTEMUI)) { final ActivityOptions opts = targetActivity.getOptions(); if (opts == null || opts.getSourceInfo() == null || opts.getSourceInfo().type != ActivityOptions.SourceInfo.TYPE_LOCKSCREEN) { reason |= ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY; } } mService.startLaunchPowerMode(reason); } // TODO(b/191434136): handle this properly when we add multi-window support on secondary Loading
services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +9 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,15 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { // The top app should not change while sleeping. assertEquals(topActivity.app, mAtm.mInternal.getTopApp()); mAtm.startLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY | ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY); assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState()); // Because there is no unknown visibility record, the state will be restored if other // reasons are all done. mAtm.endLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY); assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING, mAtm.mInternal.getTopProcessState()); // If all activities are stopped, the sleep wake lock must be released. final Task topRootTask = topActivity.getRootTask(); doReturn(true).when(rootHomeTask).goToSleepIfPossible(anyBoolean()); Loading