Merge "Use saved window surface to start entering animation"
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 98cfc7c..7e47006 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2876,13 +2876,16 @@
}
if (stackId != task.stack.mStackId) {
- moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, FORCE_FOCUS, reason);
- } else {
- task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
- task.getTopActivity() == null ? null : task.getTopActivity().appTimeTracker,
- reason);
+ moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
+
+ // moveTaskToStackUncheckedLocked() should already placed the task on top,
+ // still need moveTaskToFrontLocked() below for any transition settings.
}
+ final ActivityRecord r = task.getTopActivity();
+ task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+ r == null ? null : r.appTimeTracker, reason);
+
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + task.stack);
}
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index bf7063f..a61e83f 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -300,7 +300,8 @@
return false;
}
- if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
+ if ((mAppToken.allDrawn || mAppToken.mAnimatingWithSavedSurface
+ || animating || mAppToken.startingDisplayed)
&& animation != null) {
if (!animating) {
if (DEBUG_ANIM) Slog.v(TAG,
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index d18c854..943e3ea 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -52,6 +52,13 @@
final boolean voiceInteraction;
+ // Whether the window has a saved surface from last pause, which can be
+ // used to start an entering animation earlier.
+ boolean mHasSavedSurface;
+
+ // Whether we're performing an entering animation with a saved surface.
+ boolean mAnimatingWithSavedSurface;
+
Task mTask;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -260,10 +267,13 @@
final int N = allAppWindows.size();
for (int i=0; i<N; i++) {
WindowState win = allAppWindows.get(i);
+ // 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 ||
- (win.mWinAnimator.isAnimating() &&
- !service.mAppTransition.isTransitionSet()))
+ && (win.mViewVisibility == View.VISIBLE
+ || mAnimatingWithSavedSurface
+ || (win.mWinAnimator.isAnimating() &&
+ !service.mAppTransition.isTransitionSet()))
&& !win.mDestroying && win.isDrawnLw()) {
return true;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6527881..4d11452 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -18,6 +18,7 @@
import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.HOME_STACK_ID;
import static android.app.ActivityManager.PINNED_STACK_ID;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static com.android.server.wm.WindowManagerService.TAG;
@@ -324,6 +325,10 @@
return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
}
+ boolean inHomeStack() {
+ return mStack != null && mStack.mStackId == HOME_STACK_ID;
+ }
+
boolean inFreeformWorkspace() {
return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 928a117..be86e2f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -413,7 +413,7 @@
final AppWindowToken atoken = win.mAppToken;
if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
- if (atoken == null || atoken.allDrawn) {
+ if (atoken == null || atoken.allDrawn || atoken.mAnimatingWithSavedSurface) {
if (winAnimator.performShowLocked()) {
setPendingLayoutChanges(displayId,
WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e3e3693..8a2442a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2687,9 +2687,16 @@
if (winAnimator.mSurfaceControl != null) {
if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
+ ": mExiting=" + win.mExiting);
+ // If we are using a saved surface to do enter animation, just let the
+ // animation run and don't destroy the surface. This could happen when
+ // the app sets visibility to invisible for the first time after resume,
+ // or when the user exits immediately after a resume. In both cases, we
+ // don't want to destroy the saved surface.
+ final boolean isAnimatingWithSavedSurface =
+ win.mAppToken != null && win.mAppToken.mAnimatingWithSavedSurface;
// If we are not currently running the exit animation, we
// need to see about starting one.
- if (!win.mExiting) {
+ if (!win.mExiting && !isAnimatingWithSavedSurface) {
surfaceChanged = true;
// Try starting an animation; if there isn't one, we
// can destroy the surface right away.
@@ -2848,6 +2855,12 @@
getDefaultDisplayContentLocked().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
+ if (win.mAppToken != null) {
+ // 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.
+ win.mAppToken.mAnimatingWithSavedSurface = false;
+ }
win.setDisplayLayoutNeeded();
mWindowPlacerLocked.requestTraversal();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 42a0e9d..e9ea3a8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -36,6 +36,7 @@
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.graphics.Point;
import android.os.PowerManager;
@@ -1504,6 +1505,31 @@
return mExiting || (mService.mClosingApps.contains(mAppToken));
}
+ boolean saveSurfaceIfNeeded() {
+ if (ActivityManager.isLowRamDeviceStatic()) {
+ // Don't save surfaces on Svelte devices.
+ return false;
+ }
+
+ Task task = getTask();
+ if (task == null || task.inHomeStack()) {
+ // Don't save surfaces for home stack apps. These usually resume and draw
+ // first frame very fast. Saving surfaces are mostly a waste of memory.
+ return false;
+ }
+
+ // We want to save surface if the app's windows are "allDrawn", or if we're
+ // currently animating with save surfaces. (If the app didn't even finish
+ // drawing when the user exits, but we have a saved surface from last time,
+ // we still want to keep that surface.)
+ if (mAppToken.allDrawn || mAppToken.mAnimatingWithSavedSurface) {
+ mAppToken.mHasSavedSurface = true;
+ return true;
+ }
+
+ return false;
+ }
+
@Override
public boolean isDefaultDisplay() {
final DisplayContent displayContent = getDisplayContent();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9344b8d..68c39ba 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -535,6 +535,7 @@
mDrawState = COMMIT_DRAW_PENDING;
return true;
}
+
return false;
}
@@ -554,7 +555,8 @@
mDrawState = READY_TO_SHOW;
boolean result = false;
final AppWindowToken atoken = mWin.mAppToken;
- if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
+ if (atoken == null || atoken.allDrawn || atoken.mAnimatingWithSavedSurface ||
+ mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = performShowLocked();
}
if (mDestroyPreservedSurfaceUponRedraw && result) {
@@ -995,12 +997,16 @@
}
void destroySurfaceLocked() {
- if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) {
- mWin.mAppToken.startingDisplayed = false;
+ final AppWindowToken wtoken = mWin.mAppToken;
+ if (wtoken != null) {
+ wtoken.mHasSavedSurface = false;
+ wtoken.mAnimatingWithSavedSurface = false;
+ if (mWin == wtoken.startingWindow) {
+ wtoken.startingDisplayed = false;
+ }
}
if (mSurfaceControl != null) {
-
int i = mWin.mChildWindows.size();
while (i > 0) {
i--;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 0c004b2..e2f4dd9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -17,6 +17,7 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.WindowManagerService.DEBUG;
import static com.android.server.wm.WindowManagerService.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerService.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT_REPEATS;
@@ -340,6 +341,10 @@
// Don't remove this window until rotation has completed.
continue;
}
+ // Discard the saved surface if window size is changed, it can't be reused.
+ if (win.mAppToken != null && win.mAppToken.mHasSavedSurface) {
+ win.mWinAnimator.destroySurfaceLocked();
+ }
win.reportResized();
mService.mResizingWindows.remove(i);
}
@@ -371,7 +376,9 @@
if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
wallpaperDestroyed = true;
}
- win.mWinAnimator.destroySurfaceLocked();
+ if (!win.saveSurfaceIfNeeded()) {
+ win.mWinAnimator.destroySurfaceLocked();
+ }
} while (i > 0);
mService.mDestroySurface.clear();
}
@@ -1174,6 +1181,18 @@
}
}
createThumbnailAppAnimator(transit, wtoken, topOpeningLayer, topClosingLayer);
+
+ if (wtoken.mHasSavedSurface) {
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+ "Early start of animation: " + wtoken + ", allDrawn=" + wtoken.allDrawn);
+
+ for (int j = 0; j < wtoken.windows.size(); j++) {
+ WindowState ws = wtoken.windows.get(j);
+ ws.mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
+ }
+ wtoken.mHasSavedSurface = false;
+ wtoken.mAnimatingWithSavedSurface = true;
+ }
}
AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
@@ -1219,6 +1238,10 @@
+ wtoken.allDrawn + " startingDisplayed="
+ wtoken.startingDisplayed + " startingMoved="
+ wtoken.startingMoved);
+
+ if (wtoken.mHasSavedSurface || wtoken.mAnimatingWithSavedSurface) {
+ continue;
+ }
if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
return false;
}