From 8e3a0e498c657d2c73bf58b83ad108e60cd4a08e Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Thu, 6 Jan 2022 19:58:38 +0100 Subject: [PATCH] Add option to override background color for animation through overridePendingTransition Test: atest CtsWindowManagerDeviceTestCases:AnimationBackgroundTests Change-Id: I3debc8c1f4646cfd7c20c3f8e57abd465aec23ad --- core/api/current.txt | 2 + core/api/test-current.txt | 2 +- core/java/android/app/Activity.java | 27 +++++++++- core/java/android/app/ActivityClient.java | 6 +-- core/java/android/app/ActivityOptions.java | 50 ++++++++++++++++--- .../app/IActivityClientController.aidl | 2 +- core/java/android/window/TransitionInfo.java | 12 ++++- .../transition/DefaultTransitionHandler.java | 12 +++-- .../server/wm/ActivityClientController.java | 5 +- .../com/android/server/wm/ActivityRecord.java | 1 + 10 files changed, 97 insertions(+), 22 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index ee5b2e1b12c7f..f00a942478f35 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -4181,6 +4181,7 @@ package android.app { method public void openContextMenu(android.view.View); method public void openOptionsMenu(); method public void overridePendingTransition(int, int); + method public void overridePendingTransition(int, int, int); method public void postponeEnterTransition(); method public void recreate(); method public void registerActivityLifecycleCallbacks(@NonNull android.app.Application.ActivityLifecycleCallbacks); @@ -4484,6 +4485,7 @@ package android.app { method public static android.app.ActivityOptions makeBasic(); method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int); method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int); + method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int); method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int); method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, String); method @java.lang.SafeVarargs public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair...); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 2303ddb8428d6..f755f10c89978 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -151,7 +151,7 @@ package android.app { public class ActivityOptions { method @NonNull public static android.app.ActivityOptions fromBundle(@NonNull android.os.Bundle); - method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener); + method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener); method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener); method public static void setExitTransitionTimeout(long); method public void setLaunchActivityType(int); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 38138d81885d1..869320db3ba82 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6131,8 +6131,31 @@ public class Activity extends ContextThemeWrapper * the outgoing activity. Use 0 for no animation. */ public void overridePendingTransition(int enterAnim, int exitAnim) { - ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), - enterAnim, exitAnim); + overridePendingTransition(enterAnim, exitAnim, 0); + } + + /** + * Call immediately after one of the flavors of {@link #startActivity(Intent)} + * or {@link #finish} to specify an explicit transition animation to + * perform next. + * + *

As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN} an alternative + * to using this with starting activities is to supply the desired animation + * information through a {@link ActivityOptions} bundle to + * {@link #startActivity(Intent, Bundle)} or a related function. This allows + * you to specify a custom animation even when starting an activity from + * outside the context of the current top activity. + * + * @param enterAnim A resource ID of the animation resource to use for + * the incoming activity. Use 0 for no animation. + * @param exitAnim A resource ID of the animation resource to use for + * the outgoing activity. Use 0 for no animation. + * @param backgroundColor The background color to use for the background during the animation if + * the animation requires a background. Set to 0 to not override the default color. + */ + public void overridePendingTransition(int enterAnim, int exitAnim, int backgroundColor) { + ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), enterAnim, + exitAnim, backgroundColor); } /** diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index eb4a355c8ae70..605a1fa822541 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -428,11 +428,11 @@ public class ActivityClient { } } - void overridePendingTransition(IBinder token, String packageName, - int enterAnim, int exitAnim) { + void overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim, + int backgroundColor) { try { getActivityClientController().overridePendingTransition(token, packageName, - enterAnim, exitAnim); + enterAnim, exitAnim, backgroundColor); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 5e5649f4eadf4..e405b60c8daaf 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -125,6 +125,12 @@ public class ActivityOptions extends ComponentOptions { */ public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:activity.animInPlaceRes"; + /** + * Custom background color for animation. + * @hide + */ + public static final String KEY_ANIM_BACKGROUND_COLOR = "android:activity.backgroundColor"; + /** * Bitmap for thumbnail animation. * @hide @@ -389,6 +395,7 @@ public class ActivityOptions extends ComponentOptions { private int mCustomEnterResId; private int mCustomExitResId; private int mCustomInPlaceResId; + private int mCustomBackgroundColor; private Bitmap mThumbnail; private int mStartX; private int mStartY; @@ -453,7 +460,27 @@ public class ActivityOptions extends ComponentOptions { */ public static ActivityOptions makeCustomAnimation(Context context, int enterResId, int exitResId) { - return makeCustomAnimation(context, enterResId, exitResId, null, null, null); + return makeCustomAnimation(context, enterResId, exitResId, 0, null, null); + } + + /** + * Create an ActivityOptions specifying a custom animation to run when + * the activity is displayed. + * + * @param context Who is defining this. This is the application that the + * animation resources will be loaded from. + * @param enterResId A resource ID of the animation resource to use for + * the incoming activity. Use 0 for no animation. + * @param exitResId A resource ID of the animation resource to use for + * the outgoing activity. Use 0 for no animation. + * @param backgroundColor The background color to use for the background during the animation if + * the animation requires a background. Set to 0 to not override the default color. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + */ + public static @NonNull ActivityOptions makeCustomAnimation(@NonNull Context context, + int enterResId, int exitResId, int backgroundColor) { + return makeCustomAnimation(context, enterResId, exitResId, backgroundColor, null, null); } /** @@ -477,12 +504,14 @@ public class ActivityOptions extends ComponentOptions { */ @UnsupportedAppUsage public static ActivityOptions makeCustomAnimation(Context context, - int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) { + int enterResId, int exitResId, int backgroundColor, Handler handler, + OnAnimationStartedListener listener) { ActivityOptions opts = new ActivityOptions(); opts.mPackageName = context.getPackageName(); opts.mAnimationType = ANIM_CUSTOM; opts.mCustomEnterResId = enterResId; opts.mCustomExitResId = exitResId; + opts.mCustomBackgroundColor = backgroundColor; opts.setOnAnimationStartedListener(handler, listener); return opts; } @@ -510,11 +539,11 @@ public class ActivityOptions extends ComponentOptions { */ @TestApi public static @NonNull ActivityOptions makeCustomAnimation(@NonNull Context context, - int enterResId, int exitResId, @Nullable Handler handler, + int enterResId, int exitResId, int backgroundColor, @Nullable Handler handler, @Nullable OnAnimationStartedListener startedListener, @Nullable OnAnimationFinishedListener finishedListener) { - ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, handler, - startedListener); + ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, backgroundColor, + handler, startedListener); opts.setOnAnimationFinishedListener(handler, finishedListener); return opts; } @@ -547,8 +576,8 @@ public class ActivityOptions extends ComponentOptions { int enterResId, int exitResId, @Nullable Handler handler, @Nullable OnAnimationStartedListener startedListener, @Nullable OnAnimationFinishedListener finishedListener) { - ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, handler, - startedListener, finishedListener); + ActivityOptions opts = makeCustomAnimation(context, enterResId, exitResId, 0, + handler, startedListener, finishedListener); opts.mOverrideTaskTransition = true; return opts; } @@ -1243,6 +1272,11 @@ public class ActivityOptions extends ComponentOptions { return mCustomInPlaceResId; } + /** @hide */ + public int getCustomBackgroundColor() { + return mCustomBackgroundColor; + } + /** * The thumbnail is copied into a hardware bitmap when it is bundled and sent to the system, so * it should always be backed by a HardwareBuffer on the other end. @@ -1775,6 +1809,7 @@ public class ActivityOptions extends ComponentOptions { case ANIM_CUSTOM: mCustomEnterResId = otherOptions.mCustomEnterResId; mCustomExitResId = otherOptions.mCustomExitResId; + mCustomBackgroundColor = otherOptions.mCustomBackgroundColor; mThumbnail = null; if (mAnimationStartedListener != null) { try { @@ -1862,6 +1897,7 @@ public class ActivityOptions extends ComponentOptions { case ANIM_CUSTOM: b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId); b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId); + b.putInt(KEY_ANIM_BACKGROUND_COLOR, mCustomBackgroundColor); b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener != null ? mAnimationStartedListener.asBinder() : null); break; diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index 83c57c573b827..396e5528ab0c2 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -112,7 +112,7 @@ interface IActivityClientController { * calls, so this method should be the same as them to keep the invocation order. */ void overridePendingTransition(in IBinder token, in String packageName, - int enterAnim, int exitAnim); + int enterAnim, int exitAnim, int backgroundColor); int setVrMode(in IBinder token, boolean enabled, in ComponentName packageName); /** See {@link android.app.Activity#setDisablePreviewScreenshots}. */ diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index fd1e848221938..3fa62e017976d 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -599,6 +599,7 @@ public final class TransitionInfo implements Parcelable { private final Rect mTransitionBounds = new Rect(); private HardwareBuffer mThumbnail; private int mAnimations; + private @ColorInt int mBackgroundColor; private AnimationOptions(int type) { mType = type; @@ -608,6 +609,7 @@ public final class TransitionInfo implements Parcelable { mType = in.readInt(); mEnterResId = in.readInt(); mExitResId = in.readInt(); + mBackgroundColor = in.readInt(); mOverrideTaskTransition = in.readBoolean(); mPackageName = in.readString(); mTransitionBounds.readFromParcel(in); @@ -624,11 +626,12 @@ public final class TransitionInfo implements Parcelable { } public static AnimationOptions makeCustomAnimOptions(String packageName, int enterResId, - int exitResId, boolean overrideTaskTransition) { + int exitResId, @ColorInt int backgroundColor, boolean overrideTaskTransition) { AnimationOptions options = new AnimationOptions(ANIM_CUSTOM); options.mPackageName = packageName; options.mEnterResId = enterResId; options.mExitResId = exitResId; + options.mBackgroundColor = backgroundColor; options.mOverrideTaskTransition = overrideTaskTransition; return options; } @@ -673,6 +676,10 @@ public final class TransitionInfo implements Parcelable { return mExitResId; } + public @ColorInt int getBackgroundColor() { + return mBackgroundColor; + } + public boolean getOverrideTaskTransition() { return mOverrideTaskTransition; } @@ -698,6 +705,7 @@ public final class TransitionInfo implements Parcelable { dest.writeInt(mType); dest.writeInt(mEnterResId); dest.writeInt(mExitResId); + dest.writeInt(mBackgroundColor); dest.writeBoolean(mOverrideTaskTransition); dest.writeString(mPackageName); mTransitionBounds.writeToParcel(dest, flags); @@ -740,7 +748,7 @@ public final class TransitionInfo implements Parcelable { @Override public String toString() { - return "{ AnimationOtions type= " + typeToString(mType) + " package=" + mPackageName + return "{ AnimationOptions type= " + typeToString(mType) + " package=" + mPackageName + " override=" + mOverrideTaskTransition + " b=" + mTransitionBounds + "}"; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 13e81bdb3c0b4..79c8a87acb5b8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -371,10 +371,14 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } if (a.getShowBackground()) { - // use the window's background color if provided as the background color for the - // animation - the top most window with a valid background color and - // showBackground set takes precedence. - if (change.getBackgroundColor() != 0) { + if (info.getAnimationOptions().getBackgroundColor() != 0) { + // If available use the background color provided through AnimationOptions + backgroundColorForTransition = + info.getAnimationOptions().getBackgroundColor(); + } else if (change.getBackgroundColor() != 0) { + // Otherwise default to the window's background color if provided through + // the theme as the background color for the animation - the top most window + // with a valid background color and showBackground set takes precedence. backgroundColorForTransition = change.getBackgroundColor(); } } diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 7164c6c601ef3..ff96aebba7086 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -43,6 +43,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_N import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH; import static com.android.server.wm.ActivityTaskManagerService.enforceNotIsolatedCaller; +import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; @@ -1081,7 +1082,7 @@ class ActivityClientController extends IActivityClientController.Stub { @Override public void overridePendingTransition(IBinder token, String packageName, - int enterAnim, int exitAnim) { + int enterAnim, int exitAnim, @ColorInt int backgroundColor) { final long origId = Binder.clearCallingIdentity(); synchronized (mGlobalLock) { final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); @@ -1091,7 +1092,7 @@ class ActivityClientController extends IActivityClientController.Stub { r.mOverrideTaskTransition); r.mTransitionController.setOverrideAnimation( TransitionInfo.AnimationOptions.makeCustomAnimOptions(packageName, - enterAnim, exitAnim, r.mOverrideTaskTransition), + enterAnim, exitAnim, backgroundColor, r.mOverrideTaskTransition), null /* startCallback */, null /* finishCallback */); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c0eee6136f34d..3908874d854d2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4469,6 +4469,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pendingOptions.getOverrideTaskTransition()); options = AnimationOptions.makeCustomAnimOptions(pendingOptions.getPackageName(), pendingOptions.getCustomEnterResId(), pendingOptions.getCustomExitResId(), + pendingOptions.getCustomBackgroundColor(), pendingOptions.getOverrideTaskTransition()); startCallback = pendingOptions.getAnimationStartedListener(); finishCallback = pendingOptions.getAnimationFinishedListener();