Ensure surfaces stay alive until activity stop.
am: e12aece4ca
* commit 'e12aece4cad849efbbe6a806f132613a56699230':
Ensure surfaces stay alive until activity stop.
This commit is contained in:
@@ -166,6 +166,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 notifyAppStopped(IBinder token);
|
||||
void startAppFreezingScreen(IBinder token, int configChanges);
|
||||
void stopAppFreezingScreen(IBinder token, boolean force);
|
||||
void removeAppToken(IBinder token);
|
||||
|
||||
@@ -1097,6 +1097,9 @@ final class ActivityStack {
|
||||
mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
|
||||
r.stopped = true;
|
||||
r.state = ActivityState.STOPPED;
|
||||
|
||||
mWindowManager.notifyAppStopped(r.appToken);
|
||||
|
||||
if (getVisibleBehindActivity() == r) {
|
||||
mStackSupervisor.requestVisibleBehindLocked(r, false);
|
||||
}
|
||||
|
||||
@@ -127,6 +127,8 @@ class AppWindowToken extends WindowToken {
|
||||
|
||||
boolean mAlwaysFocusable;
|
||||
|
||||
boolean mAppStopped;
|
||||
|
||||
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
|
||||
|
||||
AppWindowToken(WindowManagerService _service, IApplicationToken _token,
|
||||
@@ -311,6 +313,47 @@ 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() {
|
||||
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 (!win.mDestroying) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mAppStopped && !win.mClientRemoveRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
win.destroyOrSaveSurface();
|
||||
if (win.mRemoveOnExit) {
|
||||
win.mExiting = false;
|
||||
service.removeWindowInnerLocked(win);
|
||||
}
|
||||
final DisplayContent displayContent = win.getDisplayContent();
|
||||
if (displayContent != null && !displayList.contains(displayContent)) {
|
||||
displayList.add(displayContent);
|
||||
}
|
||||
win.mDestroying = false;
|
||||
}
|
||||
for (int i = 0; i < displayList.size(); i++) {
|
||||
final DisplayContent displayContent = displayList.get(i);
|
||||
service.mLayersController.assignLayersLocked(displayContent.getWindowList());
|
||||
displayContent.layoutNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The application has stopped, so destroy any surfaces which were keeping alive
|
||||
// in case they were still being used.
|
||||
void notifyAppStopped() {
|
||||
mAppStopped = true;
|
||||
destroySurfaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we should save surfaces for this app.
|
||||
*
|
||||
|
||||
@@ -2154,6 +2154,14 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (win == null) {
|
||||
return;
|
||||
}
|
||||
// We set this here instead of removeWindowLocked because we only want it to be
|
||||
// true when the client has requested we remove the window. In other remove
|
||||
// cases, we have to wait for activity stop to safely remove the window (as the
|
||||
// client may still be using the surface). In this case though, the client has
|
||||
// just dismissed a window (for example a Dialog) and activity stop isn't
|
||||
// necessarily imminent, so we need to know not to wait for it after our
|
||||
// hanimation (if applicable) finishes.
|
||||
win.mClientRemoveRequested = true;
|
||||
removeWindowLocked(win);
|
||||
}
|
||||
}
|
||||
@@ -4187,6 +4195,24 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAppStopped(IBinder token) {
|
||||
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
|
||||
"notifyAppStopped()")) {
|
||||
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 set visibility of non-existing app token: " + token);
|
||||
return;
|
||||
}
|
||||
wtoken.notifyAppStopped();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAppVisibility(IBinder token, boolean visible) {
|
||||
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
|
||||
@@ -4210,6 +4236,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
mOpeningApps.remove(wtoken);
|
||||
mClosingApps.remove(wtoken);
|
||||
wtoken.mAppStopped = false;
|
||||
wtoken.waitingToShow = false;
|
||||
wtoken.hiddenRequested = !visible;
|
||||
|
||||
|
||||
@@ -385,6 +385,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
/** Is this window now (or just being) removed? */
|
||||
boolean mRemoved;
|
||||
|
||||
/**
|
||||
* Has the client requested we remove the window? In this case we know
|
||||
* that we can dispose of it when we wish without further synchronization
|
||||
* with the client
|
||||
*/
|
||||
boolean mClientRemoveRequested;
|
||||
|
||||
/**
|
||||
* Temp for keeping track of windows that have been removed when
|
||||
* rebuilding window list.
|
||||
|
||||
@@ -471,16 +471,31 @@ class WindowStateAnimator {
|
||||
if (WindowManagerService.localLOGV) Slog.v(
|
||||
TAG, "Exit animation finished in " + this
|
||||
+ ": remove=" + mWin.mRemoveOnExit);
|
||||
if (hasSurface()) {
|
||||
mService.mDestroySurface.add(mWin);
|
||||
mWin.mDestroying = true;
|
||||
hide("finishExit");
|
||||
}
|
||||
mWin.mExiting = false;
|
||||
if (mWin.mRemoveOnExit) {
|
||||
mService.mPendingRemove.add(mWin);
|
||||
mWin.mRemoveOnExit = false;
|
||||
|
||||
|
||||
mWin.mDestroying = true;
|
||||
|
||||
// If we have an app token, we ask it to destroy the surface for us,
|
||||
// so that it can take care to ensure the activity has actually stopped
|
||||
// and the surface is not still in use. Otherwise we add the service to
|
||||
// mDestroySurface and allow it to be processed in our next transaction.
|
||||
if (mWin.mAppToken != null) {
|
||||
if (hasSurface()) {
|
||||
hide("finishExit");
|
||||
}
|
||||
mWin.mAppToken.destroySurfaces();
|
||||
} else {
|
||||
if (hasSurface()) {
|
||||
mService.mDestroySurface.add(mWin);
|
||||
hide("finishExit");
|
||||
}
|
||||
mWin.mExiting = false;
|
||||
if (mWin.mRemoveOnExit) {
|
||||
mService.mPendingRemove.add(mWin);
|
||||
mWin.mRemoveOnExit = false;
|
||||
}
|
||||
}
|
||||
|
||||
mWallpaperControllerLocked.hideWallpapers(mWin);
|
||||
}
|
||||
|
||||
|
||||
@@ -347,6 +347,11 @@ public class IWindowManagerImpl implements IWindowManager {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAppStopped(IBinder token) throws RemoteException {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEventDispatching(boolean arg0) throws RemoteException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
Reference in New Issue
Block a user