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

Commit 0638f968 authored by Jon Miranda's avatar Jon Miranda Committed by Evan Rosky
Browse files

Crop by navigation-bar inset during animations

This will update the surface crop of animating tasks/activities
to match the navigation-bar insets.

Bug: 336511494
Test: Enable pinned taskbar, launch app, note correct bounds
Flag: com.android.wm.shell.enable_dynamic_insets_for_app_launch
Change-Id: I0d3a62fc0e680f9d79ea796da9f94372c1c4d5c2
parent 32f78c5e
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.shared;


import android.window.RemoteTransition;
import android.window.RemoteTransition;
import android.window.TransitionFilter;
import android.window.TransitionFilter;
import android.view.InsetsState;


/**
/**
 * Listener interface that Launcher attaches to SystemUI to get home activity transition callbacks
 * Listener interface that Launcher attaches to SystemUI to get home activity transition callbacks
@@ -29,5 +30,10 @@ oneway interface IHomeTransitionListener {
     * Called when a transition changes the visibility of the home activity on the default display.
     * Called when a transition changes the visibility of the home activity on the default display.
     */
     */
    void onHomeVisibilityChanged(in boolean isVisible);
    void onHomeVisibilityChanged(in boolean isVisible);

    /**
     * Called when the insets at display-level change.
     */
    void onDisplayInsetsChanged(in InsetsState insets);
}
}
+9 −4
Original line number Original line Diff line number Diff line
@@ -762,6 +762,7 @@ public abstract class WMShellBaseModule {
            ShellTaskOrganizer organizer,
            ShellTaskOrganizer organizer,
            TransactionPool pool,
            TransactionPool pool,
            DisplayController displayController,
            DisplayController displayController,
            DisplayInsetsController displayInsetsController,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread ShellExecutor mainExecutor,
            @ShellMainThread Handler mainHandler,
            @ShellMainThread Handler mainHandler,
            @ShellAnimationThread ShellExecutor animExecutor,
            @ShellAnimationThread ShellExecutor animExecutor,
@@ -773,15 +774,19 @@ public abstract class WMShellBaseModule {
            shellInit = new ShellInit(mainExecutor);
            shellInit = new ShellInit(mainExecutor);
        }
        }
        return new Transitions(context, shellInit, shellCommandHandler, shellController, organizer,
        return new Transitions(context, shellInit, shellCommandHandler, shellController, organizer,
                pool, displayController, mainExecutor, mainHandler, animExecutor,
                pool, displayController, displayInsetsController, mainExecutor, mainHandler,
                rootTaskDisplayAreaOrganizer, homeTransitionObserver, focusTransitionObserver);
                animExecutor, rootTaskDisplayAreaOrganizer, homeTransitionObserver,
                focusTransitionObserver);
    }
    }


    @WMSingleton
    @WMSingleton
    @Provides
    @Provides
    static HomeTransitionObserver provideHomeTransitionObserver(Context context,
    static HomeTransitionObserver provideHomeTransitionObserver(Context context,
            @ShellMainThread ShellExecutor mainExecutor) {
            @ShellMainThread ShellExecutor mainExecutor,
        return new HomeTransitionObserver(context, mainExecutor);
            DisplayInsetsController displayInsetsController,
            ShellInit shellInit) {
        return new HomeTransitionObserver(context, mainExecutor, displayInsetsController,
                shellInit);
    }
    }


    @WMSingleton
    @WMSingleton
+19 −3
Original line number Original line Diff line number Diff line
@@ -42,9 +42,10 @@ public class DefaultSurfaceAnimator {
            @NonNull Animation anim, @NonNull SurfaceControl leash,
            @NonNull Animation anim, @NonNull SurfaceControl leash,
            @NonNull Runnable finishCallback, @NonNull TransactionPool pool,
            @NonNull Runnable finishCallback, @NonNull TransactionPool pool,
            @NonNull ShellExecutor mainExecutor, @Nullable Point position, float cornerRadius,
            @NonNull ShellExecutor mainExecutor, @Nullable Point position, float cornerRadius,
            @Nullable Rect clipRect) {
            @Nullable Rect clipRect,
            @Nullable TransitionAnimationHelper.RoundedContentPerDisplay roundedBounds) {
        final DefaultAnimationAdapter adapter = new DefaultAnimationAdapter(anim, leash,
        final DefaultAnimationAdapter adapter = new DefaultAnimationAdapter(anim, leash,
                position, clipRect, cornerRadius);
                position, clipRect, cornerRadius, roundedBounds);
        buildSurfaceAnimation(animations, anim, finishCallback, pool, mainExecutor, adapter);
        buildSurfaceAnimation(animations, anim, finishCallback, pool, mainExecutor, adapter);
    }
    }


@@ -109,9 +110,17 @@ public class DefaultSurfaceAnimator {
        @Nullable final Rect mClipRect;
        @Nullable final Rect mClipRect;
        @Nullable private final Rect mAnimClipRect;
        @Nullable private final Rect mAnimClipRect;
        final float mCornerRadius;
        final float mCornerRadius;
        final int mWindowBottom;

        /**
         * Inset changes aren't synchronized with transitions, so use a "provider" to track the
         * bottom of the display content during the animation.
         */
        @Nullable final TransitionAnimationHelper.RoundedContentPerDisplay mRoundedContentBounds;


        DefaultAnimationAdapter(@NonNull Animation anim, @NonNull SurfaceControl leash,
        DefaultAnimationAdapter(@NonNull Animation anim, @NonNull SurfaceControl leash,
                @Nullable Point position, @Nullable Rect clipRect, float cornerRadius) {
                @Nullable Point position, @Nullable Rect clipRect, float cornerRadius,
                TransitionAnimationHelper.RoundedContentPerDisplay roundedBounds) {
            super(leash);
            super(leash);
            mAnim = anim;
            mAnim = anim;
            mPosition = (position != null && (position.x != 0 || position.y != 0))
            mPosition = (position != null && (position.x != 0 || position.y != 0))
@@ -119,6 +128,8 @@ public class DefaultSurfaceAnimator {
            mClipRect = (clipRect != null && !clipRect.isEmpty()) ? clipRect : null;
            mClipRect = (clipRect != null && !clipRect.isEmpty()) ? clipRect : null;
            mAnimClipRect = mClipRect != null ? new Rect() : null;
            mAnimClipRect = mClipRect != null ? new Rect() : null;
            mCornerRadius = cornerRadius;
            mCornerRadius = cornerRadius;
            mWindowBottom = clipRect != null ? clipRect.bottom : 0;
            mRoundedContentBounds = roundedBounds;
        }
        }


        @Override
        @Override
@@ -136,6 +147,11 @@ public class DefaultSurfaceAnimator {


            if (mClipRect != null) {
            if (mClipRect != null) {
                boolean needCrop = false;
                boolean needCrop = false;
                if (mRoundedContentBounds != null) {
                    mClipRect.bottom = Math.min(mRoundedContentBounds.mBounds.bottom,
                            mWindowBottom);
                }

                mAnimClipRect.set(mClipRect);
                mAnimClipRect.set(mClipRect);
                if (transformation.hasClipRect()) {
                if (transformation.hasClipRect()) {
                    mAnimClipRect.intersectUnchecked(transformation.getClipRect());
                    mAnimClipRect.intersectUnchecked(transformation.getClipRect());
+30 −6
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_INTRA_OPEN;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_INTRA_OPEN;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_NONE;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_NONE;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_OPEN;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_OPEN;
import static com.android.wm.shell.Flags.enableDynamicInsetsForAppLaunch;
import static com.android.wm.shell.transition.DefaultSurfaceAnimator.buildSurfaceAnimation;
import static com.android.wm.shell.transition.DefaultSurfaceAnimator.buildSurfaceAnimation;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo;
@@ -111,6 +112,7 @@ import com.android.window.flags.Flags;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.animation.SizeChangeAnimation;
import com.android.wm.shell.animation.SizeChangeAnimation;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -134,6 +136,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
    private final ShellExecutor mAnimExecutor;
    private final ShellExecutor mAnimExecutor;
    private final TransitionAnimation mTransitionAnimation;
    private final TransitionAnimation mTransitionAnimation;
    private final DevicePolicyManager mDevicePolicyManager;
    private final DevicePolicyManager mDevicePolicyManager;
    private final TransitionAnimationHelper.RoundedContentTracker mRoundedContentBounds;


    /** Keeps track of the currently-running animations associated with each transition. */
    /** Keeps track of the currently-running animations associated with each transition. */
    private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
    private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
@@ -163,6 +166,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
    DefaultTransitionHandler(@NonNull Context context,
    DefaultTransitionHandler(@NonNull Context context,
            @NonNull ShellInit shellInit,
            @NonNull ShellInit shellInit,
            @NonNull DisplayController displayController,
            @NonNull DisplayController displayController,
            @NonNull DisplayInsetsController displayInsetsController,
            @NonNull TransactionPool transactionPool,
            @NonNull TransactionPool transactionPool,
            @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler,
            @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler,
            @NonNull ShellExecutor animExecutor,
            @NonNull ShellExecutor animExecutor,
@@ -179,6 +183,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
        shellInit.addInitCallback(this::onInit, this);
        shellInit.addInitCallback(this::onInit, this);
        mRootTDAOrganizer = rootTDAOrganizer;
        mRootTDAOrganizer = rootTDAOrganizer;
        mRoundedContentBounds = new TransitionAnimationHelper.RoundedContentTracker(
                displayController, displayInsetsController);
        mInteractionJankMonitor = interactionJankMonitor;
        mInteractionJankMonitor = interactionJankMonitor;
    }
    }


@@ -191,6 +197,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                mMainHandler);
                mMainHandler);


        TransitionAnimation.initAttributeCache(mContext, mMainHandler);
        TransitionAnimation.initAttributeCache(mContext, mMainHandler);
        mRoundedContentBounds.init();
    }
    }


    private void updateEnterpriseThumbnailDrawable() {
    private void updateEnterpriseThumbnailDrawable() {
@@ -297,6 +304,18 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
        return ROTATION_ANIMATION_SEAMLESS;
        return ROTATION_ANIMATION_SEAMLESS;
    }
    }


    @Nullable
    final TransitionAnimationHelper.RoundedContentPerDisplay getRoundedContentBounds(
            TransitionInfo.Change change) {
        if (!enableDynamicInsetsForAppLaunch()) {
            return null;
        }
        if (change.getTaskInfo() == null && change.getActivityComponent() == null) {
            return null;
        }
        return mRoundedContentBounds.forDisplay(change.getEndDisplayId());
    }

    @Override
    @Override
    public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
    public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction startTransaction,
@@ -556,7 +575,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                        change.getEndAbsBounds().left - animRoot.getOffset().x,
                        change.getEndAbsBounds().left - animRoot.getOffset().x,
                        change.getEndAbsBounds().top - animRoot.getOffset().y);
                        change.getEndAbsBounds().top - animRoot.getOffset().y);


                if (change.getActivityComponent() != null) {
                final boolean isActivity = change.getActivityComponent() != null;
                if (isActivity) {
                    // For appcompat letterbox: we intentionally report the task-bounds so that we
                    // For appcompat letterbox: we intentionally report the task-bounds so that we
                    // can animate as-if letterboxes are "part of" the activity. This means we can't
                    // can animate as-if letterboxes are "part of" the activity. This means we can't
                    // always rely solely on endAbsBounds and need to also max with endRelOffset.
                    // always rely solely on endAbsBounds and need to also max with endRelOffset.
@@ -564,7 +584,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                    animRelOffset.y = Math.max(animRelOffset.y, change.getEndRelOffset().y);
                    animRelOffset.y = Math.max(animRelOffset.y, change.getEndRelOffset().y);
                }
                }


                if (change.getActivityComponent() != null && !isActivityLevel
                if (isActivity && !isActivityLevel
                        && !mRotator.isRotated(change)) {
                        && !mRotator.isRotated(change)) {
                    // At this point, this is an independent activity change in a non-activity
                    // At this point, this is an independent activity change in a non-activity
                    // transition. This means that an activity transition got erroneously combined
                    // transition. This means that an activity transition got erroneously combined
@@ -589,8 +609,10 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                }
                }


                buildSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
                buildSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
                        mTransactionPool, mMainExecutor, animRelOffset, cornerRadius,
                        mTransactionPool, mMainExecutor, animRelOffset, cornerRadius, clipRect,
                        clipRect);
                        isTask || isActivity
                                ? mRoundedContentBounds.forDisplay(change.getEndDisplayId())
                                : null);


                final TransitionInfo.AnimationOptions options = change.getAnimationOptions();
                final TransitionInfo.AnimationOptions options = change.getAnimationOptions();
                if (options != null) {
                if (options != null) {
@@ -932,7 +954,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
        a.restrictDuration(MAX_ANIMATION_DURATION);
        a.restrictDuration(MAX_ANIMATION_DURATION);
        a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
        a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
        buildSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
        buildSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
                mMainExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds());
                mMainExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds(),
                getRoundedContentBounds(change));
    }
    }


    private void attachThumbnailAnimation(@NonNull ArrayList<Animator> animations,
    private void attachThumbnailAnimation(@NonNull ArrayList<Animator> animations,
@@ -956,7 +979,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
        a.restrictDuration(MAX_ANIMATION_DURATION);
        a.restrictDuration(MAX_ANIMATION_DURATION);
        a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
        a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
        buildSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
        buildSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
                mMainExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds());
                mMainExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds(),
                getRoundedContentBounds(change));
    }
    }


    private static int getWallpaperTransitType(TransitionInfo info) {
    private static int getWallpaperTransitType(TransitionInfo info) {
+21 −1
Original line number Original line Diff line number Diff line
@@ -29,15 +29,18 @@ import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Context;
import android.os.IBinder;
import android.os.IBinder;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.TransitionInfo;


import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
import com.android.wm.shell.shared.IHomeTransitionListener;
import com.android.wm.shell.shared.IHomeTransitionListener;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.sysui.ShellInit;


/**
/**
 * The {@link TransitionObserver} that observes for transitions involving the home
 * The {@link TransitionObserver} that observes for transitions involving the home
@@ -51,13 +54,30 @@ public class HomeTransitionObserver implements TransitionObserver,


    private @NonNull final Context mContext;
    private @NonNull final Context mContext;
    private @NonNull final ShellExecutor mMainExecutor;
    private @NonNull final ShellExecutor mMainExecutor;
    private @NonNull final DisplayInsetsController mDisplayInsetsController;
    private IBinder mPendingStartDragTransition;
    private IBinder mPendingStartDragTransition;
    private Boolean mPendingHomeVisibilityUpdate;
    private Boolean mPendingHomeVisibilityUpdate;


    public HomeTransitionObserver(@NonNull Context context,
    public HomeTransitionObserver(@NonNull Context context,
            @NonNull ShellExecutor mainExecutor) {
            @NonNull ShellExecutor mainExecutor,
            @NonNull DisplayInsetsController displayInsetsController,
            @NonNull ShellInit shellInit) {
        mContext = context;
        mContext = context;
        mMainExecutor = mainExecutor;
        mMainExecutor = mainExecutor;
        mDisplayInsetsController = displayInsetsController;

        shellInit.addInitCallback(this::onInit, this);
    }

    private void onInit() {
        mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY,
                new DisplayInsetsController.OnInsetsChangedListener() {
                    @Override
                    public void insetsChanged(InsetsState insetsState) {
                        if (mListener == null) return;
                        mListener.call(l -> l.onDisplayInsetsChanged(insetsState));
                    }
                });
    }
    }


    @Override
    @Override
Loading