Merge "Fixed some activity visiblility issues in picture-in-picutre mode"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9540ae1..2175a9e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -592,6 +592,14 @@
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 4fb87c3..eb0945bf 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 @@
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 @@
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 @@
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 @@
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 c44b4cf..312e309 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 @@
if (r.finishing) {
r.clearOptionsLocked();
} else {
- if (r.configDestroy) {
+ if (r.deferRelaunchUntilPaused) {
destroyActivityLocked(r, true, "stop-config");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
} else {
@@ -1114,14 +1114,11 @@
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 @@
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 @@
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 @@
}
mService.resetFocusedActivityIfNeededLocked(r);
- r.configDestroy = false;
+ r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
if (setState) {
@@ -4175,38 +4173,33 @@
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 @@
private void relaunchActivityLocked(
ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
if (mService.mSuppressResizeConfigChanges && preserveWindow) {
+ r.configChangeFlags = 0;
return;
}
@@ -4341,6 +4335,8 @@
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 4672023..c634e0e 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 @@
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 @@
// 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<>();
}