Merge "Prevents activity being stopped while folding/unfolding device" into udc-dev am: 5e48604691
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22789263
Change-Id: I2a296f168ab86247816f3a466979f834c16b119f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 78c5f0e..33f0552 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 @@
&& !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 a76f907..f96b58e 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 @@
&& !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 247a5c0..8433c47 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4987,11 +4987,11 @@
// 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) {
@@ -5042,7 +5042,7 @@
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;
@@ -5561,9 +5561,9 @@
}
// 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 5d558e9..7c3f1aa 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 @@
/**
* 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 bc3a1a2..f843b7c 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 @@
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 bfb735d..62b7a4e 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 @@
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 ea0731a..c92ca103 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4822,10 +4822,16 @@
@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 7d220df..0121513 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 @@
// 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 @@
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 @@
}
}
+ // 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 cd4b3c5..3f4296a 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 @@
}
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 @@
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 @@
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 2a2641e..32033fb 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 @@
}
@Override
- public void screenTurnedOff(int displayId) {
+ public void screenTurnedOff(int displayId, boolean isSwappingDisplay) {
}
@Override