Clean up surfaces when app is resumed without being stopped. am: 45e6d2dc8b

am: b76adc5117

Change-Id: I35c39c4fc49a953262b5b6ab4cbc2dca2ddf0b8f
This commit is contained in:
Chong Zhang
2016-07-22 17:26:15 +00:00
committed by android-build-merger
5 changed files with 77 additions and 22 deletions

View File

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

View File

@@ -1245,7 +1245,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);
@@ -2495,7 +2495,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);

View File

@@ -336,21 +336,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;
}
@@ -360,7 +380,9 @@ class AppWindowToken extends WindowToken {
+ " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
+ " win.mRemoveOnExit=" + win.mRemoveOnExit);
win.destroyOrSaveSurface();
if (!cleanupOnResume || win.mRemoveOnExit) {
win.destroyOrSaveSurface();
}
if (win.mRemoveOnExit) {
win.remove();
}
@@ -378,20 +400,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.
*

View File

@@ -4412,7 +4412,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");
@@ -4422,10 +4440,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();
}
}

View File

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