Merge "Replace SurfaceViews across resize trigerred relaunches."
This commit is contained in:
@@ -4325,6 +4325,21 @@ public final class ActivityThread {
|
||||
|
||||
r.activity.mChangingConfigurations = true;
|
||||
|
||||
// If we are preserving the main window across relaunches we would also like to preserve
|
||||
// the children. However the client side view system does not support preserving
|
||||
// the child views so we notify the window manager to expect these windows to
|
||||
// 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.
|
||||
try {
|
||||
if (r.mPreserveWindow) {
|
||||
WindowManagerGlobal.getWindowSession().prepareToReplaceChildren(r.token);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// If the system process has died, it's game over for everyone.
|
||||
}
|
||||
|
||||
|
||||
// Need to ensure state is saved.
|
||||
if (!r.paused) {
|
||||
performPauseActivity(r.token, false, r.isPreHoneycomb());
|
||||
|
||||
@@ -123,6 +123,14 @@ interface IWindowSession {
|
||||
void repositionChild(IWindow childWindow, int left, int top, int right, int bottom,
|
||||
long deferTransactionUntilFrame, out Rect outFrame);
|
||||
|
||||
/*
|
||||
* Notify the window manager that an application is relaunching and
|
||||
* child windows should be prepared for replacement.
|
||||
*
|
||||
* @param appToken The application
|
||||
*/
|
||||
void prepareToReplaceChildren(IBinder appToken);
|
||||
|
||||
/**
|
||||
* If a call to relayout() asked to have the surface destroy deferred,
|
||||
* it must call this once it is okay to destroy that surface.
|
||||
|
||||
@@ -405,6 +405,17 @@ class AppWindowToken extends WindowToken {
|
||||
}
|
||||
}
|
||||
|
||||
void setReplacingChildren() {
|
||||
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken
|
||||
+ " with replacing child windows.");
|
||||
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
|
||||
final WindowState w = allAppWindows.get(i);
|
||||
if (w.isChildWindow()) {
|
||||
w.setReplacing(false /* animate */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resetReplacingWindows() {
|
||||
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Resetting app token " + appWindowToken
|
||||
+ " of replacing window marks.");
|
||||
|
||||
@@ -200,6 +200,11 @@ final class Session extends IWindowSession.Stub
|
||||
deferTransactionUntilFrame, outFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareToReplaceChildren(IBinder appToken) {
|
||||
mService.setReplacingChildren(appToken);
|
||||
}
|
||||
|
||||
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
|
||||
int requestedWidth, int requestedHeight, int viewFlags,
|
||||
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
|
||||
|
||||
@@ -2693,7 +2693,14 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
final boolean notExitingOrAnimating =
|
||||
!win.mExiting && !win.isAnimatingWithSavedSurface();
|
||||
result |= notExitingOrAnimating ? RELAYOUT_RES_SURFACE_CHANGED : 0;
|
||||
if (notExitingOrAnimating) {
|
||||
// We don't want to animate visibility of windows which are pending
|
||||
// replacement. In the case of activity relaunch child windows
|
||||
// could request visibility changes as they are detached from the main
|
||||
// application window during the tear down process. If we satisfied
|
||||
// these visibility changes though, we would cause a visual glitch
|
||||
// hiding the window before it's replacement was available.
|
||||
// So we just do nothing on our side.
|
||||
if (notExitingOrAnimating && win.mWillReplaceWindow == false) {
|
||||
focusMayChange = tryStartingAnimation(win, winAnimator, isDefaultDisplay,
|
||||
focusMayChange);
|
||||
|
||||
@@ -2893,9 +2900,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
try {
|
||||
synchronized (mWindowMap) {
|
||||
WindowState win = windowForClientLocked(session, client, false);
|
||||
if (win == null) {
|
||||
if (win == null || win.mWillReplaceWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
win.mWinAnimator.destroyDeferredSurfaceLocked();
|
||||
}
|
||||
} finally {
|
||||
@@ -10183,6 +10191,27 @@ 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
|
||||
* activity is torn down.
|
||||
* @param token Application token for which the activity will be relaunched.
|
||||
*/
|
||||
public void setReplacingChildren(IBinder token) {
|
||||
AppWindowToken appWindowToken = null;
|
||||
synchronized (mWindowMap) {
|
||||
appWindowToken = findAppWindowToken(token);
|
||||
if (appWindowToken == null || !appWindowToken.isVisible()) {
|
||||
Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
|
||||
+ token);
|
||||
return;
|
||||
}
|
||||
|
||||
appWindowToken.setReplacingChildren();
|
||||
scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're replacing the window, schedule a timer to clear the replaced window
|
||||
* after a timeout, in case the replacing window is not coming.
|
||||
|
||||
@@ -231,4 +231,9 @@ public final class BridgeWindowSession implements IWindowSession {
|
||||
public void pokeDrawLock(IBinder window) {
|
||||
// pass for now.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareToReplaceChildren(IBinder appToken) {
|
||||
// pass for now.
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user