Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +8 −5 Original line number Diff line number Diff line Loading @@ -361,8 +361,11 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { final int anim = getRotationAnimationHint(change, info, mDisplayController); isSeamlessDisplayChange = anim == ROTATION_ANIMATION_SEAMLESS; if (!(isSeamlessDisplayChange || anim == ROTATION_ANIMATION_JUMPCUT)) { startRotationAnimation(startTransaction, change, info, anim, animations, onAnimFinish); final int flags = wallpaperTransit != WALLPAPER_TRANSITION_NONE && Flags.commonSurfaceAnimator() ? ScreenRotationAnimation.FLAG_HAS_WALLPAPER : 0; startRotationAnimation(startTransaction, change, info, anim, flags, animations, onAnimFinish); isDisplayRotationAnimationStarted = true; continue; } Loading Loading @@ -414,7 +417,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { if (change.getParent() == null && !change.hasFlags(FLAG_IS_DISPLAY) && change.getStartRotation() != change.getEndRotation()) { startRotationAnimation(startTransaction, change, info, ROTATION_ANIMATION_ROTATE, animations, onAnimFinish); ROTATION_ANIMATION_ROTATE, 0 /* flags */, animations, onAnimFinish); continue; } } Loading Loading @@ -699,12 +702,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } private void startRotationAnimation(SurfaceControl.Transaction startTransaction, TransitionInfo.Change change, TransitionInfo info, int animHint, TransitionInfo.Change change, TransitionInfo info, int animHint, int flags, ArrayList<Animator> animations, Runnable onAnimFinish) { final int rootIdx = TransitionUtil.rootIndexFor(change, info); final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext, mTransactionPool, startTransaction, change, info.getRoot(rootIdx).getLeash(), animHint); animHint, flags); // The rotation animation may consist of 3 animations: fade-out screenshot, fade-in real // content, and background color. The item of "animGroup" will be removed if the sub // animation is finished. Then if the list becomes empty, the rotation animation is done. Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +79 −53 Original line number Diff line number Diff line Loading @@ -25,12 +25,9 @@ import static com.android.wm.shell.transition.DefaultTransitionHandler.buildSurf import static com.android.wm.shell.transition.Transitions.TAG; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.Context; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Rect; import android.hardware.HardwareBuffer; Loading @@ -38,6 +35,7 @@ import android.util.Slog; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.window.ScreenCapture; Loading Loading @@ -74,6 +72,7 @@ import java.util.ArrayList; */ class ScreenRotationAnimation { static final int MAX_ANIMATION_DURATION = 10 * 1000; static final int FLAG_HAS_WALLPAPER = 1; private final Context mContext; private final TransactionPool mTransactionPool; Loading @@ -98,6 +97,12 @@ class ScreenRotationAnimation { private SurfaceControl mBackColorSurface; /** The leash using to animate screenshot layer. */ private final SurfaceControl mAnimLeash; /** * The container with background color for {@link #mSurfaceControl}. It is only created if * {@link #mSurfaceControl} may be translucent. E.g. visible wallpaper with alpha < 1 (dimmed). * That prevents flickering of alpha blending. */ private SurfaceControl mBackEffectSurface; // The current active animation to move from the old to the new rotated // state. Which animation is run here will depend on the old and new Loading @@ -111,8 +116,8 @@ class ScreenRotationAnimation { /** Intensity of light/whiteness of the layout after rotation occurs. */ private float mEndLuma; ScreenRotationAnimation(Context context, TransactionPool pool, Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint) { ScreenRotationAnimation(Context context, TransactionPool pool, Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint, int flags) { mContext = context; mTransactionPool = pool; mAnimHint = animHint; Loading Loading @@ -170,11 +175,20 @@ class ScreenRotationAnimation { } hardwareBuffer.close(); } if ((flags & FLAG_HAS_WALLPAPER) != 0) { mBackEffectSurface = new SurfaceControl.Builder() .setCallsite("ShellRotationAnimation").setParent(rootLeash) .setEffectLayer().setOpaque(true).setName("BackEffect").build(); t.reparent(mSurfaceControl, mBackEffectSurface) .setColor(mBackEffectSurface, new float[] {mStartLuma, mStartLuma, mStartLuma}) .show(mBackEffectSurface); } t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.show(mAnimLeash); // Crop the real content in case it contains a larger child layer, e.g. wallpaper. t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight)); t.setCrop(getEnterSurface(), new Rect(0, 0, mEndWidth, mEndHeight)); if (!isCustomRotate()) { mBackColorSurface = new SurfaceControl.Builder() Loading Loading @@ -202,6 +216,11 @@ class ScreenRotationAnimation { return mAnimHint == ROTATION_ANIMATION_CROSSFADE || mAnimHint == ROTATION_ANIMATION_JUMPCUT; } /** Returns the surface which contains the real content to animate enter. */ private SurfaceControl getEnterSurface() { return mBackEffectSurface != null ? mBackEffectSurface : mSurfaceControl; } private void setScreenshotTransform(SurfaceControl.Transaction t) { if (mScreenshotLayer == null) { return; Loading Loading @@ -314,7 +333,11 @@ class ScreenRotationAnimation { } else { startDisplayRotation(animations, finishCallback, mainExecutor); startScreenshotRotationAnimation(animations, finishCallback, mainExecutor); //startColorAnimation(mTransaction, animationScale); if (mBackEffectSurface != null && mStartLuma > 0.1f) { // Animate from the color of background to black for smooth alpha blending. buildLumaAnimation(animations, mStartLuma, 0f /* endLuma */, mBackEffectSurface, animationScale, finishCallback, mainExecutor); } } return true; Loading @@ -322,7 +345,7 @@ class ScreenRotationAnimation { private void startDisplayRotation(@NonNull ArrayList<Animator> animations, @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) { buildSurfaceAnimation(animations, mRotateEnterAnimation, mSurfaceControl, finishCallback, buildSurfaceAnimation(animations, mRotateEnterAnimation, getEnterSurface(), finishCallback, mTransactionPool, mainExecutor, null /* position */, 0 /* cornerRadius */, null /* clipRect */, false /* isActivity */); } Loading @@ -341,40 +364,17 @@ class ScreenRotationAnimation { null /* clipRect */, false /* isActivity */); } private void startColorAnimation(float animationScale, @NonNull ShellExecutor animExecutor) { int colorTransitionMs = mContext.getResources().getInteger( R.integer.config_screen_rotation_color_transition); final float[] rgbTmpFloat = new float[3]; final int startColor = Color.rgb(mStartLuma, mStartLuma, mStartLuma); final int endColor = Color.rgb(mEndLuma, mEndLuma, mEndLuma); final long duration = colorTransitionMs * (long) animationScale; final Transaction t = mTransactionPool.acquire(); final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f); // Animation length is already expected to be scaled. va.overrideDurationScale(1.0f); va.setDuration(duration); va.addUpdateListener(animation -> { final long currentPlayTime = Math.min(va.getDuration(), va.getCurrentPlayTime()); final float fraction = currentPlayTime / va.getDuration(); applyColor(startColor, endColor, rgbTmpFloat, fraction, mBackColorSurface, t); }); va.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { applyColor(startColor, endColor, rgbTmpFloat, 1f /* fraction */, mBackColorSurface, t); mTransactionPool.release(t); } @Override public void onAnimationEnd(Animator animation) { applyColor(startColor, endColor, rgbTmpFloat, 1f /* fraction */, mBackColorSurface, t); mTransactionPool.release(t); } }); animExecutor.execute(va::start); private void buildLumaAnimation(@NonNull ArrayList<Animator> animations, float startLuma, float endLuma, SurfaceControl surface, float animationScale, @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) { final long durationMillis = (long) (mContext.getResources().getInteger( R.integer.config_screen_rotation_color_transition) * animationScale); final LumaAnimation animation = new LumaAnimation(durationMillis); // Align the end with the enter animation. animation.setStartOffset(mRotateEnterAnimation.getDuration() - durationMillis); final LumaAnimationAdapter adapter = new LumaAnimationAdapter(surface, startLuma, endLuma); DefaultSurfaceAnimator.buildSurfaceAnimation(animations, animation, finishCallback, mTransactionPool, mainExecutor, adapter); } public void kill() { Loading @@ -389,21 +389,47 @@ class ScreenRotationAnimation { if (mBackColorSurface != null && mBackColorSurface.isValid()) { t.remove(mBackColorSurface); } if (mBackEffectSurface != null && mBackEffectSurface.isValid()) { t.remove(mBackEffectSurface); } t.apply(); mTransactionPool.release(t); } private static void applyColor(int startColor, int endColor, float[] rgbFloat, float fraction, SurfaceControl surface, SurfaceControl.Transaction t) { final int color = (Integer) ArgbEvaluator.getInstance().evaluate(fraction, startColor, endColor); Color middleColor = Color.valueOf(color); rgbFloat[0] = middleColor.red(); rgbFloat[1] = middleColor.green(); rgbFloat[2] = middleColor.blue(); if (surface.isValid()) { t.setColor(surface, rgbFloat); /** A no-op wrapper to provide animation duration. */ private static class LumaAnimation extends Animation { LumaAnimation(long durationMillis) { setDuration(durationMillis); } } private static class LumaAnimationAdapter extends DefaultSurfaceAnimator.AnimationAdapter { final float[] mColorArray = new float[3]; final float mStartLuma; final float mEndLuma; final AccelerateInterpolator mInterpolation; LumaAnimationAdapter(@NonNull SurfaceControl leash, float startLuma, float endLuma) { super(leash); mStartLuma = startLuma; mEndLuma = endLuma; // Make the initial progress color lighter if the background is light. That avoids // darker content when fading into the entering surface. final float factor = Math.min(3f, (Math.max(0.5f, mStartLuma) - 0.5f) * 10); Slog.d(TAG, "Luma=" + mStartLuma + " factor=" + factor); mInterpolation = factor > 0.5f ? new AccelerateInterpolator(factor) : null; } @Override void applyTransformation(ValueAnimator animator, long currentPlayTime) { final float fraction = mInterpolation != null ? mInterpolation.getInterpolation(animator.getAnimatedFraction()) : animator.getAnimatedFraction(); final float luma = mStartLuma + fraction * (mEndLuma - mStartLuma); mColorArray[0] = luma; mColorArray[1] = luma; mColorArray[2] = luma; mTransaction.setColor(mLeash, mColorArray); } t.apply(); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +8 −5 Original line number Diff line number Diff line Loading @@ -361,8 +361,11 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { final int anim = getRotationAnimationHint(change, info, mDisplayController); isSeamlessDisplayChange = anim == ROTATION_ANIMATION_SEAMLESS; if (!(isSeamlessDisplayChange || anim == ROTATION_ANIMATION_JUMPCUT)) { startRotationAnimation(startTransaction, change, info, anim, animations, onAnimFinish); final int flags = wallpaperTransit != WALLPAPER_TRANSITION_NONE && Flags.commonSurfaceAnimator() ? ScreenRotationAnimation.FLAG_HAS_WALLPAPER : 0; startRotationAnimation(startTransaction, change, info, anim, flags, animations, onAnimFinish); isDisplayRotationAnimationStarted = true; continue; } Loading Loading @@ -414,7 +417,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { if (change.getParent() == null && !change.hasFlags(FLAG_IS_DISPLAY) && change.getStartRotation() != change.getEndRotation()) { startRotationAnimation(startTransaction, change, info, ROTATION_ANIMATION_ROTATE, animations, onAnimFinish); ROTATION_ANIMATION_ROTATE, 0 /* flags */, animations, onAnimFinish); continue; } } Loading Loading @@ -699,12 +702,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } private void startRotationAnimation(SurfaceControl.Transaction startTransaction, TransitionInfo.Change change, TransitionInfo info, int animHint, TransitionInfo.Change change, TransitionInfo info, int animHint, int flags, ArrayList<Animator> animations, Runnable onAnimFinish) { final int rootIdx = TransitionUtil.rootIndexFor(change, info); final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext, mTransactionPool, startTransaction, change, info.getRoot(rootIdx).getLeash(), animHint); animHint, flags); // The rotation animation may consist of 3 animations: fade-out screenshot, fade-in real // content, and background color. The item of "animGroup" will be removed if the sub // animation is finished. Then if the list becomes empty, the rotation animation is done. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +79 −53 Original line number Diff line number Diff line Loading @@ -25,12 +25,9 @@ import static com.android.wm.shell.transition.DefaultTransitionHandler.buildSurf import static com.android.wm.shell.transition.Transitions.TAG; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.Context; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Rect; import android.hardware.HardwareBuffer; Loading @@ -38,6 +35,7 @@ import android.util.Slog; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.window.ScreenCapture; Loading Loading @@ -74,6 +72,7 @@ import java.util.ArrayList; */ class ScreenRotationAnimation { static final int MAX_ANIMATION_DURATION = 10 * 1000; static final int FLAG_HAS_WALLPAPER = 1; private final Context mContext; private final TransactionPool mTransactionPool; Loading @@ -98,6 +97,12 @@ class ScreenRotationAnimation { private SurfaceControl mBackColorSurface; /** The leash using to animate screenshot layer. */ private final SurfaceControl mAnimLeash; /** * The container with background color for {@link #mSurfaceControl}. It is only created if * {@link #mSurfaceControl} may be translucent. E.g. visible wallpaper with alpha < 1 (dimmed). * That prevents flickering of alpha blending. */ private SurfaceControl mBackEffectSurface; // The current active animation to move from the old to the new rotated // state. Which animation is run here will depend on the old and new Loading @@ -111,8 +116,8 @@ class ScreenRotationAnimation { /** Intensity of light/whiteness of the layout after rotation occurs. */ private float mEndLuma; ScreenRotationAnimation(Context context, TransactionPool pool, Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint) { ScreenRotationAnimation(Context context, TransactionPool pool, Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint, int flags) { mContext = context; mTransactionPool = pool; mAnimHint = animHint; Loading Loading @@ -170,11 +175,20 @@ class ScreenRotationAnimation { } hardwareBuffer.close(); } if ((flags & FLAG_HAS_WALLPAPER) != 0) { mBackEffectSurface = new SurfaceControl.Builder() .setCallsite("ShellRotationAnimation").setParent(rootLeash) .setEffectLayer().setOpaque(true).setName("BackEffect").build(); t.reparent(mSurfaceControl, mBackEffectSurface) .setColor(mBackEffectSurface, new float[] {mStartLuma, mStartLuma, mStartLuma}) .show(mBackEffectSurface); } t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE); t.show(mAnimLeash); // Crop the real content in case it contains a larger child layer, e.g. wallpaper. t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight)); t.setCrop(getEnterSurface(), new Rect(0, 0, mEndWidth, mEndHeight)); if (!isCustomRotate()) { mBackColorSurface = new SurfaceControl.Builder() Loading Loading @@ -202,6 +216,11 @@ class ScreenRotationAnimation { return mAnimHint == ROTATION_ANIMATION_CROSSFADE || mAnimHint == ROTATION_ANIMATION_JUMPCUT; } /** Returns the surface which contains the real content to animate enter. */ private SurfaceControl getEnterSurface() { return mBackEffectSurface != null ? mBackEffectSurface : mSurfaceControl; } private void setScreenshotTransform(SurfaceControl.Transaction t) { if (mScreenshotLayer == null) { return; Loading Loading @@ -314,7 +333,11 @@ class ScreenRotationAnimation { } else { startDisplayRotation(animations, finishCallback, mainExecutor); startScreenshotRotationAnimation(animations, finishCallback, mainExecutor); //startColorAnimation(mTransaction, animationScale); if (mBackEffectSurface != null && mStartLuma > 0.1f) { // Animate from the color of background to black for smooth alpha blending. buildLumaAnimation(animations, mStartLuma, 0f /* endLuma */, mBackEffectSurface, animationScale, finishCallback, mainExecutor); } } return true; Loading @@ -322,7 +345,7 @@ class ScreenRotationAnimation { private void startDisplayRotation(@NonNull ArrayList<Animator> animations, @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) { buildSurfaceAnimation(animations, mRotateEnterAnimation, mSurfaceControl, finishCallback, buildSurfaceAnimation(animations, mRotateEnterAnimation, getEnterSurface(), finishCallback, mTransactionPool, mainExecutor, null /* position */, 0 /* cornerRadius */, null /* clipRect */, false /* isActivity */); } Loading @@ -341,40 +364,17 @@ class ScreenRotationAnimation { null /* clipRect */, false /* isActivity */); } private void startColorAnimation(float animationScale, @NonNull ShellExecutor animExecutor) { int colorTransitionMs = mContext.getResources().getInteger( R.integer.config_screen_rotation_color_transition); final float[] rgbTmpFloat = new float[3]; final int startColor = Color.rgb(mStartLuma, mStartLuma, mStartLuma); final int endColor = Color.rgb(mEndLuma, mEndLuma, mEndLuma); final long duration = colorTransitionMs * (long) animationScale; final Transaction t = mTransactionPool.acquire(); final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f); // Animation length is already expected to be scaled. va.overrideDurationScale(1.0f); va.setDuration(duration); va.addUpdateListener(animation -> { final long currentPlayTime = Math.min(va.getDuration(), va.getCurrentPlayTime()); final float fraction = currentPlayTime / va.getDuration(); applyColor(startColor, endColor, rgbTmpFloat, fraction, mBackColorSurface, t); }); va.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { applyColor(startColor, endColor, rgbTmpFloat, 1f /* fraction */, mBackColorSurface, t); mTransactionPool.release(t); } @Override public void onAnimationEnd(Animator animation) { applyColor(startColor, endColor, rgbTmpFloat, 1f /* fraction */, mBackColorSurface, t); mTransactionPool.release(t); } }); animExecutor.execute(va::start); private void buildLumaAnimation(@NonNull ArrayList<Animator> animations, float startLuma, float endLuma, SurfaceControl surface, float animationScale, @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) { final long durationMillis = (long) (mContext.getResources().getInteger( R.integer.config_screen_rotation_color_transition) * animationScale); final LumaAnimation animation = new LumaAnimation(durationMillis); // Align the end with the enter animation. animation.setStartOffset(mRotateEnterAnimation.getDuration() - durationMillis); final LumaAnimationAdapter adapter = new LumaAnimationAdapter(surface, startLuma, endLuma); DefaultSurfaceAnimator.buildSurfaceAnimation(animations, animation, finishCallback, mTransactionPool, mainExecutor, adapter); } public void kill() { Loading @@ -389,21 +389,47 @@ class ScreenRotationAnimation { if (mBackColorSurface != null && mBackColorSurface.isValid()) { t.remove(mBackColorSurface); } if (mBackEffectSurface != null && mBackEffectSurface.isValid()) { t.remove(mBackEffectSurface); } t.apply(); mTransactionPool.release(t); } private static void applyColor(int startColor, int endColor, float[] rgbFloat, float fraction, SurfaceControl surface, SurfaceControl.Transaction t) { final int color = (Integer) ArgbEvaluator.getInstance().evaluate(fraction, startColor, endColor); Color middleColor = Color.valueOf(color); rgbFloat[0] = middleColor.red(); rgbFloat[1] = middleColor.green(); rgbFloat[2] = middleColor.blue(); if (surface.isValid()) { t.setColor(surface, rgbFloat); /** A no-op wrapper to provide animation duration. */ private static class LumaAnimation extends Animation { LumaAnimation(long durationMillis) { setDuration(durationMillis); } } private static class LumaAnimationAdapter extends DefaultSurfaceAnimator.AnimationAdapter { final float[] mColorArray = new float[3]; final float mStartLuma; final float mEndLuma; final AccelerateInterpolator mInterpolation; LumaAnimationAdapter(@NonNull SurfaceControl leash, float startLuma, float endLuma) { super(leash); mStartLuma = startLuma; mEndLuma = endLuma; // Make the initial progress color lighter if the background is light. That avoids // darker content when fading into the entering surface. final float factor = Math.min(3f, (Math.max(0.5f, mStartLuma) - 0.5f) * 10); Slog.d(TAG, "Luma=" + mStartLuma + " factor=" + factor); mInterpolation = factor > 0.5f ? new AccelerateInterpolator(factor) : null; } @Override void applyTransformation(ValueAnimator animator, long currentPlayTime) { final float fraction = mInterpolation != null ? mInterpolation.getInterpolation(animator.getAnimatedFraction()) : animator.getAnimatedFraction(); final float luma = mStartLuma + fraction * (mEndLuma - mStartLuma); mColorArray[0] = luma; mColorArray[1] = luma; mColorArray[2] = luma; mTransaction.setColor(mLeash, mColorArray); } t.apply(); } }