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

Commit 7ac8bac7 authored by Ben Lin's avatar Ben Lin Committed by Android (Google) Code Review
Browse files

Merge "Run transitions on multi-activity PIP when moved to back."

parents da39ac41 6e054b4f
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -658,6 +658,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
    boolean mIsExiting;
    // Force an app transition to be ran in the case the visibility of the app did not change.
    // We use this for the case of moving a Root Task to the back with multiple activities, and the
    // top activity enters PIP; the bottom activity's visibility stays the same, but we need to
    // run the transition.
    boolean mRequestForceTransition;

    boolean mEnteringAnimation;

@@ -4199,6 +4204,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (mUseTransferredAnimation) {
            return false;
        }
        // If it was set to true, reset the last request to force the transition.
        mRequestForceTransition = false;
        return super.applyAnimation(lp, transit, enter, isVoiceInteraction, sources);
    }

@@ -4342,7 +4349,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // transition animation
        // * or this is an opening app and windows are being replaced (e.g. freeform window to
        //   normal window).
        return isVisible() != visible || (!isVisible() && mIsExiting)
        return isVisible() != visible || mRequestForceTransition || (!isVisible() && mIsExiting)
                || (visible && forAllWindows(WindowState::waitingForReplacement, true));
    }

+4 −6
Original line number Diff line number Diff line
@@ -2489,15 +2489,13 @@ class ActivityStack extends Task {
            return true;
        }

        ActivityRecord topActivity = getDisplayArea().topRunningActivity();
        ActivityStack topStack = topActivity.getRootTask();
        if (topStack != null && topStack != this && topActivity.isState(RESUMED)) {
            // The new top activity is already resumed, so there's a good chance that nothing will
            // get resumed below. So, update visibility now in case the transition is closed
            // prematurely.
        mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
                getDisplay().mDisplayId, false /* markFrozenIfConfigChanged */,
                false /* deferResume */);

        ActivityRecord topActivity = getDisplayArea().topRunningActivity();
        ActivityStack topStack = topActivity.getRootTask();
        if (topStack != null && topStack != this && topActivity.isState(RESUMED)) {
            // Usually resuming a top activity triggers the next app transition, but nothing's got
            // resumed in this case, so we need to execute it explicitly.
            getDisplay().mDisplayContent.executeAppTransition();
+15 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;

import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -2156,6 +2157,20 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                // On the other hand, ActivityRecord#onParentChanged takes care of setting the
                // up-to-dated pinned stack information on this newly created stack.
                r.reparent(stack, MAX_VALUE, reason);

                // In the case of this activity entering PIP due to it being moved to the back,
                // the old activity would have a TRANSIT_TASK_TO_BACK transition that needs to be
                // ran. But, since its visibility did not change (note how it was STOPPED/not
                // visible, and with it now at the back stack, it remains not visible), the logic to
                // add the transition is automatically skipped. We then add this activity manually
                // to the list of apps being closed, and request its transition to be ran.
                final ActivityRecord oldTopActivity = task.getTopMostActivity();
                if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
                        && task.getDisplayContent().mAppTransition.getAppTransition()
                                == TRANSIT_TASK_TO_BACK) {
                    task.getDisplayContent().mClosingApps.add(oldTopActivity);
                    oldTopActivity.mRequestForceTransition = true;
                }
            }
            // The intermediate windowing mode to be set on the ActivityRecord later.
            // This needs to happen before the re-parenting, otherwise we will always set the
+34 −0
Original line number Diff line number Diff line
@@ -198,6 +198,40 @@ public class AppTransitionControllerTest extends WindowTestsBase {
                        opening, closing, false /* visible */));
    }

    @Test
    public void testGetAnimationTargets_visibilityAlreadyUpdated_butForcedTransitionRequested() {
        // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (closing, invisible)
        //                   +- [TaskStack2] - [Task2] - [ActivityRecord2] (opening, visible)
        final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
        final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
        activity1.setVisible(true);
        activity1.mVisibleRequested = true;
        activity1.mRequestForceTransition = true;

        final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
        final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
        activity2.setVisible(false);
        activity2.mVisibleRequested = false;
        activity2.mRequestForceTransition = true;

        final ArraySet<ActivityRecord> opening = new ArraySet<>();
        opening.add(activity1);
        final ArraySet<ActivityRecord> closing = new ArraySet<>();
        closing.add(activity2);

        // The visibility are already updated, but since forced transition is requested, it will
        // be included.
        WindowManagerService.sHierarchicalAnimations = false;
        assertEquals(
                new ArraySet<>(new WindowContainer[]{activity1}),
                AppTransitionController.getAnimationTargets(
                        opening, closing, true /* visible */));
        assertEquals(
                new ArraySet<>(new WindowContainer[]{activity2}),
                AppTransitionController.getAnimationTargets(
                        opening, closing, false /* visible */));
    }

    @Test
    public void testGetAnimationTargets_exitingBeforeTransition() {
        // Create another non-empty task so the animation target won't promote to task display area.
+24 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;

@@ -148,6 +149,29 @@ public class RootActivityContainerTests extends ActivityTestsBase {
        ensureStackPlacement(mFullscreenStack, firstActivity);
    }

    @Test
    public void testMovingBottomMostStackActivityToPinnedStack() {
        final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
                .setStack(mFullscreenStack).build();
        final Task task = firstActivity.getTask();

        final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(task)
                .setStack(mFullscreenStack).build();

        mFullscreenStack.moveTaskToBack(task);

        // Ensure full screen stack has both tasks.
        ensureStackPlacement(mFullscreenStack, firstActivity, secondActivity);
        assertEquals(task.getTopMostActivity(), secondActivity);
        firstActivity.setState(STOPPED, "testMovingBottomMostStackActivityToPinnedStack");


        // Move first activity to pinned stack.
        mRootWindowContainer.moveActivityToPinnedStack(secondActivity, "initialMove");

        assertTrue(firstActivity.mRequestForceTransition);
    }

    private static void ensureStackPlacement(ActivityStack stack, ActivityRecord... activities) {
        final Task task = stack.getBottomMostTask();
        final ArrayList<ActivityRecord> stackActivities = new ArrayList<>();