summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alejandro Nijamkin <nijamkin@google.com> 2023-11-07 07:07:21 -0800
committer Alejandro Nijamkin <nijamkin@google.com> 2023-11-09 10:16:44 -0800
commitda276c76890051185a3f3a515d1b4ef15328faef (patch)
tree578231601664d9607fbf8f5d5f37e7c8e76254e3
parent0849504665dcb45271e5055b6a2f4d4c417e5e28 (diff)
[flexiglass] Password bouncer isn't side-by-side on unfolded.
When the auth method is password and a foldable device is unfolded, the chosen layout is the standard layout and not the side-by-side layout. Bug: 304630105 Test: please see comment #6 on the attached bug Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT Change-Id: Ie15da0f615db18e46b1f1df81d4780b9c7159c72
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt24
5 files changed, 66 insertions, 7 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index defaa20a84c7..4400786fe9c3 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -142,7 +142,11 @@ private fun SceneScope.BouncerScene(
modifier: Modifier = Modifier,
) {
val backgroundColor = MaterialTheme.colorScheme.surface
- val layout = calculateLayout()
+ val isSideBySideSupported by viewModel.isSideBySideSupported.collectAsState()
+ val layout =
+ calculateLayout(
+ isSideBySideSupported = isSideBySideSupported,
+ )
Box(modifier) {
Canvas(Modifier.element(Bouncer.Elements.Background).fillMaxSize()) {
@@ -567,6 +571,11 @@ private fun SwappableLayout(
/**
* Arranges the bouncer contents and user switcher contents side-by-side, supporting a double tap
* anywhere on the background to flip their positions.
+ *
+ * In situations when [isUserSwitcherVisible] is `false`, one of two things may happen: either the
+ * UI for the bouncer will be shown on its own, taking up one side, with the other side just being
+ * empty space or, if that kind of "stand-alone side-by-side" isn't supported, the standard
+ * rendering of the bouncer will be used instead of the side-by-side layout.
*/
@Composable
private fun SideBySide(
@@ -628,7 +637,9 @@ private fun Stacked(
}
@Composable
-private fun calculateLayout(): Layout {
+private fun calculateLayout(
+ isSideBySideSupported: Boolean,
+): Layout {
val windowSizeClass = LocalWindowSizeClass.current
val width = windowSizeClass.widthSizeClass
val height = windowSizeClass.heightSizeClass
@@ -657,7 +668,7 @@ private fun calculateLayout(): Layout {
// Large and tall devices (i.e. tablet in portrait).
isTall -> Layout.STACKED
// Large and wide/square devices (i.e. tablet in landscape, unfolded).
- else -> Layout.SIDE_BY_SIDE
+ else -> if (isSideBySideSupported) Layout.SIDE_BY_SIDE else Layout.STANDARD
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt
index b2a7607cb323..7265c0c1cb94 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/BouncerRepository.kt
@@ -29,14 +29,15 @@ import kotlinx.coroutines.flow.asStateFlow
class BouncerRepository
@Inject
constructor(
- flags: FeatureFlagsClassic,
+ private val flags: FeatureFlagsClassic,
) {
private val _message = MutableStateFlow<String?>(null)
/** The user-facing message to show in the bouncer. */
val message: StateFlow<String?> = _message.asStateFlow()
/** Whether the user switcher should be displayed within the bouncer UI on large screens. */
- val isUserSwitcherVisible: Boolean = flags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)
+ val isUserSwitcherVisible: Boolean
+ get() = flags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)
fun setMessage(message: String?) {
_message.value = message
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index 4ce1422b91e8..b9a913ea866f 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -97,7 +97,8 @@ constructor(
val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible
/** Whether the user switcher should be displayed within the bouncer UI on large screens. */
- val isUserSwitcherVisible: Boolean = repository.isUserSwitcherVisible
+ val isUserSwitcherVisible: Boolean
+ get() = repository.isUserSwitcherVisible
init {
if (flags.isEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 0f7772454b78..73d15f0f369b 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -100,7 +100,8 @@ class BouncerViewModel(
initialValue = emptyList(),
)
- val isUserSwitcherVisible: Boolean = bouncerInteractor.isUserSwitcherVisible
+ val isUserSwitcherVisible: Boolean
+ get() = bouncerInteractor.isUserSwitcherVisible
private val isInputEnabled: StateFlow<Boolean> =
bouncerInteractor.isThrottled
@@ -162,6 +163,23 @@ class BouncerViewModel(
initialValue = null
)
+ /**
+ * Whether the "side-by-side" layout is supported.
+ *
+ * When presented on its own, without a user switcher (e.g. not on communal devices like
+ * tablets, for example), some authentication method UIs don't do well if they're shown in the
+ * side-by-side layout; these need to be shown with the standard layout so they can take up as
+ * much width as possible.
+ */
+ val isSideBySideSupported: StateFlow<Boolean> =
+ authMethodViewModel
+ .map { authMethod -> isSideBySideSupported(authMethod) }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = isSideBySideSupported(authMethodViewModel.value),
+ )
+
init {
if (flags.isEnabled()) {
applicationScope.launch {
@@ -190,6 +208,10 @@ class BouncerViewModel(
_throttlingDialogMessage.value = null
}
+ private fun isSideBySideSupported(authMethod: AuthMethodBouncerViewModel?): Boolean {
+ return isUserSwitcherVisible || authMethod !is PasswordBouncerViewModel
+ }
+
private fun toMessageViewModel(
message: String?,
isThrottled: Boolean,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index c159b66c10a0..6ef518e3ab51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -20,9 +20,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
+import com.android.systemui.authentication.data.model.AuthenticationMethodModel
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.Flags
import com.android.systemui.scene.SceneTestUtils
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
@@ -202,6 +204,28 @@ class BouncerViewModelTest : SysuiTestCase() {
assertThat(throttlingDialogMessage).isNull()
}
+ @Test
+ fun isSideBySideSupported() =
+ testScope.runTest {
+ val isSideBySideSupported by collectLastValue(underTest.isSideBySideSupported)
+ utils.featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+ assertThat(isSideBySideSupported).isTrue()
+ utils.authenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Password
+ )
+ assertThat(isSideBySideSupported).isTrue()
+
+ utils.featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+ assertThat(isSideBySideSupported).isTrue()
+
+ utils.authenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Password
+ )
+ assertThat(isSideBySideSupported).isFalse()
+ }
+
private fun authMethodsToTest(): List<DomainLayerAuthenticationMethodModel> {
return listOf(
DomainLayerAuthenticationMethodModel.None,