diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 4f00f91ee5f57..cf2ef45212917 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4168,7 +4168,7 @@ public final class ActivityThread { } IBinder wtoken = v.getWindowToken(); if (r.activity.mWindowAdded) { - if (r.onlyLocalRequest || r.mPreserveWindow) { + if (r.mPreserveWindow) { // Hold off on removing this until the new activity's // window is being added. r.mPendingRemoveWindow = r.window; @@ -4403,15 +4403,20 @@ public final class ActivityThread { // be replaced and defer requests to destroy or hide them. This way we can achieve // visual continuity. It's important that we do this here prior to pause and destroy // as that is when we may hide or remove the child views. + // + // There is another scenario, if we have decided locally to relaunch the app from a + // call to recreate, then none of the windows will be prepared for replacement or + // preserved by the server, so we want to notify it that we are preparing to replace + // everything try { - if (r.mPreserveWindow) { - WindowManagerGlobal.getWindowSession().prepareToReplaceChildren(r.token); + if (r.mPreserveWindow || r.onlyLocalRequest) { + WindowManagerGlobal.getWindowSession().prepareToReplaceWindows( + r.token, !r.onlyLocalRequest); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - // Need to ensure state is saved. if (!r.paused) { performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity"); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 8e1609c587a3e..1facc106d6451 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -125,11 +125,13 @@ interface IWindowSession { /* * Notify the window manager that an application is relaunching and - * child windows should be prepared for replacement. + * windows should be prepared for replacement. * * @param appToken The application + * @param childrenOnly Whether to only prepare child windows for replacement + * (for example when main windows are being reused via preservation). */ - void prepareToReplaceChildren(IBinder appToken); + void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly); /** * If a call to relayout() asked to have the surface destroy deferred, diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index daeb860e2ef53..08c0a4b013579 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -201,8 +201,8 @@ final class Session extends IWindowSession.Stub } @Override - public void prepareToReplaceChildren(IBinder appToken) { - mService.setReplacingChildren(appToken); + public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { + mService.setReplacingWindows(appToken, childrenOnly); } public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5a5f10c0303b8..4762cbfd793ab 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -10700,12 +10700,16 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Hint to a token that its children will be replaced across activity relaunch. - * The children would otherwise be removed shortly following this as the + * Hint to a token that its windows will be replaced across activity relaunch. + * The windows would otherwise be removed shortly following this as the * activity is torn down. * @param token Application token for which the activity will be relaunched. + * @param childrenOnly Whether to mark only child windows for replacement + * (for the case where main windows are being preserved/ + * reused rather than replaced). + * */ - public void setReplacingChildren(IBinder token) { + public void setReplacingWindows(IBinder token, boolean childrenOnly) { AppWindowToken appWindowToken = null; synchronized (mWindowMap) { appWindowToken = findAppWindowToken(token); @@ -10715,7 +10719,12 @@ public class WindowManagerService extends IWindowManager.Stub return; } - appWindowToken.setReplacingChildren(); + if (childrenOnly) { + appWindowToken.setReplacingChildren(); + } else { + appWindowToken.setReplacingWindows(false /* animate */); + } + scheduleClearReplacingWindowIfNeeded(token, true /* replacing */); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java index 5a6a00fc3985d..7582fda6a0fbf 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java @@ -233,7 +233,7 @@ public final class BridgeWindowSession implements IWindowSession { } @Override - public void prepareToReplaceChildren(IBinder appToken) { + public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { // pass for now. }