Implement crossfade and jumpcut rotation
Implement crossfade and jumpcut rotation animation into shell transition. Bug: 194715257 Test: manual Test: pass existing tests Change-Id: I12269971b22614ce16fb3329b52fc7bdef25af05
This commit is contained in:
@@ -313,7 +313,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
|
||||
final int anim = getRotationAnimation(info);
|
||||
if (!(isSeamless || anim == ROTATION_ANIMATION_JUMPCUT)) {
|
||||
mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
|
||||
mTransactionPool, startTransaction, change, info.getRootLeash());
|
||||
mTransactionPool, startTransaction, change, info.getRootLeash(),
|
||||
anim);
|
||||
mRotationAnimation.startAnimation(animations, onAnimFinish,
|
||||
mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
|
||||
continue;
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.wm.shell.transition;
|
||||
import static android.hardware.HardwareBuffer.RGBA_8888;
|
||||
import static android.hardware.HardwareBuffer.USAGE_PROTECTED_CONTENT;
|
||||
import static android.util.RotationUtils.deltaRotation;
|
||||
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
|
||||
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
|
||||
import static android.view.WindowManagerPolicyConstants.SCREEN_FREEZE_LAYER_BASE;
|
||||
|
||||
import static com.android.wm.shell.transition.DefaultTransitionHandler.startSurfaceAnimation;
|
||||
@@ -59,7 +61,7 @@ import java.util.Arrays;
|
||||
* This class handles the rotation animation when the device is rotated.
|
||||
*
|
||||
* <p>
|
||||
* The screen rotation animation is composed of 4 different part:
|
||||
* The screen rotation animation is composed of 3 different part:
|
||||
* <ul>
|
||||
* <li> The screenshot: <p>
|
||||
* A screenshot of the whole screen prior the change of orientation is taken to hide the
|
||||
@@ -75,10 +77,6 @@ import java.util.Arrays;
|
||||
* To have the animation seem more seamless, we add a color transitioning background behind the
|
||||
* exiting and entering layouts. We compute the brightness of the start and end
|
||||
* layouts and transition from the two brightness values as grayscale underneath the animation
|
||||
*
|
||||
* <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>
|
||||
*/
|
||||
class ScreenRotationAnimation {
|
||||
@@ -94,6 +92,7 @@ class ScreenRotationAnimation {
|
||||
private final Rect mStartBounds = new Rect();
|
||||
private final Rect mEndBounds = new Rect();
|
||||
|
||||
private final int mAnimHint;
|
||||
private final int mStartWidth;
|
||||
private final int mStartHeight;
|
||||
private final int mEndWidth;
|
||||
@@ -117,6 +116,7 @@ class ScreenRotationAnimation {
|
||||
// rotations.
|
||||
private Animation mRotateExitAnimation;
|
||||
private Animation mRotateEnterAnimation;
|
||||
private Animation mRotateAlphaAnimation;
|
||||
|
||||
/** Intensity of light/whiteness of the layout before rotation occurs. */
|
||||
private float mStartLuma;
|
||||
@@ -124,9 +124,10 @@ class ScreenRotationAnimation {
|
||||
private float mEndLuma;
|
||||
|
||||
ScreenRotationAnimation(Context context, SurfaceSession session, TransactionPool pool,
|
||||
Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash) {
|
||||
Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint) {
|
||||
mContext = context;
|
||||
mTransactionPool = pool;
|
||||
mAnimHint = animHint;
|
||||
|
||||
mSurfaceControl = change.getLeash();
|
||||
mStartWidth = change.getStartAbsBounds().width();
|
||||
@@ -160,13 +161,6 @@ class ScreenRotationAnimation {
|
||||
return;
|
||||
}
|
||||
|
||||
mBackColorSurface = new SurfaceControl.Builder(session)
|
||||
.setParent(rootLeash)
|
||||
.setColorLayer()
|
||||
.setCallsite("ShellRotationAnimation")
|
||||
.setName("BackColorSurface")
|
||||
.build();
|
||||
|
||||
mScreenshotLayer = new SurfaceControl.Builder(session)
|
||||
.setParent(mAnimLeash)
|
||||
.setBLASTLayer()
|
||||
@@ -175,17 +169,9 @@ class ScreenRotationAnimation {
|
||||
.setName("RotationLayer")
|
||||
.build();
|
||||
|
||||
HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
|
||||
mStartLuma = getMedianBorderLuma(hardwareBuffer, screenshotBuffer.getColorSpace());
|
||||
|
||||
GraphicBuffer buffer = GraphicBuffer.createFromHardwareBuffer(
|
||||
screenshotBuffer.getHardwareBuffer());
|
||||
|
||||
t.setLayer(mBackColorSurface, -1);
|
||||
t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
|
||||
t.setAlpha(mBackColorSurface, 1);
|
||||
t.show(mBackColorSurface);
|
||||
|
||||
t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE);
|
||||
t.setPosition(mAnimLeash, 0, 0);
|
||||
t.setAlpha(mAnimLeash, 1);
|
||||
@@ -195,6 +181,23 @@ class ScreenRotationAnimation {
|
||||
t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace());
|
||||
t.show(mScreenshotLayer);
|
||||
|
||||
if (!isCustomRotate()) {
|
||||
mBackColorSurface = new SurfaceControl.Builder(session)
|
||||
.setParent(rootLeash)
|
||||
.setColorLayer()
|
||||
.setCallsite("ShellRotationAnimation")
|
||||
.setName("BackColorSurface")
|
||||
.build();
|
||||
|
||||
HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
|
||||
mStartLuma = getMedianBorderLuma(hardwareBuffer, screenshotBuffer.getColorSpace());
|
||||
|
||||
t.setLayer(mBackColorSurface, -1);
|
||||
t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
|
||||
t.setAlpha(mBackColorSurface, 1);
|
||||
t.show(mBackColorSurface);
|
||||
}
|
||||
|
||||
} catch (Surface.OutOfResourcesException e) {
|
||||
Slog.w(TAG, "Unable to allocate freeze surface", e);
|
||||
}
|
||||
@@ -203,6 +206,10 @@ class ScreenRotationAnimation {
|
||||
t.apply();
|
||||
}
|
||||
|
||||
private boolean isCustomRotate() {
|
||||
return mAnimHint == ROTATION_ANIMATION_CROSSFADE || mAnimHint == ROTATION_ANIMATION_JUMPCUT;
|
||||
}
|
||||
|
||||
private void setRotation(SurfaceControl.Transaction t) {
|
||||
// Compute the transformation matrix that must be applied
|
||||
// to the snapshot to make it stay in the same original position
|
||||
@@ -244,33 +251,44 @@ class ScreenRotationAnimation {
|
||||
// color frame animation.
|
||||
//mEndLuma = getLumaOfSurfaceControl(mEndBounds, mSurfaceControl);
|
||||
|
||||
// Figure out how the screen has moved from the original rotation.
|
||||
int delta = deltaRotation(mEndRotation, mStartRotation);
|
||||
switch (delta) { /* Counter-Clockwise Rotations */
|
||||
case Surface.ROTATION_0:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_0_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.rotation_animation_enter);
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_plus_90_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_plus_90_enter);
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_180_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_180_enter);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_minus_90_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_minus_90_enter);
|
||||
break;
|
||||
final boolean customRotate = isCustomRotate();
|
||||
if (customRotate) {
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
mAnimHint == ROTATION_ANIMATION_JUMPCUT ? R.anim.rotation_animation_jump_exit
|
||||
: R.anim.rotation_animation_xfade_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.rotation_animation_enter);
|
||||
mRotateAlphaAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_alpha);
|
||||
} else {
|
||||
// Figure out how the screen has moved from the original rotation.
|
||||
int delta = deltaRotation(mEndRotation, mStartRotation);
|
||||
switch (delta) { /* Counter-Clockwise Rotations */
|
||||
case Surface.ROTATION_0:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_0_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.rotation_animation_enter);
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_plus_90_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_plus_90_enter);
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_180_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_180_enter);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_minus_90_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_minus_90_enter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mRotateExitAnimation.initialize(mEndWidth, mEndHeight, mStartWidth, mStartHeight);
|
||||
@@ -281,9 +299,20 @@ class ScreenRotationAnimation {
|
||||
mRotateEnterAnimation.scaleCurrentDuration(animationScale);
|
||||
|
||||
mTransaction = mTransactionPool.acquire();
|
||||
startDisplayRotation(animations, finishCallback, mainExecutor, animExecutor);
|
||||
startScreenshotRotationAnimation(animations, finishCallback, mainExecutor, animExecutor);
|
||||
//startColorAnimation(mTransaction, animationScale);
|
||||
if (customRotate) {
|
||||
mRotateAlphaAnimation.initialize(mEndWidth, mEndHeight, mStartWidth, mStartHeight);
|
||||
mRotateAlphaAnimation.restrictDuration(MAX_ANIMATION_DURATION);
|
||||
mRotateAlphaAnimation.scaleCurrentDuration(animationScale);
|
||||
|
||||
startScreenshotAlphaAnimation(animations, finishCallback, mainExecutor,
|
||||
animExecutor);
|
||||
startDisplayRotation(animations, finishCallback, mainExecutor, animExecutor);
|
||||
} else {
|
||||
startDisplayRotation(animations, finishCallback, mainExecutor, animExecutor);
|
||||
startScreenshotRotationAnimation(animations, finishCallback, mainExecutor,
|
||||
animExecutor);
|
||||
//startColorAnimation(mTransaction, animationScale);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -304,6 +333,14 @@ class ScreenRotationAnimation {
|
||||
0 /* cornerRadius */, null /* clipRect */);
|
||||
}
|
||||
|
||||
private void startScreenshotAlphaAnimation(@NonNull ArrayList<Animator> animations,
|
||||
@NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
|
||||
@NonNull ShellExecutor animExecutor) {
|
||||
startSurfaceAnimation(animations, mRotateAlphaAnimation, mAnimLeash, finishCallback,
|
||||
mTransactionPool, mainExecutor, animExecutor, null /* position */,
|
||||
0 /* cornerRadius */, null /* clipRect */);
|
||||
}
|
||||
|
||||
private void startColorAnimation(float animationScale, @NonNull ShellExecutor animExecutor) {
|
||||
int colorTransitionMs = mContext.getResources().getInteger(
|
||||
R.integer.config_screen_rotation_color_transition);
|
||||
@@ -351,13 +388,12 @@ class ScreenRotationAnimation {
|
||||
t.remove(mScreenshotLayer);
|
||||
}
|
||||
mScreenshotLayer = null;
|
||||
|
||||
if (mBackColorSurface != null) {
|
||||
if (mBackColorSurface.isValid()) {
|
||||
t.remove(mBackColorSurface);
|
||||
}
|
||||
mBackColorSurface = null;
|
||||
}
|
||||
if (mBackColorSurface != null) {
|
||||
if (mBackColorSurface.isValid()) {
|
||||
t.remove(mBackColorSurface);
|
||||
}
|
||||
mBackColorSurface = null;
|
||||
}
|
||||
t.apply();
|
||||
mTransactionPool.release(t);
|
||||
|
||||
Reference in New Issue
Block a user