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

Commit 3f9bb2e1 authored by Maryam Dehaini's avatar Maryam Dehaini Committed by Android (Google) Code Review
Browse files

Merge "Stop status bar from handling touch events in app handle area" into main

parents 34cffe3a 517054a9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -225,6 +225,8 @@ public enum DesktopExperienceFlags {
            Flags.FLAG_ENABLE_REJECT_HOME_TRANSITION),
    ENABLE_REMOVE_DESK_ON_LAST_TASK_REMOVAL(Flags::removeDeskOnLastTaskRemoval, false,
            Flags.FLAG_REMOVE_DESK_ON_LAST_TASK_REMOVAL),
    ENABLE_REMOVE_STATUS_BAR_INPUT_LAYER(Flags::enableRemoveStatusBarInputLayer, false,
            Flags.FLAG_ENABLE_REMOVE_STATUS_BAR_INPUT_LAYER),
    ENABLE_REQUEST_FULLSCREEN_REFACTOR(
            Flags::enableRequestFullscreenRefactor, false,
            Flags.FLAG_ENABLE_REQUEST_FULLSCREEN_REFACTOR),
+10 −0
Original line number Diff line number Diff line
@@ -1180,6 +1180,16 @@ flag {
    bug: "378443899"
}

flag {
    name: "enable_remove_status_bar_input_layer"
    namespace: "lse_desktop_experience"
    description: "Removes app handle bounds from the status bar's touchable region so that input is sent directly to the app handle."
    bug: "412444139"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "enable_request_fullscreen_bugfix"
    namespace: "lse_desktop_experience"
+13 −1
Original line number Diff line number Diff line
@@ -138,6 +138,12 @@ class AppHandleViewHolder(
        setVisibility(isCaptionVisible)
        captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo))
        this.taskInfo = taskInfo
        if (
            DesktopExperienceFlags.ENABLE_REMOVE_STATUS_BAR_INPUT_LAYER.isTrue &&
                DesktopExperienceFlags.ENABLE_APP_HANDLE_POSITION_REPORTING.isTrue
        ) {
            return
        }
        // If handle is not in status bar region(i.e., bottom stage in vertical split),
        // do not create an input layer
        if (position.y >= SystemBarUtils.getStatusBarHeight(context) || !showInputLayer) {
@@ -270,7 +276,13 @@ class AppHandleViewHolder(
     * visible.
     */
    fun disposeStatusBarInputLayer() {
        if (!statusBarInputLayerExists) return
        if (
            !statusBarInputLayerExists ||
                (DesktopExperienceFlags.ENABLE_REMOVE_STATUS_BAR_INPUT_LAYER.isTrue &&
                    DesktopExperienceFlags.ENABLE_APP_HANDLE_POSITION_REPORTING.isTrue)
        ) {
            return
        }
        statusBarInputLayerExists = false
        statusBarInputLayer?.view?.setOnTouchListener(null)
        handler.post {
+112 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.layout.ui.viewmodel

import android.content.testableContext
import android.graphics.Rect
import android.graphics.Region
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -38,6 +39,7 @@ import com.android.wm.shell.windowdecor.viewholder.AppHandleIdentifier.AppHandle
import com.android.wm.shell.windowdecor.viewholder.AppHandleIdentifier.AppHandleWindowingMode.APP_HANDLE_WINDOWING_MODE_SPLIT_SCREEN
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import kotlin.test.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -173,4 +175,114 @@ class AppHandlesViewModelTest : SysuiTestCase() {

            assertThat(underTest.appHandleBounds).isEmpty()
        }

    @Test
    @DisableFlags(StatusBarAppHandleTracking.FLAG_NAME)
    fun touchableExclusionRegion_emptyIfFlagDisabled() =
        kosmos.runTest {
            val taskId = 10
            val rect = Rect(1, 2, 3, 4)
            fakeAppHandles.setAppHandles(
                mapOf(
                    taskId to
                        AppHandleIdentifier(
                            rect = rect,
                            displayId = testableContext.displayId,
                            taskId = taskId,
                            windowingMode = APP_HANDLE_WINDOWING_MODE_FULLSCREEN,
                        )
                )
            )

            assertThat(underTest.touchableExclusionRegion.isEmpty)
        }

    @Test
    @EnableFlags(StatusBarAppHandleTracking.FLAG_NAME)
    fun touchableExclusionRegion_emptyRegionIfNoAppHandleBoundsReported() =
        kosmos.runTest {
            fakeAppHandles.setAppHandles(emptyMap())
            assertThat(underTest.touchableExclusionRegion.isEmpty)
        }

    @Test
    @EnableFlags(StatusBarAppHandleTracking.FLAG_NAME)
    fun touchableExclusionRegion_regionContainsSingleAppHandleBounds() =
        kosmos.runTest {
            val taskId = 10
            val rect = Rect(1, 2, 3, 4)
            fakeAppHandles.setAppHandles(
                mapOf(
                    taskId to
                        AppHandleIdentifier(
                            rect = rect,
                            displayId = testableContext.displayId,
                            taskId = taskId,
                            windowingMode = APP_HANDLE_WINDOWING_MODE_FULLSCREEN,
                        )
                )
            )

            underTest.touchableExclusionRegion.containsExactly(rect)
        }

    @Test
    @EnableFlags(StatusBarAppHandleTracking.FLAG_NAME)
    fun touchableExclusionRegion_regionContainsMultipleAppHandleBounds() =
        kosmos.runTest {
            val taskId1 = 10
            val rect1 = Rect(1, 2, 3, 4)

            val taskId2 = 20
            val rect2 = Rect(5, 6, 7, 8)
            fakeAppHandles.setAppHandles(
                mapOf(
                    taskId1 to
                        AppHandleIdentifier(
                            rect = rect1,
                            displayId = testableContext.displayId,
                            taskId = taskId1,
                            windowingMode = APP_HANDLE_WINDOWING_MODE_SPLIT_SCREEN,
                        ),
                    taskId2 to
                        AppHandleIdentifier(
                            rect = rect2,
                            displayId = testableContext.displayId,
                            taskId = taskId2,
                            windowingMode = APP_HANDLE_WINDOWING_MODE_SPLIT_SCREEN,
                        ),
                )
            )

            underTest.touchableExclusionRegion.containsExactly(rect1, rect2)
        }

    @Test
    @EnableFlags(StatusBarAppHandleTracking.FLAG_NAME)
    fun touchableExclusionRegion_notForThisDisplay_empty() =
        kosmos.runTest {
            val taskId = 10
            val rect = Rect(1, 2, 3, 4)
            fakeAppHandles.setAppHandles(
                mapOf(
                    taskId to
                        AppHandleIdentifier(
                            rect = rect,
                            displayId = testableContext.displayId + 2,
                            taskId = taskId,
                            windowingMode = APP_HANDLE_WINDOWING_MODE_FULLSCREEN,
                        )
                )
            )

            assertThat(underTest.touchableExclusionRegion.isEmpty)
        }

    /** Checks that region is equal to the union of the given rects. */
    private fun Region.containsExactly(vararg rects: Rect) {
        val intersect = Region.obtain()
        rects.forEach { intersect.op(it, intersect, Region.Op.UNION) }
        assertEquals(intersect, this)
        intersect.recycle()
    }
}
+20 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.layout.ui.viewmodel

import android.graphics.Rect
import android.graphics.Region
import androidx.compose.runtime.getValue
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -36,6 +37,7 @@ import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn

/** View model for on-screen bounds of app handles overlapping with the status bar. */
@@ -76,6 +78,24 @@ constructor(
            source = _appHandleBounds,
        )

    private val _touchableExclusionRegion: Flow<Region> =
        _appHandleBounds.map { appHandles ->
            val exclusionRegion = Region.obtain()
            appHandles.forEach { exclusionRegion.op(it, Region.Op.UNION) }
            exclusionRegion
        }

    /**
     * The on-screen bounds that should be excluded from the status bar's touchable region due to
     * its overlap with app handles.
     */
    val touchableExclusionRegion: Region by
        hydrator.hydratedStateOf(
            traceName = "StatusBar.touchableExclusionRegion",
            initialValue = Region.obtain(),
            source = _touchableExclusionRegion,
        )

    override suspend fun onActivated(): Nothing {
        hydrator.activate()
    }
Loading