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

Commit 92cb2b79 authored by Eric Lin's avatar Eric Lin Committed by Android (Google) Code Review
Browse files

Merge "Fix regression in desktop decor visibility for bubble tasks." into main

parents 3918cb65 b8b1f62b
Loading
Loading
Loading
Loading
+46 −2
Original line number Diff line number Diff line
@@ -320,7 +320,51 @@ class BubbleControllerTest(flags: FlagsParameterization) {
        }
    }

    private fun createBubble(key: String): Bubble {
    @Test
    fun hasStableBubbleForTask_whenBubbleIsCollapsed_returnsTrue() {
        val taskId = 777
        val bubble = createBubble("key", taskId)
        getInstrumentation().runOnMainSync {
            bubbleData.notificationEntryUpdated(
                bubble,
                true /* suppressFlyout */,
                true /* showInShade= */,
            )
        }

        assertThat(bubbleController.hasStableBubbleForTask(taskId)).isTrue()
    }

    @Test
    fun hasStableBubbleForTask_whenBubbleInTransition_returnsFalse() {
        val taskId = 777
        val bubble = createBubble("key", taskId).apply { preparingTransition = mock() }
        getInstrumentation().runOnMainSync {
            bubbleData.notificationEntryUpdated(
                bubble,
                true /* suppressFlyout */,
                true /* showInShade= */,
            )
        }

        assertThat(bubbleController.hasStableBubbleForTask(taskId)).isFalse()
    }

    @Test
    fun hasStableBubbleForTask_noBubble_returnsFalse() {
        val bubble = createBubble("key", taskId = 123)
        getInstrumentation().runOnMainSync {
            bubbleData.notificationEntryUpdated(
                bubble,
                true /* suppressFlyout */,
                true /* showInShade= */,
            )
        }

        assertThat(bubbleController.hasStableBubbleForTask(777)).isFalse()
    }

    private fun createBubble(key: String, taskId: Int = 0): Bubble {
        val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button)
        val shortcutInfo = ShortcutInfo.Builder(context, "fakeId").setIcon(icon).build()
        val bubble =
@@ -330,7 +374,7 @@ class BubbleControllerTest(flags: FlagsParameterization) {
                /* desiredHeight= */ 0,
                Resources.ID_NULL,
                "title",
                /* taskId= */ 0,
                taskId,
                "locus",
                /* isDismissable= */ true,
                directExecutor(),
+6 −0
Original line number Diff line number Diff line
@@ -1374,6 +1374,12 @@ public class BubbleController implements ConfigurationChangeListener,
        return mBubbleData.hasBubbles() || mBubbleData.isShowingOverflow();
    }

    /** Returns whether the given task is a non-transient bubble. */
    public boolean hasStableBubbleForTask(int taskId) {
        final Bubble bubble = mBubbleData.getBubbleInStackWithTaskId(taskId);
        return bubble != null && bubble.getPreparingTransition() == null;
    }

    public boolean isStackExpanded() {
        return mBubbleData.isExpanded();
    }
+3 −2
Original line number Diff line number Diff line
@@ -1168,9 +1168,10 @@ public abstract class WMShellModule {
    static AppHandleAndHeaderVisibilityHelper provideAppHandleAndHeaderVisibilityHelper(
            @NonNull DisplayController displayController,
            @NonNull DesktopModeCompatPolicy desktopModeCompatPolicy,
            @NonNull DesktopState desktopState) {
            @NonNull DesktopState desktopState,
            Optional<BubbleController> bubbleController) {
        return new AppHandleAndHeaderVisibilityHelper(displayController,
                desktopModeCompatPolicy, desktopState);
                desktopModeCompatPolicy, desktopState, bubbleController);
    }

    @WMSingleton
+14 −0
Original line number Diff line number Diff line
@@ -21,12 +21,14 @@ import android.app.WindowConfiguration
import android.view.Display
import android.view.WindowManager
import android.window.DesktopExperienceFlags.ENABLE_BUG_FIXES_FOR_SECONDARY_DISPLAY
import com.android.wm.shell.bubbles.BubbleController
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.desktopmode.DesktopWallpaperActivity.Companion.isWallpaperTask
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.shared.desktopmode.DesktopState
import com.android.wm.shell.splitscreen.SplitScreenController
import java.util.Optional

/**
 * Resolves whether, given a task and its associated display that it is currently on, to show the
@@ -36,6 +38,7 @@ class AppHandleAndHeaderVisibilityHelper (
    private val displayController: DisplayController,
    private val desktopModeCompatPolicy: DesktopModeCompatPolicy,
    private val desktopState: DesktopState,
    private val bubbleController: Optional<BubbleController>,
) {
    var splitScreenController: SplitScreenController? = null

@@ -90,11 +93,22 @@ class AppHandleAndHeaderVisibilityHelper (
                return false
            }
        }

        // Bubble tasks reset alwaysOnTop when reordering a task to the bottom to hide its task view
        // in TaskViewTransitions#setTaskViewVisible, so we need to explicitly check here.
        fun ActivityManager.RunningTaskInfo.isBubble(): Boolean =
            if (BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents()) {
                bubbleController.map { it.hasStableBubbleForTask(taskId) }.orElse(false)
            } else {
                false
            }

        return desktopState.canEnterDesktopModeOrShowAppHandle
                && !isWallpaperTask(taskInfo)
                && taskInfo.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED
                && taskInfo.activityType == WindowConfiguration.ACTIVITY_TYPE_STANDARD
                && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop
                && !taskInfo.isBubble()
    }

    private fun allowedForDisplay(display: Display): Boolean {
+64 −0
Original line number Diff line number Diff line
@@ -66,13 +66,16 @@ import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction
import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.util.StubTransaction
import com.google.common.truth.Truth.assertThat
import java.util.function.Consumer
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -1292,6 +1295,67 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest
        verify(decoration, times(1)).setIsRecentsTransitionRunning(true)
    }

    @Test
    fun testOnTaskOpening_expandedBubbleTask_skipsWindowDecorationCreation() {
        val taskInfo = createTask(windowingMode = WINDOWING_MODE_MULTI_WINDOW).apply {
            // Bubble task is launched with ActivityOptions#setTaskAlwaysOnTop
            // in BubbleTaskViewListener#onInitialized.
            configuration.windowConfiguration.setAlwaysOnTop(true)
        }
        mockBubbleController.stub {
            on { hasStableBubbleForTask(taskInfo.taskId) } doReturn true
        }

        val isWindowDecorCreated = desktopModeWindowDecorViewModel.onTaskOpening(
            taskInfo,
            SurfaceControl(), /* taskSurface */
            StubTransaction(), /* startT */
            StubTransaction(), /* finishT */
        )

        assertThat(isWindowDecorCreated).isFalse()
    }

    @Test
    fun testOnTaskChanging_collapsedBubbleTask_skipsWindowDecorationCreation() {
        assumeTrue(BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents())

        val taskInfo = createTask(windowingMode = WINDOWING_MODE_MULTI_WINDOW)
        mockBubbleController.stub {
            on { hasStableBubbleForTask(taskInfo.taskId) } doReturn true
        }

        desktopModeWindowDecorViewModel.onTaskChanging(
            taskInfo,
            SurfaceControl(), /* taskSurface */
            StubTransaction(), /* startT */
            StubTransaction(), /* finishT */
        )

        assertThat(windowDecorByTaskIdSpy.contains(taskInfo.taskId)).isFalse()
    }

    @Test
    fun testOnTaskChanging_convertTaskToBubble_destroysWindowDecoration() {
        assumeTrue(BubbleAnythingFlagHelper.enableCreateAnyBubbleWithForceExcludedFromRecents())

        val taskInfo = createTask(windowingMode = WINDOWING_MODE_MULTI_WINDOW)
        mockBubbleController.stub {
            on { hasStableBubbleForTask(taskInfo.taskId) } doReturn true
        }
        val mockDecoration = mock<DesktopModeWindowDecoration>()
        windowDecorByTaskIdSpy.put(taskInfo.taskId, mockDecoration)

        desktopModeWindowDecorViewModel.onTaskChanging(
            taskInfo,
            SurfaceControl(), /* taskSurface */
            StubTransaction(), /* startT */
            StubTransaction(), /* finishT */
        )

        verify(mockDecoration).close()
    }

    private fun createOpenTaskDecoration(
        @WindowingMode windowingMode: Int,
        taskSurface: SurfaceControl = SurfaceControl(),
Loading