Defer removal of relaunching activity window due to config change.
This is the first step towards having a better maximization experience. When the window gets replaced during relaunch of maximized activity we keep the old window around until the new one is added. Change-Id: Ia8ce26aee6577740cd38096ed2633216a07ceb60
This commit is contained in:
@@ -3043,6 +3043,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
||||
ensureActivitiesVisibleLocked(r, 0);
|
||||
if (!kept) {
|
||||
resumeTopActivitiesLocked(stack, null, null);
|
||||
// We are about to relaunch the activity because its configuration changed due
|
||||
// to size change. The activity will first remove the old window and then add a
|
||||
// new one. This call will tell window manager about this, so it can preserve
|
||||
// the old window until the new one is drawn. This prevents having a gap between
|
||||
// the removal and addition, in which no window is visible.
|
||||
mWindowManager.setReplacingWindow(r.appToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,11 @@ class AppWindowToken extends WindowToken {
|
||||
boolean mLaunchTaskBehind;
|
||||
boolean mEnteringAnimation;
|
||||
|
||||
// This application will have its window replaced due to relaunch. This allows window manager
|
||||
// to differentiate between simple removal of a window and replacement. In the latter case it
|
||||
// will preserve the old window until the new one is drawn.
|
||||
boolean mReplacingWindow;
|
||||
|
||||
AppWindowToken(WindowManagerService _service, IApplicationToken _token,
|
||||
boolean _voiceInteraction) {
|
||||
super(_service, _token.asBinder(),
|
||||
|
||||
@@ -2068,6 +2068,15 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
// If the display is frozen, just remove immediately, since the
|
||||
// animation wouldn't be seen.
|
||||
if (win.mHasSurface && okToDisplay()) {
|
||||
final AppWindowToken appToken = win.mAppToken;
|
||||
if (appToken != null && appToken.mReplacingWindow) {
|
||||
// This window is going to be replaced. We need to kepp it around until the new one
|
||||
// gets added, then we will get rid of this one.
|
||||
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Preserving " + win + " until the new one is "
|
||||
+ "added");
|
||||
win.mExiting = true;
|
||||
return;
|
||||
}
|
||||
// If we are not currently running the exit animation, we
|
||||
// need to see about starting one.
|
||||
wasVisible = win.isWinVisibleLw();
|
||||
@@ -2087,7 +2096,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
mAccessibilityController.onWindowTransitionLocked(win, transit);
|
||||
}
|
||||
}
|
||||
final AppWindowToken appToken = win.mAppToken;
|
||||
final boolean isAnimating = win.mWinAnimator.isAnimating();
|
||||
// The starting window is the last window in this app token and it isn't animating.
|
||||
// Allow it to be removed now as there is no additional window or animation that will
|
||||
@@ -9718,6 +9726,17 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
return mWindowMap;
|
||||
}
|
||||
|
||||
public void setReplacingWindow(IBinder token) {
|
||||
synchronized (mWindowMap) {
|
||||
AppWindowToken appWindowToken = findAppWindowToken(token);
|
||||
if (appWindowToken == null) {
|
||||
Slog.w(TAG, "Attempted to set replacing window on non-existing app token " + token);
|
||||
return;
|
||||
}
|
||||
appWindowToken.mReplacingWindow = true;
|
||||
}
|
||||
}
|
||||
|
||||
private final class LocalService extends WindowManagerInternal {
|
||||
@Override
|
||||
public void requestTraversalFromDisplayManager() {
|
||||
|
||||
@@ -1270,6 +1270,19 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
}
|
||||
}
|
||||
|
||||
void maybeRemoveReplacedWindow() {
|
||||
AppWindowToken token = mAppToken;
|
||||
if (token != null && token.mReplacingWindow) {
|
||||
token.mReplacingWindow = false;
|
||||
for (int i = token.allAppWindows.size() - 1; i >= 0; i--) {
|
||||
WindowState win = token.allAppWindows.get(i);
|
||||
if (win.mExiting) {
|
||||
mService.removeWindowInnerLocked(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DeathRecipient implements IBinder.DeathRecipient {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
|
||||
@@ -1765,6 +1765,8 @@ class WindowStateAnimator {
|
||||
mWin.mAppToken.updateReportedVisibilityLocked();
|
||||
}
|
||||
|
||||
mWin.maybeRemoveReplacedWindow();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user