Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3447e5cf authored by Pablo Gamito's avatar Pablo Gamito Committed by Android (Google) Code Review
Browse files

Merge "Add support for WindowAnimationStyle theme attribute in shell"

parents 03d5c1b7 a4843175
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
+17 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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,
@@ -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);
@@ -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
+28 −4
Original line number Diff line number Diff line
@@ -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) {
@@ -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) {
+58 −47
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
+81 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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.
@@ -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;

@@ -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);
@@ -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