diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index cd4555d5c08cd..5995e9c3bb5e7 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -950,6 +950,16 @@ public class AppTransition implements Dump { return prepareThumbnailAnimation(a, appWidth, appHeight, transit); } + /** + * @return true if and only if the first frame of the transition can be skipped, i.e. the first + * frame of the transition doesn't change the visuals on screen, so we can start + * directly with the second one + */ + boolean canSkipFirstFrame() { + return mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM + && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE + && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL; + } Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets, diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 2e8938597e33d..df7b23d882761 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -24,6 +24,7 @@ import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; import android.graphics.Matrix; import android.util.Slog; import android.util.TimeUtils; +import android.view.Choreographer; import android.view.Display; import android.view.SurfaceControl; import android.view.WindowManagerPolicy; @@ -89,6 +90,8 @@ public class AppWindowAnimator { * See {@link #transferCurrentAnimation}*/ boolean usingTransferredAnimation = false; + private boolean mSkipFirstFrame = false; + static final Animation sDummyAnimation = new DummyAnimation(); public AppWindowAnimator(final AppWindowToken atoken) { @@ -97,7 +100,7 @@ public class AppWindowAnimator { mAnimator = atoken.mAnimator; } - public void setAnimation(Animation anim, int width, int height) { + public void setAnimation(Animation anim, int width, int height, boolean skipFirstFrame) { if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken + ": " + anim + " wxh=" + width + "x" + height + " isVisible=" + mAppToken.isVisible()); @@ -125,6 +128,8 @@ public class AppWindowAnimator { transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); hasTransformation = true; + this.mSkipFirstFrame = skipFirstFrame; + if (!mAppToken.appFullscreen) { anim.setBackgroundColor(0); } @@ -271,6 +276,18 @@ public class AppWindowAnimator { return hasMoreFrames; } + private long getStartTimeCorrection() { + if (mSkipFirstFrame) { + + // If the transition is an animation in which the first frame doesn't change the screen + // contents at all, we can just skip it and start at the second frame. So we shift the + // start time of the animation forward by minus the frame duration. + return -Choreographer.getInstance().getFrameIntervalNanos() / TimeUtils.NANOS_PER_MS; + } else { + return 0; + } + } + // This must be called while inside a transaction. boolean stepAnimationLocked(long currentTime, final int displayId) { if (mService.okToDisplay()) { @@ -292,12 +309,14 @@ public class AppWindowAnimator { " @ " + currentTime + " scale=" + mService.getTransitionAnimationScaleLocked() + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); - animation.setStartTime(currentTime); + long correction = getStartTimeCorrection(); + animation.setStartTime(currentTime + correction); animating = true; if (thumbnail != null) { thumbnail.show(); - thumbnailAnimation.setStartTime(currentTime); + thumbnailAnimation.setStartTime(currentTime + correction); } + mSkipFirstFrame = false; } if (stepAnimation(currentTime)) { // animation isn't over, step any thumbnail and that's diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6b5c224af2209..38e27653c2ec2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3489,7 +3489,8 @@ public class WindowManagerService extends IWindowManager.Stub } Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e); } - atoken.mAppAnimator.setAnimation(a, width, height); + atoken.mAppAnimator.setAnimation(a, width, height, + mAppTransition.canSkipFirstFrame()); } } else { atoken.mAppAnimator.clearAnimation();