Merge "Fix a flicker when window is removed during entering animation" into nyc-dev

This commit is contained in:
Chong Zhang
2016-05-13 01:58:51 +00:00
committed by Android (Google) Code Review
5 changed files with 149 additions and 7 deletions

View File

@@ -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

View File

@@ -788,6 +788,7 @@ public class WindowAnimator {
removeReplacedWindowsLocked();
}
mService.stopUsingSavedSurfaceLocked();
mService.destroyPreservedSurfaceLocked();
mService.mWindowPlacerLocked.destroyPendingSurfaces();

View File

@@ -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
// -------------------------------------------------------------

View File

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

View File

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