Loading core/java/android/window/SplashScreenView.java +20 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ public final class SplashScreenView extends FrameLayout { private static final boolean DEBUG = false; private boolean mNotCopyable; private boolean mRevealAnimationSupported = true; private int mInitBackgroundColor; private int mInitIconBackgroundColor; private View mIconView; Loading Loading @@ -263,6 +264,25 @@ public final class SplashScreenView extends FrameLayout { return !mNotCopyable; } /** * If set to true, indicates to the system that this view can be dismissed by playing the * Reveal animation. * <p> * If the exit animation is handled by the client, the animation won't be played anyway. * @hide */ public void setRevealAnimationSupported(boolean support) { mRevealAnimationSupported = support; } /** * Whether this view support reveal animation. * @hide */ public boolean isRevealAnimationSupported() { return mRevealAnimationSupported; } /** * Returns the duration of the icon animation if icon is animatable. * Loading libs/WindowManager/Shell/res/values/config.xml +0 −3 Original line number Diff line number Diff line Loading @@ -52,9 +52,6 @@ when the PIP menu is shown in center. --> <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string> <!-- Animation duration when exit starting window: icon going away --> <integer name="starting_window_icon_exit_anim_duration">166</integer> <!-- Animation duration when exit starting window: reveal app --> <integer name="starting_window_app_reveal_anim_duration">333</integer> </resources> libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java +51 −86 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.wm.shell.startingsurface; import static android.view.Choreographer.CALLBACK_COMMIT; import static android.view.View.GONE; import android.animation.Animator; Loading @@ -29,13 +30,12 @@ import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.Shader; import android.util.Slog; import android.view.Choreographer; import android.view.SurfaceControl; import android.view.SyncRtSurfaceTransactionApplier; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.animation.Transformation; Loading @@ -53,51 +53,36 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { private static final boolean DEBUG_EXIT_ANIMATION_BLEND = false; private static final String TAG = StartingSurfaceDrawer.TAG; private static final Interpolator ICON_EXIT_INTERPOLATOR = new PathInterpolator(1f, 0f, 1f, 1f); private static final Interpolator APP_EXIT_INTERPOLATOR = new PathInterpolator(0f, 0f, 0f, 1f); private static final int EXTRA_REVEAL_DELAY = 133; private final Matrix mTmpTransform = new Matrix(); private final float[] mTmpFloat9 = new float[9]; private SurfaceControl mFirstWindowSurface; private final SurfaceControl mFirstWindowSurface; private final Rect mFirstWindowFrame = new Rect(); private final SplashScreenView mSplashScreenView; private final int mMainWindowShiftLength; private final int mIconShiftLength; private final int mAppDuration; private final int mIconDuration; private final TransactionPool mTransactionPool; private ValueAnimator mMainAnimator; private Animation mShiftUpAnimation; private AnimationSet mIconAnimationSet; private ShiftUpAnimation mShiftUpAnimation; private Runnable mFinishCallback; SplashScreenExitAnimation(SplashScreenView view, SurfaceControl leash, Rect frame, int appDuration, int iconDuration, int mainWindowShiftLength, int iconShiftLength, TransactionPool pool, Runnable handleFinish) { int appDuration, int mainWindowShiftLength, TransactionPool pool, Runnable handleFinish) { mSplashScreenView = view; mFirstWindowSurface = leash; if (frame != null) { mFirstWindowFrame.set(frame); } mAppDuration = appDuration; mIconDuration = iconDuration; mMainWindowShiftLength = mainWindowShiftLength; mIconShiftLength = iconShiftLength; mFinishCallback = handleFinish; mTransactionPool = pool; } void prepareAnimations() { prepareRevealAnimation(); prepareShiftAnimation(); } void startAnimations() { if (mIconAnimationSet != null) { mIconAnimationSet.start(); } prepareRevealAnimation(); if (mMainAnimator != null) { mMainAnimator.start(); } Loading @@ -114,8 +99,7 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { mMainAnimator.setInterpolator(APP_EXIT_INTERPOLATOR); mMainAnimator.addListener(this); final int startDelay = mIconDuration + EXTRA_REVEAL_DELAY; final float transparentRatio = 0.95f; final float transparentRatio = 0.8f; final int globalHeight = mSplashScreenView.getHeight(); final int verticalCircleCenter = 0; final int finalVerticalLength = globalHeight - verticalCircleCenter; Loading @@ -130,9 +114,8 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { final float[] stops = {0f, transparentRatio, 1f}; radialVanishAnimation.setRadialPaintParam(colors, stops); radialVanishAnimation.setReady(); mMainAnimator.setStartDelay(startDelay); if (mFirstWindowSurface != null) { if (mFirstWindowSurface != null && mFirstWindowSurface.isValid()) { // shift up main window View occludeHoleView = new View(mSplashScreenView.getContext()); if (DEBUG_EXIT_ANIMATION_BLEND) { Loading @@ -144,59 +127,16 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { WindowManager.LayoutParams.MATCH_PARENT, mMainWindowShiftLength); mSplashScreenView.addView(occludeHoleView, params); mShiftUpAnimation = new ShiftUpAnimation(0, -mMainWindowShiftLength); mShiftUpAnimation = new ShiftUpAnimation(0, -mMainWindowShiftLength, occludeHoleView); mShiftUpAnimation.setDuration(mAppDuration); mShiftUpAnimation.setInterpolator(APP_EXIT_INTERPOLATOR); mShiftUpAnimation.setStartOffset(startDelay); occludeHoleView.setAnimation(mShiftUpAnimation); } } // shift down icon and branding view private void prepareShiftAnimation() { final View iconView = mSplashScreenView.getIconView(); if (iconView == null) { return; } if (mIconShiftLength > 0) { mIconAnimationSet = new AnimationSet(true /* shareInterpolator */); if (DEBUG_EXIT_ANIMATION) { Slog.v(TAG, "first exit animation, shift length: " + mIconShiftLength); } mIconAnimationSet.addAnimation(new TranslateYAnimation(0, mIconShiftLength)); mIconAnimationSet.addAnimation(new AlphaAnimation(1, 0)); mIconAnimationSet.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (DEBUG_EXIT_ANIMATION) { Slog.v(TAG, "first exit animation finished"); } iconView.post(() -> iconView.setVisibility(GONE)); } @Override public void onAnimationRepeat(Animation animation) { // ignore } }); mIconAnimationSet.setDuration(mIconDuration); mIconAnimationSet.setInterpolator(ICON_EXIT_INTERPOLATOR); iconView.setAnimation(mIconAnimationSet); final View brandingView = mSplashScreenView.getBrandingView(); if (brandingView != null) { brandingView.setAnimation(mIconAnimationSet); } } } private static class RadialVanishAnimation extends View { private SplashScreenView mView; private final SplashScreenView mView; private int mInitRadius; private int mFinishRadius; private boolean mReady; Loading @@ -217,7 +157,7 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { mVanishMatrix.setScale(scale, scale); mVanishMatrix.postTranslate(mCircleCenter.x, mCircleCenter.y); mVanishPaint.getShader().setLocalMatrix(mVanishMatrix); mView.postInvalidate(); postInvalidate(); }); mView.addView(this); } Loading Loading @@ -262,28 +202,57 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { } private final class ShiftUpAnimation extends TranslateYAnimation { ShiftUpAnimation(float fromYDelta, float toYDelta) { final SyncRtSurfaceTransactionApplier mApplier; ShiftUpAnimation(float fromYDelta, float toYDelta, View targetView) { super(fromYDelta, toYDelta); mApplier = new SyncRtSurfaceTransactionApplier(targetView); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); if (mFirstWindowSurface == null) { if (mFirstWindowSurface == null || !mFirstWindowSurface.isValid()) { return; } mTmpTransform.set(t.getMatrix()); // set the vsyncId to ensure the transaction doesn't get applied too early. final SurfaceControl.Transaction tx = mTransactionPool.acquire(); tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); mTmpTransform.postTranslate(mFirstWindowFrame.left, mFirstWindowFrame.top + mMainWindowShiftLength); tx.setMatrix(mFirstWindowSurface, mTmpTransform, mTmpFloat9); // TODO set the vsyncId to ensure the transaction doesn't get applied too early. // Additionally, do you want to have this synchronized with your view animations? // If so, you'll need to use SyncRtSurfaceTransactionApplier tx.apply(); SyncRtSurfaceTransactionApplier.SurfaceParams params = new SyncRtSurfaceTransactionApplier.SurfaceParams .Builder(mFirstWindowSurface) .withMatrix(mTmpTransform) .withMergeTransaction(tx) .build(); mApplier.scheduleApply(params); mTransactionPool.release(tx); } void finish() { if (mFirstWindowSurface == null || !mFirstWindowSurface.isValid()) { return; } final SurfaceControl.Transaction tx = mTransactionPool.acquire(); tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); SyncRtSurfaceTransactionApplier.SurfaceParams params = new SyncRtSurfaceTransactionApplier.SurfaceParams .Builder(mFirstWindowSurface) .withWindowCrop(null) .withMergeTransaction(tx) .build(); mApplier.scheduleApply(params); mTransactionPool.release(tx); Choreographer.getSfInstance().postCallback(CALLBACK_COMMIT, mFirstWindowSurface::release, null); } } private void reset() { Loading @@ -297,12 +266,8 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { mFinishCallback = null; } }); if (mFirstWindowSurface != null) { final SurfaceControl.Transaction tx = mTransactionPool.acquire(); tx.setWindowCrop(mFirstWindowSurface, null); tx.apply(); mFirstWindowSurface.release(); mFirstWindowSurface = null; if (mShiftUpAnimation != null) { mShiftUpAnimation.finish(); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +4 −14 Original line number Diff line number Diff line Loading @@ -75,20 +75,15 @@ public class SplashscreenContentDrawer { private int mBrandingImageWidth; private int mBrandingImageHeight; private final int mAppRevealDuration; private final int mIconExitDuration; private int mMainWindowShiftLength; private int mIconNormalExitDistance; private int mIconEarlyExitDistance; private final TransactionPool mTransactionPool; private final SplashScreenWindowAttrs mTmpAttrs = new SplashScreenWindowAttrs(); private final Handler mSplashscreenWorkerHandler; SplashscreenContentDrawer(Context context, int iconExitAnimDuration, int appRevealAnimDuration, TransactionPool pool) { SplashscreenContentDrawer(Context context, int appRevealAnimDuration, TransactionPool pool) { mContext = context; mIconProvider = new IconProvider(context); mAppRevealDuration = appRevealAnimDuration; mIconExitDuration = iconExitAnimDuration; mTransactionPool = pool; // Initialize Splashscreen worker thread Loading Loading @@ -139,10 +134,6 @@ public class SplashscreenContentDrawer { com.android.wm.shell.R.dimen.starting_surface_brand_image_height); mMainWindowShiftLength = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length); mIconNormalExitDistance = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_normal_exit_icon_distance); mIconEarlyExitDistance = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_early_exit_icon_distance); } private int getSystemBGColor() { Loading Loading @@ -406,6 +397,7 @@ public class SplashscreenContentDrawer { } if (mEmptyView) { splashScreenView.setNotCopyable(); splashScreenView.setRevealAnimationSupported(false); } splashScreenView.makeSystemUIColorsTransparent(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Loading Loading @@ -678,12 +670,10 @@ public class SplashscreenContentDrawer { * Create and play the default exit animation for splash screen view. */ void applyExitAnimation(SplashScreenView view, SurfaceControl leash, Rect frame, boolean isEarlyExit, Runnable finishCallback) { Rect frame, Runnable finishCallback) { final SplashScreenExitAnimation animation = new SplashScreenExitAnimation(view, leash, frame, mAppRevealDuration, mIconExitDuration, mMainWindowShiftLength, isEarlyExit ? mIconEarlyExitDistance : mIconNormalExitDistance, mTransactionPool, frame, mAppRevealDuration, mMainWindowShiftLength, mTransactionPool, finishCallback); animation.prepareAnimations(); animation.startAnimations(); } } libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +20 −23 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.os.IBinder; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -106,6 +106,8 @@ public class StartingSurfaceDrawer { private final SplashscreenContentDrawer mSplashscreenContentDrawer; private Choreographer mChoreographer; private static final boolean DEBUG_ENABLE_REVEAL_ANIMATION = SystemProperties.getBoolean("persist.debug.enable_reveal_animation", false); /** * @param splashScreenExecutor The thread used to control add and remove starting window. */ Loading @@ -114,12 +116,10 @@ public class StartingSurfaceDrawer { mContext = context; mDisplayManager = mContext.getSystemService(DisplayManager.class); mSplashScreenExecutor = splashScreenExecutor; final int iconExitAnimDuration = context.getResources().getInteger( com.android.wm.shell.R.integer.starting_window_icon_exit_anim_duration); final int appRevealAnimDuration = context.getResources().getInteger( com.android.wm.shell.R.integer.starting_window_app_reveal_anim_duration); mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconExitAnimDuration, appRevealAnimDuration, pool); mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, appRevealAnimDuration, pool); mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance()); } Loading Loading @@ -467,20 +467,24 @@ public class StartingSurfaceDrawer { if (DEBUG_SPLASH_SCREEN) { Slog.v(TAG, "Removing splash screen window for task: " + taskId); } if (record.mContentView != null) { if (leash != null || playRevealAnimation) { if (record.mContentView != null && record.mContentView.isRevealAnimationSupported()) { if (playRevealAnimation) { if (DEBUG_ENABLE_REVEAL_ANIMATION) { mSplashscreenContentDrawer.applyExitAnimation(record.mContentView, leash, frame, record.isEarlyExit(), leash, frame, () -> removeWindowInner(record.mDecorView, true)); } else { // TODO(183004107) Always hide decorView when playRevealAnimation is enabled // from TaskOrganizerController#removeStartingWindow // the SplashScreenView has been copied to client, skip default exit // animation // using the default exit animation from framework removeWindowInner(record.mDecorView, false); } } else { // no animation will be applied // the SplashScreenView has been copied to client, hide the view to skip // default exit animation removeWindowInner(record.mDecorView, true); } } else { // this is a blank splash screen, don't apply reveal animation removeWindowInner(record.mDecorView, false); } } Loading Loading @@ -514,12 +518,10 @@ public class StartingSurfaceDrawer { * Record the view or surface for a starting window. */ private static class StartingWindowRecord { private static final long EARLY_START_MINIMUM_TIME_MS = 250; private final View mDecorView; private final TaskSnapshotWindow mTaskSnapshotWindow; private SplashScreenView mContentView; private boolean mSetSplashScreen; private long mContentCreateTime; StartingWindowRecord(View decorView, TaskSnapshotWindow taskSnapshotWindow) { mDecorView = decorView; Loading @@ -531,12 +533,7 @@ public class StartingSurfaceDrawer { return; } mContentView = splashScreenView; mContentCreateTime = SystemClock.uptimeMillis(); mSetSplashScreen = true; } boolean isEarlyExit() { return SystemClock.uptimeMillis() - mContentCreateTime < EARLY_START_MINIMUM_TIME_MS; } } } Loading
core/java/android/window/SplashScreenView.java +20 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ public final class SplashScreenView extends FrameLayout { private static final boolean DEBUG = false; private boolean mNotCopyable; private boolean mRevealAnimationSupported = true; private int mInitBackgroundColor; private int mInitIconBackgroundColor; private View mIconView; Loading Loading @@ -263,6 +264,25 @@ public final class SplashScreenView extends FrameLayout { return !mNotCopyable; } /** * If set to true, indicates to the system that this view can be dismissed by playing the * Reveal animation. * <p> * If the exit animation is handled by the client, the animation won't be played anyway. * @hide */ public void setRevealAnimationSupported(boolean support) { mRevealAnimationSupported = support; } /** * Whether this view support reveal animation. * @hide */ public boolean isRevealAnimationSupported() { return mRevealAnimationSupported; } /** * Returns the duration of the icon animation if icon is animatable. * Loading
libs/WindowManager/Shell/res/values/config.xml +0 −3 Original line number Diff line number Diff line Loading @@ -52,9 +52,6 @@ when the PIP menu is shown in center. --> <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string> <!-- Animation duration when exit starting window: icon going away --> <integer name="starting_window_icon_exit_anim_duration">166</integer> <!-- Animation duration when exit starting window: reveal app --> <integer name="starting_window_app_reveal_anim_duration">333</integer> </resources>
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java +51 −86 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.wm.shell.startingsurface; import static android.view.Choreographer.CALLBACK_COMMIT; import static android.view.View.GONE; import android.animation.Animator; Loading @@ -29,13 +30,12 @@ import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.Shader; import android.util.Slog; import android.view.Choreographer; import android.view.SurfaceControl; import android.view.SyncRtSurfaceTransactionApplier; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.animation.Transformation; Loading @@ -53,51 +53,36 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { private static final boolean DEBUG_EXIT_ANIMATION_BLEND = false; private static final String TAG = StartingSurfaceDrawer.TAG; private static final Interpolator ICON_EXIT_INTERPOLATOR = new PathInterpolator(1f, 0f, 1f, 1f); private static final Interpolator APP_EXIT_INTERPOLATOR = new PathInterpolator(0f, 0f, 0f, 1f); private static final int EXTRA_REVEAL_DELAY = 133; private final Matrix mTmpTransform = new Matrix(); private final float[] mTmpFloat9 = new float[9]; private SurfaceControl mFirstWindowSurface; private final SurfaceControl mFirstWindowSurface; private final Rect mFirstWindowFrame = new Rect(); private final SplashScreenView mSplashScreenView; private final int mMainWindowShiftLength; private final int mIconShiftLength; private final int mAppDuration; private final int mIconDuration; private final TransactionPool mTransactionPool; private ValueAnimator mMainAnimator; private Animation mShiftUpAnimation; private AnimationSet mIconAnimationSet; private ShiftUpAnimation mShiftUpAnimation; private Runnable mFinishCallback; SplashScreenExitAnimation(SplashScreenView view, SurfaceControl leash, Rect frame, int appDuration, int iconDuration, int mainWindowShiftLength, int iconShiftLength, TransactionPool pool, Runnable handleFinish) { int appDuration, int mainWindowShiftLength, TransactionPool pool, Runnable handleFinish) { mSplashScreenView = view; mFirstWindowSurface = leash; if (frame != null) { mFirstWindowFrame.set(frame); } mAppDuration = appDuration; mIconDuration = iconDuration; mMainWindowShiftLength = mainWindowShiftLength; mIconShiftLength = iconShiftLength; mFinishCallback = handleFinish; mTransactionPool = pool; } void prepareAnimations() { prepareRevealAnimation(); prepareShiftAnimation(); } void startAnimations() { if (mIconAnimationSet != null) { mIconAnimationSet.start(); } prepareRevealAnimation(); if (mMainAnimator != null) { mMainAnimator.start(); } Loading @@ -114,8 +99,7 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { mMainAnimator.setInterpolator(APP_EXIT_INTERPOLATOR); mMainAnimator.addListener(this); final int startDelay = mIconDuration + EXTRA_REVEAL_DELAY; final float transparentRatio = 0.95f; final float transparentRatio = 0.8f; final int globalHeight = mSplashScreenView.getHeight(); final int verticalCircleCenter = 0; final int finalVerticalLength = globalHeight - verticalCircleCenter; Loading @@ -130,9 +114,8 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { final float[] stops = {0f, transparentRatio, 1f}; radialVanishAnimation.setRadialPaintParam(colors, stops); radialVanishAnimation.setReady(); mMainAnimator.setStartDelay(startDelay); if (mFirstWindowSurface != null) { if (mFirstWindowSurface != null && mFirstWindowSurface.isValid()) { // shift up main window View occludeHoleView = new View(mSplashScreenView.getContext()); if (DEBUG_EXIT_ANIMATION_BLEND) { Loading @@ -144,59 +127,16 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { WindowManager.LayoutParams.MATCH_PARENT, mMainWindowShiftLength); mSplashScreenView.addView(occludeHoleView, params); mShiftUpAnimation = new ShiftUpAnimation(0, -mMainWindowShiftLength); mShiftUpAnimation = new ShiftUpAnimation(0, -mMainWindowShiftLength, occludeHoleView); mShiftUpAnimation.setDuration(mAppDuration); mShiftUpAnimation.setInterpolator(APP_EXIT_INTERPOLATOR); mShiftUpAnimation.setStartOffset(startDelay); occludeHoleView.setAnimation(mShiftUpAnimation); } } // shift down icon and branding view private void prepareShiftAnimation() { final View iconView = mSplashScreenView.getIconView(); if (iconView == null) { return; } if (mIconShiftLength > 0) { mIconAnimationSet = new AnimationSet(true /* shareInterpolator */); if (DEBUG_EXIT_ANIMATION) { Slog.v(TAG, "first exit animation, shift length: " + mIconShiftLength); } mIconAnimationSet.addAnimation(new TranslateYAnimation(0, mIconShiftLength)); mIconAnimationSet.addAnimation(new AlphaAnimation(1, 0)); mIconAnimationSet.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (DEBUG_EXIT_ANIMATION) { Slog.v(TAG, "first exit animation finished"); } iconView.post(() -> iconView.setVisibility(GONE)); } @Override public void onAnimationRepeat(Animation animation) { // ignore } }); mIconAnimationSet.setDuration(mIconDuration); mIconAnimationSet.setInterpolator(ICON_EXIT_INTERPOLATOR); iconView.setAnimation(mIconAnimationSet); final View brandingView = mSplashScreenView.getBrandingView(); if (brandingView != null) { brandingView.setAnimation(mIconAnimationSet); } } } private static class RadialVanishAnimation extends View { private SplashScreenView mView; private final SplashScreenView mView; private int mInitRadius; private int mFinishRadius; private boolean mReady; Loading @@ -217,7 +157,7 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { mVanishMatrix.setScale(scale, scale); mVanishMatrix.postTranslate(mCircleCenter.x, mCircleCenter.y); mVanishPaint.getShader().setLocalMatrix(mVanishMatrix); mView.postInvalidate(); postInvalidate(); }); mView.addView(this); } Loading Loading @@ -262,28 +202,57 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { } private final class ShiftUpAnimation extends TranslateYAnimation { ShiftUpAnimation(float fromYDelta, float toYDelta) { final SyncRtSurfaceTransactionApplier mApplier; ShiftUpAnimation(float fromYDelta, float toYDelta, View targetView) { super(fromYDelta, toYDelta); mApplier = new SyncRtSurfaceTransactionApplier(targetView); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); if (mFirstWindowSurface == null) { if (mFirstWindowSurface == null || !mFirstWindowSurface.isValid()) { return; } mTmpTransform.set(t.getMatrix()); // set the vsyncId to ensure the transaction doesn't get applied too early. final SurfaceControl.Transaction tx = mTransactionPool.acquire(); tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); mTmpTransform.postTranslate(mFirstWindowFrame.left, mFirstWindowFrame.top + mMainWindowShiftLength); tx.setMatrix(mFirstWindowSurface, mTmpTransform, mTmpFloat9); // TODO set the vsyncId to ensure the transaction doesn't get applied too early. // Additionally, do you want to have this synchronized with your view animations? // If so, you'll need to use SyncRtSurfaceTransactionApplier tx.apply(); SyncRtSurfaceTransactionApplier.SurfaceParams params = new SyncRtSurfaceTransactionApplier.SurfaceParams .Builder(mFirstWindowSurface) .withMatrix(mTmpTransform) .withMergeTransaction(tx) .build(); mApplier.scheduleApply(params); mTransactionPool.release(tx); } void finish() { if (mFirstWindowSurface == null || !mFirstWindowSurface.isValid()) { return; } final SurfaceControl.Transaction tx = mTransactionPool.acquire(); tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); SyncRtSurfaceTransactionApplier.SurfaceParams params = new SyncRtSurfaceTransactionApplier.SurfaceParams .Builder(mFirstWindowSurface) .withWindowCrop(null) .withMergeTransaction(tx) .build(); mApplier.scheduleApply(params); mTransactionPool.release(tx); Choreographer.getSfInstance().postCallback(CALLBACK_COMMIT, mFirstWindowSurface::release, null); } } private void reset() { Loading @@ -297,12 +266,8 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { mFinishCallback = null; } }); if (mFirstWindowSurface != null) { final SurfaceControl.Transaction tx = mTransactionPool.acquire(); tx.setWindowCrop(mFirstWindowSurface, null); tx.apply(); mFirstWindowSurface.release(); mFirstWindowSurface = null; if (mShiftUpAnimation != null) { mShiftUpAnimation.finish(); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +4 −14 Original line number Diff line number Diff line Loading @@ -75,20 +75,15 @@ public class SplashscreenContentDrawer { private int mBrandingImageWidth; private int mBrandingImageHeight; private final int mAppRevealDuration; private final int mIconExitDuration; private int mMainWindowShiftLength; private int mIconNormalExitDistance; private int mIconEarlyExitDistance; private final TransactionPool mTransactionPool; private final SplashScreenWindowAttrs mTmpAttrs = new SplashScreenWindowAttrs(); private final Handler mSplashscreenWorkerHandler; SplashscreenContentDrawer(Context context, int iconExitAnimDuration, int appRevealAnimDuration, TransactionPool pool) { SplashscreenContentDrawer(Context context, int appRevealAnimDuration, TransactionPool pool) { mContext = context; mIconProvider = new IconProvider(context); mAppRevealDuration = appRevealAnimDuration; mIconExitDuration = iconExitAnimDuration; mTransactionPool = pool; // Initialize Splashscreen worker thread Loading Loading @@ -139,10 +134,6 @@ public class SplashscreenContentDrawer { com.android.wm.shell.R.dimen.starting_surface_brand_image_height); mMainWindowShiftLength = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length); mIconNormalExitDistance = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_normal_exit_icon_distance); mIconEarlyExitDistance = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_early_exit_icon_distance); } private int getSystemBGColor() { Loading Loading @@ -406,6 +397,7 @@ public class SplashscreenContentDrawer { } if (mEmptyView) { splashScreenView.setNotCopyable(); splashScreenView.setRevealAnimationSupported(false); } splashScreenView.makeSystemUIColorsTransparent(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Loading Loading @@ -678,12 +670,10 @@ public class SplashscreenContentDrawer { * Create and play the default exit animation for splash screen view. */ void applyExitAnimation(SplashScreenView view, SurfaceControl leash, Rect frame, boolean isEarlyExit, Runnable finishCallback) { Rect frame, Runnable finishCallback) { final SplashScreenExitAnimation animation = new SplashScreenExitAnimation(view, leash, frame, mAppRevealDuration, mIconExitDuration, mMainWindowShiftLength, isEarlyExit ? mIconEarlyExitDistance : mIconNormalExitDistance, mTransactionPool, frame, mAppRevealDuration, mMainWindowShiftLength, mTransactionPool, finishCallback); animation.prepareAnimations(); animation.startAnimations(); } }
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +20 −23 Original line number Diff line number Diff line Loading @@ -35,7 +35,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.os.IBinder; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -106,6 +106,8 @@ public class StartingSurfaceDrawer { private final SplashscreenContentDrawer mSplashscreenContentDrawer; private Choreographer mChoreographer; private static final boolean DEBUG_ENABLE_REVEAL_ANIMATION = SystemProperties.getBoolean("persist.debug.enable_reveal_animation", false); /** * @param splashScreenExecutor The thread used to control add and remove starting window. */ Loading @@ -114,12 +116,10 @@ public class StartingSurfaceDrawer { mContext = context; mDisplayManager = mContext.getSystemService(DisplayManager.class); mSplashScreenExecutor = splashScreenExecutor; final int iconExitAnimDuration = context.getResources().getInteger( com.android.wm.shell.R.integer.starting_window_icon_exit_anim_duration); final int appRevealAnimDuration = context.getResources().getInteger( com.android.wm.shell.R.integer.starting_window_app_reveal_anim_duration); mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconExitAnimDuration, appRevealAnimDuration, pool); mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, appRevealAnimDuration, pool); mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance()); } Loading Loading @@ -467,20 +467,24 @@ public class StartingSurfaceDrawer { if (DEBUG_SPLASH_SCREEN) { Slog.v(TAG, "Removing splash screen window for task: " + taskId); } if (record.mContentView != null) { if (leash != null || playRevealAnimation) { if (record.mContentView != null && record.mContentView.isRevealAnimationSupported()) { if (playRevealAnimation) { if (DEBUG_ENABLE_REVEAL_ANIMATION) { mSplashscreenContentDrawer.applyExitAnimation(record.mContentView, leash, frame, record.isEarlyExit(), leash, frame, () -> removeWindowInner(record.mDecorView, true)); } else { // TODO(183004107) Always hide decorView when playRevealAnimation is enabled // from TaskOrganizerController#removeStartingWindow // the SplashScreenView has been copied to client, skip default exit // animation // using the default exit animation from framework removeWindowInner(record.mDecorView, false); } } else { // no animation will be applied // the SplashScreenView has been copied to client, hide the view to skip // default exit animation removeWindowInner(record.mDecorView, true); } } else { // this is a blank splash screen, don't apply reveal animation removeWindowInner(record.mDecorView, false); } } Loading Loading @@ -514,12 +518,10 @@ public class StartingSurfaceDrawer { * Record the view or surface for a starting window. */ private static class StartingWindowRecord { private static final long EARLY_START_MINIMUM_TIME_MS = 250; private final View mDecorView; private final TaskSnapshotWindow mTaskSnapshotWindow; private SplashScreenView mContentView; private boolean mSetSplashScreen; private long mContentCreateTime; StartingWindowRecord(View decorView, TaskSnapshotWindow taskSnapshotWindow) { mDecorView = decorView; Loading @@ -531,12 +533,7 @@ public class StartingSurfaceDrawer { return; } mContentView = splashScreenView; mContentCreateTime = SystemClock.uptimeMillis(); mSetSplashScreen = true; } boolean isEarlyExit() { return SystemClock.uptimeMillis() - mContentCreateTime < EARLY_START_MINIMUM_TIME_MS; } } }