From 813be138ae6f1fbe60a9efc082a30e7d25d03f7e Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Thu, 25 Aug 2016 12:12:33 -0700 Subject: [PATCH] DO NOT MERGE -- Only use saved surface if started by launcher or moved to front Restrict saved surface to launcher start (ACTION_MAIN&CATEGORY_ LAUNCHER), 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. This solves problems like the launcher shortcuts on DeckClock, each of them is a different intent and will show one specific view regardless of last states. Another example is Chrome tab opened directly by action VIEW to open some URL. (Note that this doesn't solve the problem with Chrome homescreen shortcuts, it will still start with saved surface (if Chrome is already open). This is because the shortcut is a trampoline activity that starts the real chrome tab activity, but when the trampoline is started, the whole task is already brought to front, and ChromeTab could become visible with the task before we actually start it.) bug: 31055479 bug: 27747315 Change-Id: Id3e61c61ef516b0edc1f174320f02661222f226b (cherry picked from commit ad24f96def42016049de05220593aa049b136def) --- core/java/android/view/IWindowManager.aidl | 2 +- .../core/java/com/android/server/am/ActivityRecord.java | 8 ++++++++ .../core/java/com/android/server/am/ActivityStack.java | 14 +++++++++++++- .../core/java/com/android/server/wm/AppWindowToken.java | 8 ++++++-- .../java/com/android/server/wm/WindowManagerService.java | 4 ++-- .../bridge/src/android/view/IWindowManagerImpl.java | 3 ++- 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 06012198333c..81469c86810c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -173,7 +173,7 @@ interface IWindowManager in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded); void setAppVisibility(IBinder token, boolean visible); - void notifyAppResumed(IBinder token, boolean wasStopped); + void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface); void notifyAppStopped(IBinder token); void startAppFreezingScreen(IBinder token, int configChanges); void stopAppFreezingScreen(IBinder token, boolean force); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 00fda43f4ca4..489eb77729e3 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -750,6 +750,14 @@ final class ActivityRecord { && intent.getType() == null; } + static boolean isMainIntent(Intent intent) { + return Intent.ACTION_MAIN.equals(intent.getAction()) + && intent.hasCategory(Intent.CATEGORY_LAUNCHER) + && intent.getCategories().size() == 1 + && intent.getData() == null + && intent.getType() == null; + } + private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) { if (uid == Process.myUid() || uid == 0) { // System process can launch home activity. diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index a27adf7fcf16..8c4c0ad9af05 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2485,13 +2485,25 @@ final class ActivityStack { } } + 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); } // Well the app will no longer be stopped. // Clear app token stopped state in window manager if needed. - mWindowManager.notifyAppResumed(next.appToken, next.stopped); + mWindowManager.notifyAppResumed(next.appToken, next.stopped, allowSavedSurface); EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, System.identityHashCode(next), next.task.taskId, next.shortComponentName); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index b0653921caf1..621e43a12d48 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -439,12 +439,16 @@ class AppWindowToken extends WindowToken { * Notify that the app is now resumed, and it was not stopped before, perform a clean * up of the surfaces */ - void notifyAppResumed(boolean wasStopped) { - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped + " " + this); + void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) { + if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped + + " allowSavedSurface=" + allowSavedSurface + " " + this); mAppStopped = false; if (!wasStopped) { destroySurfaces(true /*cleanupOnResume*/); } + if (!allowSavedSurface) { + destroySavedSurfaces(); + } } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f2f85bf184cf..eb9ad6caee8c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4480,7 +4480,7 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void notifyAppResumed(IBinder token, boolean wasStopped) { + public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "notifyAppResumed()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -4493,7 +4493,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token); return; } - wtoken.notifyAppResumed(wasStopped); + wtoken.notifyAppResumed(wasStopped, allowSavedSurface); } } diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 5a9860d5c80a..58df301b1cfc 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -351,7 +351,8 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void notifyAppResumed(IBinder token, boolean wasStopped) throws RemoteException { + public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) + throws RemoteException { // TODO Auto-generated method stub } -- 2.11.0