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
diff --git a/core/api/current.txt b/core/api/current.txt
index 25e1838..d848bbf 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -55842,6 +55842,8 @@
}
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 3e2accc..29be5c6 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2731,7 +2731,6 @@
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 5292875..35ccfca 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -33,6 +33,7 @@
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 @@
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 @@
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 @@
parcelable.mBrandingHeight);
mParceledBrandingBitmap = parcelable.mBrandingBitmap;
}
+ mIconAnimationStart = parcelable.mIconAnimationStart;
+ mIconAnimationDuration = parcelable.mIconAnimationDuration;
return this;
}
@@ -186,6 +191,8 @@
view.mIconView.setBackground(mIconDrawable);
view.initIconAnimation(mIconDrawable, mIconAnimationDuration);
}
+ view.mIconAnimationStart = mIconAnimationStart;
+ view.mIconAnimationDuration = mIconAnimationDuration;
if (mParceledIconBitmap != null) {
view.mParceledIconBitmap = mParceledIconBitmap;
}
@@ -238,28 +245,44 @@
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 @@
}
}
- 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 @@
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 @@
mBrandingWidth = params.width;
mBrandingHeight = params.height;
+ mIconAnimationStart = view.getIconAnimationStartMillis();
+ mIconAnimationDuration = view.getIconAnimationDurationMillis();
}
private Bitmap copyDrawable(Drawable drawable) {
@@ -444,6 +454,8 @@
mBrandingWidth = source.readInt();
mBrandingHeight = source.readInt();
mBrandingBitmap = source.readTypedObject(Bitmap.CREATOR);
+ mIconAnimationStart = source.readLong();
+ mIconAnimationDuration = source.readLong();
}
@Override
@@ -459,6 +471,8 @@
dest.writeInt(mBrandingWidth);
dest.writeInt(mBrandingHeight);
dest.writeTypedObject(mBrandingBitmap, flags);
+ dest.writeLong(mIconAnimationStart);
+ dest.writeLong(mIconAnimationDuration);
}
public static final @NonNull Parcelable.Creator<SplashScreenViewParcelable> 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 8fe1c6e..5332291 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 @@
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 @@
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 @@
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<TaskListener> 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 @@
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);