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

Commit e7aa4339 authored by Ming-Shin Lu's avatar Ming-Shin Lu Committed by Android (Google) Code Review
Browse files

Merge "Fix a transition issue when starting an activity with CLEAR_TOP flag" into main

parents 193f68e1 d9509f2e
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.app.ActivityOptions.ANIM_CUSTOM;


import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_NONE;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_NONE;
import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;
import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
@@ -253,7 +254,8 @@ class ActivityEmbeddingAnimationSpec {


    private boolean shouldShowBackdrop(@NonNull TransitionInfo info,
    private boolean shouldShowBackdrop(@NonNull TransitionInfo info,
            @NonNull TransitionInfo.Change change) {
            @NonNull TransitionInfo.Change change) {
        final Animation a = loadAttributeAnimation(info, change, WALLPAPER_TRANSITION_NONE,
        final int type = getTransitionTypeFromInfo(info);
        final Animation a = loadAttributeAnimation(type, info, change, WALLPAPER_TRANSITION_NONE,
                mTransitionAnimation, false);
                mTransitionAnimation, false);
        return a != null && a.getShowBackdrop();
        return a != null && a.getShowBackdrop();
    }
    }
+7 −6
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI
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.transition.TransitionAnimationHelper.edgeExtendWindow;
import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow;
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.loadAttributeAnimation;
import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;


import android.animation.Animator;
import android.animation.Animator;
@@ -424,7 +425,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
            // Don't animate anything that isn't independent.
            // Don't animate anything that isn't independent.
            if (!TransitionInfo.isIndependent(change, info)) continue;
            if (!TransitionInfo.isIndependent(change, info)) continue;


            Animation a = loadAnimation(info, change, wallpaperTransit, isDreamTransition);
            final int type = getTransitionTypeFromInfo(info);
            Animation a = loadAnimation(type, info, change, wallpaperTransit, isDreamTransition);
            if (a != null) {
            if (a != null) {
                if (isTask) {
                if (isTask) {
                    final boolean isTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0;
                    final boolean isTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0;
@@ -660,12 +662,11 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
    }
    }


    @Nullable
    @Nullable
    private Animation loadAnimation(@NonNull TransitionInfo info,
    private Animation loadAnimation(@WindowManager.TransitionType int type,
            @NonNull TransitionInfo.Change change, int wallpaperTransit,
            @NonNull TransitionInfo info, @NonNull TransitionInfo.Change change,
            boolean isDreamTransition) {
            int wallpaperTransit, boolean isDreamTransition) {
        Animation a;
        Animation a;


        final int type = info.getType();
        final int flags = info.getFlags();
        final int flags = info.getFlags();
        final int changeMode = change.getMode();
        final int changeMode = change.getMode();
        final int changeFlags = change.getFlags();
        final int changeFlags = change.getFlags();
@@ -721,7 +722,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
            return null;
            return null;
        } else {
        } else {
            a = loadAttributeAnimation(
            a = loadAttributeAnimation(
                    info, change, wallpaperTransit, mTransitionAnimation, isDreamTransition);
                    type, info, change, wallpaperTransit, mTransitionAnimation, isDreamTransition);
        }
        }


        if (a != null) {
        if (a != null) {
+36 −2
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManager.transitTypeToString;
import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW;
import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;


@@ -45,6 +46,7 @@ import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.Shader;
import android.view.Surface;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.view.animation.Transformation;
import android.window.ScreenCapture;
import android.window.ScreenCapture;
@@ -61,10 +63,10 @@ public class TransitionAnimationHelper {


    /** Loads the animation that is defined through attribute id for the given transition. */
    /** Loads the animation that is defined through attribute id for the given transition. */
    @Nullable
    @Nullable
    public static Animation loadAttributeAnimation(@NonNull TransitionInfo info,
    public static Animation loadAttributeAnimation(@WindowManager.TransitionType int type,
            @NonNull TransitionInfo info,
            @NonNull TransitionInfo.Change change, int wallpaperTransit,
            @NonNull TransitionInfo.Change change, int wallpaperTransit,
            @NonNull TransitionAnimation transitionAnimation, boolean isDreamTransition) {
            @NonNull TransitionAnimation transitionAnimation, boolean isDreamTransition) {
        final int type = info.getType();
        final int changeMode = change.getMode();
        final int changeMode = change.getMode();
        final int changeFlags = change.getFlags();
        final int changeFlags = change.getFlags();
        final boolean enter = TransitionUtil.isOpeningType(changeMode);
        final boolean enter = TransitionUtil.isOpeningType(changeMode);
@@ -186,6 +188,38 @@ public class TransitionAnimationHelper {
        return options.getCustomActivityTransition(isOpen);
        return options.getCustomActivityTransition(isOpen);
    }
    }


    /**
     * Gets the final transition type from {@link TransitionInfo} for determining the animation.
     */
    public static int getTransitionTypeFromInfo(@NonNull TransitionInfo info) {
        final int type = info.getType();
        // If the info transition type is opening transition, iterate its changes to see if it
        // has any opening change, if none, returns TRANSIT_CLOSE type for closing animation.
        if (type == TRANSIT_OPEN) {
            boolean hasOpenTransit = false;
            for (TransitionInfo.Change change : info.getChanges()) {
                if ((change.getTaskInfo() != null || change.hasFlags(FLAG_IS_DISPLAY))
                        && !TransitionUtil.isOrderOnly(change)) {
                    // This isn't an activity-level transition.
                    return type;
                }
                if (change.getTaskInfo() != null
                        && change.hasFlags(FLAG_IS_DISPLAY | FLAGS_IS_NON_APP_WINDOW)) {
                    // Ignore non-activity containers.
                    continue;
                }
                if (change.getMode() == TRANSIT_OPEN) {
                    hasOpenTransit = true;
                    break;
                }
            }
            if (!hasOpenTransit) {
                return TRANSIT_CLOSE;
            }
        }
        return type;
    }

    static Animation loadCustomActivityTransition(
    static Animation loadCustomActivityTransition(
            @NonNull TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim,
            @NonNull TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim,
            TransitionInfo.AnimationOptions options, boolean enter,
            TransitionInfo.AnimationOptions options, boolean enter,
+41 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,8 @@ import static android.window.TransitionInfo.FLAG_SYNC;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
@@ -93,6 +95,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.platform.app.InstrumentationRegistry;


import com.android.internal.R;
import com.android.internal.policy.TransitionAnimation;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.TestShellExecutor;
@@ -1463,6 +1467,43 @@ public class ShellTransitionTests extends ShellTestCase {
        assertEquals(0, mDefaultHandler.activeCount());
        assertEquals(0, mDefaultHandler.activeCount());
    }
    }


    @Test
    public void testCloseTransitAnimationWhenClosingChangesExists() {
        Transitions transitions = createTestTransitions();
        Transitions.TransitionObserver observer = mock(Transitions.TransitionObserver.class);
        transitions.registerObserver(observer);
        transitions.replaceDefaultHandlerForTest(mDefaultHandler);
        final TransitionAnimation transitionAnimation = new TransitionAnimation(mContext, false,
                Transitions.TAG);
        spyOn(transitionAnimation);

        // Creating a transition by the app hooking the back key event to start the
        // previous activity with FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
        // flags in order to clear the top activity and bring the exist previous activity to front.
        // Expects the activity transition should playing the close animation instead the initiated
        // open animation made by startActivity.
        IBinder transitToken = new Binder();
        transitions.requestStartTransition(transitToken,
                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
        TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
                .addChange(TRANSIT_CLOSE).addChange(TRANSIT_TO_FRONT).build();
        transitions.onTransitionReady(transitToken, info, new StubTransaction(),
                new StubTransaction());

        final int type = getTransitionTypeFromInfo(info);
        assertEquals(TRANSIT_CLOSE, type);

        TransitionAnimationHelper.loadAttributeAnimation(type, info, info.getChanges().get(0), 0,
                transitionAnimation, false);
        verify(transitionAnimation).loadDefaultAnimationAttr(
                eq(R.styleable.WindowAnimation_activityCloseExitAnimation), anyBoolean());

        TransitionAnimationHelper.loadAttributeAnimation(type, info, info.getChanges().get(1), 0,
                transitionAnimation, false);
        verify(transitionAnimation).loadDefaultAnimationAttr(
                eq(R.styleable.WindowAnimation_activityCloseEnterAnimation), anyBoolean());
    }

    class ChangeBuilder {
    class ChangeBuilder {
        final TransitionInfo.Change mChange;
        final TransitionInfo.Change mChange;