Merge "Fix a flicker when window is removed during entering animation" into nyc-dev
This commit is contained in:
@@ -88,6 +88,11 @@ class AppWindowToken extends WindowToken {
|
||||
// case do not clear allDrawn until the animation completes.
|
||||
boolean deferClearAllDrawn;
|
||||
|
||||
// These are to track the app's real drawing status if there were no saved surfaces.
|
||||
boolean allDrawnExcludingSaved;
|
||||
int numInterestingWindowsExcludingSaved;
|
||||
int numDrawnWindowsExclusingSaved;
|
||||
|
||||
// Is this window's surface needed? This is almost like hidden, except
|
||||
// it will sometimes be true a little earlier: when the token has
|
||||
// been shown, but is still waiting for its app transition to execute
|
||||
@@ -411,6 +416,39 @@ class AppWindowToken extends WindowToken {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the app has some window that is invisible in layout, but
|
||||
* animating with saved surface.
|
||||
*/
|
||||
boolean isAnimatingInvisibleWithSavedSurface() {
|
||||
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
|
||||
final WindowState w = allAppWindows.get(i);
|
||||
if (w.isAnimatingInvisibleWithSavedSurface()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide all window surfaces that's still invisible in layout but animating
|
||||
* with a saved surface, and mark them destroying.
|
||||
*/
|
||||
void stopUsingSavedSurfaceLocked() {
|
||||
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
|
||||
final WindowState w = allAppWindows.get(i);
|
||||
if (w.isAnimatingInvisibleWithSavedSurface()) {
|
||||
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
|
||||
"stopUsingSavedSurfaceLocked: " + w);
|
||||
w.clearAnimatingWithSavedSurface();
|
||||
w.mDestroying = true;
|
||||
w.mWinAnimator.hide("stopUsingSavedSurfaceLocked");
|
||||
w.mWinAnimator.mWallpaperControllerLocked.hideWallpapers(w);
|
||||
}
|
||||
}
|
||||
destroySurfaces();
|
||||
}
|
||||
|
||||
void restoreSavedSurfaces() {
|
||||
if (!canRestoreSurfaces()) {
|
||||
clearVisibleBeforeClientHidden();
|
||||
@@ -456,6 +494,7 @@ class AppWindowToken extends WindowToken {
|
||||
void clearAllDrawn() {
|
||||
allDrawn = false;
|
||||
deferClearAllDrawn = false;
|
||||
allDrawnExcludingSaved = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -788,6 +788,7 @@ public class WindowAnimator {
|
||||
removeReplacedWindowsLocked();
|
||||
}
|
||||
|
||||
mService.stopUsingSavedSurfaceLocked();
|
||||
mService.destroyPreservedSurfaceLocked();
|
||||
mService.mWindowPlacerLocked.destroyPendingSurfaces();
|
||||
|
||||
|
||||
@@ -414,6 +414,13 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
*/
|
||||
final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* List of window tokens that have finished drawing their own windows and
|
||||
* no longer need to show any saved surfaces. Windows that's still showing
|
||||
* saved surfaces will be cleaned up after next animation pass.
|
||||
*/
|
||||
final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* List of app window tokens that are waiting for replacing windows. If the
|
||||
* replacement doesn't come in time the stale windows needs to be disposed of.
|
||||
@@ -2330,6 +2337,23 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (win.isAnimatingWithSavedSurface() && !appToken.allDrawnExcludingSaved) {
|
||||
// We started enter animation early with a saved surface, now the app asks to remove
|
||||
// this window. If we remove it now and the app is not yet drawn, we'll show a
|
||||
// flicker. Delay the removal now until it's really drawn.
|
||||
if (DEBUG_ADD_REMOVE) {
|
||||
Slog.d(TAG_WM, "removeWindowLocked: delay removal of " + win
|
||||
+ " due to early animation");
|
||||
}
|
||||
// Do not set mAnimatingExit to true here, it will cause the surface to be hidden
|
||||
// immediately after the enter animation is done. If the app is not yet drawn then
|
||||
// it will show up as a flicker.
|
||||
win.mRemoveOnExit = true;
|
||||
win.mWindowRemovalAllowed = true;
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
return;
|
||||
}
|
||||
// If we are not currently running the exit animation, we need to see about starting one
|
||||
wasVisible = win.isWinVisibleLw();
|
||||
|
||||
@@ -8560,6 +8584,15 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
mDestroyPreservedSurface.clear();
|
||||
}
|
||||
|
||||
void stopUsingSavedSurfaceLocked() {
|
||||
for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) {
|
||||
final AppWindowToken wtoken = mFinishedEarlyAnim.get(i);
|
||||
wtoken.stopUsingSavedSurfaceLocked();
|
||||
}
|
||||
mFinishedEarlyAnim.clear();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// IWindowManager API
|
||||
// -------------------------------------------------------------
|
||||
|
||||
@@ -437,7 +437,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
// used to start an entering animation earlier.
|
||||
private boolean mSurfaceSaved = false;
|
||||
|
||||
// Whether we're performing an entering animation with a saved surface.
|
||||
// Whether we're performing an entering animation with a saved surface. This flag is
|
||||
// true during the time we're showing a window with a previously saved surface. It's
|
||||
// cleared when surface is destroyed, saved, or re-drawn by the app.
|
||||
private boolean mAnimatingWithSavedSurface;
|
||||
|
||||
// Whether the window was visible when we set the app to invisible last time. WM uses
|
||||
@@ -1255,6 +1257,32 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
return !mAttachedHidden || mWinAnimator.mAnimation != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this window's drawn state might affect the drawn states of the app token.
|
||||
*
|
||||
* @param visibleOnly Whether we should consider only the windows that's currently
|
||||
* visible in layout. If true, windows that has not relayout to VISIBLE
|
||||
* would always return false.
|
||||
*
|
||||
* @return true if the window should be considered while evaluating allDrawn flags.
|
||||
*/
|
||||
boolean mightAffectAllDrawn(boolean visibleOnly) {
|
||||
final boolean isViewVisible = (mViewVisibility == View.VISIBLE)
|
||||
&& (mAppToken == null || !mAppToken.clientHidden);
|
||||
return (isOnScreenIgnoringKeyguard() && (!visibleOnly || isViewVisible)
|
||||
|| mWinAnimator.mAttrType == TYPE_BASE_APPLICATION)
|
||||
&& !mAnimatingExit && !mDestroying;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this window is "interesting" when evaluating allDrawn. If it's interesting,
|
||||
* it must be drawn before allDrawn can become true.
|
||||
*/
|
||||
boolean isInteresting() {
|
||||
return mAppToken != null && !mAppDied
|
||||
&& (!mAppToken.mAppAnimator.freezingScreen || !mAppFreezing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like isOnScreen(), but we don't return true if the window is part
|
||||
* of a transition that has not yet been started.
|
||||
@@ -1960,6 +1988,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
return mAnimatingWithSavedSurface;
|
||||
}
|
||||
|
||||
boolean isAnimatingInvisibleWithSavedSurface() {
|
||||
return mAnimatingWithSavedSurface
|
||||
&& (mViewVisibility != View.VISIBLE || mWindowRemovalAllowed);
|
||||
}
|
||||
|
||||
public void setVisibleBeforeClientHidden() {
|
||||
mWasVisibleBeforeClientHidden |=
|
||||
(mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
|
||||
@@ -2042,6 +2075,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
if (mWinAnimator.mSurfaceController != null) {
|
||||
mWinAnimator.mSurfaceController.disconnectInTransaction();
|
||||
}
|
||||
mAnimatingWithSavedSurface = false;
|
||||
} else {
|
||||
mWinAnimator.destroySurfaceLocked();
|
||||
}
|
||||
|
||||
@@ -792,15 +792,16 @@ class WindowSurfacePlacer {
|
||||
+ " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
|
||||
+ " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
|
||||
}
|
||||
if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
|
||||
if (atoken != null && (!atoken.allDrawn || !atoken.allDrawnExcludingSaved
|
||||
|| atoken.mAppAnimator.freezingScreen)) {
|
||||
if (atoken.lastTransactionSequence != mService.mTransactionSequence) {
|
||||
atoken.lastTransactionSequence = mService.mTransactionSequence;
|
||||
atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
|
||||
atoken.numInterestingWindowsExcludingSaved = 0;
|
||||
atoken.numDrawnWindowsExclusingSaved = 0;
|
||||
atoken.startingDisplayed = false;
|
||||
}
|
||||
if ((w.isOnScreenIgnoringKeyguard()
|
||||
|| winAnimator.mAttrType == TYPE_BASE_APPLICATION)
|
||||
&& !w.mAnimatingExit && !w.mDestroying) {
|
||||
if (!atoken.allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) {
|
||||
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
|
||||
Slog.v(TAG, "Eval win " + w + ": isDrawn="
|
||||
+ w.isDrawnLw()
|
||||
@@ -816,13 +817,14 @@ class WindowSurfacePlacer {
|
||||
}
|
||||
}
|
||||
if (w != atoken.startingWindow) {
|
||||
if (!w.mAppDied &&
|
||||
(!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing)) {
|
||||
if (w.isInteresting()) {
|
||||
atoken.numInterestingWindows++;
|
||||
if (w.isDrawnLw()) {
|
||||
atoken.numDrawnWindows++;
|
||||
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
|
||||
Slog.v(TAG, "tokenMayBeDrawn: " + atoken
|
||||
+ " w=" + w + " numInteresting="
|
||||
+ atoken.numInterestingWindows
|
||||
+ " freezingScreen="
|
||||
+ atoken.mAppAnimator.freezingScreen
|
||||
+ " mAppFreezing=" + w.mAppFreezing);
|
||||
@@ -834,6 +836,23 @@ class WindowSurfacePlacer {
|
||||
atoken.startingDisplayed = true;
|
||||
}
|
||||
}
|
||||
if (!atoken.allDrawnExcludingSaved
|
||||
&& w.mightAffectAllDrawn(true /* visibleOnly */)) {
|
||||
if (w != atoken.startingWindow && w.isInteresting()) {
|
||||
atoken.numInterestingWindowsExcludingSaved++;
|
||||
if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) {
|
||||
atoken.numDrawnWindowsExclusingSaved++;
|
||||
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION)
|
||||
Slog.v(TAG, "tokenMayBeDrawnExcludingSaved: " + atoken
|
||||
+ " w=" + w + " numInteresting="
|
||||
+ atoken.numInterestingWindowsExcludingSaved
|
||||
+ " freezingScreen="
|
||||
+ atoken.mAppAnimator.freezingScreen
|
||||
+ " mAppFreezing=" + w.mAppFreezing);
|
||||
updateAllDrawn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
|
||||
@@ -1539,6 +1558,22 @@ class WindowSurfacePlacer {
|
||||
wtoken.token).sendToTarget();
|
||||
}
|
||||
}
|
||||
if (!wtoken.allDrawnExcludingSaved) {
|
||||
int numInteresting = wtoken.numInterestingWindowsExcludingSaved;
|
||||
if (numInteresting > 0
|
||||
&& wtoken.numDrawnWindowsExclusingSaved >= numInteresting) {
|
||||
if (DEBUG_VISIBILITY)
|
||||
Slog.v(TAG, "allDrawnExcludingSaved: " + wtoken
|
||||
+ " interesting=" + numInteresting
|
||||
+ " drawn=" + wtoken.numDrawnWindowsExclusingSaved);
|
||||
wtoken.allDrawnExcludingSaved = true;
|
||||
displayContent.layoutNeeded = true;
|
||||
if (wtoken.isAnimatingInvisibleWithSavedSurface()
|
||||
&& !mService.mFinishedEarlyAnim.contains(wtoken)) {
|
||||
mService.mFinishedEarlyAnim.add(wtoken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user