diff options
| -rw-r--r-- | core/res/res/anim/screen_rotate_0_exit.xml | 3 | ||||
| -rw-r--r-- | core/res/res/anim/screen_rotate_180_exit.xml | 3 | ||||
| -rw-r--r-- | core/res/res/anim/screen_rotate_alpha.xml (renamed from core/res/res/anim/screen_rotate_minus_90_frame.xml) | 11 | ||||
| -rw-r--r-- | core/res/res/anim/screen_rotate_minus_90_exit.xml | 5 | ||||
| -rw-r--r-- | core/res/res/anim/screen_rotate_plus_90_exit.xml | 5 | ||||
| -rw-r--r-- | core/res/res/anim/screen_rotate_plus_90_frame.xml | 28 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 3 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/BlackFrame.java | 17 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DisplayContent.java | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ScreenRotationAnimation.java | 378 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowAnimator.java | 28 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 1 |
12 files changed, 276 insertions, 226 deletions
diff --git a/core/res/res/anim/screen_rotate_0_exit.xml b/core/res/res/anim/screen_rotate_0_exit.xml index f1df2de04619..37d5a4115621 100644 --- a/core/res/res/anim/screen_rotate_0_exit.xml +++ b/core/res/res/anim/screen_rotate_0_exit.xml @@ -19,7 +19,4 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> - <alpha android:fromAlpha="1.0" android:toAlpha="0" - android:interpolator="@interpolator/decelerate_quint" - android:duration="@android:integer/config_shortAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_180_exit.xml b/core/res/res/anim/screen_rotate_180_exit.xml index 1eb6361c736f..58a1868bd398 100644 --- a/core/res/res/anim/screen_rotate_180_exit.xml +++ b/core/res/res/anim/screen_rotate_180_exit.xml @@ -25,7 +25,4 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_mediumAnimTime" /> - <alpha android:fromAlpha="1.0" android:toAlpha="0" - android:interpolator="@interpolator/decelerate_cubic" - android:duration="@android:integer/config_mediumAnimTime"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/screen_rotate_minus_90_frame.xml b/core/res/res/anim/screen_rotate_alpha.xml index 2d198f3929e6..c49ef9cafd39 100644 --- a/core/res/res/anim/screen_rotate_minus_90_frame.xml +++ b/core/res/res/anim/screen_rotate_alpha.xml @@ -19,10 +19,9 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> - <rotate android:fromDegrees="0" android:toDegrees="90" - android:pivotX="50%" android:pivotY="50%" - android:interpolator="@interpolator/decelerate_quint" - android:fillEnabled="true" - android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_longAnimTime" /> + <alpha android:fromAlpha="1.0" android:toAlpha="0.0" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_minus_90_exit.xml b/core/res/res/anim/screen_rotate_minus_90_exit.xml index 9b389392c3e4..0927dd30ceb3 100644 --- a/core/res/res/anim/screen_rotate_minus_90_exit.xml +++ b/core/res/res/anim/screen_rotate_minus_90_exit.xml @@ -40,9 +40,4 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_mediumAnimTime" /> - <alpha android:fromAlpha="1.0" android:toAlpha="0" - android:interpolator="@interpolator/decelerate_quint" - android:fillEnabled="true" - android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_plus_90_exit.xml b/core/res/res/anim/screen_rotate_plus_90_exit.xml index fa345337cbf6..fd786f9afce0 100644 --- a/core/res/res/anim/screen_rotate_plus_90_exit.xml +++ b/core/res/res/anim/screen_rotate_plus_90_exit.xml @@ -40,9 +40,4 @@ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_mediumAnimTime" /> - <alpha android:fromAlpha="1.0" android:toAlpha="0" - android:interpolator="@interpolator/decelerate_quint" - android:fillEnabled="true" - android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_plus_90_frame.xml b/core/res/res/anim/screen_rotate_plus_90_frame.xml deleted file mode 100644 index cd2005087291..000000000000 --- a/core/res/res/anim/screen_rotate_plus_90_frame.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false"> - <rotate android:fromDegrees="0" android:toDegrees="-90" - android:pivotX="50%" android:pivotY="50%" - android:interpolator="@interpolator/decelerate_quint" - android:fillEnabled="true" - android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_longAnimTime" /> -</set> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 761e02fe5dad..5a1531315332 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1880,15 +1880,14 @@ <java-symbol type="anim" name="screen_rotate_180_enter" /> <java-symbol type="anim" name="screen_rotate_180_exit" /> <java-symbol type="anim" name="screen_rotate_180_frame" /> + <java-symbol type="anim" name="screen_rotate_alpha"/> <java-symbol type="anim" name="screen_rotate_finish_enter" /> <java-symbol type="anim" name="screen_rotate_finish_exit" /> <java-symbol type="anim" name="screen_rotate_finish_frame" /> <java-symbol type="anim" name="screen_rotate_minus_90_enter" /> <java-symbol type="anim" name="screen_rotate_minus_90_exit" /> - <java-symbol type="anim" name="screen_rotate_minus_90_frame" /> <java-symbol type="anim" name="screen_rotate_plus_90_enter" /> <java-symbol type="anim" name="screen_rotate_plus_90_exit" /> - <java-symbol type="anim" name="screen_rotate_plus_90_frame" /> <java-symbol type="anim" name="screen_rotate_start_enter" /> <java-symbol type="anim" name="screen_rotate_start_exit" /> <java-symbol type="anim" name="screen_rotate_start_frame" /> diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java index 7557271a2416..727850a087ab 100644 --- a/services/core/java/com/android/server/wm/BlackFrame.java +++ b/services/core/java/com/android/server/wm/BlackFrame.java @@ -40,7 +40,8 @@ public class BlackFrame { final SurfaceControl surface; BlackSurface(SurfaceControl.Transaction transaction, int layer, - int l, int t, int r, int b, DisplayContent dc) throws OutOfResourcesException { + int l, int t, int r, int b, DisplayContent dc, + SurfaceControl surfaceControl) throws OutOfResourcesException { left = l; top = t; this.layer = layer; @@ -50,7 +51,7 @@ public class BlackFrame { surface = dc.makeOverlay() .setName("BlackSurface") .setColorLayer() - .setParent(null) // TODO: Work-around for b/69259549 + .setParent(surfaceControl) .build(); transaction.setWindowCrop(surface, w, h); transaction.setLayerStack(surface, dc.getDisplayId()); @@ -114,7 +115,8 @@ public class BlackFrame { } public BlackFrame(Supplier<SurfaceControl.Transaction> factory, SurfaceControl.Transaction t, - Rect outer, Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation) + Rect outer, Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation, + SurfaceControl surfaceControl) throws OutOfResourcesException { boolean success = false; @@ -128,19 +130,20 @@ public class BlackFrame { try { if (outer.top < inner.top) { mBlackSurfaces[0] = new BlackSurface(t, layer, - outer.left, outer.top, inner.right, inner.top, dc); + outer.left, outer.top, inner.right, inner.top, dc, surfaceControl); } if (outer.left < inner.left) { mBlackSurfaces[1] = new BlackSurface(t, layer, - outer.left, inner.top, inner.left, outer.bottom, dc); + outer.left, inner.top, inner.left, outer.bottom, dc, surfaceControl); } if (outer.bottom > inner.bottom) { mBlackSurfaces[2] = new BlackSurface(t, layer, - inner.left, inner.bottom, outer.right, outer.bottom, dc); + inner.left, inner.bottom, outer.right, outer.bottom, dc, + surfaceControl); } if (outer.right > inner.right) { mBlackSurfaces[3] = new BlackSurface(t, layer, - inner.right, outer.top, outer.right, inner.bottom, dc); + inner.right, outer.top, outer.right, inner.bottom, dc, surfaceControl); } success = true; } finally { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 63ff2ea8069c..a16036bca2eb 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -521,9 +521,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ private int mDeferUpdateImeTargetCount; - /** Temporary float array to retrieve 3x3 matrix values. */ - private final float[] mTmpFloats = new float[9]; - private MagnificationSpec mMagnificationSpec; private InputMonitor mInputMonitor; @@ -4659,20 +4656,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo void prepareSurfaces() { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces"); try { - final ScreenRotationAnimation screenRotationAnimation = - mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); final Transaction transaction = getPendingTransaction(); - if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { - screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats); - transaction.setMatrix(mWindowingLayer, - mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], - mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); - transaction.setPosition(mWindowingLayer, - mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]); - transaction.setAlpha(mWindowingLayer, - screenRotationAnimation.getEnterTransformation().getAlpha()); - } - super.prepareSurfaces(); // TODO: Once we totally eliminate global transaction we will pass transaction in here @@ -4902,6 +4886,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mWindowingLayer; } + SurfaceControl getOverlayLayer() { + return mOverlayLayer; + } + /** * Updates the display's system gesture exclusion. * diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index cbaf098fa4bd..c4bfe4b0c6c5 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -27,6 +27,7 @@ import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER; import android.content.Context; import android.graphics.Matrix; +import android.graphics.Point; import android.graphics.Rect; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -41,6 +42,34 @@ import android.view.animation.Transformation; import java.io.PrintWriter; +/** + * This class handles the rotation animation when the device is rotated. + * + * <p> + * The screen rotation animation is composed of 4 different part: + * <ul> + * <li> The screenshot: <p> + * A screenshot of the whole screen prior the change of orientation is taken to hide the + * element resizing below. The screenshot is then animated to rotate and cross-fade to + * the new orientation with the content in the new orientation. + * + * <li> The windows on the display: <p>y + * Once the device is rotated, the screen and its content are in the new orientation. The + * animation first rotate the new content into the old orientation to then be able to + * animate to the new orientation + * + * <li> The exiting Blackframe: <p> + * Because the change of orientation might change the width and height of the content (i.e + * when rotating from portrait to landscape) we "crop" the new content using black frames + * around the screenshot so the new content does not go beyond the screenshot's bounds + * + * <li> The entering Blackframe: <p> + * The enter Blackframe is similar to the exit Blackframe but is only used when a custom + * rotation animation is used and matches the new content size instead of the screenshot. + * </ul> + * + * Each part has its own Surface which are then animated by {@link SurfaceAnimator}s. + */ class ScreenRotationAnimation { private static final String TAG = TAG_WITH_CLASS_NAME ? "ScreenRotationAnimation" : TAG_WM; @@ -66,6 +95,8 @@ class ScreenRotationAnimation { private final Matrix mSnapshotFinalMatrix = new Matrix(); private final Matrix mExitFrameFinalMatrix = new Matrix(); private final WindowManagerService mService; + private SurfaceControl mEnterBlackFrameLayer; + private SurfaceControl mRotationLayer; private SurfaceControl mSurfaceControl; private BlackFrame mEnteringBlackFrame; private int mWidth, mHeight; @@ -81,15 +112,14 @@ class ScreenRotationAnimation { // rotations. private Animation mRotateExitAnimation; private Animation mRotateEnterAnimation; + private Animation mRotateAlphaAnimation; private boolean mStarted; private boolean mAnimRunning; private boolean mFinishAnimReady; private long mFinishAnimStartTime; private boolean mForceDefaultOrientation; private BlackFrame mExitingBlackFrame; - private boolean mMoreRotateEnter; - private boolean mMoreRotateExit; - private long mHalfwayPoint; + private SurfaceRotationAnimationController mSurfaceRotationAnimationController; public ScreenRotationAnimation(Context context, DisplayContent displayContent, boolean fixedToUserRotation, boolean isSecure, WindowManagerService service) { @@ -126,11 +156,23 @@ class ScreenRotationAnimation { mOriginalRotation = originalRotation; mOriginalWidth = originalWidth; mOriginalHeight = originalHeight; + mSurfaceRotationAnimationController = new SurfaceRotationAnimationController(); final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); try { - mSurfaceControl = displayContent.makeOverlay() + mRotationLayer = displayContent.makeOverlay() + .setName("RotationLayer") + .setContainerLayer() + .build(); + + mEnterBlackFrameLayer = displayContent.makeOverlay() + .setName("EnterBlackFrameLayer") + .setContainerLayer() + .build(); + + mSurfaceControl = displayContent.makeSurface(null) .setName("ScreenshotSurface") + .setParent(mRotationLayer) .setBufferSize(mWidth, mHeight) .setSecure(isSecure) .build(); @@ -160,8 +202,10 @@ class ScreenRotationAnimation { if (gb.containsSecureLayers()) { t.setSecure(mSurfaceControl, true); } + t.setLayer(mRotationLayer, SCREEN_FREEZE_LAYER_BASE); t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT); t.setAlpha(mSurfaceControl, 0); + t.show(mRotationLayer); t.show(mSurfaceControl); } else { Slog.w(TAG, "Unable to take screenshot of display " + displayId); @@ -211,22 +255,26 @@ class ScreenRotationAnimation { return mSurfaceControl != null; } - private void setSnapshotTransform(SurfaceControl.Transaction t, Matrix matrix, float alpha) { - if (mSurfaceControl != null) { - matrix.getValues(mTmpFloats); - float x = mTmpFloats[Matrix.MTRANS_X]; - float y = mTmpFloats[Matrix.MTRANS_Y]; - if (mForceDefaultOrientation) { - mDisplayContent.getBounds(mCurrentDisplayRect); - x -= mCurrentDisplayRect.left; - y -= mCurrentDisplayRect.top; - } - t.setPosition(mSurfaceControl, x, y); - t.setMatrix(mSurfaceControl, - mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], - mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); - t.setAlpha(mSurfaceControl, alpha); + private void setRotationTransform(SurfaceControl.Transaction t, Matrix matrix) { + if (mRotationLayer == null) { + return; } + matrix.getValues(mTmpFloats); + float x = mTmpFloats[Matrix.MTRANS_X]; + float y = mTmpFloats[Matrix.MTRANS_Y]; + if (mForceDefaultOrientation) { + mDisplayContent.getBounds(mCurrentDisplayRect); + x -= mCurrentDisplayRect.left; + y -= mCurrentDisplayRect.top; + } + t.setPosition(mRotationLayer, x, y); + t.setMatrix(mRotationLayer, + mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], + mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); + + t.setAlpha(mSurfaceControl, (float) 1.0); + t.setAlpha(mRotationLayer, (float) 1.0); + t.show(mRotationLayer); } public void printTo(String prefix, PrintWriter pw) { @@ -237,7 +285,9 @@ class ScreenRotationAnimation { if (mExitingBlackFrame != null) { mExitingBlackFrame.printTo(prefix + " ", pw); } - pw.print(prefix); pw.print("mEnteringBlackFrame="); pw.println(mEnteringBlackFrame); + pw.print(prefix); + pw.print("mEnteringBlackFrame="); + pw.println(mEnteringBlackFrame); if (mEnteringBlackFrame != null) { mEnteringBlackFrame.printTo(prefix + " ", pw); } @@ -283,7 +333,7 @@ class ScreenRotationAnimation { int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0); createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix); - setSnapshotTransform(t, mSnapshotInitialMatrix, 1.0f); + setRotationTransform(t, mSnapshotInitialMatrix); } /** @@ -304,6 +354,9 @@ class ScreenRotationAnimation { // Figure out how the screen has moved from the original rotation. int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation); + mRotateAlphaAnimation = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.screen_rotate_alpha); + final boolean customAnim; if (exitAnim != 0 && enterAnim != 0) { customAnim = true; @@ -353,6 +406,8 @@ class ScreenRotationAnimation { mRotateExitAnimation.scaleCurrentDuration(animationScale); mRotateEnterAnimation.restrictDuration(maxAnimationDuration); mRotateEnterAnimation.scaleCurrentDuration(animationScale); + mRotateAlphaAnimation.restrictDuration(maxAnimationDuration); + mRotateAlphaAnimation.scaleCurrentDuration(animationScale); if (!customAnim && mExitingBlackFrame == null) { try { @@ -373,13 +428,12 @@ class ScreenRotationAnimation { outer = mCurrentDisplayRect; inner = mOriginalDisplayRect; } else { - outer = new Rect(-mOriginalWidth * 1, -mOriginalHeight * 1, - mOriginalWidth * 2, mOriginalHeight * 2); - inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); + outer = new Rect(-mWidth, -mHeight, mWidth * 2, mHeight * 2); + inner = new Rect(0, 0, mWidth, mHeight); } mExitingBlackFrame = new BlackFrame(mService.mTransactionFactory, t, outer, inner, - SCREEN_FREEZE_LAYER_EXIT, mDisplayContent, mForceDefaultOrientation); - mExitingBlackFrame.setMatrix(t, mFrameInitialMatrix); + SCREEN_FREEZE_LAYER_EXIT, mDisplayContent, mForceDefaultOrientation, + mRotationLayer); } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); } @@ -387,16 +441,17 @@ class ScreenRotationAnimation { if (customAnim && mEnteringBlackFrame == null) { try { - Rect outer = new Rect(-finalWidth * 1, -finalHeight * 1, + Rect outer = new Rect(-finalWidth, -finalHeight, finalWidth * 2, finalHeight * 2); Rect inner = new Rect(0, 0, finalWidth, finalHeight); mEnteringBlackFrame = new BlackFrame(mService.mTransactionFactory, t, outer, inner, - SCREEN_FREEZE_LAYER_ENTER, mDisplayContent, false); + SCREEN_FREEZE_LAYER_ENTER, mDisplayContent, false, mEnterBlackFrameLayer); } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); } } + mSurfaceRotationAnimationController.startAnimation(); return true; } @@ -421,14 +476,31 @@ class ScreenRotationAnimation { } public void kill() { + if (mSurfaceRotationAnimationController != null) { + mSurfaceRotationAnimationController.cancel(); + mSurfaceRotationAnimationController = null; + } if (mSurfaceControl != null) { if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { Slog.i(TAG_WM, " FREEZE " + mSurfaceControl + ": DESTROY"); } - mService.mTransactionFactory.get().remove(mSurfaceControl).apply(); mSurfaceControl = null; + SurfaceControl.Transaction t = mService.mTransactionFactory.get(); + if (mRotationLayer != null) { + if (mRotationLayer.isValid()) { + t.remove(mRotationLayer); + } + mRotationLayer = null; + } + if (mEnterBlackFrameLayer != null) { + if (mEnterBlackFrameLayer.isValid()) { + t.remove(mEnterBlackFrameLayer); + } + mEnterBlackFrameLayer = null; + } + t.apply(); } if (mExitingBlackFrame != null) { mExitingBlackFrame.kill(); @@ -446,124 +518,186 @@ class ScreenRotationAnimation { mRotateEnterAnimation.cancel(); mRotateEnterAnimation = null; } + if (mRotateAlphaAnimation != null) { + mRotateAlphaAnimation.cancel(); + mRotateAlphaAnimation = null; + } } public boolean isAnimating() { - return hasAnimations(); + return mSurfaceRotationAnimationController != null + && mSurfaceRotationAnimationController.isAnimating(); } public boolean isRotating() { return mCurRotation != mOriginalRotation; } - private boolean hasAnimations() { - return mRotateEnterAnimation != null || mRotateExitAnimation != null; + public Transformation getEnterTransformation() { + return mEnterTransformation; } - private boolean stepAnimation(long now) { - if (now > mHalfwayPoint) { - mHalfwayPoint = Long.MAX_VALUE; - } - if (mFinishAnimReady && mFinishAnimStartTime < 0) { - mFinishAnimStartTime = now; - } - - mMoreRotateExit = false; - if (mRotateExitAnimation != null) { - mMoreRotateExit = mRotateExitAnimation.getTransformation(now, - mRotateExitTransformation); - } - - mMoreRotateEnter = false; - if (mRotateEnterAnimation != null) { - mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, - mRotateEnterTransformation); - } - - if (!mMoreRotateExit) { - if (mRotateExitAnimation != null) { - mRotateExitAnimation.cancel(); - mRotateExitAnimation = null; - mRotateExitTransformation.clear(); + /** + * Utility class that runs a {@link ScreenRotationAnimation} on the {@link + * SurfaceAnimationRunner}. + * <p> + * The rotation animation is divided into the following hierarchy: + * <ul> + * <li> A first rotation layer, containing the blackframes. This layer is animated by the + * "screen_rotate_X_exit" that applies a scale and rotate and where X is value of the rotation. + * <ul> + * <li> A child layer containing the screenshot on which is added an animation of it's + * alpha channel ("screen_rotate_alpha") and that will rotate with his parent layer.</li> + * </ul> + * <li> A second rotation layer used when custom animations are passed in + * {@link ScreenRotationAnimation#startAnimation( + * SurfaceControl.Transaction, long, float, int, int, int, int)}. + * </ul> + * <p> + * Thus an {@link LocalAnimationAdapter.AnimationSpec} is created for each of + * this three {@link SurfaceControl}s which then delegates the animation to the + * {@link ScreenRotationAnimation}. + */ + class SurfaceRotationAnimationController { + private SurfaceAnimator mDisplayAnimator; + private SurfaceAnimator mEnterBlackFrameAnimator; + private SurfaceAnimator mScreenshotRotationAnimator; + private SurfaceAnimator mRotateScreenAnimator; + private final Runnable mNoopCallback = () -> { // b/141177184 + }; + + /** + * Start the rotation animation of the display and the screenshot on the + * {@link SurfaceAnimationRunner}. + */ + void startAnimation() { + mRotateScreenAnimator = startScreenshotAlphaAnimation(); + mDisplayAnimator = startDisplayRotation(); + if (mExitingBlackFrame != null) { + mScreenshotRotationAnimator = startScreenshotRotationAnimation(); } - } - - if (!mMoreRotateEnter) { - if (mRotateEnterAnimation != null) { - mRotateEnterAnimation.cancel(); - mRotateEnterAnimation = null; - mRotateEnterTransformation.clear(); + if (mEnteringBlackFrame != null) { + mEnterBlackFrameAnimator = startEnterBlackFrameAnimation(); } } - mExitTransformation.set(mRotateExitTransformation); - mEnterTransformation.set(mRotateEnterTransformation); - - final boolean more = mMoreRotateEnter || mMoreRotateExit - || !mFinishAnimReady; - - mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix); - - return more; - } - - void updateSurfaces(SurfaceControl.Transaction t) { - if (!mStarted) { - return; - } - - if (mSurfaceControl != null) { - if (!mMoreRotateExit) { - t.hide(mSurfaceControl); + private SimpleSurfaceAnimatable.Builder initializeBuilder() { + return new SimpleSurfaceAnimatable.Builder() + .setPendingTransactionSupplier(mDisplayContent::getPendingTransaction) + .setCommitTransactionRunnable(mDisplayContent::commitPendingTransaction) + .setAnimationLeashSupplier(mDisplayContent::makeOverlay); + } + + private SurfaceAnimator startDisplayRotation() { + return startAnimation(initializeBuilder() + .setAnimationLeashParent(mDisplayContent.getSurfaceControl()) + .setSurfaceControl(mDisplayContent.getWindowingLayer()) + .setParentSurfaceControl(mDisplayContent.getSurfaceControl()) + .setWidth(mDisplayContent.getSurfaceWidth()) + .setHeight(mDisplayContent.getSurfaceHeight()) + .build(), + createWindowAnimationSpec(mRotateEnterAnimation), + this::cancel); + } + + private SurfaceAnimator startScreenshotAlphaAnimation() { + return startAnimation(initializeBuilder() + .setSurfaceControl(mSurfaceControl) + .setAnimationLeashParent(mRotationLayer) + .setWidth(mWidth) + .setHeight(mHeight) + .build(), + createWindowAnimationSpec(mRotateAlphaAnimation), + mNoopCallback); + } + + private SurfaceAnimator startEnterBlackFrameAnimation() { + return startAnimation(initializeBuilder() + .setSurfaceControl(mEnterBlackFrameLayer) + .setAnimationLeashParent(mDisplayContent.getOverlayLayer()) + .build(), + createWindowAnimationSpec(mRotateEnterAnimation), + mNoopCallback); + } + + private SurfaceAnimator startScreenshotRotationAnimation() { + return startAnimation(initializeBuilder() + .setSurfaceControl(mRotationLayer) + .setAnimationLeashParent(mDisplayContent.getOverlayLayer()) + .build(), + createWindowAnimationSpec(mRotateExitAnimation), + this::onAnimationEnd); + } + + private WindowAnimationSpec createWindowAnimationSpec(Animation mAnimation) { + return new WindowAnimationSpec(mAnimation, new Point(0, 0) /* position */, + false /* canSkipFirstFrame */, 0 /* WindowCornerRadius */); + } + + /** + * Start an animation defined by animationSpec on a new {@link SurfaceAnimator}. + * + * @param animatable The animatable used for the animation. + * @param animationSpec The spec of the animation. + * @param animationFinishedCallback Callback passed to the {@link SurfaceAnimator} and + * called when the animation finishes. + * @return The newly created {@link SurfaceAnimator} that as been started. + */ + private SurfaceAnimator startAnimation( + SurfaceAnimator.Animatable animatable, + LocalAnimationAdapter.AnimationSpec animationSpec, + Runnable animationFinishedCallback) { + SurfaceAnimator animator = new SurfaceAnimator( + animatable, animationFinishedCallback, mService); + + LocalAnimationAdapter localAnimationAdapter = new LocalAnimationAdapter( + animationSpec, mService.mSurfaceAnimationRunner); + + animator.startAnimation(mDisplayContent.getPendingTransaction(), + localAnimationAdapter, false); + return animator; + } + + private void onAnimationEnd() { + mEnterBlackFrameAnimator = null; + mScreenshotRotationAnimator = null; + mRotateScreenAnimator = null; + mService.mAnimator.mBulkUpdateParams |= WindowSurfacePlacer.SET_UPDATE_ROTATION; + kill(); + mService.updateRotation(false, false); + AccessibilityController accessibilityController = mService.mAccessibilityController; + + if (accessibilityController != null) { + // We just finished rotation animation which means we did not + // announce the rotation and waited for it to end, announce now. + accessibilityController.onRotationChangedLocked(mDisplayContent); } } - if (mExitingBlackFrame != null) { - if (!mMoreRotateExit) { - mExitingBlackFrame.hide(t); - } else { - mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), - mFrameInitialMatrix); - mExitingBlackFrame.setMatrix(t, mExitFrameFinalMatrix); - if (mForceDefaultOrientation) { - mExitingBlackFrame.setAlpha(t, mExitTransformation.getAlpha()); - } + public void cancel() { + if (mEnterBlackFrameAnimator != null) { + mEnterBlackFrameAnimator.cancelAnimation(); } - } - if (mEnteringBlackFrame != null) { - if (!mMoreRotateEnter) { - mEnteringBlackFrame.hide(t); - } else { - mEnteringBlackFrame.setMatrix(t, mEnterTransformation.getMatrix()); + if (mScreenshotRotationAnimator != null) { + mScreenshotRotationAnimator.cancelAnimation(); } - } - - t.setEarlyWakeup(); - setSnapshotTransform(t, mSnapshotFinalMatrix, mExitTransformation.getAlpha()); - } - - public boolean stepAnimationLocked(long now) { - if (!hasAnimations()) { - mFinishAnimReady = false; - return false; - } - if (!mAnimRunning) { - if (mRotateEnterAnimation != null) { - mRotateEnterAnimation.setStartTime(now); + if (mRotateScreenAnimator != null) { + mRotateScreenAnimator.cancelAnimation(); } - if (mRotateExitAnimation != null) { - mRotateExitAnimation.setStartTime(now); + + if (mDisplayAnimator != null) { + mDisplayAnimator.cancelAnimation(); } - mAnimRunning = true; - mHalfwayPoint = now + mRotateEnterAnimation.getDuration() / 2; } - return stepAnimation(now); - } - - public Transformation getEnterTransformation() { - return mEnterTransformation; + public boolean isAnimating() { + return mDisplayAnimator != null && mDisplayAnimator.isAnimating() + || mEnterBlackFrameAnimator != null && mEnterBlackFrameAnimator.isAnimating() + || mRotateScreenAnimator != null && mRotateScreenAnimator.isAnimating() + || mScreenshotRotationAnimator != null + && mScreenshotRotationAnimator.isAnimating(); + } } } diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index c7916e829349..f5356e9f78b8 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -21,7 +21,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 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.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; -import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION; import android.content.Context; import android.os.Trace; @@ -156,27 +155,6 @@ public class WindowAnimator { for (int i = 0; i < numDisplays; i++) { final int displayId = mDisplayContentsAnimators.keyAt(i); final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); - DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i); - - final ScreenRotationAnimation screenRotationAnimation = - displayAnimator.mScreenRotationAnimation; - if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { - if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) { - setAnimating(true); - } else { - mBulkUpdateParams |= SET_UPDATE_ROTATION; - screenRotationAnimation.kill(); - displayAnimator.mScreenRotationAnimation = null; - - // display. - if (accessibilityController != null) { - // We just finished rotation animation which means we did not - // announce the rotation and waited for it to end, announce now. - accessibilityController.onRotationChangedLocked(dc); - } - } - } - // Update animations of all applications, including those // associated with exiting/removed apps dc.updateWindowsForAnimator(); @@ -188,12 +166,6 @@ public class WindowAnimator { final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); dc.checkAppWindowsReadyToShow(); - - final ScreenRotationAnimation screenRotationAnimation = - mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation; - if (screenRotationAnimation != null) { - screenRotationAnimation.updateSurfaces(mTransaction); - } orAnimating(dc.getDockedDividerController().animate(mCurrentTime)); if (accessibilityController != null) { accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 14214b4be7d1..56bdd4b02249 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5458,7 +5458,6 @@ public class WindowManagerService extends IWindowManager.Stub getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { mTransaction.apply(); - scheduleAnimationLocked(); } else { screenRotationAnimation.kill(); mAnimator.setScreenRotationAnimationLocked(displayId, null); |