Loading packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt→packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerOverlayModule.kt +5 −6 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * Copyright (C) 2025 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. Loading @@ -16,14 +16,13 @@ package com.android.systemui.scene import com.android.systemui.bouncer.ui.composable.BouncerScene import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.bouncer.ui.composable.BouncerOverlay import com.android.systemui.scene.ui.composable.Overlay import dagger.Binds import dagger.Module import dagger.multibindings.IntoSet @Module interface BouncerSceneModule { @Binds @IntoSet fun bouncerScene(scene: BouncerScene): Scene interface BouncerOverlayModule { @Binds @IntoSet fun bouncer(overlay: BouncerOverlay): Overlay } packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +23 −19 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerMessageViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerOverlayContentViewModel import com.android.systemui.bouncer.ui.viewmodel.MessageViewModel import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel Loading @@ -118,7 +118,7 @@ import platform.test.motion.compose.values.motionTestValues @Composable fun BouncerContent( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading @@ -131,8 +131,8 @@ fun BouncerContent( @Composable @VisibleForTesting fun BouncerContent( layout: BouncerSceneLayout, viewModel: BouncerSceneContentViewModel, layout: BouncerOverlayLayout, viewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier, ) { Loading @@ -147,11 +147,12 @@ fun BouncerContent( modifier = modifier.imePadding().onKeyEvent(viewModel::onKeyEvent).scale(scale) ) { when (layout) { BouncerSceneLayout.STANDARD_BOUNCER -> StandardLayout(viewModel = viewModel) BouncerSceneLayout.BESIDE_USER_SWITCHER -> BouncerOverlayLayout.STANDARD_BOUNCER -> StandardLayout(viewModel = viewModel) BouncerOverlayLayout.BESIDE_USER_SWITCHER -> BesideUserSwitcherLayout(viewModel = viewModel) BouncerSceneLayout.BELOW_USER_SWITCHER -> BelowUserSwitcherLayout(viewModel = viewModel) BouncerSceneLayout.SPLIT_BOUNCER -> SplitLayout(viewModel = viewModel) BouncerOverlayLayout.BELOW_USER_SWITCHER -> BelowUserSwitcherLayout(viewModel = viewModel) BouncerOverlayLayout.SPLIT_BOUNCER -> SplitLayout(viewModel = viewModel) } Dialog(bouncerViewModel = viewModel, dialogFactory = dialogFactory) Loading @@ -163,7 +164,10 @@ fun BouncerContent( * authentication attempt, including all messaging UI (directives, reasoning, errors, etc.). */ @Composable private fun StandardLayout(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun StandardLayout( viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier, ) { val isHeightExpanded = LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Expanded Loading Loading @@ -208,7 +212,7 @@ private fun StandardLayout(viewModel: BouncerSceneContentViewModel, modifier: Mo * by double-tapping on the side. */ @Composable private fun SplitLayout(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun SplitLayout(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val authMethod by viewModel.authMethodViewModel.collectAsStateWithLifecycle() Row( Loading Loading @@ -297,7 +301,7 @@ private fun SplitLayout(viewModel: BouncerSceneContentViewModel, modifier: Modif */ @Composable private fun BesideUserSwitcherLayout( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier, ) { val isLeftToRight = LocalLayoutDirection.current == LayoutDirection.Ltr Loading Loading @@ -452,7 +456,7 @@ private fun BesideUserSwitcherLayout( /** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */ @Composable private fun BelowUserSwitcherLayout( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier, ) { Column(modifier = modifier.padding(vertical = 128.dp)) { Loading Loading @@ -483,7 +487,7 @@ private fun BelowUserSwitcherLayout( @Composable private fun FoldAware( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, aboveFold: @Composable BoxScope.() -> Unit, belowFold: @Composable BoxScope.() -> Unit, modifier: Modifier = Modifier, Loading Loading @@ -606,7 +610,7 @@ private fun StatusMessage(viewModel: BouncerMessageViewModel, modifier: Modifier * For example, this can be the PIN shapes or password text field. */ @Composable private fun OutputArea(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun OutputArea(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val authMethodViewModel: AuthMethodBouncerViewModel? by viewModel.authMethodViewModel.collectAsStateWithLifecycle() when (val nonNullViewModel = authMethodViewModel) { Loading @@ -631,7 +635,7 @@ private fun OutputArea(viewModel: BouncerSceneContentViewModel, modifier: Modifi */ @Composable private fun InputArea( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, pinButtonRowVerticalSpacing: Dp, centerPatternDotsVertically: Boolean, modifier: Modifier = Modifier, Loading Loading @@ -659,7 +663,7 @@ private fun InputArea( } @Composable private fun ActionArea(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun ActionArea(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsStateWithLifecycle() val appearFadeInAnimatable = remember { Animatable(0f) } Loading Loading @@ -723,7 +727,7 @@ private fun ActionArea(viewModel: BouncerSceneContentViewModel, modifier: Modifi @Composable private fun Dialog( bouncerViewModel: BouncerSceneContentViewModel, bouncerViewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, ) { val dialogViewModel by bouncerViewModel.dialogViewModel.collectAsStateWithLifecycle() Loading Loading @@ -751,7 +755,7 @@ private fun Dialog( /** Renders the UI of the user switcher that's displayed on large screens next to the bouncer UI. */ @Composable private fun UserSwitcher(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val isUserSwitcherVisible by viewModel.isUserSwitcherVisible.collectAsStateWithLifecycle() if (!isUserSwitcherVisible) { // Take up the same space as the user switcher normally would, but with nothing inside it. Loading Loading @@ -829,7 +833,7 @@ private fun UserSwitcher(viewModel: BouncerSceneContentViewModel, modifier: Modi @Composable private fun UserSwitcherDropdownMenu( isExpanded: Boolean, items: List<BouncerSceneContentViewModel.UserSwitcherDropdownItemViewModel>, items: List<BouncerOverlayContentViewModel.UserSwitcherDropdownItemViewModel>, onDismissed: () -> Unit, ) { val context = LocalContext.current Loading packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt→packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerOverlay.kt +16 −16 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * Copyright (C) 2025 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. Loading Loading @@ -29,19 +29,19 @@ import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerOverlayContentViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.ui.composable.Overlay import javax.inject.Inject import kotlinx.coroutines.flow.Flow object Bouncer { object Elements { val Root = ElementKey("BouncerRoot") val Background = ElementKey("BouncerBackground") val Content = ElementKey("BouncerContent") } Loading @@ -51,16 +51,16 @@ object Bouncer { } } /** The bouncer scene displays authentication challenges like PIN, password, or pattern. */ /** The bouncer overlay displays authentication challenges like PIN, password, or pattern. */ @SysUISingleton class BouncerScene class BouncerOverlay @Inject constructor( private val actionsViewModelFactory: BouncerUserActionsViewModel.Factory, private val contentViewModelFactory: BouncerSceneContentViewModel.Factory, private val contentViewModelFactory: BouncerOverlayContentViewModel.Factory, private val dialogFactory: BouncerDialogFactory, ) : ExclusiveActivatable(), Scene { override val key = Scenes.Bouncer ) : Overlay { override val key = Overlays.Bouncer private val actionsViewModel: BouncerUserActionsViewModel by lazy { actionsViewModelFactory.create() Loading @@ -68,22 +68,22 @@ constructor( override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions override suspend fun onActivated(): Nothing { override suspend fun activate(): Nothing { actionsViewModel.activate() } @Composable override fun ContentScope.Content(modifier: Modifier) = BouncerScene( viewModel = rememberViewModel("BouncerScene") { contentViewModelFactory.create() }, BouncerOverlay( viewModel = rememberViewModel("BouncerOverlay") { contentViewModelFactory.create() }, dialogFactory = dialogFactory, modifier = modifier, modifier = modifier.element(Bouncer.Elements.Root), ) } @Composable private fun ContentScope.BouncerScene( viewModel: BouncerSceneContentViewModel, private fun ContentScope.BouncerOverlay( viewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt→packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerOverlayLayout.kt +15 −15 Original line number Diff line number Diff line Loading @@ -23,12 +23,12 @@ import androidx.compose.runtime.Composable import com.android.compose.windowsizeclass.LocalWindowSizeClass /** * Returns the [BouncerSceneLayout] that should be used by the bouncer scene. If * [isOneHandedModeSupported] is `false`, then [BouncerSceneLayout.BESIDE_USER_SWITCHER] is replaced * by [BouncerSceneLayout.STANDARD_BOUNCER]. * Returns the [BouncerOverlayLayout] that should be used by the bouncer scene. If * [isOneHandedModeSupported] is `false`, then [BouncerOverlayLayout.BESIDE_USER_SWITCHER] is * replaced by [BouncerOverlayLayout.STANDARD_BOUNCER]. */ @Composable fun calculateLayout(isOneHandedModeSupported: Boolean): BouncerSceneLayout { fun calculateLayout(isOneHandedModeSupported: Boolean): BouncerOverlayLayout { val windowSizeClass = LocalWindowSizeClass.current return calculateLayoutInternal( Loading Loading @@ -57,7 +57,7 @@ private fun WindowHeightSizeClass.toEnum(): SizeClass { } /** Enumerates all known adaptive layout configurations. */ enum class BouncerSceneLayout { enum class BouncerOverlayLayout { /** The default UI with the bouncer laid out normally. */ STANDARD_BOUNCER, /** The bouncer is displayed vertically stacked with the user switcher. */ Loading @@ -84,21 +84,21 @@ fun calculateLayoutInternal( width: SizeClass, height: SizeClass, isOneHandedModeSupported: Boolean, ): BouncerSceneLayout { ): BouncerOverlayLayout { return when (height) { SizeClass.COMPACT -> BouncerSceneLayout.SPLIT_BOUNCER SizeClass.COMPACT -> BouncerOverlayLayout.SPLIT_BOUNCER SizeClass.MEDIUM -> when (width) { SizeClass.COMPACT -> BouncerSceneLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerSceneLayout.STANDARD_BOUNCER SizeClass.EXPANDED -> BouncerSceneLayout.BESIDE_USER_SWITCHER SizeClass.COMPACT -> BouncerOverlayLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerOverlayLayout.STANDARD_BOUNCER SizeClass.EXPANDED -> BouncerOverlayLayout.BESIDE_USER_SWITCHER } SizeClass.EXPANDED -> when (width) { SizeClass.COMPACT -> BouncerSceneLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerSceneLayout.BELOW_USER_SWITCHER SizeClass.EXPANDED -> BouncerSceneLayout.BESIDE_USER_SWITCHER SizeClass.COMPACT -> BouncerOverlayLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerOverlayLayout.BELOW_USER_SWITCHER SizeClass.EXPANDED -> BouncerOverlayLayout.BESIDE_USER_SWITCHER } }.takeIf { it != BouncerSceneLayout.BESIDE_USER_SWITCHER || isOneHandedModeSupported } ?: BouncerSceneLayout.STANDARD_BOUNCER }.takeIf { it != BouncerOverlayLayout.BESIDE_USER_SWITCHER || isOneHandedModeSupported } ?: BouncerOverlayLayout.STANDARD_BOUNCER } packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationLockscreenScrim.kt +3 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.content.state.TransitionState import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationLockscreenScrimViewModel Loading Loading @@ -100,7 +101,7 @@ fun ContentScope.NotificationLockscreenScrim( val isBouncerToLockscreen = layoutState.currentTransition?.isTransitioning( from = Scenes.Bouncer, from = Overlays.Bouncer, to = Scenes.Lockscreen, ) ?: false Loading @@ -120,5 +121,5 @@ private fun shouldShowScrimFadeOut( return shadeMode != ShadeMode.Dual && currentTransition.isInitiatedByUserInput && (currentTransition.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) || currentTransition.isTransitioning(from = Scenes.Bouncer, to = Scenes.Lockscreen)) currentTransition.isTransitioning(from = Overlays.Bouncer, to = Scenes.Lockscreen)) } Loading
packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt→packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerOverlayModule.kt +5 −6 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * Copyright (C) 2025 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. Loading @@ -16,14 +16,13 @@ package com.android.systemui.scene import com.android.systemui.bouncer.ui.composable.BouncerScene import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.bouncer.ui.composable.BouncerOverlay import com.android.systemui.scene.ui.composable.Overlay import dagger.Binds import dagger.Module import dagger.multibindings.IntoSet @Module interface BouncerSceneModule { @Binds @IntoSet fun bouncerScene(scene: BouncerScene): Scene interface BouncerOverlayModule { @Binds @IntoSet fun bouncer(overlay: BouncerOverlay): Overlay }
packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +23 −19 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerMessageViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerOverlayContentViewModel import com.android.systemui.bouncer.ui.viewmodel.MessageViewModel import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel Loading @@ -118,7 +118,7 @@ import platform.test.motion.compose.values.motionTestValues @Composable fun BouncerContent( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading @@ -131,8 +131,8 @@ fun BouncerContent( @Composable @VisibleForTesting fun BouncerContent( layout: BouncerSceneLayout, viewModel: BouncerSceneContentViewModel, layout: BouncerOverlayLayout, viewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier, ) { Loading @@ -147,11 +147,12 @@ fun BouncerContent( modifier = modifier.imePadding().onKeyEvent(viewModel::onKeyEvent).scale(scale) ) { when (layout) { BouncerSceneLayout.STANDARD_BOUNCER -> StandardLayout(viewModel = viewModel) BouncerSceneLayout.BESIDE_USER_SWITCHER -> BouncerOverlayLayout.STANDARD_BOUNCER -> StandardLayout(viewModel = viewModel) BouncerOverlayLayout.BESIDE_USER_SWITCHER -> BesideUserSwitcherLayout(viewModel = viewModel) BouncerSceneLayout.BELOW_USER_SWITCHER -> BelowUserSwitcherLayout(viewModel = viewModel) BouncerSceneLayout.SPLIT_BOUNCER -> SplitLayout(viewModel = viewModel) BouncerOverlayLayout.BELOW_USER_SWITCHER -> BelowUserSwitcherLayout(viewModel = viewModel) BouncerOverlayLayout.SPLIT_BOUNCER -> SplitLayout(viewModel = viewModel) } Dialog(bouncerViewModel = viewModel, dialogFactory = dialogFactory) Loading @@ -163,7 +164,10 @@ fun BouncerContent( * authentication attempt, including all messaging UI (directives, reasoning, errors, etc.). */ @Composable private fun StandardLayout(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun StandardLayout( viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier, ) { val isHeightExpanded = LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Expanded Loading Loading @@ -208,7 +212,7 @@ private fun StandardLayout(viewModel: BouncerSceneContentViewModel, modifier: Mo * by double-tapping on the side. */ @Composable private fun SplitLayout(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun SplitLayout(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val authMethod by viewModel.authMethodViewModel.collectAsStateWithLifecycle() Row( Loading Loading @@ -297,7 +301,7 @@ private fun SplitLayout(viewModel: BouncerSceneContentViewModel, modifier: Modif */ @Composable private fun BesideUserSwitcherLayout( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier, ) { val isLeftToRight = LocalLayoutDirection.current == LayoutDirection.Ltr Loading Loading @@ -452,7 +456,7 @@ private fun BesideUserSwitcherLayout( /** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */ @Composable private fun BelowUserSwitcherLayout( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier, ) { Column(modifier = modifier.padding(vertical = 128.dp)) { Loading Loading @@ -483,7 +487,7 @@ private fun BelowUserSwitcherLayout( @Composable private fun FoldAware( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, aboveFold: @Composable BoxScope.() -> Unit, belowFold: @Composable BoxScope.() -> Unit, modifier: Modifier = Modifier, Loading Loading @@ -606,7 +610,7 @@ private fun StatusMessage(viewModel: BouncerMessageViewModel, modifier: Modifier * For example, this can be the PIN shapes or password text field. */ @Composable private fun OutputArea(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun OutputArea(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val authMethodViewModel: AuthMethodBouncerViewModel? by viewModel.authMethodViewModel.collectAsStateWithLifecycle() when (val nonNullViewModel = authMethodViewModel) { Loading @@ -631,7 +635,7 @@ private fun OutputArea(viewModel: BouncerSceneContentViewModel, modifier: Modifi */ @Composable private fun InputArea( viewModel: BouncerSceneContentViewModel, viewModel: BouncerOverlayContentViewModel, pinButtonRowVerticalSpacing: Dp, centerPatternDotsVertically: Boolean, modifier: Modifier = Modifier, Loading Loading @@ -659,7 +663,7 @@ private fun InputArea( } @Composable private fun ActionArea(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun ActionArea(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsStateWithLifecycle() val appearFadeInAnimatable = remember { Animatable(0f) } Loading Loading @@ -723,7 +727,7 @@ private fun ActionArea(viewModel: BouncerSceneContentViewModel, modifier: Modifi @Composable private fun Dialog( bouncerViewModel: BouncerSceneContentViewModel, bouncerViewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, ) { val dialogViewModel by bouncerViewModel.dialogViewModel.collectAsStateWithLifecycle() Loading Loading @@ -751,7 +755,7 @@ private fun Dialog( /** Renders the UI of the user switcher that's displayed on large screens next to the bouncer UI. */ @Composable private fun UserSwitcher(viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier) { private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) { val isUserSwitcherVisible by viewModel.isUserSwitcherVisible.collectAsStateWithLifecycle() if (!isUserSwitcherVisible) { // Take up the same space as the user switcher normally would, but with nothing inside it. Loading Loading @@ -829,7 +833,7 @@ private fun UserSwitcher(viewModel: BouncerSceneContentViewModel, modifier: Modi @Composable private fun UserSwitcherDropdownMenu( isExpanded: Boolean, items: List<BouncerSceneContentViewModel.UserSwitcherDropdownItemViewModel>, items: List<BouncerOverlayContentViewModel.UserSwitcherDropdownItemViewModel>, onDismissed: () -> Unit, ) { val context = LocalContext.current Loading
packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt→packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerOverlay.kt +16 −16 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * Copyright (C) 2025 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. Loading Loading @@ -29,19 +29,19 @@ import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerOverlayContentViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.ui.composable.Overlay import javax.inject.Inject import kotlinx.coroutines.flow.Flow object Bouncer { object Elements { val Root = ElementKey("BouncerRoot") val Background = ElementKey("BouncerBackground") val Content = ElementKey("BouncerContent") } Loading @@ -51,16 +51,16 @@ object Bouncer { } } /** The bouncer scene displays authentication challenges like PIN, password, or pattern. */ /** The bouncer overlay displays authentication challenges like PIN, password, or pattern. */ @SysUISingleton class BouncerScene class BouncerOverlay @Inject constructor( private val actionsViewModelFactory: BouncerUserActionsViewModel.Factory, private val contentViewModelFactory: BouncerSceneContentViewModel.Factory, private val contentViewModelFactory: BouncerOverlayContentViewModel.Factory, private val dialogFactory: BouncerDialogFactory, ) : ExclusiveActivatable(), Scene { override val key = Scenes.Bouncer ) : Overlay { override val key = Overlays.Bouncer private val actionsViewModel: BouncerUserActionsViewModel by lazy { actionsViewModelFactory.create() Loading @@ -68,22 +68,22 @@ constructor( override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions override suspend fun onActivated(): Nothing { override suspend fun activate(): Nothing { actionsViewModel.activate() } @Composable override fun ContentScope.Content(modifier: Modifier) = BouncerScene( viewModel = rememberViewModel("BouncerScene") { contentViewModelFactory.create() }, BouncerOverlay( viewModel = rememberViewModel("BouncerOverlay") { contentViewModelFactory.create() }, dialogFactory = dialogFactory, modifier = modifier, modifier = modifier.element(Bouncer.Elements.Root), ) } @Composable private fun ContentScope.BouncerScene( viewModel: BouncerSceneContentViewModel, private fun ContentScope.BouncerOverlay( viewModel: BouncerOverlayContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading
packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt→packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerOverlayLayout.kt +15 −15 Original line number Diff line number Diff line Loading @@ -23,12 +23,12 @@ import androidx.compose.runtime.Composable import com.android.compose.windowsizeclass.LocalWindowSizeClass /** * Returns the [BouncerSceneLayout] that should be used by the bouncer scene. If * [isOneHandedModeSupported] is `false`, then [BouncerSceneLayout.BESIDE_USER_SWITCHER] is replaced * by [BouncerSceneLayout.STANDARD_BOUNCER]. * Returns the [BouncerOverlayLayout] that should be used by the bouncer scene. If * [isOneHandedModeSupported] is `false`, then [BouncerOverlayLayout.BESIDE_USER_SWITCHER] is * replaced by [BouncerOverlayLayout.STANDARD_BOUNCER]. */ @Composable fun calculateLayout(isOneHandedModeSupported: Boolean): BouncerSceneLayout { fun calculateLayout(isOneHandedModeSupported: Boolean): BouncerOverlayLayout { val windowSizeClass = LocalWindowSizeClass.current return calculateLayoutInternal( Loading Loading @@ -57,7 +57,7 @@ private fun WindowHeightSizeClass.toEnum(): SizeClass { } /** Enumerates all known adaptive layout configurations. */ enum class BouncerSceneLayout { enum class BouncerOverlayLayout { /** The default UI with the bouncer laid out normally. */ STANDARD_BOUNCER, /** The bouncer is displayed vertically stacked with the user switcher. */ Loading @@ -84,21 +84,21 @@ fun calculateLayoutInternal( width: SizeClass, height: SizeClass, isOneHandedModeSupported: Boolean, ): BouncerSceneLayout { ): BouncerOverlayLayout { return when (height) { SizeClass.COMPACT -> BouncerSceneLayout.SPLIT_BOUNCER SizeClass.COMPACT -> BouncerOverlayLayout.SPLIT_BOUNCER SizeClass.MEDIUM -> when (width) { SizeClass.COMPACT -> BouncerSceneLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerSceneLayout.STANDARD_BOUNCER SizeClass.EXPANDED -> BouncerSceneLayout.BESIDE_USER_SWITCHER SizeClass.COMPACT -> BouncerOverlayLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerOverlayLayout.STANDARD_BOUNCER SizeClass.EXPANDED -> BouncerOverlayLayout.BESIDE_USER_SWITCHER } SizeClass.EXPANDED -> when (width) { SizeClass.COMPACT -> BouncerSceneLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerSceneLayout.BELOW_USER_SWITCHER SizeClass.EXPANDED -> BouncerSceneLayout.BESIDE_USER_SWITCHER SizeClass.COMPACT -> BouncerOverlayLayout.STANDARD_BOUNCER SizeClass.MEDIUM -> BouncerOverlayLayout.BELOW_USER_SWITCHER SizeClass.EXPANDED -> BouncerOverlayLayout.BESIDE_USER_SWITCHER } }.takeIf { it != BouncerSceneLayout.BESIDE_USER_SWITCHER || isOneHandedModeSupported } ?: BouncerSceneLayout.STANDARD_BOUNCER }.takeIf { it != BouncerOverlayLayout.BESIDE_USER_SWITCHER || isOneHandedModeSupported } ?: BouncerOverlayLayout.STANDARD_BOUNCER }
packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationLockscreenScrim.kt +3 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.content.state.TransitionState import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationLockscreenScrimViewModel Loading Loading @@ -100,7 +101,7 @@ fun ContentScope.NotificationLockscreenScrim( val isBouncerToLockscreen = layoutState.currentTransition?.isTransitioning( from = Scenes.Bouncer, from = Overlays.Bouncer, to = Scenes.Lockscreen, ) ?: false Loading @@ -120,5 +121,5 @@ private fun shouldShowScrimFadeOut( return shadeMode != ShadeMode.Dual && currentTransition.isInitiatedByUserInput && (currentTransition.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) || currentTransition.isTransitioning(from = Scenes.Bouncer, to = Scenes.Lockscreen)) currentTransition.isTransitioning(from = Overlays.Bouncer, to = Scenes.Lockscreen)) }