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

Commit 67784971 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Fixes back navigation.

Turns out that back navigation was implemented correctly, but the
EdgeBackGestureHandler required the SysUiState to be in certain states
to make the arrow and gesture enabled.

This CL achieves that.

Fix: 289515848
Test: manually verified that back works in the bouncer scene in
Flexiglass

Change-Id: I72b657afc9484569f7883c0a23ec2891a7abeff9
parent a3a8f22a
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.model

import com.android.systemui.dagger.qualifiers.DisplayId

/**
 * In-bulk updates multiple flag values and commits the update.
 *
 * Example:
 * ```
 * sysuiState.updateFlags(
 *     displayId,
 *     SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE to (sceneKey != SceneKey.Gone),
 *     SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED to (sceneKey == SceneKey.Shade),
 *     SYSUI_STATE_QUICK_SETTINGS_EXPANDED to (sceneKey == SceneKey.QuickSettings),
 *     SYSUI_STATE_BOUNCER_SHOWING to (sceneKey == SceneKey.Bouncer),
 *     SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING to (sceneKey == SceneKey.Lockscreen),
 * )
 * ```
 *
 * You can inject [displayId] by injecting it using:
 * ```
 *     @DisplayId private val displayId: Int`,
 * ```
 */
fun SysUiState.updateFlags(
    @DisplayId displayId: Int,
    vararg flagValuePairs: Pair<Int, Boolean>,
) {
    flagValuePairs.forEach { (flag, enabled) -> setFlag(flag, enabled) }
    commitUpdate(displayId)
}
+32 −0
Original line number Diff line number Diff line
@@ -20,14 +20,22 @@ import com.android.systemui.CoreStartable
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.DisplayId
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -49,12 +57,15 @@ constructor(
    private val authenticationInteractor: AuthenticationInteractor,
    private val keyguardInteractor: KeyguardInteractor,
    private val featureFlags: FeatureFlags,
    private val sysUiState: SysUiState,
    @DisplayId private val displayId: Int,
) : CoreStartable {

    override fun start() {
        if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
            hydrateVisibility()
            automaticallySwitchScenes()
            hydrateSystemUiState()
        }
    }

@@ -121,6 +132,27 @@ constructor(
        }
    }

    /** Keeps [SysUiState] up-to-date */
    private fun hydrateSystemUiState() {
        applicationScope.launch {
            sceneInteractor
                .currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT)
                .map { it.key }
                .distinctUntilChanged()
                .collect { sceneKey ->
                    sysUiState.updateFlags(
                        displayId,
                        SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE to (sceneKey != SceneKey.Gone),
                        SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED to (sceneKey == SceneKey.Shade),
                        SYSUI_STATE_QUICK_SETTINGS_EXPANDED to (sceneKey == SceneKey.QuickSettings),
                        SYSUI_STATE_BOUNCER_SHOWING to (sceneKey == SceneKey.Bouncer),
                        SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING to
                            (sceneKey == SceneKey.Lockscreen),
                    )
                }
        }
    }

    private fun switchToScene(targetSceneKey: SceneKey) {
        sceneInteractor.setCurrentScene(
            containerName = CONTAINER_NAME,
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.model

import android.view.Display
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeDisplayTracker
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@SmallTest
@RunWith(JUnit4::class)
class SysUiStateExtTest : SysuiTestCase() {

    private val underTest = SysUiState(FakeDisplayTracker(context))

    @Test
    fun updateFlags() {
        underTest.updateFlags(
            Display.DEFAULT_DISPLAY,
            1 to true,
            2 to false,
            3 to true,
        )

        assertThat(underTest.flags and 1).isNotEqualTo(0)
        assertThat(underTest.flags and 2).isEqualTo(0)
        assertThat(underTest.flags and 3).isNotEqualTo(0)
    }
}
+38 −0
Original line number Diff line number Diff line
@@ -14,8 +14,11 @@
 * limitations under the License.
 */

@file:OptIn(ExperimentalCoroutinesApi::class)

package com.android.systemui.scene.domain.startable

import android.view.Display
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -23,17 +26,24 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.times
import org.mockito.Mockito.verify

@SmallTest
@RunWith(JUnit4::class)
@@ -53,6 +63,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
        utils.keyguardInteractor(
            repository = keyguardRepository,
        )
    private val sysUiState: SysUiState = mock()

    private val underTest =
        SystemUiDefaultSceneContainerStartable(
@@ -61,6 +72,8 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
            authenticationInteractor = authenticationInteractor,
            keyguardInteractor = keyguardInteractor,
            featureFlags = featureFlags,
            sysUiState = sysUiState,
            displayId = Display.DEFAULT_DISPLAY,
        )

    @Before
@@ -375,6 +388,31 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
            assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
        }

    @Test
    fun hydrateSystemUiState() =
        testScope.runTest {
            underTest.start()
            runCurrent()
            clearInvocations(sysUiState)

            listOf(
                    SceneKey.Gone,
                    SceneKey.Lockscreen,
                    SceneKey.Bouncer,
                    SceneKey.Shade,
                    SceneKey.QuickSettings,
                )
                .forEachIndexed { index, sceneKey ->
                    sceneInteractor.setCurrentScene(
                        SceneContainerNames.SYSTEM_UI_DEFAULT,
                        SceneModel(sceneKey),
                    )
                    runCurrent()

                    verify(sysUiState, times(index + 1)).commitUpdate(Display.DEFAULT_DISPLAY)
                }
        }

    private fun prepareState(
        isFeatureEnabled: Boolean = true,
        isDeviceUnlocked: Boolean = false,