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:
Filip Gruszczynski
2015-09-03 16:03:10 -07:00
parent ed76be0caa
commit 76cc44f31c
5 changed files with 46 additions and 1 deletions

View File

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

View File

@@ -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(),

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -1765,6 +1765,8 @@ class WindowStateAnimator {
mWin.mAppToken.updateReportedVisibilityLocked();
}
mWin.maybeRemoveReplacedWindow();
return true;
}