diff options
10 files changed, 75 insertions, 15 deletions
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index f1efec04fa69..74c62ba7498d 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -2228,14 +2228,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call && !mScreenOffBecauseOfProximity) { setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF); unblockScreenOn(); - mWindowManagerPolicy.screenTurnedOff(mDisplayId); + mWindowManagerPolicy.screenTurnedOff(mDisplayId, mIsInTransition); } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) { // We told policy already that screen was turning off, but now we changed our minds. // Complete the full state transition on -> turningOff -> off. unblockScreenOff(); - mWindowManagerPolicy.screenTurnedOff(mDisplayId); + mWindowManagerPolicy.screenTurnedOff(mDisplayId, mIsInTransition); setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF); } if (!isOff diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java index 59e112ecbccb..d36e5548e654 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController2.java +++ b/services/core/java/com/android/server/display/DisplayPowerController2.java @@ -1859,14 +1859,14 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal && !mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) { setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF); unblockScreenOn(); - mWindowManagerPolicy.screenTurnedOff(mDisplayId); + mWindowManagerPolicy.screenTurnedOff(mDisplayId, mIsInTransition); } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) { // We told policy already that screen was turning off, but now we changed our minds. // Complete the full state transition on -> turningOff -> off. unblockScreenOff(); - mWindowManagerPolicy.screenTurnedOff(mDisplayId); + mWindowManagerPolicy.screenTurnedOff(mDisplayId, mIsInTransition); setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF); } if (!isOff diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 4094b1a06d94..cceb26ff3e79 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5001,11 +5001,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the DisplayManager's DisplayPowerController thread. @Override - public void screenTurnedOff(int displayId) { + public void screenTurnedOff(int displayId, boolean isSwappingDisplay) { if (DEBUG_WAKEUP) Slog.i(TAG, "Display" + displayId + " turned off..."); if (displayId == DEFAULT_DISPLAY) { - updateScreenOffSleepToken(true); + updateScreenOffSleepToken(true, isSwappingDisplay); mRequestedOrSleepingDefaultDisplay = false; mDefaultDisplayPolicy.screenTurnedOff(); synchronized (mLock) { @@ -5056,7 +5056,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (displayId == DEFAULT_DISPLAY) { Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */); - updateScreenOffSleepToken(false); + updateScreenOffSleepToken(false /* acquire */, false /* isSwappingDisplay */); mDefaultDisplayPolicy.screenTurnedOn(screenOnListener); mBootAnimationDismissable = false; @@ -5575,9 +5575,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. - private void updateScreenOffSleepToken(boolean acquire) { + private void updateScreenOffSleepToken(boolean acquire, boolean isSwappingDisplay) { if (acquire) { - mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY); + mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY, isSwappingDisplay); } else { mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY); } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 5d558e9c1e2f..7c3f1aad435b 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -835,8 +835,10 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { /** * Called when the display has turned off. + * @param displayId The display to apply to. + * @param isSwappingDisplay Whether the display is swapping to another physical display. */ - public void screenTurnedOff(int displayId); + void screenTurnedOff(int displayId, boolean isSwappingDisplay); public interface ScreenOnListener { void onScreenOn(); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c6a2e0e51227..c867452d3a23 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -8525,6 +8525,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return inTransitionSelfOrParent(); } + boolean isDisplaySleepingAndSwapping() { + for (int i = mDisplayContent.mAllSleepTokens.size() - 1; i >= 0; i--) { + RootWindowContainer.SleepToken sleepToken = mDisplayContent.mAllSleepTokens.get(i); + if (sleepToken.isDisplaySwapping()) { + return true; + } + } + return false; + } + /** * Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed * orientation then aspect ratio restrictions are also already respected. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index bfb735de2d0a..62b7a4eaae2f 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -144,6 +144,13 @@ public abstract class ActivityTaskManagerInternal { void acquire(int displayId); /** + * Acquires a sleep token. + * @param displayId The display to apply to. + * @param isSwappingDisplay Whether the display is swapping to another physical display. + */ + void acquire(int displayId, boolean isSwappingDisplay); + + /** * Releases the sleep token. * @param displayId The display to apply to. */ diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f93afe81f804..e5d5e04319fb 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4804,10 +4804,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void acquire(int displayId) { + acquire(displayId, false /* isSwappingDisplay */); + } + + @Override + public void acquire(int displayId, boolean isSwappingDisplay) { synchronized (mGlobalLock) { if (!mSleepTokens.contains(displayId)) { mSleepTokens.append(displayId, - mRootWindowContainer.createSleepToken(mTag, displayId)); + mRootWindowContainer.createSleepToken(mTag, displayId, + isSwappingDisplay)); updateSleepIfNeededLocked(); } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 7d220df949e0..012151321ed2 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -188,6 +188,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // How long we can hold the launch wake lock before giving up. private static final int LAUNCH_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; + // How long we delay processing the stopping and finishing activities. + private static final int SCHEDULE_FINISHING_STOPPING_ACTIVITY_MS = 200; + /** How long we wait until giving up on the activity telling us it released the top state. */ private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500; @@ -2181,13 +2184,15 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { boolean processPausingActivities, String reason) { // Stop any activities that are scheduled to do so but have been waiting for the transition // animation to finish. + boolean displaySwapping = false; ArrayList<ActivityRecord> readyToStopActivities = null; for (int i = 0; i < mStoppingActivities.size(); i++) { final ActivityRecord s = mStoppingActivities.get(i); final boolean animating = s.isInTransition(); + displaySwapping |= s.isDisplaySleepingAndSwapping(); ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b " + "finishing=%s", s, s.nowVisible, animating, s.finishing); - if (!animating || mService.mShuttingDown) { + if ((!animating && !displaySwapping) || mService.mShuttingDown) { if (!processPausingActivities && s.isState(PAUSING)) { // Defer processing pausing activities in this iteration and reschedule // a delayed idle to reprocess it again @@ -2207,6 +2212,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } } + // Stopping activities are deferred processing if the display is swapping. Check again + // later to ensure the stopping activities can be stopped after display swapped. + if (displaySwapping) { + mHandler.postDelayed(() -> { + synchronized (mService.mGlobalLock) { + scheduleProcessStoppingAndFinishingActivitiesIfNeeded(); + } + }, SCHEDULE_FINISHING_STOPPING_ACTIVITY_MS); + } + final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size(); for (int i = 0; i < numReadyStops; i++) { final ActivityRecord r = readyToStopActivities.get(i); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index cd4b3c565a41..3f4296a5eee5 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2601,6 +2601,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } SleepToken createSleepToken(String tag, int displayId) { + return createSleepToken(tag, displayId, false /* isSwappingDisplay */); + } + + SleepToken createSleepToken(String tag, int displayId, boolean isSwappingDisplay) { final DisplayContent display = getDisplayContent(displayId); if (display == null) { throw new IllegalArgumentException("Invalid display: " + displayId); @@ -2609,7 +2613,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final int tokenKey = makeSleepTokenKey(tag, displayId); SleepToken token = mSleepTokens.get(tokenKey); if (token == null) { - token = new SleepToken(tag, displayId); + token = new SleepToken(tag, displayId, isSwappingDisplay); mSleepTokens.put(tokenKey, token); display.mAllSleepTokens.add(token); ProtoLog.d(WM_DEBUG_STATES, "Create sleep token: tag=%s, displayId=%d", tag, displayId); @@ -3518,18 +3522,34 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private final String mTag; private final long mAcquireTime; private final int mDisplayId; + private final boolean mIsSwappingDisplay; final int mHashKey; - SleepToken(String tag, int displayId) { + // The display could remain in sleep after the physical display swapped, adding a 1 + // seconds display swap timeout to prevent activities staying in PAUSED state. + // Otherwise, the sleep token should be removed once display turns back on after swapped. + private static final long DISPLAY_SWAP_TIMEOUT = 1000; + + SleepToken(String tag, int displayId, boolean isSwappingDisplay) { mTag = tag; mDisplayId = displayId; mAcquireTime = SystemClock.uptimeMillis(); + mIsSwappingDisplay = isSwappingDisplay; mHashKey = makeSleepTokenKey(mTag, mDisplayId); } + public boolean isDisplaySwapping() { + long now = SystemClock.uptimeMillis(); + if (now - mAcquireTime > DISPLAY_SWAP_TIMEOUT) { + return false; + } + return mIsSwappingDisplay; + } + @Override public String toString() { return "{\"" + mTag + "\", display " + mDisplayId + + (mIsSwappingDisplay ? " is swapping " : "") + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index 2a2641edb637..32033fb7403d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -147,7 +147,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public void screenTurnedOff(int displayId) { + public void screenTurnedOff(int displayId, boolean isSwappingDisplay) { } @Override |