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

Commit e4b2d224 authored by Annie Lin's avatar Annie Lin Committed by Android (Google) Code Review
Browse files

Merge "Allow custom animations for AE change transitions behind a flag." into main

parents e335107f 73c4a2d1
Loading
Loading
Loading
Loading
+27 −6
Original line number Diff line number Diff line
@@ -265,7 +265,7 @@ class ActivityEmbeddingAnimationRunner {
        for (TransitionInfo.Change change : openingChanges) {
            final Animation animation =
                    animationProvider.get(info, change, openingWholeScreenBounds);
            if (animation.getDuration() == 0) {
            if (shouldUseJumpCutForAnimation(animation)) {
                continue;
            }
            final ActivityEmbeddingAnimationAdapter adapter = createOpenCloseAnimationAdapter(
@@ -290,7 +290,7 @@ class ActivityEmbeddingAnimationRunner {
            }
            final Animation animation =
                    animationProvider.get(info, change, closingWholeScreenBounds);
            if (animation.getDuration() == 0) {
            if (shouldUseJumpCutForAnimation(animation)) {
                continue;
            }
            final ActivityEmbeddingAnimationAdapter adapter = createOpenCloseAnimationAdapter(
@@ -444,8 +444,16 @@ class ActivityEmbeddingAnimationRunner {
            calculateParentBounds(change, boundsAnimationChange, parentBounds);
            // There are two animations in the array. The first one is for the start leash
            // (snapshot), and the second one is for the end leash (TaskFragment).
            final Animation[] animations = mAnimationSpec.createChangeBoundsChangeAnimations(change,
                    parentBounds);
            final Animation[] animations =
                    mAnimationSpec.createChangeBoundsChangeAnimations(info, change, parentBounds);
            // Jump cut if either animation has zero for duration.
            if (Flags.activityEmbeddingAnimationCustomizationFlag()) {
                for (Animation animation : animations) {
                    if (shouldUseJumpCutForAnimation(animation)) {
                        return new ArrayList<>();
                    }
                }
            }
            // Keep track as we might need to add background color for the animation.
            // Although there may be multiple change animation, record one of them is sufficient
            // because the background color will be added to the root leash for the whole animation.
@@ -492,12 +500,19 @@ class ActivityEmbeddingAnimationRunner {
                // window without bounds change.
                animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change);
            } else if (TransitionUtil.isClosingType(change.getMode())) {
                animation = mAnimationSpec.createChangeBoundsCloseAnimation(change, parentBounds);
                animation =
                        mAnimationSpec.createChangeBoundsCloseAnimation(info, change, parentBounds);
                shouldShowBackgroundColor = false;
            } else {
                animation = mAnimationSpec.createChangeBoundsOpenAnimation(change, parentBounds);
                animation =
                        mAnimationSpec.createChangeBoundsOpenAnimation(info, change, parentBounds);
                shouldShowBackgroundColor = false;
            }
            if (Flags.activityEmbeddingAnimationCustomizationFlag()) {
                if (shouldUseJumpCutForAnimation(animation)) {
                    return new ArrayList<>();
                }
            }
            adapters.add(new ActivityEmbeddingAnimationAdapter(animation, change,
                    TransitionUtil.getRootFor(change, info)));
        }
@@ -640,6 +655,12 @@ class ActivityEmbeddingAnimationRunner {
        return true;
    }

    /** Whether or not to use jump cut based on the animation. */
    @VisibleForTesting
    static boolean shouldUseJumpCutForAnimation(@NonNull Animation animation) {
        return animation.getDuration() == 0;
    }

    /** Updates the changes to end states in {@code startTransaction} for jump cut animation. */
    private void prepareForJumpCut(@NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction) {
+27 −7
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import com.android.window.flags.Flags;
import com.android.wm.shell.shared.TransitionUtil;

/** Animation spec for ActivityEmbedding transition. */
// TODO(b/206557124): provide an easier way to customize animation
class ActivityEmbeddingAnimationSpec {

    private static final String TAG = "ActivityEmbeddingAnimSpec";
@@ -95,8 +94,14 @@ class ActivityEmbeddingAnimationSpec {

    /** Animation for window that is opening in a change transition. */
    @NonNull
    Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo.Change change,
            @NonNull Rect parentBounds) {
    Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo info,
            @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) {
        if (Flags.activityEmbeddingAnimationCustomizationFlag()) {
            final Animation customAnimation = loadCustomAnimation(info, change);
            if (customAnimation != null) {
                return customAnimation;
            }
        }
        // Use end bounds for opening.
        final Rect bounds = change.getEndAbsBounds();
        final int startLeft;
@@ -123,8 +128,14 @@ class ActivityEmbeddingAnimationSpec {

    /** Animation for window that is closing in a change transition. */
    @NonNull
    Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo.Change change,
            @NonNull Rect parentBounds) {
    Animation createChangeBoundsCloseAnimation(@NonNull TransitionInfo info,
            @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) {
        if (Flags.activityEmbeddingAnimationCustomizationFlag()) {
            final Animation customAnimation = loadCustomAnimation(info, change);
            if (customAnimation != null) {
                return customAnimation;
            }
        }
        // Use start bounds for closing.
        final Rect bounds = change.getStartAbsBounds();
        final int endTop;
@@ -155,8 +166,17 @@ class ActivityEmbeddingAnimationSpec {
     *         the second one is for the end leash.
     */
    @NonNull
    Animation[] createChangeBoundsChangeAnimations(@NonNull TransitionInfo.Change change,
            @NonNull Rect parentBounds) {
    Animation[] createChangeBoundsChangeAnimations(@NonNull TransitionInfo info,
            @NonNull TransitionInfo.Change change, @NonNull Rect parentBounds) {
        if (Flags.activityEmbeddingAnimationCustomizationFlag()) {
            // TODO(b/293658614): Support more complicated animations that may need more than a noop
            // animation as the start leash.
            final Animation noopAnimation = createNoopAnimation(change);
            final Animation customAnimation = loadCustomAnimation(info, change);
            if (customAnimation != null) {
                return new Animation[]{noopAnimation, customAnimation};
            }
        }
        // Both start bounds and end bounds are in screen coordinates. We will post translate
        // to the local coordinates in ActivityEmbeddingAnimationAdapter#onAnimationUpdate
        final Rect startBounds = change.getStartAbsBounds();
+16 −0
Original line number Diff line number Diff line
@@ -21,10 +21,12 @@ import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW;

import static com.android.wm.shell.activityembedding.ActivityEmbeddingAnimationRunner.calculateParentBounds;
import static com.android.wm.shell.activityembedding.ActivityEmbeddingAnimationRunner.shouldUseJumpCutForAnimation;
import static com.android.wm.shell.transition.Transitions.TRANSIT_TASK_FRAGMENT_DRAG_RESIZE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
@@ -40,6 +42,8 @@ import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.window.TransitionInfo;

import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -281,6 +285,18 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim
                actualParentBounds);
    }

    @Test
    public void testShouldUseJumpCutForAnimation() {
        final Animation noopAnimation = new AlphaAnimation(0f, 1f);
        assertTrue("Animation without duration should use jump cut.",
                shouldUseJumpCutForAnimation(noopAnimation));

        final Animation alphaAnimation = new AlphaAnimation(0f, 1f);
        alphaAnimation.setDuration(100);
        assertFalse("Animation with duration should not use jump cut.",
                shouldUseJumpCutForAnimation(alphaAnimation));
    }

    @NonNull
    private static TransitionInfo.Change prepareChangeForParentBoundsCalculationTest(
            @NonNull Point endRelOffset, @NonNull Rect endAbsBounds, @NonNull Point endParentSize) {