Disallow task snapshot starting window for intent != ACTION_MAIN
We don't want to show a task snapshot if the intent wasn't the
launcher intent. Likely the app will show something different, so
we shouldn't show a snapshot in this case.
Test: AppWindowContainerControllerTests
Test: Open app, make sure we get snapshot window
Test: Open Chrome, go home, Open chrome incognito from shortcut,
make sure no flash
Change-Id: Ib608ba8070ce09f418f1036248d81eebfa354128
Fixes: 35099602
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 95d7158..cfbd2b5 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1561,8 +1561,8 @@
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
}
- void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
- mWindowContainerController.notifyAppResumed(wasStopped, allowSavedSurface);
+ void notifyAppResumed(boolean wasStopped) {
+ mWindowContainerController.notifyAppResumed(wasStopped);
}
void notifyUnknownVisibilityLaunched() {
@@ -2112,7 +2112,8 @@
service.compatibilityInfoForPackageLocked(info.applicationInfo);
final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
- prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning());
+ prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
+ allowTaskSnapshot());
if (shown) {
mStartingWindowState = STARTING_WINDOW_SHOWN;
}
@@ -2552,7 +2553,7 @@
preserveWindowOnDeferredRelaunch = false;
}
- boolean isProcessRunning() {
+ private boolean isProcessRunning() {
ProcessRecord proc = app;
if (proc == null) {
proc = service.mProcessNames.get(processName, info.applicationInfo.uid);
@@ -2560,6 +2561,26 @@
return proc != null && proc.thread != null;
}
+ /**
+ * @return Whether a task snapshot starting window may be shown.
+ */
+ private boolean allowTaskSnapshot() {
+ if (newIntents == null) {
+ return true;
+ }
+
+ // Restrict task snapshot starting window to launcher start, or there is no intent at all
+ // (eg. task being brought to front). If the intent is something else, likely the app is
+ // going to show some specific page or view, instead of what's left last time.
+ for (int i = newIntents.size() - 1; i >= 0; i--) {
+ final Intent intent = newIntents.get(i);
+ if (intent != null && !ActivityRecord.isMainIntent(intent)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
out.attribute(null, ATTR_ID, String.valueOf(createTime));
out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 78887c6..5148619 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2519,26 +2519,14 @@
}
}
- boolean allowSavedSurface = true;
if (next.newIntents != null) {
- // Restrict saved surface to launcher start, or there is no intent at all
- // (eg. task being brought to front). If the intent is something else,
- // likely the app is going to show some specific page or view, instead of
- // what's left last time.
- for (int i = next.newIntents.size() - 1; i >= 0; i--) {
- final Intent intent = next.newIntents.get(i);
- if (intent != null && !ActivityRecord.isMainIntent(intent)) {
- allowSavedSurface = false;
- break;
- }
- }
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
- next.notifyAppResumed(next.stopped, allowSavedSurface);
+ next.notifyAppResumed(next.stopped);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.getTask().taskId,
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index e26914e..0b90bad 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -449,7 +449,8 @@
public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
- IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning) {
+ IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot) {
synchronized(mWindowMap) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
+ " pkg=" + pkg + " transferFrom=" + transferFrom);
@@ -469,7 +470,8 @@
return false;
}
- final int type = getStartingWindowType(newTask, taskSwitch, processRunning);
+ final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
+ allowTaskSnapshot);
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
return createSnapshot();
@@ -539,10 +541,11 @@
return true;
}
- private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning) {
+ private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot) {
if (newTask || !processRunning) {
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
- } else if (taskSwitch) {
+ } else if (taskSwitch && allowTaskSnapshot) {
return STARTING_WINDOW_TYPE_SNAPSHOT;
} else {
return STARTING_WINDOW_TYPE_NONE;
@@ -612,13 +615,13 @@
}
}
- public void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
+ public void notifyAppResumed(boolean wasStopped) {
synchronized(mWindowMap) {
if (mContainer == null) {
Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
return;
}
- mContainer.notifyAppResumed(wasStopped, allowSavedSurface);
+ mContainer.notifyAppResumed(wasStopped);
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a8664a5..f4f6b63 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -582,16 +582,13 @@
* Notify that the app is now resumed, and it was not stopped before, perform a clean
* up of the surfaces
*/
- void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
+ void notifyAppResumed(boolean wasStopped) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
- + " allowSavedSurface=" + allowSavedSurface + " " + this);
+ + " " + this);
mAppStopped = false;
if (!wasStopped) {
destroySurfaces(true /*cleanupOnResume*/);
}
- if (!allowSavedSurface) {
- destroySavedSurfaces();
- }
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 3c8bf20..d206407 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -97,7 +97,7 @@
final WindowTestUtils.TestAppWindowContainerController controller =
createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
waitUntilHandlersIdle();
final AppWindowToken atoken = controller.getAppWindowToken();
assertHasStartingWindow(atoken);
@@ -113,11 +113,11 @@
final WindowTestUtils.TestAppWindowContainerController controller2 =
createAppWindowController();
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
waitUntilHandlersIdle();
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false);
+ true, true, false, true);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken());
assertHasStartingWindow(controller2.getAppWindowToken());
@@ -134,10 +134,10 @@
// Surprise, ...! Transfer window in the middle of the creation flow.
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false);
+ true, true, false, true);
});
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken());
assertHasStartingWindow(controller2.getAppWindowToken());