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 ad24f96def)
This commit is contained in:
Chong Zhang
2016-08-25 12:12:33 -07:00
parent d6a64d788b
commit 813be138ae
6 changed files with 32 additions and 7 deletions

View File

@@ -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);

View File

@@ -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.

View File

@@ -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);

View File

@@ -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();
}
}
/**

View File

@@ -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);
}
}

View File

@@ -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
}