diff options
4 files changed, 46 insertions, 40 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 9540ae1cfbf3..2175a9eed90f 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -592,6 +592,14 @@ public class ActivityManager { public static boolean isAlwaysOnTop(int stackId) { return stackId == PINNED_STACK_ID; } + + /** + * Returns true if the top task in the task is allowed to return home when finished and + * there are other tasks in the stack. + */ + public static boolean allowTopTaskToReturnHome(int stackId) { + return stackId != PINNED_STACK_ID; + } } /** diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 4fb87c3a2660..eb0945bfe5f1 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -171,7 +171,9 @@ final class ActivityRecord { boolean stopped; // is activity pause finished? boolean delayedResume; // not yet resumed because of stopped app switches? boolean finishing; // activity in pending finish list? - boolean configDestroy; // need to destroy due to config change? + boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is + // completed + boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch int configChangeFlags; // which config values have changed boolean keysPaused; // has key dispatching been paused for it? int launchMode; // the launch mode activity attribute. @@ -184,9 +186,9 @@ final class ActivityRecord { boolean immersive; // immersive mode (don't interrupt if possible) boolean forceNewConfig; // force re-create with new config next time int launchCount; // count of launches since last state - long lastLaunchTime; // time of last lauch of this activity + long lastLaunchTime; // time of last launch of this activity boolean isVrActivity; // is the activity running in VR mode? - ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>(); + ArrayList<ActivityContainer> mChildContainers = new ArrayList<>(); String stringName; // for caching of toString(). @@ -341,8 +343,8 @@ final class ActivityRecord { else TimeUtils.formatDuration(lastVisibleTime, now, pw); pw.println(); } - if (configDestroy || configChangeFlags != 0) { - pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy); + if (deferRelaunchUntilPaused || configChangeFlags != 0) { + pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused); pw.print(" configChangeFlags="); pw.println(Integer.toHexString(configChangeFlags)); } @@ -551,7 +553,7 @@ final class ActivityRecord { stopped = false; delayedResume = false; finishing = false; - configDestroy = false; + deferRelaunchUntilPaused = false; keysPaused = false; inHistory = false; visible = false; diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index c44b4cfa7b26..312e309e3950 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1088,7 +1088,7 @@ final class ActivityStack { if (r.finishing) { r.clearOptionsLocked(); } else { - if (r.configDestroy) { + if (r.deferRelaunchUntilPaused) { destroyActivityLocked(r, true, "stop-config"); mStackSupervisor.resumeFocusedStackTopActivityLocked(); } else { @@ -1114,14 +1114,11 @@ final class ActivityStack { if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause, no longer waiting: " + prev); } - if (prev.configDestroy) { - // The previous is being paused because the configuration - // is changing, which means it is actually stopping... - // To juggle the fact that we are also starting a new - // instance right now, we need to first completely stop - // the current instance before starting the new one. - if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev); - destroyActivityLocked(prev, true, "pause-config"); + if (prev.deferRelaunchUntilPaused) { + // Complete the deferred relaunch that was waiting for pause to complete. + if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev); + relaunchActivityLocked(prev, prev.configChangeFlags, false, + prev.preserveWindowOnDeferredRelaunch); } else if (wasStopping) { // We are also stopping, the stop request must have gone soon after the pause. // We can't clobber it, because the stop confirmation will not be handled. @@ -2318,11 +2315,12 @@ final class ActivityStack { ActivityStack lastStack = mStackSupervisor.getLastStack(); final boolean fromHome = lastStack.isHomeStack(); if (!isHomeStack() && (fromHome || topTask() != task)) { - task.setTaskToReturnTo(fromHome - ? lastStack.topTask() == null - ? HOME_ACTIVITY_TYPE - : lastStack.topTask().taskType - : APPLICATION_ACTIVITY_TYPE); + int returnToType = APPLICATION_ACTIVITY_TYPE; + if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) { + returnToType = lastStack.topTask() == null + ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType; + } + task.setTaskToReturnTo(returnToType); } } else { task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); @@ -2972,7 +2970,7 @@ final class ActivityStack { r.stopped = true; if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r); r.state = ActivityState.STOPPED; - if (r.configDestroy) { + if (r.deferRelaunchUntilPaused) { destroyActivityLocked(r, true, "stop-except"); } } @@ -3403,7 +3401,7 @@ final class ActivityStack { } mService.resetFocusedActivityIfNeededLocked(r); - r.configDestroy = false; + r.deferRelaunchUntilPaused = false; r.frozenBeforeDestroy = false; if (setState) { @@ -4175,38 +4173,33 @@ final class ActivityStack { r.configChangeFlags |= changes; r.startFreezingScreenLocked(r.app, globalChanges); r.forceNewConfig = false; + preserveWindow &= isResizeOnlyChange(changes); if (r.app == null || r.app.thread == null) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Config is destroying non-running " + r); destroyActivityLocked(r, true, "config"); } else if (r.state == ActivityState.PAUSING) { - // A little annoying: we are waiting for this activity to - // finish pausing. Let's not do anything now, but just - // flag that it needs to be restarted when done pausing. + // A little annoying: we are waiting for this activity to finish pausing. Let's not + // do anything now, but just flag that it needs to be restarted when done pausing. if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Config is skipping already pausing " + r); - r.configDestroy = true; + r.deferRelaunchUntilPaused = true; + r.preserveWindowOnDeferredRelaunch = preserveWindow; return true; } else if (r.state == ActivityState.RESUMED) { - // Try to optimize this case: the configuration is changing - // and we need to restart the top, resumed activity. - // Instead of doing the normal handshaking, just say + // Try to optimize this case: the configuration is changing and we need to restart + // the top, resumed activity. Instead of doing the normal handshaking, just say // "restart!". if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Config is relaunching resumed " + r); - relaunchActivityLocked(r, r.configChangeFlags, true, - preserveWindow && isResizeOnlyChange(changes)); - r.configChangeFlags = 0; + relaunchActivityLocked(r, r.configChangeFlags, true, preserveWindow); } else { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Config is relaunching non-resumed " + r); - relaunchActivityLocked(r, r.configChangeFlags, false, - preserveWindow && isResizeOnlyChange(changes)); - r.configChangeFlags = 0; + relaunchActivityLocked(r, r.configChangeFlags, false, preserveWindow); } - // All done... tell the caller we weren't able to keep this - // activity around. + // All done... tell the caller we weren't able to keep this activity around. return false; } @@ -4298,6 +4291,7 @@ final class ActivityStack { private void relaunchActivityLocked( ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) { if (mService.mSuppressResizeConfigChanges && preserveWindow) { + r.configChangeFlags = 0; return; } @@ -4341,6 +4335,8 @@ final class ActivityStack { mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); r.state = ActivityState.PAUSED; } + + r.configChangeFlags = 0; } boolean willActivityBeVisibleLocked(IBinder token) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 4672023a220e..c634e0e6a6ac 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2722,7 +2722,7 @@ public final class ActivityStackSupervisor implements DisplayListener { for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); final boolean waitingVisible = mWaitingVisibleActivities.contains(s); - if (DEBUG_ALL) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing); if (waitingVisible && nowVisible) { mWaitingVisibleActivities.remove(s); @@ -2732,12 +2732,12 @@ public final class ActivityStackSupervisor implements DisplayListener { // so get rid of it. Otherwise, we need to go through the // normal flow and hide it once we determine that it is // hidden by the activities in front of it. - if (DEBUG_ALL) Slog.v(TAG, "Before stopping, can hide: " + s); + if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s); mWindowManager.setAppVisibility(s.appToken, false); } } if ((!waitingVisible || mService.isSleepingOrShuttingDown()) && remove) { - if (DEBUG_ALL) Slog.v(TAG, "Ready to stop: " + s); + if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); if (stops == null) { stops = new ArrayList<>(); } |