summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Louis Chang <louischang@google.com> 2023-04-21 06:31:44 +0000
committer Louis Chang <louischang@google.com> 2023-04-25 07:11:56 +0000
commit0687f9d3cd831428c48efab6d38a6103b7e2c8cb (patch)
treede8ecc7e7f908f688f25c327f678b87062a249bb
parent1ce89ea19dc5c820ba83b6c260dbab32e01b9764 (diff)
Prevents activity being stopped while folding/unfolding device
Display is turning off while swapping the physical display, usually happens while folding/unfolding a foldable device. The display will be turn back on after some time later, but the top activity could be stopped if the display is not turning back on soon enough. Bug: 271098735 Test: tested on Youtube and some other apps Change-Id: I687f35f4989f9e23276451c9b3a3ce8578e64280
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java4
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController2.java4
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java10
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java10
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java17
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java24
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java2
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