summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/res/anim/screen_rotate_0_exit.xml3
-rw-r--r--core/res/res/anim/screen_rotate_180_exit.xml3
-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.xml5
-rw-r--r--core/res/res/anim/screen_rotate_plus_90_exit.xml5
-rw-r--r--core/res/res/anim/screen_rotate_plus_90_frame.xml28
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--services/core/java/com/android/server/wm/BlackFrame.java17
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java20
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java378
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java1
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);