clearThumbnail();
setNullAnimation();
if (mAppToken.deferClearAllDrawn) {
- mAppToken.allDrawn = false;
- mAppToken.deferClearAllDrawn = false;
+ mAppToken.clearAllDrawn();
}
mStackClip = STACK_CLIP_BEFORE_ANIM;
}
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.WINDOW_REPLACEMENT_TIMEOUT_DURATION;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
final boolean voiceInteraction;
- // Whether we're performing an entering animation with a saved surface.
- boolean mAnimatingWithSavedSurface;
-
-
Task mTask;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
}
+ void setVisibleBeforeClientHidden() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = allAppWindows.get(i);
+ w.setVisibleBeforeClientHidden();
+ }
+ }
+
void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
firstWindowDrawn = true;
// If we're animating with a saved surface, we're already visible.
// Return true so that the alpha doesn't get cleared.
if (!win.mAppFreezing
- && (win.mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface
+ && (win.mViewVisibility == View.VISIBLE || win.isAnimatingWithSavedSurface()
|| (win.mWinAnimator.isAnimationSet()
&& !service.mAppTransition.isTransitionSet()))
&& !win.mDestroying
win.destroyOrSaveSurface();
if (win.mRemoveOnExit) {
- win.mAnimatingExit = false;
service.removeWindowInnerLocked(win);
}
final DisplayContent displayContent = win.getDisplayContent();
return allDrawn;
}
- boolean hasSavedSurface() {
+ boolean canRestoreSurfaces() {
for (int i = allAppWindows.size() -1; i >= 0; i--) {
- final WindowState ws = allAppWindows.get(i);
- if (ws.hasSavedSurface()) {
+ final WindowState w = allAppWindows.get(i);
+ if (w.canRestoreSurface()) {
return true;
}
}
return false;
}
+ void clearVisibleBeforeClientHidden() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = allAppWindows.get(i);
+ w.clearVisibleBeforeClientHidden();
+ }
+ }
+
void restoreSavedSurfaces() {
- if (!hasSavedSurface()) {
+ if (!canRestoreSurfaces()) {
+ clearVisibleBeforeClientHidden();
return;
}
- mAnimatingWithSavedSurface = true;
-
// Check if we have enough drawn windows to mark allDrawn= true.
int numInteresting = 0;
int numDrawn = 0;
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
WindowState w = allAppWindows.get(i);
- if (w.hasSavedSurface()) {
- w.restoreSavedSurface();
- }
- if (w != startingWindow && !w.mAppDied
+ if (w != startingWindow && !w.mAppDied && w.wasVisibleBeforeClientHidden()
&& (!mAppAnimator.freezingScreen || !w.mAppFreezing)) {
numInteresting++;
+ if (w.hasSavedSurface()) {
+ w.restoreSavedSurface();
+ }
if (w.isDrawnLw()) {
numDrawn++;
}
}
}
- allDrawn |= (numInteresting > 0) && (numInteresting == numDrawn);
+ if (!allDrawn) {
+ allDrawn = (numInteresting > 0) && (numInteresting == numDrawn);
+ if (allDrawn) {
+ service.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
+ }
+ }
+ clearVisibleBeforeClientHidden();
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
- "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn);
+ "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn
+ + " numInteresting=" + numInteresting + " numDrawn=" + numDrawn);
}
void destroySavedSurfaces() {
WindowState win = allAppWindows.get(i);
win.destroySavedSurface();
}
- mAnimatingWithSavedSurface = false;
+ }
+
+ void clearAllDrawn() {
+ allDrawn = false;
+ deferClearAllDrawn = false;
}
@Override
* Returns true if we're done setting up any transitions.
*/
private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
- atoken.allDrawn = false;
+ atoken.clearAllDrawn();
WindowState replacedWindow = null;
for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
WindowState candidate = atoken.windows.get(i);
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
+ "added");
// TODO: We are overloading mAnimatingExit flag to prevent the window state from
- // been removed. We probably need another falg to indicate that window removal
+ // been removed. We probably need another flag to indicate that window removal
// should be deffered vs. overloading the flag that says we are playing an exit
// animation.
win.mAnimatingExit = true;
mTokenMap.remove(token.token);
} else if (atoken != null) {
atoken.firstWindowDrawn = false;
- atoken.allDrawn = false;
+ atoken.clearAllDrawn();
}
}
// Now that the app is going invisible, we can remove it. It will be restarted
// if made visible again.
wtoken.removeAllDeadWindows();
+ wtoken.setVisibleBeforeClientHidden();
} else if (visible) {
if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
// Add the app mOpeningApps if transition is unset but ready. This means
// If the token is currently hidden (should be the common case), or has been
// stopped, then we need to set up to wait for its windows to be ready.
if (wtoken.hidden || wtoken.mAppStopped) {
- wtoken.allDrawn = false;
- wtoken.deferClearAllDrawn = false;
+ wtoken.clearAllDrawn();
// If the app was already visible, don't reset the waitingToShow state.
if (wtoken.hidden) {
}
winAnimator.mDrawState = DRAW_PENDING;
if (w.mAppToken != null) {
- w.mAppToken.allDrawn = false;
- w.mAppToken.deferClearAllDrawn = false;
+ w.mAppToken.clearAllDrawn();
}
}
if (!mResizingWindows.contains(w)) {
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
+ ws + " surface=" + wsa.mSurfaceController
+ " token=" + ws.mAppToken
- + " saved=" + ws.mAppToken.hasSavedSurface());
+ + " saved=" + ws.hasSavedSurface());
if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
wsa.destroySurface();
leakedSurface = true;
// Whether the window has a saved surface from last pause, which can be
// used to start an entering animation earlier.
- public boolean mSurfaceSaved = false;
+ private boolean mSurfaceSaved = false;
+
+ // Whether we're performing an entering animation with a saved surface.
+ private boolean mAnimatingWithSavedSurface;
+
+ // Whether the window was visible when we set the app to invisible last time. WM uses
+ // this as a hint to restore the surface (if available) for early animation next time
+ // the app is brought visible.
+ boolean mWasVisibleBeforeClientHidden;
// This window will be replaced due to relaunch. This allows window manager
// to differentiate between simple removal of a window and replacement. In the latter case it
}
boolean isAnimatingWithSavedSurface() {
- return mAppToken != null && mAppToken.mAnimatingWithSavedSurface;
+ return mAnimatingWithSavedSurface;
+ }
+
+ public void setVisibleBeforeClientHidden() {
+ mWasVisibleBeforeClientHidden |=
+ (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
+ }
+
+ public void clearVisibleBeforeClientHidden() {
+ mWasVisibleBeforeClientHidden = false;
+ }
+
+ public boolean wasVisibleBeforeClientHidden() {
+ return mWasVisibleBeforeClientHidden;
}
private boolean shouldSaveSurface() {
return false;
}
+ if (!mWasVisibleBeforeClientHidden) {
+ return false;
+ }
+
if ((mAttrs.flags & FLAG_SECURE) != 0) {
// We don't save secure surfaces since their content shouldn't be shown while the app
// isn't on screen and content might leak through during the transition animation with
} else {
mWinAnimator.destroySurfaceLocked();
}
+ // Clear animating flags now, since the surface is now gone. (Note this is true even
+ // if the surface is saved, to outside world the surface is still NO_SURFACE.)
+ mAnimatingExit = false;
}
- public void destroySavedSurface() {
+ void destroySavedSurface() {
if (mSurfaceSaved) {
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Slog.v(TAG, "Destroying saved surface: " + this);
}
mWinAnimator.destroySurfaceLocked();
}
+ mWasVisibleBeforeClientHidden = false;
}
- public void restoreSavedSurface() {
+ void restoreSavedSurface() {
if (!mSurfaceSaved) {
return;
}
if (mWinAnimator.mSurfaceController != null) {
setHasSurface(true);
mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
+ mAnimatingWithSavedSurface = true;
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Slog.v(TAG, "Restoring saved surface: " + this);
}
}
- public boolean hasSavedSurface() {
+ boolean canRestoreSurface() {
+ return mWasVisibleBeforeClientHidden && mSurfaceSaved;
+ }
+
+ boolean hasSavedSurface() {
return mSurfaceSaved;
}
+ void clearHasSavedSurface() {
+ mSurfaceSaved = false;
+ mAnimatingWithSavedSurface = false;
+ mWasVisibleBeforeClientHidden = false;
+ }
+
+ void clearAnimatingWithSavedSurface() {
+ if (mAnimatingWithSavedSurface) {
+ // App has drawn something to its windows, we're no longer animating with
+ // the saved surfaces.
+ if (DEBUG_ANIM) Slog.d(TAG,
+ "clearAnimatingWithSavedSurface(): win=" + this);
+ mAnimatingWithSavedSurface = false;
+ }
+ }
+
@Override
public boolean isDefaultDisplay() {
final DisplayContent displayContent = getDisplayContent();
+ drawStateToString());
}
- if (mWin.mAppToken != null && mWin.mAppToken.mAnimatingWithSavedSurface) {
- // App has drawn something to its windows, we're no longer animating with
- // the saved surfaces. If the user exits now, we only want to save again
- // if allDrawn is true.
- if (DEBUG_ANIM) Slog.d(TAG,
- "finishDrawingLocked: mAnimatingWithSavedSurface=false " + mWin);
- mWin.mAppToken.mAnimatingWithSavedSurface = false;
- }
+ mWin.clearAnimatingWithSavedSurface();
+
if (mDrawState == DRAW_PENDING) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
mDrawState = DRAW_PENDING;
if (w.mAppToken != null) {
if (w.mAppToken.mAppAnimator.animation == null) {
- w.mAppToken.allDrawn = false;
- w.mAppToken.deferClearAllDrawn = false;
+ w.mAppToken.clearAllDrawn();
} else {
// Currently animating, persist current state of allDrawn until animation
// is complete.
}
boolean hasSurface() {
- return !mWin.mSurfaceSaved
+ return !mWin.hasSavedSurface()
&& mSurfaceController != null && mSurfaceController.hasSurface();
}
void destroySurfaceLocked() {
final AppWindowToken wtoken = mWin.mAppToken;
if (wtoken != null) {
- wtoken.mAnimatingWithSavedSurface = false;
if (mWin == wtoken.startingWindow) {
wtoken.startingDisplayed = false;
}
}
- mWin.mSurfaceSaved = false;
+ mWin.clearHasSavedSurface();
if (mSurfaceController == null) {
return;