Merge "Clean up surfaces when app is resumed without being stopped." into nyc-mr1-dev
This commit is contained in:
@@ -173,7 +173,8 @@ 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 notifyAppStopped(IBinder token, boolean stopped);
|
||||
void notifyAppResumed(IBinder token, boolean wasStopped);
|
||||
void notifyAppStopped(IBinder token);
|
||||
void startAppFreezingScreen(IBinder token, int configChanges);
|
||||
void stopAppFreezingScreen(IBinder token, boolean force);
|
||||
void removeAppToken(IBinder token);
|
||||
|
||||
@@ -1249,7 +1249,7 @@ final class ActivityStack {
|
||||
r.stopped = true;
|
||||
r.state = ActivityState.STOPPED;
|
||||
|
||||
mWindowManager.notifyAppStopped(r.appToken, true);
|
||||
mWindowManager.notifyAppStopped(r.appToken);
|
||||
|
||||
if (getVisibleBehindActivity() == r) {
|
||||
mStackSupervisor.requestVisibleBehindLocked(r, false);
|
||||
@@ -2490,7 +2490,7 @@ final class ActivityStack {
|
||||
|
||||
// Well the app will no longer be stopped.
|
||||
// Clear app token stopped state in window manager if needed.
|
||||
mWindowManager.notifyAppStopped(next.appToken, false);
|
||||
mWindowManager.notifyAppResumed(next.appToken, next.stopped);
|
||||
|
||||
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
|
||||
System.identityHashCode(next), next.task.taskId, next.shortComponentName);
|
||||
|
||||
@@ -337,21 +337,41 @@ class AppWindowToken extends WindowToken {
|
||||
}
|
||||
}
|
||||
|
||||
// Here we destroy surfaces which have been marked as eligible by the animator, taking care
|
||||
// to ensure the client has finished with them. If the client could still be using them
|
||||
// we will skip destruction and try again when the client has stopped.
|
||||
void destroySurfaces() {
|
||||
destroySurfaces(false /*cleanupOnResume*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
|
||||
* the client has finished with them.
|
||||
*
|
||||
* @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
|
||||
* set to true, destroy only surfaces of removed windows, and clear relevant flags of the
|
||||
* others so that they are ready to be reused. If set to false (common case), destroy all
|
||||
* surfaces that's eligible, if the app is already stopped.
|
||||
*/
|
||||
|
||||
private void destroySurfaces(boolean cleanupOnResume) {
|
||||
final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) allAppWindows.clone();
|
||||
final DisplayContentList displayList = new DisplayContentList();
|
||||
for (int i = allWindows.size() - 1; i >= 0; i--) {
|
||||
final WindowState win = allWindows.get(i);
|
||||
|
||||
if (!(mAppStopped || win.mWindowRemovalAllowed)) {
|
||||
if (!(mAppStopped || win.mWindowRemovalAllowed || cleanupOnResume)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
win.mWinAnimator.destroyPreservedSurfaceLocked();
|
||||
|
||||
if (cleanupOnResume) {
|
||||
// If the window has an unfinished exit animation, consider that animation
|
||||
// done and mark the window destroying so that it goes through the cleanup.
|
||||
if (win.mAnimatingExit) {
|
||||
win.mDestroying = true;
|
||||
win.mAnimatingExit = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!win.mDestroying) {
|
||||
continue;
|
||||
}
|
||||
@@ -361,7 +381,9 @@ class AppWindowToken extends WindowToken {
|
||||
+ " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
|
||||
+ " win.mRemoveOnExit=" + win.mRemoveOnExit);
|
||||
|
||||
win.destroyOrSaveSurface();
|
||||
if (!cleanupOnResume || win.mRemoveOnExit) {
|
||||
win.destroyOrSaveSurface();
|
||||
}
|
||||
if (win.mRemoveOnExit) {
|
||||
service.removeWindowInnerLocked(win);
|
||||
}
|
||||
@@ -379,20 +401,29 @@ class AppWindowToken extends WindowToken {
|
||||
}
|
||||
|
||||
/**
|
||||
* If the application has stopped it is okay to destroy any surfaces which were keeping alive
|
||||
* in case they were still being used.
|
||||
* Notify that the app is now resumed, and it was not stopped before, perform a clean
|
||||
* up of the surfaces
|
||||
*/
|
||||
void notifyAppStopped(boolean stopped) {
|
||||
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
|
||||
mAppStopped = stopped;
|
||||
|
||||
if (stopped) {
|
||||
destroySurfaces();
|
||||
// Remove any starting window that was added for this app if they are still around.
|
||||
mTask.mService.scheduleRemoveStartingWindowLocked(this);
|
||||
void notifyAppResumed(boolean wasStopped) {
|
||||
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped + " " + this);
|
||||
mAppStopped = false;
|
||||
if (!wasStopped) {
|
||||
destroySurfaces(true /*cleanupOnResume*/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that the app has stopped, and it is okay to destroy any surfaces which were
|
||||
* keeping alive in case they were still being used.
|
||||
*/
|
||||
void notifyAppStopped() {
|
||||
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
|
||||
mAppStopped = true;
|
||||
destroySurfaces();
|
||||
// Remove any starting window that was added for this app if they are still around.
|
||||
mTask.mService.scheduleRemoveStartingWindowLocked(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we should save surfaces for this app.
|
||||
*
|
||||
|
||||
@@ -4476,7 +4476,25 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAppStopped(IBinder token, boolean stopped) {
|
||||
public void notifyAppResumed(IBinder token, boolean wasStopped) {
|
||||
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
|
||||
"notifyAppResumed()")) {
|
||||
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
|
||||
}
|
||||
|
||||
synchronized(mWindowMap) {
|
||||
final AppWindowToken wtoken;
|
||||
wtoken = findAppWindowToken(token);
|
||||
if (wtoken == null) {
|
||||
Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
|
||||
return;
|
||||
}
|
||||
wtoken.notifyAppResumed(wasStopped);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAppStopped(IBinder token) {
|
||||
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
|
||||
"notifyAppStopped()")) {
|
||||
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
|
||||
@@ -4486,10 +4504,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
final AppWindowToken wtoken;
|
||||
wtoken = findAppWindowToken(token);
|
||||
if (wtoken == null) {
|
||||
Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
|
||||
Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
|
||||
return;
|
||||
}
|
||||
wtoken.notifyAppStopped(stopped);
|
||||
wtoken.notifyAppStopped();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -351,7 +351,12 @@ public class IWindowManagerImpl implements IWindowManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
|
||||
public void notifyAppResumed(IBinder token, boolean wasStopped) throws RemoteException {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAppStopped(IBinder token) throws RemoteException {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user