From bfb28f2f3cee0a1754245453c9c02b10587414fe Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Thu, 4 Feb 2021 18:01:31 +0800 Subject: [PATCH] Add two more Api for SplashScreenView(7/N) getIconAnimationDuration - Returns the duration of the icon animation if icon is animatable. getIconAnimationStart - If the replaced icon is animatable, return the animation start time in millisecond based on system. Bug: 73289295 Test: atest CtsWindowManagerDeviceTestCases:SplashscreenTests Change-Id: Ie4332d6764b4d0892a0e5e6f7c297102b71a79f9 --- core/api/current.txt | 2 + core/api/test-current.txt | 1 - .../java/android/window/SplashScreenView.java | 64 ++++++++++------- .../StartingSurfaceDrawer.java | 68 +------------------ 4 files changed, 43 insertions(+), 92 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 25e183805f8bd..d848bbf7a2d1e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -55842,6 +55842,8 @@ package android.window { } public final class SplashScreenView extends android.widget.FrameLayout { + method public long getIconAnimationDurationMillis(); + method public long getIconAnimationStartMillis(); method @Nullable public android.view.View getIconView(); method public void remove(); } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 3e2accccc45f6..29be5c6e46815 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2731,7 +2731,6 @@ package android.window { public final class SplashScreenView extends android.widget.FrameLayout { method @Nullable public android.view.View getBrandingView(); - method public boolean isIconAnimating(); } public final class StartingWindowInfo implements android.os.Parcelable { diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index 5292875f46f2a..35ccfca101d35 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -33,6 +33,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; @@ -71,10 +72,11 @@ public final class SplashScreenView extends FrameLayout { private Bitmap mParceledIconBitmap; private View mBrandingImageView; private Bitmap mParceledBrandingBitmap; + private long mIconAnimationDuration; + private long mIconAnimationStart; private Animatable mAnimatableIcon; private ValueAnimator mAnimator; - private Runnable mAnimationFinishListener; // cache original window and status private Window mWindow; @@ -92,11 +94,12 @@ public final class SplashScreenView extends FrameLayout { private @ColorInt int mBackgroundColor; private Bitmap mParceledIconBitmap; private Drawable mIconDrawable; - private int mIconAnimationDuration; private int mBrandingImageWidth; private int mBrandingImageHeight; private Drawable mBrandingDrawable; private Bitmap mParceledBrandingBitmap; + private long mIconAnimationStart; + private long mIconAnimationDuration; public Builder(@NonNull Context context) { mContext = context; @@ -119,6 +122,8 @@ public final class SplashScreenView extends FrameLayout { parcelable.mBrandingHeight); mParceledBrandingBitmap = parcelable.mBrandingBitmap; } + mIconAnimationStart = parcelable.mIconAnimationStart; + mIconAnimationDuration = parcelable.mIconAnimationDuration; return this; } @@ -186,6 +191,8 @@ public final class SplashScreenView extends FrameLayout { view.mIconView.setBackground(mIconDrawable); view.initIconAnimation(mIconDrawable, mIconAnimationDuration); } + view.mIconAnimationStart = mIconAnimationStart; + view.mIconAnimationDuration = mIconAnimationDuration; if (mParceledIconBitmap != null) { view.mParceledIconBitmap = mParceledIconBitmap; } @@ -238,28 +245,44 @@ public final class SplashScreenView extends FrameLayout { return !mNotCopyable; } - void initIconAnimation(Drawable iconDrawable, int duration) { + /** + * Returns the duration of the icon animation if icon is animatable. + * + * @see android.R.attr#windowSplashScreenAnimatedIcon + * @see android.R.attr#windowSplashScreenAnimationDuration + */ + public long getIconAnimationDurationMillis() { + return mIconAnimationDuration; + } + + /** + * If the replaced icon is animatable, return the animation start time in millisecond based on + * system. The start time is set using {@link SystemClock#uptimeMillis()}. + */ + public long getIconAnimationStartMillis() { + return mIconAnimationStart; + } + + void initIconAnimation(Drawable iconDrawable, long duration) { if (iconDrawable instanceof Animatable) { mAnimatableIcon = (Animatable) iconDrawable; mAnimator = ValueAnimator.ofInt(0, 1); mAnimator.setDuration(duration); - mAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { + mIconAnimationStart = SystemClock.uptimeMillis(); mAnimatableIcon.start(); } @Override public void onAnimationEnd(Animator animation) { mAnimatableIcon.stop(); - onIconAnimationFinish(); } @Override public void onAnimationCancel(Animator animation) { mAnimatableIcon.stop(); - onIconAnimationFinish(); } @Override @@ -271,30 +294,12 @@ public final class SplashScreenView extends FrameLayout { } } - private void onIconAnimationFinish() { - if (mAnimationFinishListener != null) { - mAnimationFinishListener.run(); - mAnimationFinishListener = null; - } - } - /** * @hide */ - @TestApi - public boolean isIconAnimating() { - return mAnimatableIcon != null && mAnimator.isRunning(); - } - - /** - * @hide - */ - public void startIntroAnimation(Runnable finishListener) { + public void startIntroAnimation() { if (mAnimatableIcon != null) { - mAnimationFinishListener = finishListener; mAnimator.start(); - } else if (finishListener != null) { - finishListener.run(); } } @@ -403,6 +408,9 @@ public final class SplashScreenView extends FrameLayout { private int mBrandingHeight; private Bitmap mBrandingBitmap; + private long mIconAnimationStart; + private long mIconAnimationDuration; + public SplashScreenViewParcelable(SplashScreenView view) { ViewGroup.LayoutParams params = view.getIconView().getLayoutParams(); mIconSize = params.height; @@ -414,6 +422,8 @@ public final class SplashScreenView extends FrameLayout { mBrandingWidth = params.width; mBrandingHeight = params.height; + mIconAnimationStart = view.getIconAnimationStartMillis(); + mIconAnimationDuration = view.getIconAnimationDurationMillis(); } private Bitmap copyDrawable(Drawable drawable) { @@ -444,6 +454,8 @@ public final class SplashScreenView extends FrameLayout { mBrandingWidth = source.readInt(); mBrandingHeight = source.readInt(); mBrandingBitmap = source.readTypedObject(Bitmap.CREATOR); + mIconAnimationStart = source.readLong(); + mIconAnimationDuration = source.readLong(); } @Override @@ -459,6 +471,8 @@ public final class SplashScreenView extends FrameLayout { dest.writeInt(mBrandingWidth); dest.writeInt(mBrandingHeight); dest.writeTypedObject(mBrandingBitmap, flags); + dest.writeLong(mIconAnimationStart); + dest.writeLong(mIconAnimationDuration); } public static final @NonNull Parcelable.Creator CREATOR = diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 8fe1c6ebbd774..5332291fd1bd3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -74,8 +74,6 @@ public class StartingSurfaceDrawer { private final DisplayManager mDisplayManager; final ShellExecutor mMainExecutor; private final SplashscreenContentDrawer mSplashscreenContentDrawer; - private final IconAnimationFinishListener mIconAnimationFinishListener = - new IconAnimationFinishListener(); // TODO(b/131727939) remove this when clearing ActivityRecord private static final int REMOVE_WHEN_TIMEOUT = 2000; @@ -410,16 +408,7 @@ public class StartingSurfaceDrawer { SplashScreenViewParcelable parcelable; if (preView != null && preView.mContentView != null && preView.mContentView.isCopyable()) { - if (preView.mContentView.isIconAnimating()) { - // if animating, wait until animation finish - if (DEBUG_SPLASH_SCREEN) { - Slog.v(TAG, "Copying splash screen view but icon is animating " + taskId); - } - mIconAnimationFinishListener.waitingForCopyTask(taskId); - return; - } else { - parcelable = new SplashScreenViewParcelable(preView.mContentView); - } + parcelable = new SplashScreenViewParcelable(preView.mContentView); } else { parcelable = null; } @@ -460,60 +449,12 @@ public class StartingSurfaceDrawer { mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT); final StartingWindowRecord tView = new StartingWindowRecord(view, null /* TaskSnapshotWindow */, splashScreenView); - splashScreenView.startIntroAnimation( - mIconAnimationFinishListener.makeListener(taskId)); + splashScreenView.startIntroAnimation(); mStartingWindowRecords.put(taskId, tView); } }); } - private class IconAnimationFinishListener { - private final SparseArray mListeners = new SparseArray<>(); - - private class TaskListener implements Runnable { - private int mTargetTaskId; - private boolean mWaitingForCopy; - private boolean mWaitingForRemove; - @Override - public void run() { - if (mWaitingForCopy) { - if (DEBUG_SPLASH_SCREEN) { - Slog.v(TAG, "Icon animation finish and waiting for copy at task " - + mTargetTaskId); - } - copySplashScreenView(mTargetTaskId); - } - if (mWaitingForRemove) { - if (DEBUG_SPLASH_SCREEN) { - Slog.v(TAG, "Icon animation finish and waiting for remove at task " - + mTargetTaskId); - } - mMainExecutor.execute(() -> removeWindowSynced(mTargetTaskId)); - } - mListeners.remove(mTargetTaskId); - } - } - - private Runnable makeListener(int taskId) { - final TaskListener listener = new TaskListener(); - listener.mTargetTaskId = taskId; - mListeners.put(taskId, listener); - return listener; - } - - private void waitingForCopyTask(int taskId) { - if (mListeners.contains(taskId)) { - mListeners.get(taskId).mWaitingForCopy = true; - } - } - - private void waitingForRemove(int taskId) { - if (mListeners.contains(taskId)) { - mListeners.get(taskId).mWaitingForRemove = true; - } - } - } - protected void removeWindowSynced(int taskId) { final StartingWindowRecord record = mStartingWindowRecords.get(taskId); if (record != null) { @@ -521,11 +462,6 @@ public class StartingSurfaceDrawer { if (DEBUG_SPLASH_SCREEN) { Slog.v(TAG, "Removing splash screen window for task: " + taskId); } - if (record.mContentView != null && record.mContentView.isIconAnimating()) { - // do not remove until the animation is finish - mIconAnimationFinishListener.waitingForRemove(taskId); - return; - } final WindowManager wm = record.mDecorView.getContext() .getSystemService(WindowManager.class); wm.removeView(record.mDecorView);