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

Commit 73a71fad authored by Eric Lin's avatar Eric Lin
Browse files

Use reorder instead of hidden for bubble task visibility.

This change modifies how bubble tasks are shown and hidden by using
reordering instead of the hidden property. It is part of a larger effort
to support bubble'd app task to fullscreen transitions.

The key change is in TaskViewController#setTaskViewVisible, where the
alwaysOnTop flag is now set/reset, and the task is reordered to the
top/bottom when visibility is true/false. BubbleTaskViewController is
overridden to call the parent method with reorder=true and
toggleHiddenOnReorder=true. This removes the need for a transition
handler to reset the task's hidden flag.

This approach ensures the task remains alwaysOnTop and is reordered to
the top when the bubble expands. When the bubble collapses, the task is
no longer alwaysOnTop and is reordered to the bottom, behind the
fullscreen launcher.

Bug: 388630258
Flag: com.android.wm.shell.enable_create_any_bubble
Flag: com.android.window.flags.exclude_task_from_recents
Test: atest WMShellUnitTests:TaskViewTransitionsTest
Test: atest WMShellRobolectricTests:BubbleControllerTest
Test: atest WMShellMultivalentTestsOnDevice:BubbleControllerTest
Change-Id: Ibdc4630258cbe3edcc37c6d4bd8382f2da0c519e
parent f39298ab
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -59,10 +59,12 @@ import com.android.wm.shell.common.TestShellExecutor
import com.android.wm.shell.common.TestSyncExecutor
import com.android.wm.shell.draganddrop.DragAndDropController
import com.android.wm.shell.shared.TransactionPool
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.taskview.TaskViewRepository
import com.android.wm.shell.taskview.TaskViewTaskController
import com.android.wm.shell.taskview.TaskViewTransitions
import com.android.wm.shell.transition.Transitions
import com.google.common.truth.Truth.assertThat
@@ -298,6 +300,26 @@ class BubbleControllerTest(flags: FlagsParameterization) {
        assertThat(expandListener.bubblesExpandedState).isEqualTo(mapOf("key" to false))
    }

    @Test
    fun setTaskViewVisible_callsBaseTransitionsWithReorder() {
        val baseTransitions = mock<TaskViewTransitions>()
        val taskView = mock<TaskViewTaskController>()
        val bubbleTaskViewController = bubbleController.BubbleTaskViewController(baseTransitions)

        bubbleTaskViewController.setTaskViewVisible(taskView, true /* visible */)

        if (BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents()) {
            verify(baseTransitions).setTaskViewVisible(
                taskView,
                true, /* visible */
                true, /* reorder */
                false, /* toggleHiddenOnReorder */
            )
        } else {
            verify(baseTransitions).setTaskViewVisible(taskView, true /* visible */)
        }
    }

    private fun createBubble(key: String): Bubble {
        val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button)
        val shortcutInfo = ShortcutInfo.Builder(context, "fakeId").setIcon(icon).build()
+11 −4
Original line number Diff line number Diff line
@@ -327,7 +327,7 @@ public class BubbleController implements ConfigurationChangeListener,
            @ShellMainThread Handler mainHandler,
            @ShellBackgroundThread ShellExecutor bgExecutor,
            TaskViewRepository taskViewRepository,
            TaskViewTransitions taskViewTransitions,
            @NonNull TaskViewTransitions taskViewTransitions,
            Transitions transitions,
            SyncTransactionQueue syncQueue,
            IWindowManager wmService,
@@ -3285,10 +3285,11 @@ public class BubbleController implements ConfigurationChangeListener,
        }
    }

    private class BubbleTaskViewController implements TaskViewController {
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    class BubbleTaskViewController implements TaskViewController {
        private final TaskViewTransitions mBaseTransitions;

        BubbleTaskViewController(TaskViewTransitions baseTransitions) {
        BubbleTaskViewController(@NonNull TaskViewTransitions baseTransitions) {
            mBaseTransitions = baseTransitions;
        }

@@ -3351,8 +3352,14 @@ public class BubbleController implements ConfigurationChangeListener,

        @Override
        public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
            if (BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents()) {
                // Use reorder instead of always-on-top with hidden.
                mBaseTransitions.setTaskViewVisible(taskView, visible, true /* reorder */,
                        false /* toggleHiddenOnReorder */);
            } else {
                mBaseTransitions.setTaskViewVisible(taskView, visible);
            }
        }

        @Override
        public void setTaskBounds(TaskViewTaskController taskView, Rect boundsOnScreen) {
+29 −5
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ 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.android.window.flags.Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS;
import static com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES_NOISY;
import static com.android.wm.shell.transition.Transitions.transitTypeToString;

@@ -467,17 +469,27 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV
        setTaskViewVisible(taskView, visible, false /* reorder */);
    }

    /** See {@link #setTaskViewVisible(TaskViewTaskController, boolean, boolean, boolean)}. */
    public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible,
            boolean reorder) {
        setTaskViewVisible(taskView, visible, reorder, true /* toggleHiddenOnReorder */);
    }

    /**
     * Starts a new transition to make the given {@code taskView} visible and optionally
     * reordering it.
     *
     * @param reorder  whether to reorder the task or not. If this is {@code true}, the task will
     * @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
     * @param toggleHiddenOnReorder Whether to also toggle the hidden state of the task. This only
     *                              takes effect if {@code reorder} is {@code true}.
     * @throws IllegalStateException If the flag {@link FLAG_ENABLE_CREATE_ANY_BUBBLE} and
     *                               {@link FLAG_EXCLUDE_TASK_FROM_RECENTS} are not enabled.
     */
    public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible,
            boolean reorder) {
            boolean reorder, boolean toggleHiddenOnReorder) {
        final TaskViewRepository.TaskViewState state = useRepo()
                ? mTaskViewRepo.byTaskView(taskView)
                : mTaskViews.get(taskView);
@@ -488,15 +500,27 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV
            return;
        }
        state.mVisible = visible;

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
        wct.setBounds(taskView.getTaskInfo().token, state.mBounds);
        if (reorder && !toggleHiddenOnReorder) {
            if (!BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents()) {
                throw new IllegalStateException(
                    "Flag " + FLAG_ENABLE_CREATE_ANY_BUBBLE + " and "
                        + FLAG_EXCLUDE_TASK_FROM_RECENTS + " are not enabled");
            }
            // Order of setAlwaysOnTop() and reorder() matters; hierarchy ops apply sequentially.
            wct.setAlwaysOnTop(taskView.getTaskInfo().token, visible /* alwaysOnTop */);
        } else {
            wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
        }
        if (reorder) {
            wct.reorder(taskView.getTaskInfo().token, visible /* onTop */);
        }

        ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "Transitions.setTaskViewVisible(): taskView=%d "
                + "visible=%b", taskView.hashCode(), visible);
        PendingTransition pending = new PendingTransition(
        final PendingTransition pending = new PendingTransition(
                visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
        mPending.add(pending);
        startNextTransition();
+30 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
import com.android.wm.shell.transition.Transitions;

import org.junit.Before;
@@ -67,6 +68,7 @@ import platform.test.runner.parameterized.Parameters;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

@SmallTest
@@ -282,6 +284,34 @@ public class TaskViewTransitionsTest extends ShellTestCase {
        mTaskViewTransitions.setTaskViewVisible(mTaskViewTaskController, false);
    }

    @Test
    public void testSetTaskVisibility_reorderNoToggleHidden_resetsAlwaysOnTopAndReorder() {
        assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
        assumeTrue(TaskViewTransitions.useRepo());
        assumeTrue(BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents());

        final Rect bounds = new Rect(0, 0, 100, 100);
        mTaskViewRepository.byTaskView(mTaskViewTaskController).mBounds = bounds;
        mTaskViewRepository.byTaskView(mTaskViewTaskController).mVisible = true;
        final IBinder mockBinder = mock(IBinder.class);
        when(mToken.asBinder()).thenReturn(mockBinder);

        mTaskViewTransitions.setTaskViewVisible(mTaskViewTaskController, false /* visible */,
                true /* reorder */, false /* toggleHiddenOnReorder */);

        final TaskViewTransitions.PendingTransition pending =
                mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
        assertThat(pending).isNotNull();
        final Map<IBinder, WindowContainerTransaction.Change> chgs = pending.mWct.getChanges();
        assertThat(chgs.keySet()).containsExactly(mockBinder);
        assertThat(chgs.get(mockBinder).getConfiguration().windowConfiguration.getBounds())
                .isEqualTo(bounds);
        final List<WindowContainerTransaction.HierarchyOp> ops = pending.mWct.getHierarchyOps();
        assertThat(ops).hasSize(2);
        assertThat(ops.get(0).isAlwaysOnTop()).isFalse();
        assertThat(ops.get(1).getToTop()).isFalse();
    }

    @Test
    public void testSetTaskBounds_taskRemoved_noNPE() {
        mTaskViewTransitions.unregisterTaskView(mTaskViewTaskController);