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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -143,6 +143,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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) + "}";
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void screenTurnedOff(int displayId) {
|
||||
public void screenTurnedOff(int displayId, boolean isSwappingDisplay) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user