Merge "Introduce new API overrideActivityTransition(1/N)"

This commit is contained in:
Wei Sheng Shih
2023-02-14 12:03:28 +00:00
committed by Android (Google) Code Review
10 changed files with 453 additions and 9 deletions

View File

@@ -4319,6 +4319,7 @@ package android.app {
@UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
ctor public Activity();
method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public void clearOverrideActivityTransition(int);
method public void closeContextMenu();
method public void closeOptionsMenu();
method public android.app.PendingIntent createPendingResult(int, @NonNull android.content.Intent, int);
@@ -4487,6 +4488,8 @@ package android.app {
method @Nullable public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
method public void openContextMenu(android.view.View);
method public void openOptionsMenu();
method public void overrideActivityTransition(int, @AnimRes int, @AnimRes int);
method public void overrideActivityTransition(int, @AnimRes int, @AnimRes int, @ColorInt int);
method public void overridePendingTransition(int, int);
method public void overridePendingTransition(int, int, int);
method public void postponeEnterTransition();
@@ -4588,6 +4591,8 @@ package android.app {
field protected static final int[] FOCUSED_STATE_SET;
field public static final int FULLSCREEN_MODE_REQUEST_ENTER = 1; // 0x1
field public static final int FULLSCREEN_MODE_REQUEST_EXIT = 0; // 0x0
field public static final int OVERRIDE_TRANSITION_CLOSE = 1; // 0x1
field public static final int OVERRIDE_TRANSITION_OPEN = 0; // 0x0
field public static final int RESULT_CANCELED = 0; // 0x0
field public static final int RESULT_FIRST_USER = 1; // 0x1
field public static final int RESULT_OK = -1; // 0xffffffff

View File

@@ -26,8 +26,10 @@ import static android.os.Process.myUid;
import static java.lang.Character.MIN_VALUE;
import android.annotation.AnimRes;
import android.annotation.CallSuper;
import android.annotation.CallbackExecutor;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.IntDef;
@@ -108,6 +110,7 @@ import android.util.AttributeSet;
import android.util.Dumpable;
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
@@ -1006,6 +1009,25 @@ public class Activity extends ContextThemeWrapper
*/
public static final int FULLSCREEN_MODE_REQUEST_ENTER = 1;
/** @hide */
@IntDef(prefix = { "OVERRIDE_TRANSITION_" }, value = {
OVERRIDE_TRANSITION_OPEN,
OVERRIDE_TRANSITION_CLOSE
})
public @interface OverrideTransition {}
/**
* Request type of {@link #overrideActivityTransition(int, int, int)} or
* {@link #overrideActivityTransition(int, int, int, int)}, to override the
* opening transition.
*/
public static final int OVERRIDE_TRANSITION_OPEN = 0;
/**
* Request type of {@link #overrideActivityTransition(int, int, int)} or
* {@link #overrideActivityTransition(int, int, int, int)}, to override the
* closing transition.
*/
public static final int OVERRIDE_TRANSITION_CLOSE = 1;
private boolean mShouldDockBigOverlays;
private UiTranslationController mUiTranslationController;
@@ -6461,6 +6483,124 @@ public class Activity extends ContextThemeWrapper
flagsMask, flagsValues, options);
}
/**
* Customizes the animation for the activity transition with this activity. This can be called
* at any time while the activity still alive.
*
* <p> This is a more robust method of overriding the transition animation at runtime without
* relying on {@link #overridePendingTransition(int, int)} which doesn't work for predictive
* back. However, the animation set from {@link #overridePendingTransition(int, int)} still
* has higher priority when the system is looking for the next transition animation.</p>
* <p> The animations resources set by this method will be chosen if and only if the activity is
* on top of the task while activity transitions are being played.
* For example, if we want to customize the opening transition when launching Activity B which
* gets started from Activity A, we should call this method inside B's onCreate with
* {@code overrideType = OVERRIDE_TRANSITION_OPEN} because the Activity B will on top of the
* task. And if we want to customize the closing transition when finishing Activity B and back
* to Activity A, since B is still is above A, we should call this method in Activity B with
* {@code overrideType = OVERRIDE_TRANSITION_CLOSE}. </p>
*
* <p> If an Activity has called this method, and it also set another activity animation
* by {@link Window#setWindowAnimations(int)}, the system will choose the animation set from
* this method.</p>
*
* <p> Note that {@link Window#setWindowAnimations},
* {@link #overridePendingTransition(int, int)} and this method will be ignored if the Activity
* is started with {@link ActivityOptions#makeSceneTransitionAnimation(Activity, Pair[])}. Also
* note that this method can only be used to customize cross-activity transitions but not
* cross-task transitions which are fully non-customizable as of Android 11.</p>
*
* @param overrideType {@code OVERRIDE_TRANSITION_OPEN} This animation will be used when
* starting/entering an activity. {@code OVERRIDE_TRANSITION_CLOSE} This
* animation will be used when finishing/closing an 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.
*
* @see #overrideActivityTransition(int, int, int, int)
* @see #clearOverrideActivityTransition(int)
* @see OnBackInvokedCallback
* @see #overridePendingTransition(int, int)
* @see Window#setWindowAnimations(int)
* @see ActivityOptions#makeSceneTransitionAnimation(Activity, Pair[])
*/
public void overrideActivityTransition(@OverrideTransition int overrideType,
@AnimRes int enterAnim, @AnimRes int exitAnim) {
overrideActivityTransition(overrideType, enterAnim, exitAnim, Color.TRANSPARENT);
}
/**
* Customizes the animation for the activity transition with this activity. This can be called
* at any time while the activity still alive.
*
* <p> This is a more robust method of overriding the transition animation at runtime without
* relying on {@link #overridePendingTransition(int, int)} which doesn't work for predictive
* back. However, the animation set from {@link #overridePendingTransition(int, int)} still
* has higher priority when the system is looking for the next transition animation.</p>
* <p> The animations resources set by this method will be chosen if and only if the activity is
* on top of the task while activity transitions are being played.
* For example, if we want to customize the opening transition when launching Activity B which
* gets started from Activity A, we should call this method inside B's onCreate with
* {@code overrideType = OVERRIDE_TRANSITION_OPEN} because the Activity B will on top of the
* task. And if we want to customize the closing transition when finishing Activity B and back
* to Activity A, since B is still is above A, we should call this method in Activity B with
* {@code overrideType = OVERRIDE_TRANSITION_CLOSE}. </p>
*
* <p> If an Activity has called this method, and it also set another activity animation
* by {@link Window#setWindowAnimations(int)}, the system will choose the animation set from
* this method.</p>
*
* <p> Note that {@link Window#setWindowAnimations},
* {@link #overridePendingTransition(int, int)} and this method will be ignored if the Activity
* is started with {@link ActivityOptions#makeSceneTransitionAnimation(Activity, Pair[])}. Also
* note that this method can only be used to customize cross-activity transitions but not
* cross-task transitions which are fully non-customizable as of Android 11.</p>
*
* @param overrideType {@code OVERRIDE_TRANSITION_OPEN} This animation will be used when
* starting/entering an activity. {@code OVERRIDE_TRANSITION_CLOSE} This
* animation will be used when finishing/closing an 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
* {@link Color#TRANSPARENT} to not override the default color.
* @see #overrideActivityTransition(int, int, int)
* @see #clearOverrideActivityTransition(int)
* @see OnBackInvokedCallback
* @see #overridePendingTransition(int, int)
* @see Window#setWindowAnimations(int)
* @see ActivityOptions#makeSceneTransitionAnimation(Activity, Pair[])
*/
public void overrideActivityTransition(@OverrideTransition int overrideType,
@AnimRes int enterAnim, @AnimRes int exitAnim, @ColorInt int backgroundColor) {
if (overrideType != OVERRIDE_TRANSITION_OPEN && overrideType != OVERRIDE_TRANSITION_CLOSE) {
throw new IllegalArgumentException("Override type must be either open or close");
}
ActivityClient.getInstance().overrideActivityTransition(mToken,
overrideType == OVERRIDE_TRANSITION_OPEN, enterAnim, exitAnim, backgroundColor);
}
/**
* Clears the animations which are set from {@link #overrideActivityTransition}.
* @param overrideType {@code OVERRIDE_TRANSITION_OPEN} clear the animation set for starting a
* new activity. {@code OVERRIDE_TRANSITION_CLOSE} clear the animation set
* for finishing an activity.
*
* @see #overrideActivityTransition(int, int, int)
* @see #overrideActivityTransition(int, int, int, int)
*/
public void clearOverrideActivityTransition(@OverrideTransition int overrideType) {
if (overrideType != OVERRIDE_TRANSITION_OPEN && overrideType != OVERRIDE_TRANSITION_CLOSE) {
throw new IllegalArgumentException("Override type must be either open or close");
}
ActivityClient.getInstance().clearOverrideActivityTransition(mToken,
overrideType == OVERRIDE_TRANSITION_OPEN);
}
/**
* Call immediately after one of the flavors of {@link #startActivity(Intent)}
* or {@link #finish} to specify an explicit transition animation to

View File

@@ -486,6 +486,24 @@ public class ActivityClient {
}
}
void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim,
int backgroundColor) {
try {
getActivityClientController().overrideActivityTransition(
token, open, enterAnim, exitAnim, backgroundColor);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
void clearOverrideActivityTransition(IBinder token, boolean open) {
try {
getActivityClientController().clearOverrideActivityTransition(token, open);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
void overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim,
int backgroundColor) {
try {

View File

@@ -121,6 +121,9 @@ interface IActivityClientController {
oneway void setInheritShowWhenLocked(in IBinder token, boolean setInheritShownWhenLocked);
oneway void setTurnScreenOn(in IBinder token, boolean turnScreenOn);
oneway void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle);
oneway void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim,
int backgroundColor);
oneway void clearOverrideActivityTransition(IBinder token, boolean open);
/**
* Overrides the animation of activity pending transition. This call is not one-way because
* the method is usually used after startActivity or Activity#finish. If this is non-blocking,

View File

@@ -846,6 +846,9 @@ public final class TransitionInfo implements Parcelable {
private HardwareBuffer mThumbnail;
private int mAnimations;
private @ColorInt int mBackgroundColor;
// Customize activity transition animation
private CustomActivityTransition mCustomActivityOpenTransition;
private CustomActivityTransition mCustomActivityCloseTransition;
private AnimationOptions(int type) {
mType = type;
@@ -861,6 +864,15 @@ public final class TransitionInfo implements Parcelable {
mTransitionBounds.readFromParcel(in);
mThumbnail = in.readTypedObject(HardwareBuffer.CREATOR);
mAnimations = in.readInt();
mCustomActivityOpenTransition = in.readTypedObject(CustomActivityTransition.CREATOR);
mCustomActivityCloseTransition = in.readTypedObject(CustomActivityTransition.CREATOR);
}
/** Make basic customized animation for a package */
public static AnimationOptions makeCommonAnimOptions(String packageName) {
AnimationOptions options = new AnimationOptions(ANIM_FROM_STYLE);
options.mPackageName = packageName;
return options;
}
public static AnimationOptions makeAnimOptionsFromLayoutParameters(
@@ -871,6 +883,27 @@ public final class TransitionInfo implements Parcelable {
return options;
}
/** Add customized window animations */
public void addOptionsFromLayoutParameters(WindowManager.LayoutParams lp) {
mAnimations = lp.windowAnimations;
}
/** Add customized activity animation attributes */
public void addCustomActivityTransition(boolean isOpen,
int enterResId, int exitResId, int backgroundColor) {
CustomActivityTransition customTransition = isOpen
? mCustomActivityOpenTransition : mCustomActivityCloseTransition;
if (customTransition == null) {
customTransition = new CustomActivityTransition();
if (isOpen) {
mCustomActivityOpenTransition = customTransition;
} else {
mCustomActivityCloseTransition = customTransition;
}
}
customTransition.addCustomActivityTransition(enterResId, exitResId, backgroundColor);
}
public static AnimationOptions makeCustomAnimOptions(String packageName, int enterResId,
int exitResId, @ColorInt int backgroundColor, boolean overrideTaskTransition) {
AnimationOptions options = new AnimationOptions(ANIM_CUSTOM);
@@ -946,6 +979,11 @@ public final class TransitionInfo implements Parcelable {
return mAnimations;
}
/** Return customized activity transition if existed. */
public CustomActivityTransition getCustomActivityTransition(boolean open) {
return open ? mCustomActivityOpenTransition : mCustomActivityCloseTransition;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
@@ -957,6 +995,8 @@ public final class TransitionInfo implements Parcelable {
mTransitionBounds.writeToParcel(dest, flags);
dest.writeTypedObject(mThumbnail, flags);
dest.writeInt(mAnimations);
dest.writeTypedObject(mCustomActivityOpenTransition, flags);
dest.writeTypedObject(mCustomActivityCloseTransition, flags);
}
@NonNull
@@ -997,5 +1037,68 @@ public final class TransitionInfo implements Parcelable {
return "{ AnimationOptions type= " + typeToString(mType) + " package=" + mPackageName
+ " override=" + mOverrideTaskTransition + " b=" + mTransitionBounds + "}";
}
/** Customized activity transition. */
public static class CustomActivityTransition implements Parcelable {
private int mCustomEnterResId;
private int mCustomExitResId;
private int mCustomBackgroundColor;
/** Returns customize activity animation enter resource id */
public int getCustomEnterResId() {
return mCustomEnterResId;
}
/** Returns customize activity animation exit resource id */
public int getCustomExitResId() {
return mCustomExitResId;
}
/** Returns customize activity animation background color */
public int getCustomBackgroundColor() {
return mCustomBackgroundColor;
}
CustomActivityTransition() {}
CustomActivityTransition(Parcel in) {
mCustomEnterResId = in.readInt();
mCustomExitResId = in.readInt();
mCustomBackgroundColor = in.readInt();
}
/** Add customized activity animation attributes */
public void addCustomActivityTransition(
int enterResId, int exitResId, int backgroundColor) {
mCustomEnterResId = enterResId;
mCustomExitResId = exitResId;
mCustomBackgroundColor = backgroundColor;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mCustomEnterResId);
dest.writeInt(mCustomExitResId);
dest.writeInt(mCustomBackgroundColor);
}
@NonNull
public static final Creator<CustomActivityTransition> CREATOR =
new Creator<CustomActivityTransition>() {
@Override
public CustomActivityTransition createFromParcel(Parcel in) {
return new CustomActivityTransition(in);
}
@Override
public CustomActivityTransition[] newArray(int size) {
return new CustomActivityTransition[size];
}
};
}
}
}

View File

@@ -142,9 +142,12 @@ public class TransitionAnimationHelper {
Animation a = null;
if (animAttr != 0) {
if (overrideType == ANIM_FROM_STYLE && !isTask) {
a = transitionAnimation
.loadAnimationAttr(options.getPackageName(), options.getAnimations(),
animAttr, translucent);
a = loadCustomActivityTransition(animAttr, options, enter, transitionAnimation);
if (a == null) {
a = transitionAnimation
.loadAnimationAttr(options.getPackageName(), options.getAnimations(),
animAttr, translucent);
}
} else {
a = transitionAnimation.loadDefaultAnimationAttr(animAttr, translucent);
}
@@ -157,6 +160,37 @@ public class TransitionAnimationHelper {
return a;
}
static Animation loadCustomActivityTransition(int animAttr,
TransitionInfo.AnimationOptions options, boolean enter,
TransitionAnimation transitionAnimation) {
Animation a = null;
boolean isOpen = false;
switch (animAttr) {
case R.styleable.WindowAnimation_activityOpenEnterAnimation:
case R.styleable.WindowAnimation_activityOpenExitAnimation:
isOpen = true;
break;
case R.styleable.WindowAnimation_activityCloseEnterAnimation:
case R.styleable.WindowAnimation_activityCloseExitAnimation:
break;
default:
return null;
}
final TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim =
options.getCustomActivityTransition(isOpen);
if (transitionAnim != null) {
a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
enter ? transitionAnim.getCustomEnterResId()
: transitionAnim.getCustomExitResId());
if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
}
}
return a;
}
/**
* Gets the background {@link ColorInt} for the given transition animation if it is set.
*

View File

@@ -1381,6 +1381,31 @@ class ActivityClientController extends IActivityClientController.Stub {
}
}
@Override
public void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim,
int backgroundColor) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
if (r != null) {
r.overrideCustomTransition(open, enterAnim, exitAnim, backgroundColor);
}
}
Binder.restoreCallingIdentity(origId);
}
@Override
public void clearOverrideActivityTransition(IBinder token, boolean open) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
if (r != null) {
r.clearCustomTransition(open);
}
}
Binder.restoreCallingIdentity(origId);
}
@Override
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim, @ColorInt int backgroundColor) {

View File

@@ -945,6 +945,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Whether the ActivityEmbedding is enabled on the app.
private final boolean mAppActivityEmbeddingSplitsEnabled;
// Records whether client has overridden the WindowAnimation_(Open/Close)(Enter/Exit)Animation.
private CustomAppTransition mCustomOpenTransition;
private CustomAppTransition mCustomCloseTransition;
private final Runnable mPauseTimeoutRunnable = new Runnable() {
@Override
public void run() {
@@ -10352,6 +10356,41 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
&& !inPinnedWindowingMode() && !inFreeformWindowingMode();
}
void overrideCustomTransition(boolean open, int enterAnim, int exitAnim, int backgroundColor) {
CustomAppTransition transition = getCustomAnimation(open);
if (transition == null) {
transition = new CustomAppTransition();
if (open) {
mCustomOpenTransition = transition;
} else {
mCustomCloseTransition = transition;
}
}
transition.mEnterAnim = enterAnim;
transition.mExitAnim = exitAnim;
transition.mBackgroundColor = backgroundColor;
}
void clearCustomTransition(boolean open) {
if (open) {
mCustomOpenTransition = null;
} else {
mCustomCloseTransition = null;
}
}
CustomAppTransition getCustomAnimation(boolean open) {
return open ? mCustomOpenTransition : mCustomCloseTransition;
}
// Override the WindowAnimation_(Open/Close)(Enter/Exit)Animation
static class CustomAppTransition {
int mEnterAnim;
int mExitAnim;
int mBackgroundColor;
}
static class Builder {
private final ActivityTaskManagerService mAtmService;
private WindowProcessController mCallerApp;

View File

@@ -142,6 +142,7 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.DumpUtils.Dump;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.wm.ActivityRecord.CustomAppTransition;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -886,9 +887,18 @@ public class AppTransition implements Dump {
a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
} else {
int animAttr = mapOpenCloseTransitTypes(transit, enter);
a = animAttr == 0 ? null : (canCustomizeAppTransition
? loadAnimationAttr(lp, animAttr, transit)
: mTransitionAnimation.loadDefaultAnimationAttr(animAttr, transit));
if (animAttr != 0) {
a = loadCustomActivityAnimation(animAttr, enter, container);
if (a == null) {
if (canCustomizeAppTransition) {
a = loadAnimationAttr(lp, animAttr, transit);
} else {
a = mTransitionAnimation.loadDefaultAnimationAttr(animAttr, transit);
}
}
} else {
a = null;
}
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
"applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b "
@@ -901,6 +911,48 @@ public class AppTransition implements Dump {
return a;
}
Animation loadCustomActivityAnimation(int animAttr, boolean enter, WindowContainer container) {
ActivityRecord customAnimationSource = container.asActivityRecord();
if (customAnimationSource == null) {
return null;
}
// Only top activity can customize activity animation.
// If the animation is for the one below, try to get from the above activity.
if (animAttr == WindowAnimation_activityOpenExitAnimation
|| animAttr == WindowAnimation_activityCloseEnterAnimation) {
customAnimationSource = customAnimationSource.getTask()
.getActivityAbove(customAnimationSource);
if (customAnimationSource == null) {
return null;
}
}
final CustomAppTransition custom;
switch (animAttr) {
case WindowAnimation_activityOpenEnterAnimation:
case WindowAnimation_activityOpenExitAnimation:
custom = customAnimationSource.getCustomAnimation(true /* open */);
break;
case WindowAnimation_activityCloseEnterAnimation:
case WindowAnimation_activityCloseExitAnimation:
custom = customAnimationSource.getCustomAnimation(false /* open */);
break;
default:
return null;
}
if (custom != null) {
final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
customAnimationSource.packageName, enter
? custom.mEnterAnim : custom.mExitAnim);
if (a != null && custom.mBackgroundColor != 0) {
a.setBackdropColor(custom.mBackgroundColor);
a.setShowBackdrop(true);
}
return a;
}
return null;
}
int getAppRootTaskClipMode() {
return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH)
|| mNextAppTransitionRequests.contains(TRANSIT_KEYGUARD_GOING_AWAY)

View File

@@ -1881,6 +1881,12 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
out.addChange(change);
}
TransitionInfo.AnimationOptions animOptions = null;
if (topApp.asActivityRecord() != null) {
final ActivityRecord topActivity = topApp.asActivityRecord();
animOptions = addCustomActivityTransition(topActivity, true/* open */, null);
animOptions = addCustomActivityTransition(topActivity, false/* open */, animOptions);
}
final WindowManager.LayoutParams animLp =
getLayoutParamsForAnimationsStyle(type, sortedTargets);
if (animLp != null && animLp.type != TYPE_APPLICATION_STARTING
@@ -1888,14 +1894,33 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// Don't send animation options if no windowAnimations have been set or if the we are
// running an app starting animation, in which case we don't want the app to be able to
// change its animation directly.
TransitionInfo.AnimationOptions animOptions =
TransitionInfo.AnimationOptions.makeAnimOptionsFromLayoutParameters(animLp);
if (animOptions != null) {
animOptions.addOptionsFromLayoutParameters(animLp);
} else {
animOptions = TransitionInfo.AnimationOptions
.makeAnimOptionsFromLayoutParameters(animLp);
}
}
if (animOptions != null) {
out.setAnimationOptions(animOptions);
}
return out;
}
static TransitionInfo.AnimationOptions addCustomActivityTransition(ActivityRecord topActivity,
boolean open, TransitionInfo.AnimationOptions animOptions) {
final ActivityRecord.CustomAppTransition customAnim =
topActivity.getCustomAnimation(open);
if (customAnim != null) {
if (animOptions == null) {
animOptions = TransitionInfo.AnimationOptions
.makeCommonAnimOptions(topActivity.packageName);
}
animOptions.addCustomActivityTransition(open, customAnim.mEnterAnim,
customAnim.mExitAnim, customAnim.mBackgroundColor);
}
return animOptions;
}
/**
* Finds the top-most common ancestor of app targets.
*