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

Commit d739277b authored by Gaurav Bhola's avatar Gaurav Bhola Committed by Android (Google) Code Review
Browse files

Merge "A few updates to task views to enable shell transitions on auto." into main

parents 672d2128 119b6def
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Handler;
import android.os.Looper;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@@ -121,6 +120,11 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,

    @Override
    public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
        if (mTaskViewTaskController.isUsingShellTransitions()) {
            // No need for additional work as it is already taken care of during
            // prepareOpenAnimation().
            return;
        }
        onLocationChanged();
        if (taskInfo.taskDescription != null) {
            final int bgColor = taskInfo.taskDescription.getBackgroundColor();
+69 −11
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.wm.shell.taskview;

import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.WindowManager.TRANSIT_CHANGE;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -48,6 +49,23 @@ import java.util.concurrent.Executor;
 * TaskView} to {@link TaskViewTaskController} interactions are done via direct method calls.
 *
 * The reverse communication is done via the {@link TaskViewBase} interface.
 *
 * <ul>
 *     <li>The entry point for an activity based task view is {@link
 *     TaskViewTaskController#startActivity(PendingIntent, Intent, ActivityOptions, Rect)}</li>
 *
 *     <li>The entry point for an activity (represented by {@link ShortcutInfo}) based task view
 *     is {@link TaskViewTaskController#startShortcutActivity(ShortcutInfo, ActivityOptions, Rect)}
 *     </li>
 *
 *     <li>The entry point for a root-task based task view is {@link
 *     TaskViewTaskController#startRootTask(ActivityManager.RunningTaskInfo, SurfaceControl,
 *     WindowContainerTransaction)}.
 *     This method is special as it doesn't create a root task and instead expects that the
 *     launch root task is already created and started. This method just attaches the taskInfo to
 *     the TaskView.
 *     </li>
 * </ul>
 */
public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {

@@ -208,6 +226,35 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
        }
    }


    /**
     * Attaches the given root task {@code taskInfo} in the task view.
     *
     * <p> Since {@link ShellTaskOrganizer#createRootTask(int, int,
     * ShellTaskOrganizer.TaskListener)} does not use the shell transitions flow, this method is
     * used as an entry point for an already-created root-task in the task view.
     *
     * @param taskInfo the task info of the root task.
     * @param leash    the {@link android.content.pm.ShortcutInfo.Surface} of the root task
     * @param wct      The Window container work that should happen as part of this set up.
     */
    public void startRootTask(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
            @Nullable WindowContainerTransaction wct) {
        if (wct == null) {
            wct = new WindowContainerTransaction();
        }
        // This method skips the regular flow where an activity task is launched as part of a new
        // transition in taskview and then transition is intercepted using the launchcookie.
        // The task here is already created and running, it just needs to be reparented, resized
        // and tracked correctly inside taskview. Which is done by calling
        // prepareOpenAnimationInternal() and then manually enqueuing the resulting window container
        // transaction.
        prepareOpenAnimationInternal(true /* newTask */, mTransaction /* startTransaction */,
                null /* finishTransaction */, taskInfo, leash, wct);
        mTransaction.apply();
        mTaskViewTransitions.startInstantTransition(TRANSIT_CHANGE, wct);
    }

    private void prepareActivityOptions(ActivityOptions options, Rect launchBounds) {
        final Binder launchCookie = new Binder();
        mShellExecutor.execute(() -> {
@@ -342,7 +389,6 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
        final SurfaceControl taskLeash = mTaskLeash;
        handleAndNotifyTaskRemoval(mTaskInfo);

        // Unparent the task when this surface is destroyed
        mTransaction.reparent(taskLeash, null).apply();
        resetTaskInfo();
    }
@@ -597,6 +643,15 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
            @NonNull SurfaceControl.Transaction finishTransaction,
            ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
            WindowContainerTransaction wct) {
        prepareOpenAnimationInternal(newTask, startTransaction, finishTransaction, taskInfo, leash,
                wct);
    }

    private void prepareOpenAnimationInternal(final boolean newTask,
            SurfaceControl.Transaction startTransaction,
            SurfaceControl.Transaction finishTransaction,
            ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
            WindowContainerTransaction wct) {
        mPendingInfo = null;
        mTaskInfo = taskInfo;
        mTaskToken = mTaskInfo.token;
@@ -608,10 +663,12 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
            // Also reparent on finishTransaction since the finishTransaction will reparent back
            // to its "original" parent by default.
            Rect boundsOnScreen = mTaskViewBase.getCurrentBoundsOnScreen();
            if (finishTransaction != null) {
                finishTransaction.reparent(mTaskLeash, mSurfaceControl)
                        .setPosition(mTaskLeash, 0, 0)
                        // TODO: maybe once b/280900002 is fixed this will be unnecessary
                        .setWindowCrop(mTaskLeash, boundsOnScreen.width(), boundsOnScreen.height());
            }
            mTaskViewTransitions.updateBoundsState(this, boundsOnScreen);
            mTaskViewTransitions.updateVisibilityState(this, true /* visible */);
            wct.setBounds(mTaskToken, boundsOnScreen);
@@ -632,6 +689,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
            mTaskViewBase.setResizeBgColor(startTransaction, backgroundColor);
        }

        mTaskViewBase.onTaskAppeared(mTaskInfo, mTaskLeash);
        if (mListener != null) {
            final int taskId = mTaskInfo.taskId;
            final ComponentName baseActivity = mTaskInfo.baseActivity;
+51 −4
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
    /**
     * Looks through the pending transitions for a closing transaction that matches the provided
     * `taskView`.
     *
     * @param taskView the pending transition should be for this.
     */
    private PendingTransition findPendingCloseTransition(TaskViewTaskController taskView) {
@@ -134,9 +135,18 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
        return null;
    }

    /**
     * Starts a transition outside of the handler associated with {@link TaskViewTransitions}.
     */
    public void startInstantTransition(@WindowManager.TransitionType int type,
            WindowContainerTransaction wct) {
        mTransitions.startTransition(type, wct, null);
    }

    /**
     * Looks through the pending transitions for a opening transaction that matches the provided
     * `taskView`.
     *
     * @param taskView the pending transition should be for this.
     */
    @VisibleForTesting
@@ -152,6 +162,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {

    /**
     * Looks through the pending transitions for one matching `taskView`.
     *
     * @param taskView the pending transition should be for this.
     * @param type     the type of transition it's looking for
     */
@@ -220,7 +231,24 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
        startNextTransition();
    }

    void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
    /** Starts a new transition to make the given {@code taskView} visible. */
    public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
        setTaskViewVisible(taskView, visible, false /* reorder */);
    }

    /**
     * Starts a new transition to make the given {@code taskView} visible and optionally change
     * the task order.
     *
     * @param taskView the task view which the visibility is being changed for
     * @param visible  the new visibility of the task view
     * @param reorder  whether to reorder the task or not. If this is {@code true}, the task will be
     *                 reordered as per the given {@code visible}. For {@code visible = true}, task
     *                 will be reordered to top. For {@code visible = false}, task will be reordered
     *                 to the bottom
     */
    public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible,
            boolean reorder) {
        if (mTaskViews.get(taskView) == null) return;
        if (mTaskViews.get(taskView).mVisible == visible) return;
        if (taskView.getTaskInfo() == null) {
@@ -231,6 +259,9 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
        wct.setBounds(taskView.getTaskInfo().token, mTaskViews.get(taskView).mBounds);
        if (reorder) {
            wct.reorder(taskView.getTaskInfo().token, visible /* onTop */);
        }
        PendingTransition pending = new PendingTransition(
                visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
        mPending.add(pending);
@@ -238,6 +269,22 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
        // visibility is reported in transition.
    }

    /** Starts a new transition to reorder the given {@code taskView}'s task. */
    public void reorderTaskViewTask(TaskViewTaskController taskView, boolean onTop) {
        if (mTaskViews.get(taskView) == null) return;
        if (taskView.getTaskInfo() == null) {
            // Nothing to update, task is not yet available
            return;
        }
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.reorder(taskView.getTaskInfo().token, onTop /* onTop */);
        PendingTransition pending = new PendingTransition(
                onTop ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
        mPending.add(pending);
        startNextTransition();
        // visibility is reported in transition.
    }

    void updateBoundsState(TaskViewTaskController taskView, Rect boundsOnScreen) {
        TaskViewRequestedState state = mTaskViews.get(taskView);
        if (state == null) return;
+25 −1
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Handler;
import android.os.Looper;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -497,6 +496,31 @@ public class TaskViewTest extends ShellTestCase {
        assertThat(insetsInfo.touchableRegion.contains(30, 30)).isFalse();
    }

    @Test
    public void testStartRootTask_setsBoundsAndVisibility() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);

        TaskViewBase taskViewBase = mock(TaskViewBase.class);
        Rect bounds = new Rect(0, 0, 100, 100);
        when(taskViewBase.getCurrentBoundsOnScreen()).thenReturn(bounds);
        mTaskViewTaskController.setTaskViewBase(taskViewBase);

        // Surface created, but task not available so bounds / visibility isn't set
        mTaskView.surfaceCreated(mock(SurfaceHolder.class));
        verify(mTaskViewTransitions, never()).updateVisibilityState(
                eq(mTaskViewTaskController), eq(true));

        // Make the task available
        WindowContainerTransaction wct = mock(WindowContainerTransaction.class);
        mTaskViewTaskController.startRootTask(mTaskInfo, mLeash, wct);

        // Bounds got set
        verify(wct).setBounds(any(WindowContainerToken.class), eq(bounds));
        // Visibility & bounds state got set
        verify(mTaskViewTransitions).updateVisibilityState(eq(mTaskViewTaskController), eq(true));
        verify(mTaskViewTransitions).updateBoundsState(eq(mTaskViewTaskController), eq(bounds));
    }

    @Test
    public void testTaskViewPrepareOpenAnimationSetsBoundsAndVisibility() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+43 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.taskview;

import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;

import static com.google.common.truth.Truth.assertThat;
@@ -207,6 +208,48 @@ public class TaskViewTransitionsTest extends ShellTestCase {
                new Rect(0, 0, 100, 100));
    }

    @Test
    public void testReorderTask_movedToFrontTransaction() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);

        mTaskViewTransitions.reorderTaskViewTask(mTaskViewTaskController, true);
        // Consume the pending transaction from order change
        TaskViewTransitions.PendingTransition pending =
                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
        assertThat(pending).isNotNull();
        mTaskViewTransitions.startAnimation(pending.mClaimed,
                mock(TransitionInfo.class),
                new SurfaceControl.Transaction(),
                new SurfaceControl.Transaction(),
                mock(Transitions.TransitionFinishCallback.class));

        // Verify it was consumed
        TaskViewTransitions.PendingTransition pending2 =
                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
        assertThat(pending2).isNull();
    }

    @Test
    public void testReorderTask_movedToBackTransaction() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);

        mTaskViewTransitions.reorderTaskViewTask(mTaskViewTaskController, false);
        // Consume the pending transaction from order change
        TaskViewTransitions.PendingTransition pending =
                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
        assertThat(pending).isNotNull();
        mTaskViewTransitions.startAnimation(pending.mClaimed,
                mock(TransitionInfo.class),
                new SurfaceControl.Transaction(),
                new SurfaceControl.Transaction(),
                mock(Transitions.TransitionFinishCallback.class));

        // Verify it was consumed
        TaskViewTransitions.PendingTransition pending2 =
                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
        assertThat(pending2).isNull();
    }

    @Test
    public void test_startAnimation_setsTaskNotFound() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);