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

Commit 886bbddb authored by Chris Li's avatar Chris Li
Browse files

Consolidate Bubble WCT

1. Migrate WCT#setDisableLaunchAdjacent to Change since it is not a
   hierarchy operation.
2. Refactor Bubble WCT to use the same helper method.

Bug: 407669270
Test: atest WmTests:WindowContainerTransactionTests
Test: atest WMShellUnitTests:BubbleUtilsTest
Flag: EXEMPT refactor
Change-Id: Iddaf73e9fb40be26fc221f8a67a4c02db9c38cdb
parent 8fee1444
Loading
Loading
Loading
Loading
+26 −42
Original line number Diff line number Diff line
@@ -857,8 +857,9 @@ public final class WindowContainerTransaction implements Parcelable {
    @NonNull
    public WindowContainerTransaction setDisableLaunchAdjacent(
            @NonNull WindowContainerToken container, boolean disabled) {
        mHierarchyOps.add(HierarchyOp.createForSetDisableLaunchAdjacent(container.asBinder(),
                disabled));
        final Change chg = getOrCreateChange(container.asBinder());
        chg.mChangeMask |= Change.CHANGE_DISABLE_LAUNCH_ADJACENT;
        chg.mDisableLaunchAdjacent = disabled;
        return this;
    }

@@ -1377,6 +1378,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int CHANGE_FORCE_EXCLUDED_FROM_RECENTS = 1 << 9;
        public static final int CHANGE_LAUNCH_NEXT_TO_BUBBLE = 1 << 10;
        public static final int CHANGE_DISABLE_PIP = 1 << 11;
        public static final int CHANGE_DISABLE_LAUNCH_ADJACENT = 1 << 12;

        @IntDef(flag = true, prefix = { "CHANGE_" }, value = {
                CHANGE_FOCUSABLE,
@@ -1391,6 +1393,7 @@ public final class WindowContainerTransaction implements Parcelable {
                CHANGE_FORCE_EXCLUDED_FROM_RECENTS,
                CHANGE_LAUNCH_NEXT_TO_BUBBLE,
                CHANGE_DISABLE_PIP,
                CHANGE_DISABLE_LAUNCH_ADJACENT,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface ChangeMask {}
@@ -1403,6 +1406,7 @@ public final class WindowContainerTransaction implements Parcelable {
        private boolean mDragResizing = false;
        private boolean mForceExcludedFromRecents = false;
        private boolean mDisablePip = false;
        private boolean mDisableLaunchAdjacent = false;

        private @ChangeMask int mChangeMask = 0;
        private @ActivityInfo.Config int mConfigSetMask = 0;
@@ -1430,6 +1434,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mForceExcludedFromRecents = in.readBoolean();
            mLaunchNextToBubble = in.readBoolean();
            mDisablePip = in.readBoolean();
            mDisableLaunchAdjacent = in.readBoolean();
            mChangeMask = in.readInt();
            mConfigSetMask = in.readInt();
            mWindowSetMask = in.readInt();
@@ -1484,6 +1489,9 @@ public final class WindowContainerTransaction implements Parcelable {
            if ((other.mChangeMask & CHANGE_DISABLE_PIP) != 0) {
                mDisablePip = other.mDisablePip;
            }
            if ((other.mChangeMask & CHANGE_DISABLE_LAUNCH_ADJACENT) != 0) {
                mDisableLaunchAdjacent = other.mDisableLaunchAdjacent;
            }
            mChangeMask |= other.mChangeMask;
            if (other.mActivityWindowingMode >= WINDOWING_MODE_UNDEFINED) {
                mActivityWindowingMode = other.mActivityWindowingMode;
@@ -1579,6 +1587,14 @@ public final class WindowContainerTransaction implements Parcelable {
            return mDisablePip;
        }

        /**
         * Gets whether activities are disabled to be started in adjacent tasks for the specified
         * root of any child tasks .
         */
        public boolean getDisableLaunchAdjacent() {
            return mDisableLaunchAdjacent;
        }

        /** Gets whether the config should be sent to the client at the end of the transition. */
        public boolean getConfigAtTransitionEnd() {
            return mConfigAtTransitionEnd;
@@ -1655,6 +1671,9 @@ public final class WindowContainerTransaction implements Parcelable {
            if ((mChangeMask & CHANGE_DISABLE_PIP) != 0) {
                sb.append("disablePip:" + mDisablePip + ",");
            }
            if ((mChangeMask & CHANGE_DISABLE_LAUNCH_ADJACENT) != 0) {
                sb.append("disableLaunchAdjacent:" + mDisableLaunchAdjacent + ",");
            }
            if (mBoundsChangeTransaction != null) {
                sb.append("hasBoundsTransaction,");
            }
@@ -1685,6 +1704,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeBoolean(mForceExcludedFromRecents);
            dest.writeBoolean(mLaunchNextToBubble);
            dest.writeBoolean(mDisablePip);
            dest.writeBoolean(mDisableLaunchAdjacent);
            dest.writeInt(mChangeMask);
            dest.writeInt(mConfigSetMask);
            dest.writeInt(mWindowSetMask);
@@ -1749,11 +1769,10 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION = 20;
        public static final int HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES = 21;
        public static final int HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE = 22;
        public static final int HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT = 23;
        public static final int HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK = 24;
        public static final int HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY = 25;
        public static final int HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS = 26;
        public static final int HIERARCHY_OP_TYPE_SET_SYSTEM_BAR_VISIBILITY_OVERRIDE = 27;
        public static final int HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK = 23;
        public static final int HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY = 24;
        public static final int HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS = 25;
        public static final int HIERARCHY_OP_TYPE_SET_SYSTEM_BAR_VISIBILITY_OVERRIDE = 26;

        @IntDef(prefix = {"HIERARCHY_OP_TYPE_"}, value = {
                HIERARCHY_OP_TYPE_REPARENT,
@@ -1779,7 +1798,6 @@ public final class WindowContainerTransaction implements Parcelable {
                HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION,
                HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES,
                HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE,
                HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT,
                HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK,
                HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY,
                HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS,
@@ -1870,8 +1888,6 @@ public final class WindowContainerTransaction implements Parcelable {
        private @InsetsType int mForciblyShowingInsetsTypes;
        private @InsetsType int mForciblyHidingInsetsTypes;

        private boolean mLaunchAdjacentDisabled;

        @Nullable
        private Rect mSafeRegionBounds;

@@ -1975,16 +1991,6 @@ public final class WindowContainerTransaction implements Parcelable {
                    .build();
        }

        /** Creates a hierarchy op for disabling launch adjacent. */
        @NonNull
        public static HierarchyOp createForSetDisableLaunchAdjacent(@Nullable IBinder container,
                boolean disabled) {
            return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT)
                    .setContainer(container)
                    .setLaunchAdjacentDisabled(disabled)
                    .build();
        }

        /** Creates a hierarchy op for deleting a task **/
        @NonNull
        public static HierarchyOp createForRemoveTask(@NonNull IBinder container) {
@@ -2080,7 +2086,6 @@ public final class WindowContainerTransaction implements Parcelable {
            mExcludeInsetsTypes = copy.mExcludeInsetsTypes;
            mForciblyShowingInsetsTypes = copy.mForciblyShowingInsetsTypes;
            mForciblyHidingInsetsTypes = copy.mForciblyHidingInsetsTypes;
            mLaunchAdjacentDisabled = copy.mLaunchAdjacentDisabled;
            mSafeRegionBounds = copy.mSafeRegionBounds;
        }

@@ -2110,7 +2115,6 @@ public final class WindowContainerTransaction implements Parcelable {
            mExcludeInsetsTypes = in.readInt();
            mForciblyShowingInsetsTypes = in.readInt();
            mForciblyHidingInsetsTypes = in.readInt();
            mLaunchAdjacentDisabled = in.readBoolean();
            mSafeRegionBounds = in.readTypedObject(Rect.CREATOR);
        }

@@ -2236,11 +2240,6 @@ public final class WindowContainerTransaction implements Parcelable {
            return mForciblyHidingInsetsTypes;
        }

        /** Denotes whether launch-adjacent flag is respected from this task or its children */
        public boolean isLaunchAdjacentDisabled() {
            return mLaunchAdjacentDisabled;
        }

        /** Denotes the safe region bounds */
        @Nullable
        public Rect getSafeRegionBounds() {
@@ -2257,8 +2256,6 @@ public final class WindowContainerTransaction implements Parcelable {
                case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: return "setAdjacentRoots";
                case HIERARCHY_OP_TYPE_LAUNCH_TASK: return "launchTask";
                case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: return "setAdjacentFlagRoot";
                case HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT:
                    return "setDisableLaunchAdjacent";
                case HIERARCHY_OP_TYPE_PENDING_INTENT: return "pendingIntent";
                case HIERARCHY_OP_TYPE_START_SHORTCUT: return "startShortcut";
                case HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER: return "restoreTransientOrder";
@@ -2329,10 +2326,6 @@ public final class WindowContainerTransaction implements Parcelable {
                case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT:
                    sb.append("container=").append(mContainer).append(" clearRoot=").append(mToTop);
                    break;
                case HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT:
                    sb.append("container=").append(mContainer).append(" disabled=")
                            .append(mLaunchAdjacentDisabled);
                    break;
                case HIERARCHY_OP_TYPE_START_SHORTCUT:
                    sb.append("options=").append(mLaunchOptions)
                            .append(" info=").append(mShortcutInfo);
@@ -2433,7 +2426,6 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeInt(mExcludeInsetsTypes);
            dest.writeInt(mForciblyShowingInsetsTypes);
            dest.writeInt(mForciblyHidingInsetsTypes);
            dest.writeBoolean(mLaunchAdjacentDisabled);
            dest.writeTypedObject(mSafeRegionBounds, flags);
        }

@@ -2521,8 +2513,6 @@ public final class WindowContainerTransaction implements Parcelable {
            private @InsetsType int mForciblyShowingInsetsTypes;
            private @InsetsType int mForciblyHidingInsetsTypes;

            private boolean mLaunchAdjacentDisabled;

            @Nullable
            private Rect mSafeRegionBounds;

@@ -2650,11 +2640,6 @@ public final class WindowContainerTransaction implements Parcelable {
                return this;
            }

            Builder setLaunchAdjacentDisabled(boolean disabled) {
                mLaunchAdjacentDisabled = disabled;
                return this;
            }

            Builder setSafeRegionBounds(Rect safeRegionBounds) {
                mSafeRegionBounds = safeRegionBounds;
                return this;
@@ -2691,7 +2676,6 @@ public final class WindowContainerTransaction implements Parcelable {
                hierarchyOp.mExcludeInsetsTypes = mExcludeInsetsTypes;
                hierarchyOp.mForciblyShowingInsetsTypes = mForciblyShowingInsetsTypes;
                hierarchyOp.mForciblyHidingInsetsTypes = mForciblyHidingInsetsTypes;
                hierarchyOp.mLaunchAdjacentDisabled = mLaunchAdjacentDisabled;
                hierarchyOp.mSafeRegionBounds = mSafeRegionBounds;
                return hierarchyOp;
            }
+6 −4
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ android_robolectric_test {
    // TODO(b/323188766): Include BubbleStackViewTest once the robolectric issue is fixed.
    exclude_srcs: ["src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt"],
    static_libs: [
        "WMShellTests-utils",
        "junit",
        "androidx.core_core-animation-testing",
        "androidx.test.runner",
@@ -66,20 +67,21 @@ android_test {
        "src/**/*.kt",
    ],
    static_libs: [
        "WMShellTests-utils",
        "WindowManager-Shell",
        "junit",
        "androidx.core_core-animation-testing",
        "androidx.test.runner",
        "androidx.test.rules",
        "androidx.test.ext.junit",
        "androidx.test.rules",
        "androidx.test.runner",
        "frameworks-base-testutils",
        "junit",
        "mockito-kotlin2",
        "mockito-target-extended-minus-junit4",
        "platform-parametric-runner-lib",
        "truth",
        "platform-test-annotations",
        "platform-test-rules",
        "testables",
        "truth",
    ],
    libs: [
        "android.test.base.stubs.system",
+20 −22
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.window.WindowContainerTransaction
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.SmallTest
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags.FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP
import com.android.window.flags.Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS
import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_ANYTHING
import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_TASK_VIEW_LISTENER
@@ -35,9 +36,9 @@ import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.taskview.TaskViewController
import com.android.wm.shell.taskview.TaskViewTaskController
import com.android.wm.shell.bubbles.util.verifyEnterBubbleTransaction
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -49,7 +50,13 @@ import org.mockito.kotlin.verify
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters

/** Tests for [BubbleExpandedView] */
/**
 * Tests for [BubbleExpandedView].
 *
 * Build/Install/Run:
 *  atest WMShellRobolectricTests:BubbleExpandedViewTest (on host)
 *  atest WMShellMultivalentTestsOnDevice:BubbleExpandedViewTest (on device)
 */
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
class BubbleExpandedViewTest(flags: FlagsParameterization) {
@@ -102,31 +109,22 @@ class BubbleExpandedViewTest(flags: FlagsParameterization) {
    }

    @Test
    @EnableFlags(FLAG_EXCLUDE_TASK_FROM_RECENTS)
    fun onTaskCreated_excludesTaskFromRecents() {
        bubbleTaskView.listener.onTaskCreated(123 /* taskId */, componentName)

        val wctCaptor = argumentCaptor<WindowContainerTransaction>()
        verify(taskOrganizer).applyTransaction(wctCaptor.capture())
        val wct = wctCaptor.lastValue
        val hasForceExcludedFromRecents = wct.changes.entries.stream()
            .filter { it.key.equals(taskViewTaskToken.asBinder()) }
            .anyMatch { it.value.forceExcludedFromRecents }
        assertTrue(hasForceExcludedFromRecents)
    }

    @Test
    @EnableFlags(FLAG_ENABLE_BUBBLE_ANYTHING)
    fun onTaskCreated_disallowFlagLaunchAdjacent() {
    @EnableFlags(
        FLAG_ENABLE_BUBBLE_ANYTHING,
        FLAG_EXCLUDE_TASK_FROM_RECENTS,
        FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP,
    )
    fun onTaskCreated_appliesWctToEnterBubble() {
        bubbleTaskView.listener.onTaskCreated(123 /* taskId */, componentName)

        val wctCaptor = argumentCaptor<WindowContainerTransaction>()
        verify(taskOrganizer).applyTransaction(wctCaptor.capture())
        val wct = wctCaptor.lastValue
        val hasDisableLaunchAdjacent = wct.hierarchyOps.stream()
            .filter { it.container.equals(taskViewTaskToken.asBinder()) }
            .anyMatch { it.isLaunchAdjacentDisabled }
        assertTrue(hasDisableLaunchAdjacent)
        verifyEnterBubbleTransaction(
            wct,
            taskViewTaskToken.asBinder(),
            isAppBubble = false,
        )
    }

    companion object {
+27 −16
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.wm.shell.bubbles
import android.app.ActivityManager
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.os.IBinder
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.window.IWindowContainerToken
import android.window.WindowContainerToken
@@ -26,12 +27,14 @@ import android.window.WindowContainerTransaction
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags.FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP
import com.android.window.flags.Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS
import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_ANYTHING
import com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.taskview.TaskViewTaskController
import com.google.common.truth.Truth.assertThat
import org.junit.Assume.assumeTrue
import com.android.wm.shell.bubbles.util.verifyExitBubbleTransaction
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -42,7 +45,13 @@ import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify

/** Unit tests for [BubbleTaskStackListener]. */
/**
 * Unit tests for [BubbleTaskStackListener].
 *
 * Build/Install/Run:
 *  atest WMShellRobolectricTests:BubbleTaskStackListenerTest (on host)
 *  atest WMShellMultivalentTestsOnDevice:BubbleTaskStackListenerTest (on device)
 */
@SmallTest
@RunWith(AndroidJUnit4::class)
class BubbleTaskStackListenerTest {
@@ -97,9 +106,13 @@ class BubbleTaskStackListenerTest {
    }

    @Test
    @EnableFlags(
        FLAG_ENABLE_CREATE_ANY_BUBBLE,
        FLAG_ENABLE_BUBBLE_ANYTHING,
        FLAG_EXCLUDE_TASK_FROM_RECENTS,
        FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP,
    )
    fun onActivityRestartAttempt_inStackAppBubbleToFullscreen_notifiesTaskRemoval() {
        assumeTrue(BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents())

        task.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
        bubbleData.stub {
            on { getBubbleInStackWithTaskId(bubbleTaskId) } doReturn bubble
@@ -118,10 +131,7 @@ class BubbleTaskStackListenerTest {
            verify(taskOrganizer).applyTransaction(wctCaptor.capture())
            wctCaptor.lastValue
        }
        assertThat(wct.changes).hasSize(1)
        val chg = wct.changes.get(bubbleTaskToken.asBinder())
        assertThat(chg).isNotNull()
        assertThat(chg!!.forceExcludedFromRecents).isFalse()
        verifyExitBubbleTransaction(wct, bubbleTaskToken.asBinder())
        verify(taskOrganizer).setInterceptBackPressedOnTaskRoot(task.token, false /* intercept */)
        verify(taskViewTaskController).notifyTaskRemovalStarted(task)
    }
@@ -144,9 +154,13 @@ class BubbleTaskStackListenerTest {
    }

    @Test
    @EnableFlags(
        FLAG_ENABLE_CREATE_ANY_BUBBLE,
        FLAG_ENABLE_BUBBLE_ANYTHING,
        FLAG_EXCLUDE_TASK_FROM_RECENTS,
        FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP,
    )
    fun onActivityRestartAttempt_overflowAppBubbleToFullscreen_notifiesTaskRemoval() {
        assumeTrue(BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents())

        task.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
        bubbleData.stub {
            on { getOverflowBubbleWithTaskId(bubbleTaskId) } doReturn bubble
@@ -165,10 +179,7 @@ class BubbleTaskStackListenerTest {
            verify(taskOrganizer).applyTransaction(wctCaptor.capture())
            wctCaptor.lastValue
        }
        assertThat(wct.changes).hasSize(1)
        val chg = wct.changes.get(bubbleTaskToken.asBinder())
        assertThat(chg).isNotNull()
        assertThat(chg!!.forceExcludedFromRecents).isFalse()
        verifyExitBubbleTransaction(wct, bubbleTaskToken.asBinder())
        verify(taskOrganizer).setInterceptBackPressedOnTaskRoot(task.token, false /* intercept */)
        verify(taskViewTaskController).notifyTaskRemovalStarted(task)
    }
+17 −31
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags.FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP
import com.android.window.flags.Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS
import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_ANYTHING
import com.android.wm.shell.R
@@ -49,8 +50,8 @@ import com.android.wm.shell.common.TestShellExecutor
import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.taskview.TaskViewController
import com.android.wm.shell.taskview.TaskViewTaskController
import com.android.wm.shell.bubbles.util.verifyEnterBubbleTransaction
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -69,6 +70,10 @@ import org.mockito.kotlin.whenever

/**
 * Tests for [BubbleTaskViewListener].
 *
 * Build/Install/Run:
 *  atest WMShellRobolectricTests:BubbleTaskViewListenerTest (on host)
 *  atest WMShellMultivalentTestsOnDevice:BubbleTaskViewListenerTest (on device)
 */
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -416,32 +421,12 @@ class BubbleTaskViewListenerTest {
    }

    @Test
    @EnableFlags(FLAG_EXCLUDE_TASK_FROM_RECENTS)
    fun onTaskCreated_excludesTaskFromRecents() {
        val b = createAppBubble()
        bubbleTaskViewListener.setBubble(b)
        getInstrumentation().runOnMainSync {
            bubbleTaskViewListener.onInitialized()
        }
        getInstrumentation().waitForIdleSync()

        getInstrumentation().runOnMainSync {
            bubbleTaskViewListener.onTaskCreated(123 /* taskId */, mock<ComponentName>())
        }
        getInstrumentation().waitForIdleSync()

        val wctCaptor = argumentCaptor<WindowContainerTransaction>()
        verify(taskOrganizer).applyTransaction(wctCaptor.capture())
        val wct = wctCaptor.lastValue
        val hasForceExcludedFromRecents = wct.changes.entries.stream()
            .filter { it.key.equals(taskViewTaskToken.asBinder()) }
            .anyMatch { it.value.forceExcludedFromRecents }
        assertTrue(hasForceExcludedFromRecents)
    }

    @Test
    @EnableFlags(FLAG_ENABLE_BUBBLE_ANYTHING)
    fun onTaskCreated_disallowFlagLaunchAdjacent() {
    @EnableFlags(
        FLAG_ENABLE_BUBBLE_ANYTHING,
        FLAG_EXCLUDE_TASK_FROM_RECENTS,
        FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP,
    )
    fun onTaskCreated_appliesWctToEnterBubble() {
        val b = createAppBubble()
        bubbleTaskViewListener.setBubble(b)
        getInstrumentation().runOnMainSync {
@@ -457,10 +442,11 @@ class BubbleTaskViewListenerTest {
        val wctCaptor = argumentCaptor<WindowContainerTransaction>()
        verify(taskOrganizer).applyTransaction(wctCaptor.capture())
        val wct = wctCaptor.lastValue
        val hasDisableLaunchAdjacent = wct.hierarchyOps.stream()
            .filter { it.container.equals(taskViewTaskToken.asBinder()) }
            .anyMatch { it.isLaunchAdjacentDisabled }
        assertTrue(hasDisableLaunchAdjacent)
        verifyEnterBubbleTransaction(
            wct,
            taskViewTaskToken.asBinder(),
            b.isApp || b.isShortcut,
        )
    }

    @Test
Loading