Loading core/java/android/app/ActivityOptions.java +2 −0 Original line number Diff line number Diff line Loading @@ -380,6 +380,8 @@ public class ActivityOptions extends ComponentOptions { public static final int ANIM_OPEN_CROSS_PROFILE_APPS = 12; /** @hide */ public static final int ANIM_REMOTE_ANIMATION = 13; /** @hide */ public static final int ANIM_FROM_STYLE = 14; private String mPackageName; private Rect mLaunchBounds; Loading core/java/android/window/TransitionInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.window; import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; import static android.app.ActivityOptions.ANIM_CUSTOM; import static android.app.ActivityOptions.ANIM_FROM_STYLE; import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; import static android.app.ActivityOptions.ANIM_SCALE_UP; import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; Loading Loading @@ -46,6 +47,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.Surface; import android.view.SurfaceControl; import android.view.WindowManager; import java.util.ArrayList; import java.util.List; Loading Loading @@ -581,6 +583,7 @@ public final class TransitionInfo implements Parcelable { private String mPackageName; private final Rect mTransitionBounds = new Rect(); private HardwareBuffer mThumbnail; private int mAnimations; private AnimationOptions(int type) { mType = type; Loading @@ -594,6 +597,15 @@ public final class TransitionInfo implements Parcelable { mPackageName = in.readString(); mTransitionBounds.readFromParcel(in); mThumbnail = in.readTypedObject(HardwareBuffer.CREATOR); mAnimations = in.readInt(); } public static AnimationOptions makeAnimOptionsFromLayoutParameters( WindowManager.LayoutParams lp) { AnimationOptions options = new AnimationOptions(ANIM_FROM_STYLE); options.mPackageName = lp.packageName; options.mAnimations = lp.windowAnimations; return options; } public static AnimationOptions makeCustomAnimOptions(String packageName, int enterResId, Loading Loading @@ -662,6 +674,10 @@ public final class TransitionInfo implements Parcelable { return mThumbnail; } public int getAnimations() { return mAnimations; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType); Loading @@ -671,6 +687,7 @@ public final class TransitionInfo implements Parcelable { dest.writeString(mPackageName); mTransitionBounds.writeToParcel(dest, flags); dest.writeTypedObject(mThumbnail, flags); dest.writeInt(mAnimations); } @NonNull Loading core/java/com/android/internal/policy/TransitionAnimation.java +28 −4 Original line number Diff line number Diff line Loading @@ -260,25 +260,39 @@ public class TransitionAnimation { return null; } /** Load animation by attribute Id from android package. */ /** Load animation by attribute Id from a specific AnimationStyle resource. */ @Nullable public Animation loadDefaultAnimationAttr(int animAttr) { public Animation loadAnimationAttr(String packageName, int animStyleResId, int animAttr, boolean translucent) { if (animStyleResId == 0) { return null; } int resId = Resources.ID_NULL; Context context = mContext; if (animAttr >= 0) { AttributeCache.Entry ent = getCachedAnimations(DEFAULT_PACKAGE, mDefaultWindowAnimationStyleResId); packageName = packageName != null ? packageName : DEFAULT_PACKAGE; AttributeCache.Entry ent = getCachedAnimations(packageName, animStyleResId); if (ent != null) { context = ent.context; resId = ent.array.getResourceId(animAttr, 0); } } if (translucent) { resId = updateToTranslucentAnimIfNeeded(resId); } if (ResourceId.isValid(resId)) { return loadAnimationSafely(context, resId, mTag); } return null; } /** Load animation by attribute Id from android package. */ @Nullable public Animation loadDefaultAnimationAttr(int animAttr) { return loadAnimationAttr(DEFAULT_PACKAGE, mDefaultWindowAnimationStyleResId, animAttr, false /* translucent */); } @Nullable private AttributeCache.Entry getCachedAnimations(LayoutParams lp) { if (mDebug) { Loading Loading @@ -1024,6 +1038,16 @@ public class TransitionAnimation { return anim; } private static int updateToTranslucentAnimIfNeeded(int anim) { if (anim == R.anim.activity_open_enter) { return R.anim.activity_translucent_open_enter; } if (anim == R.anim.activity_close_exit) { return R.anim.activity_translucent_close_exit; } return anim; } private static @TransitionOldType int getTransitCompatType(@TransitionType int transit, int wallpaperTransit) { if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_OPEN) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +58 −47 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.wm.shell.transition; import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; import static android.app.ActivityOptions.ANIM_CUSTOM; import static android.app.ActivityOptions.ANIM_FROM_STYLE; import static android.app.ActivityOptions.ANIM_NONE; import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; import static android.app.ActivityOptions.ANIM_SCALE_UP; Loading Loading @@ -509,60 +510,70 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } else if ((changeFlags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0 && isOpeningType) { // This received a transferred starting window, so don't animate return null; } else if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_OPEN) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter } else { int animAttr = 0; boolean translucent = false; if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_OPEN) { animAttr = enter ? R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation : R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation); : R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; } else if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_CLOSE) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation : R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation); : R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; } else if (wallpaperTransit == WALLPAPER_TRANSITION_OPEN) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_wallpaperOpenEnterAnimation : R.styleable.WindowAnimation_wallpaperOpenExitAnimation); : R.styleable.WindowAnimation_wallpaperOpenExitAnimation; } else if (wallpaperTransit == WALLPAPER_TRANSITION_CLOSE) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_wallpaperCloseEnterAnimation : R.styleable.WindowAnimation_wallpaperCloseExitAnimation); : R.styleable.WindowAnimation_wallpaperCloseExitAnimation; } else if (type == TRANSIT_OPEN) { if (isTask) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskOpenEnterAnimation : R.styleable.WindowAnimation_taskOpenExitAnimation); : R.styleable.WindowAnimation_taskOpenExitAnimation; } else { if ((changeFlags & FLAG_TRANSLUCENT) != 0 && enter) { a = mTransitionAnimation.loadDefaultAnimationRes( R.anim.activity_translucent_open_enter); } else { a = mTransitionAnimation.loadDefaultAnimationAttr(enter ? R.styleable.WindowAnimation_activityOpenEnterAnimation : R.styleable.WindowAnimation_activityOpenExitAnimation); translucent = true; } animAttr = enter ? R.styleable.WindowAnimation_activityOpenEnterAnimation : R.styleable.WindowAnimation_activityOpenExitAnimation; } } else if (type == TRANSIT_TO_FRONT) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskToFrontEnterAnimation : R.styleable.WindowAnimation_taskToFrontExitAnimation); : R.styleable.WindowAnimation_taskToFrontExitAnimation; } else if (type == TRANSIT_CLOSE) { if (isTask) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskCloseEnterAnimation : R.styleable.WindowAnimation_taskCloseExitAnimation); : R.styleable.WindowAnimation_taskCloseExitAnimation; } else { if ((changeFlags & FLAG_TRANSLUCENT) != 0 && !enter) { a = mTransitionAnimation.loadDefaultAnimationRes( R.anim.activity_translucent_close_exit); } else { a = mTransitionAnimation.loadDefaultAnimationAttr(enter ? R.styleable.WindowAnimation_activityCloseEnterAnimation : R.styleable.WindowAnimation_activityCloseExitAnimation); translucent = true; } animAttr = enter ? R.styleable.WindowAnimation_activityCloseEnterAnimation : R.styleable.WindowAnimation_activityCloseExitAnimation; } } else if (type == TRANSIT_TO_BACK) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskToBackEnterAnimation : R.styleable.WindowAnimation_taskToBackExitAnimation); : R.styleable.WindowAnimation_taskToBackExitAnimation; } if (animAttr != 0) { if (overrideType == ANIM_FROM_STYLE && canCustomContainer) { a = mTransitionAnimation .loadAnimationAttr(options.getPackageName(), options.getAnimations(), animAttr, translucent); } else { a = mTransitionAnimation.loadDefaultAnimationAttr(animAttr); } } } if (a != null) { Loading services/core/java/com/android/server/wm/Transition.java +81 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; Loading Loading @@ -70,6 +71,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.view.SurfaceControl; import android.view.WindowManager; import android.view.animation.Animation; import android.window.RemoteTransition; import android.window.TransitionInfo; Loading @@ -82,6 +84,8 @@ import com.android.internal.util.function.pooled.PooledLambda; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; /** * Represents a logical transition. Loading @@ -90,6 +94,9 @@ import java.util.ArrayList; class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListener { private static final String TAG = "Transition"; /** The default package for resources */ private static final String DEFAULT_PACKAGE = "android"; /** The transition has been created and is collecting, but hasn't formally started. */ private static final int STATE_COLLECTING = 0; Loading Loading @@ -548,7 +555,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Resolve the animating targets from the participants mTargets = calculateTargets(mParticipants, mChanges); final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, mChanges); if (mOverrideOptions != null) { info.setAnimationOptions(mOverrideOptions); } // TODO(b/188669821): Move to animation impl in shell. handleLegacyRecentsStartBehavior(dc, info); Loading Loading @@ -1249,9 +1258,80 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe out.addChange(change); } final WindowManager.LayoutParams animLp = getLayoutParamsForAnimationsStyle(type, sortedTargets); if (animLp != null && animLp.type != TYPE_APPLICATION_STARTING && animLp.windowAnimations != 0) { // 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); out.setAnimationOptions(animOptions); } return out; } private static WindowManager.LayoutParams getLayoutParamsForAnimationsStyle(int type, ArrayList<WindowContainer> sortedTargets) { // Find the layout params of the top-most application window that is part of the // transition, which is what will control the animation theme. final ArraySet<Integer> activityTypes = new ArraySet<>(); for (WindowContainer target : sortedTargets) { if (target.asActivityRecord() != null) { activityTypes.add(target.getActivityType()); } else if (target.asWindowToken() == null && target.asWindowState() == null) { // We don't want app to customize animations that are not activity to activity. // Activity-level transitions can only include activities, wallpaper and subwindows. // Anything else is not a WindowToken nor a WindowState and is "higher" in the // hierarchy which means we are no longer in an activity transition. return null; } } if (activityTypes.isEmpty()) { // We don't want app to be able to customize transitions that are not activity to // activity through the layout parameter animation style. return null; } final ActivityRecord animLpActivity = findAnimLayoutParamsActivityRecord(sortedTargets, type, activityTypes); final WindowState mainWindow = animLpActivity != null ? animLpActivity.findMainWindow() : null; return mainWindow != null ? mainWindow.mAttrs : null; } private static ActivityRecord findAnimLayoutParamsActivityRecord( List<WindowContainer> sortedTargets, @TransitionType int transit, ArraySet<Integer> activityTypes) { // Remote animations always win, but fullscreen windows override non-fullscreen windows. ActivityRecord result = lookForTopWindowWithFilter(sortedTargets, w -> w.getRemoteAnimationDefinition() != null && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes)); if (result != null) { return result; } result = lookForTopWindowWithFilter(sortedTargets, w -> w.fillsParent() && w.findMainWindow() != null); if (result != null) { return result; } return lookForTopWindowWithFilter(sortedTargets, w -> w.findMainWindow() != null); } private static ActivityRecord lookForTopWindowWithFilter(List<WindowContainer> sortedTargets, Predicate<ActivityRecord> filter) { for (WindowContainer target : sortedTargets) { final ActivityRecord activityRecord = target.asTaskFragment() != null ? target.asTaskFragment().getTopNonFinishingActivity() : target.asActivityRecord(); if (activityRecord != null && filter.test(activityRecord)) { return activityRecord; } } return null; } private static int getTaskRotationAnimation(@NonNull Task task) { final ActivityRecord top = task.getTopVisibleActivity(); if (top == null) return ROTATION_ANIMATION_UNSPECIFIED; Loading Loading
core/java/android/app/ActivityOptions.java +2 −0 Original line number Diff line number Diff line Loading @@ -380,6 +380,8 @@ public class ActivityOptions extends ComponentOptions { public static final int ANIM_OPEN_CROSS_PROFILE_APPS = 12; /** @hide */ public static final int ANIM_REMOTE_ANIMATION = 13; /** @hide */ public static final int ANIM_FROM_STYLE = 14; private String mPackageName; private Rect mLaunchBounds; Loading
core/java/android/window/TransitionInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.window; import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; import static android.app.ActivityOptions.ANIM_CUSTOM; import static android.app.ActivityOptions.ANIM_FROM_STYLE; import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; import static android.app.ActivityOptions.ANIM_SCALE_UP; import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; Loading Loading @@ -46,6 +47,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.Surface; import android.view.SurfaceControl; import android.view.WindowManager; import java.util.ArrayList; import java.util.List; Loading Loading @@ -581,6 +583,7 @@ public final class TransitionInfo implements Parcelable { private String mPackageName; private final Rect mTransitionBounds = new Rect(); private HardwareBuffer mThumbnail; private int mAnimations; private AnimationOptions(int type) { mType = type; Loading @@ -594,6 +597,15 @@ public final class TransitionInfo implements Parcelable { mPackageName = in.readString(); mTransitionBounds.readFromParcel(in); mThumbnail = in.readTypedObject(HardwareBuffer.CREATOR); mAnimations = in.readInt(); } public static AnimationOptions makeAnimOptionsFromLayoutParameters( WindowManager.LayoutParams lp) { AnimationOptions options = new AnimationOptions(ANIM_FROM_STYLE); options.mPackageName = lp.packageName; options.mAnimations = lp.windowAnimations; return options; } public static AnimationOptions makeCustomAnimOptions(String packageName, int enterResId, Loading Loading @@ -662,6 +674,10 @@ public final class TransitionInfo implements Parcelable { return mThumbnail; } public int getAnimations() { return mAnimations; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType); Loading @@ -671,6 +687,7 @@ public final class TransitionInfo implements Parcelable { dest.writeString(mPackageName); mTransitionBounds.writeToParcel(dest, flags); dest.writeTypedObject(mThumbnail, flags); dest.writeInt(mAnimations); } @NonNull Loading
core/java/com/android/internal/policy/TransitionAnimation.java +28 −4 Original line number Diff line number Diff line Loading @@ -260,25 +260,39 @@ public class TransitionAnimation { return null; } /** Load animation by attribute Id from android package. */ /** Load animation by attribute Id from a specific AnimationStyle resource. */ @Nullable public Animation loadDefaultAnimationAttr(int animAttr) { public Animation loadAnimationAttr(String packageName, int animStyleResId, int animAttr, boolean translucent) { if (animStyleResId == 0) { return null; } int resId = Resources.ID_NULL; Context context = mContext; if (animAttr >= 0) { AttributeCache.Entry ent = getCachedAnimations(DEFAULT_PACKAGE, mDefaultWindowAnimationStyleResId); packageName = packageName != null ? packageName : DEFAULT_PACKAGE; AttributeCache.Entry ent = getCachedAnimations(packageName, animStyleResId); if (ent != null) { context = ent.context; resId = ent.array.getResourceId(animAttr, 0); } } if (translucent) { resId = updateToTranslucentAnimIfNeeded(resId); } if (ResourceId.isValid(resId)) { return loadAnimationSafely(context, resId, mTag); } return null; } /** Load animation by attribute Id from android package. */ @Nullable public Animation loadDefaultAnimationAttr(int animAttr) { return loadAnimationAttr(DEFAULT_PACKAGE, mDefaultWindowAnimationStyleResId, animAttr, false /* translucent */); } @Nullable private AttributeCache.Entry getCachedAnimations(LayoutParams lp) { if (mDebug) { Loading Loading @@ -1024,6 +1038,16 @@ public class TransitionAnimation { return anim; } private static int updateToTranslucentAnimIfNeeded(int anim) { if (anim == R.anim.activity_open_enter) { return R.anim.activity_translucent_open_enter; } if (anim == R.anim.activity_close_exit) { return R.anim.activity_translucent_close_exit; } return anim; } private static @TransitionOldType int getTransitCompatType(@TransitionType int transit, int wallpaperTransit) { if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_OPEN) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +58 −47 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.wm.shell.transition; import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; import static android.app.ActivityOptions.ANIM_CUSTOM; import static android.app.ActivityOptions.ANIM_FROM_STYLE; import static android.app.ActivityOptions.ANIM_NONE; import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; import static android.app.ActivityOptions.ANIM_SCALE_UP; Loading Loading @@ -509,60 +510,70 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } else if ((changeFlags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0 && isOpeningType) { // This received a transferred starting window, so don't animate return null; } else if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_OPEN) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter } else { int animAttr = 0; boolean translucent = false; if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_OPEN) { animAttr = enter ? R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation : R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation); : R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; } else if (wallpaperTransit == WALLPAPER_TRANSITION_INTRA_CLOSE) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation : R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation); : R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; } else if (wallpaperTransit == WALLPAPER_TRANSITION_OPEN) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_wallpaperOpenEnterAnimation : R.styleable.WindowAnimation_wallpaperOpenExitAnimation); : R.styleable.WindowAnimation_wallpaperOpenExitAnimation; } else if (wallpaperTransit == WALLPAPER_TRANSITION_CLOSE) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_wallpaperCloseEnterAnimation : R.styleable.WindowAnimation_wallpaperCloseExitAnimation); : R.styleable.WindowAnimation_wallpaperCloseExitAnimation; } else if (type == TRANSIT_OPEN) { if (isTask) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskOpenEnterAnimation : R.styleable.WindowAnimation_taskOpenExitAnimation); : R.styleable.WindowAnimation_taskOpenExitAnimation; } else { if ((changeFlags & FLAG_TRANSLUCENT) != 0 && enter) { a = mTransitionAnimation.loadDefaultAnimationRes( R.anim.activity_translucent_open_enter); } else { a = mTransitionAnimation.loadDefaultAnimationAttr(enter ? R.styleable.WindowAnimation_activityOpenEnterAnimation : R.styleable.WindowAnimation_activityOpenExitAnimation); translucent = true; } animAttr = enter ? R.styleable.WindowAnimation_activityOpenEnterAnimation : R.styleable.WindowAnimation_activityOpenExitAnimation; } } else if (type == TRANSIT_TO_FRONT) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskToFrontEnterAnimation : R.styleable.WindowAnimation_taskToFrontExitAnimation); : R.styleable.WindowAnimation_taskToFrontExitAnimation; } else if (type == TRANSIT_CLOSE) { if (isTask) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskCloseEnterAnimation : R.styleable.WindowAnimation_taskCloseExitAnimation); : R.styleable.WindowAnimation_taskCloseExitAnimation; } else { if ((changeFlags & FLAG_TRANSLUCENT) != 0 && !enter) { a = mTransitionAnimation.loadDefaultAnimationRes( R.anim.activity_translucent_close_exit); } else { a = mTransitionAnimation.loadDefaultAnimationAttr(enter ? R.styleable.WindowAnimation_activityCloseEnterAnimation : R.styleable.WindowAnimation_activityCloseExitAnimation); translucent = true; } animAttr = enter ? R.styleable.WindowAnimation_activityCloseEnterAnimation : R.styleable.WindowAnimation_activityCloseExitAnimation; } } else if (type == TRANSIT_TO_BACK) { a = mTransitionAnimation.loadDefaultAnimationAttr(enter animAttr = enter ? R.styleable.WindowAnimation_taskToBackEnterAnimation : R.styleable.WindowAnimation_taskToBackExitAnimation); : R.styleable.WindowAnimation_taskToBackExitAnimation; } if (animAttr != 0) { if (overrideType == ANIM_FROM_STYLE && canCustomContainer) { a = mTransitionAnimation .loadAnimationAttr(options.getPackageName(), options.getAnimations(), animAttr, translucent); } else { a = mTransitionAnimation.loadDefaultAnimationAttr(animAttr); } } } if (a != null) { Loading
services/core/java/com/android/server/wm/Transition.java +81 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; Loading Loading @@ -70,6 +71,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; import android.view.SurfaceControl; import android.view.WindowManager; import android.view.animation.Animation; import android.window.RemoteTransition; import android.window.TransitionInfo; Loading @@ -82,6 +84,8 @@ import com.android.internal.util.function.pooled.PooledLambda; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; /** * Represents a logical transition. Loading @@ -90,6 +94,9 @@ import java.util.ArrayList; class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListener { private static final String TAG = "Transition"; /** The default package for resources */ private static final String DEFAULT_PACKAGE = "android"; /** The transition has been created and is collecting, but hasn't formally started. */ private static final int STATE_COLLECTING = 0; Loading Loading @@ -548,7 +555,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Resolve the animating targets from the participants mTargets = calculateTargets(mParticipants, mChanges); final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, mChanges); if (mOverrideOptions != null) { info.setAnimationOptions(mOverrideOptions); } // TODO(b/188669821): Move to animation impl in shell. handleLegacyRecentsStartBehavior(dc, info); Loading Loading @@ -1249,9 +1258,80 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe out.addChange(change); } final WindowManager.LayoutParams animLp = getLayoutParamsForAnimationsStyle(type, sortedTargets); if (animLp != null && animLp.type != TYPE_APPLICATION_STARTING && animLp.windowAnimations != 0) { // 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); out.setAnimationOptions(animOptions); } return out; } private static WindowManager.LayoutParams getLayoutParamsForAnimationsStyle(int type, ArrayList<WindowContainer> sortedTargets) { // Find the layout params of the top-most application window that is part of the // transition, which is what will control the animation theme. final ArraySet<Integer> activityTypes = new ArraySet<>(); for (WindowContainer target : sortedTargets) { if (target.asActivityRecord() != null) { activityTypes.add(target.getActivityType()); } else if (target.asWindowToken() == null && target.asWindowState() == null) { // We don't want app to customize animations that are not activity to activity. // Activity-level transitions can only include activities, wallpaper and subwindows. // Anything else is not a WindowToken nor a WindowState and is "higher" in the // hierarchy which means we are no longer in an activity transition. return null; } } if (activityTypes.isEmpty()) { // We don't want app to be able to customize transitions that are not activity to // activity through the layout parameter animation style. return null; } final ActivityRecord animLpActivity = findAnimLayoutParamsActivityRecord(sortedTargets, type, activityTypes); final WindowState mainWindow = animLpActivity != null ? animLpActivity.findMainWindow() : null; return mainWindow != null ? mainWindow.mAttrs : null; } private static ActivityRecord findAnimLayoutParamsActivityRecord( List<WindowContainer> sortedTargets, @TransitionType int transit, ArraySet<Integer> activityTypes) { // Remote animations always win, but fullscreen windows override non-fullscreen windows. ActivityRecord result = lookForTopWindowWithFilter(sortedTargets, w -> w.getRemoteAnimationDefinition() != null && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes)); if (result != null) { return result; } result = lookForTopWindowWithFilter(sortedTargets, w -> w.fillsParent() && w.findMainWindow() != null); if (result != null) { return result; } return lookForTopWindowWithFilter(sortedTargets, w -> w.findMainWindow() != null); } private static ActivityRecord lookForTopWindowWithFilter(List<WindowContainer> sortedTargets, Predicate<ActivityRecord> filter) { for (WindowContainer target : sortedTargets) { final ActivityRecord activityRecord = target.asTaskFragment() != null ? target.asTaskFragment().getTopNonFinishingActivity() : target.asActivityRecord(); if (activityRecord != null && filter.test(activityRecord)) { return activityRecord; } } return null; } private static int getTaskRotationAnimation(@NonNull Task task) { final ActivityRecord top = task.getTopVisibleActivity(); if (top == null) return ROTATION_ANIMATION_UNSPECIFIED; Loading