[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
This commit is contained in:
Alejandro Nijamkin
2023-07-20 14:26:27 -07:00
parent a3a8f22a29
commit 67784971aa
4 changed files with 164 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
/*
* 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)
}

View File

@@ -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,

View File

@@ -0,0 +1,47 @@
/*
* 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)
}
}

View File

@@ -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,