Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +1 −14 Original line number Diff line number Diff line Loading @@ -40,10 +40,10 @@ import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.statusbar.CommandQueue import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged Loading @@ -53,7 +53,6 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart import javax.inject.Inject /** * Encapsulates business-logic related to the keyguard but not to a more specific part within it. Loading @@ -68,18 +67,6 @@ constructor( bouncerRepository: KeyguardBouncerRepository, configurationRepository: ConfigurationRepository, ) { data class PreviewMode( val isInPreviewMode: Boolean = false, val shouldHighlightSelectedAffordance: Boolean = false, ) /** * Whether this view-model instance is powering the preview experience that renders exclusively * in the wallpaper picker application. This should _always_ be `false` for the real lock screen * experience. */ val previewMode = MutableStateFlow(PreviewMode()) /** * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at * all. Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +49 −22 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder import com.android.systemui.keyguard.ui.view.KeyguardRootView import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel Loading @@ -56,25 +57,31 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel import com.android.systemui.monet.ColorScheme import com.android.systemui.plugins.ClockController import com.android.systemui.plugins.FalsingManager import com.android.systemui.shared.clocks.ClockRegistry import com.android.systemui.shared.clocks.DefaultClockController import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController import com.android.systemui.statusbar.phone.KeyguardBottomAreaView import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator import dagger.assisted.Assisted import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking /** Renders the preview of the lock screen. */ class KeyguardPreviewRenderer @OptIn(ExperimentalCoroutinesApi::class) @AssistedInject constructor( @Application private val context: Context, Loading @@ -99,6 +106,9 @@ constructor( @Assisted bundle: Bundle, private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel, private val keyguardBlueprintInteractor: KeyguardBlueprintInteractor, private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel, private val chipbarCoordinator: ChipbarCoordinator, private val keyguardStateController: KeyguardStateController, ) { val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN) Loading Loading @@ -130,11 +140,13 @@ constructor( init { if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) { keyguardRootViewModel.enablePreviewMode( keyguardRootViewModel.enablePreviewMode() quickAffordancesCombinedViewModel.enablePreviewMode( initiallySelectedSlotId = bundle.getString( KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID, ), ) ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance, ) } else { Loading Loading @@ -163,17 +175,8 @@ constructor( val rootView = FrameLayout(context) if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) { val keyguardRootView = KeyguardRootView(context, null) rootView.addView( keyguardRootView, FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, ), ) setupShortcuts(keyguardRootView) KeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) keyguardBlueprintInteractor.refreshBlueprint() setupKeyguardRootView(rootView) setupShortcuts(rootView) } else { setUpBottomArea(rootView) } Loading Loading @@ -325,10 +328,34 @@ constructor( ) } private fun setupShortcuts(keyguardRootView: KeyguardRootView) { @OptIn(ExperimentalCoroutinesApi::class) private fun setupKeyguardRootView(rootView: FrameLayout) { val keyguardRootView = KeyguardRootView(context, null) disposables.add( KeyguardRootViewBinder.bind( keyguardRootView, keyguardRootViewModel, featureFlags, occludingAppDeviceEntryMessageViewModel, chipbarCoordinator, keyguardStateController, ) ) rootView.addView( keyguardRootView, FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, ), ) KeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) keyguardBlueprintInteractor.refreshBlueprint() } private fun setupShortcuts(rootView: FrameLayout) { shortcutsBindings.add( KeyguardQuickAffordanceViewBinder.bind( keyguardRootView.requireViewById(R.id.start_button), rootView.requireViewById(R.id.start_button), quickAffordancesCombinedViewModel.startButton, keyguardRootViewModel.alpha, falsingManager, Loading @@ -340,7 +367,7 @@ constructor( shortcutsBindings.add( KeyguardQuickAffordanceViewBinder.bind( keyguardRootView.requireViewById(R.id.end_button), rootView.requireViewById(R.id.end_button), quickAffordancesCombinedViewModel.endButton, keyguardRootViewModel.alpha, falsingManager, Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt +68 −36 Original line number Diff line number Diff line Loading @@ -18,22 +18,20 @@ package com.android.systemui.keyguard.ui.viewmodel import androidx.annotation.VisibleForTesting import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import javax.inject.Inject @OptIn(ExperimentalCoroutinesApi::class) class KeyguardQuickAffordancesCombinedViewModel Loading @@ -43,6 +41,18 @@ constructor( private val keyguardInteractor: KeyguardInteractor, ) { data class PreviewMode( val isInPreviewMode: Boolean = false, val shouldHighlightSelectedAffordance: Boolean = false, ) /** * Whether this view-model instance is powering the preview experience that renders exclusively * in the wallpaper picker application. This should _always_ be `false` for the real lock screen * experience. */ private val previewMode = MutableStateFlow(PreviewMode()) /** * ID of the slot that's currently selected in the preview that renders exclusively in the * wallpaper picker application. This is ignored for the actual, real lock screen experience. Loading Loading @@ -85,10 +95,34 @@ constructor( selectedPreviewSlotId.value = slotId } /** * Puts this view-model in "preview mode", which means it's being used for UI that is rendering * the lock screen preview in wallpaper picker / settings and not the real experience on the * lock screen. * * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one. * @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be * highlighted (while all others are dimmed to make the selected one stand out). */ fun enablePreviewMode( initiallySelectedSlotId: String?, shouldHighlightSelectedAffordance: Boolean, ) { val newPreviewMode = PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance, ) onPreviewSlotSelected( initiallySelectedSlotId ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) previewMode.value = newPreviewMode } private fun button( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceViewModel> { return keyguardInteractor.previewMode.flatMapLatest { previewMode -> return previewMode.flatMapLatest { previewMode -> combine( if (previewMode.isInPreviewMode) { quickAffordanceInteractor.quickAffordanceAlwaysVisible(position = position) Loading Loading @@ -167,8 +201,6 @@ constructor( // time, we don't want the number to be too close to 1.0 such that there is a chance that we // never treat the affordance UI as "fully opaque" as that would risk making it forever not // clickable. @VisibleForTesting const val AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD = 0.95f @VisibleForTesting const val AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD = 0.95f } } packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +18 −24 Original line number Diff line number Diff line Loading @@ -19,29 +19,37 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import javax.inject.Inject @OptIn(ExperimentalCoroutinesApi::class) class KeyguardRootViewModel @Inject constructor( private val keyguardInteractor: KeyguardInteractor, private val keyguardQuickAffordancesCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel ) { ) { data class PreviewMode(val isInPreviewMode: Boolean = false) /** * Whether this view-model instance is powering the preview experience that renders exclusively * in the wallpaper picker application. This should _always_ be `false` for the real lock screen * experience. */ private val previewMode = MutableStateFlow(PreviewMode()) /** Represents the current state of the KeyguardRootView visibility */ val keyguardRootViewVisibilityState: Flow<KeyguardRootViewVisibilityState> = keyguardInteractor.keyguardRootViewVisibilityState /** An observable for the alpha level for the entire keyguard root view. */ val alpha: Flow<Float> = keyguardInteractor.previewMode.flatMapLatest { previewMode.flatMapLatest { if (it.isInPreviewMode) { flowOf(1f) } else { Loading @@ -53,23 +61,9 @@ constructor( * Puts this view-model in "preview mode", which means it's being used for UI that is rendering * the lock screen preview in wallpaper picker / settings and not the real experience on the * lock screen. * * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one. * @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be * highlighted (while all others are dimmed to make the selected one stand out). */ fun enablePreviewMode( initiallySelectedSlotId: String?, shouldHighlightSelectedAffordance: Boolean, ) { keyguardInteractor.previewMode.value = KeyguardInteractor.PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance, ) keyguardQuickAffordancesCombinedViewModel.onPreviewSlotSelected( initiallySelectedSlotId ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) fun enablePreviewMode() { val newPreviewMode = PreviewMode(true) previewMode.value = newPreviewMode } } packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt +2 −10 Original line number Diff line number Diff line Loading @@ -281,11 +281,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { underTest.onPreviewSlotSelected( KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) keyguardInteractor.previewMode.value = KeyguardInteractor.PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = true, ) underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true) repository.setKeyguardShowing(false) val latest = collectLastValue(underTest.startButton) Loading Loading @@ -330,11 +326,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { underTest.onPreviewSlotSelected( KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) keyguardInteractor.previewMode.value = KeyguardInteractor.PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = true, ) underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true) repository.setKeyguardShowing(false) val endButton = collectLastValue(underTest.endButton) Loading Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +1 −14 Original line number Diff line number Diff line Loading @@ -40,10 +40,10 @@ import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.statusbar.CommandQueue import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged Loading @@ -53,7 +53,6 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart import javax.inject.Inject /** * Encapsulates business-logic related to the keyguard but not to a more specific part within it. Loading @@ -68,18 +67,6 @@ constructor( bouncerRepository: KeyguardBouncerRepository, configurationRepository: ConfigurationRepository, ) { data class PreviewMode( val isInPreviewMode: Boolean = false, val shouldHighlightSelectedAffordance: Boolean = false, ) /** * Whether this view-model instance is powering the preview experience that renders exclusively * in the wallpaper picker application. This should _always_ be `false` for the real lock screen * experience. */ val previewMode = MutableStateFlow(PreviewMode()) /** * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at * all. Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +49 −22 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder import com.android.systemui.keyguard.ui.view.KeyguardRootView import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel Loading @@ -56,25 +57,31 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel import com.android.systemui.monet.ColorScheme import com.android.systemui.plugins.ClockController import com.android.systemui.plugins.FalsingManager import com.android.systemui.shared.clocks.ClockRegistry import com.android.systemui.shared.clocks.DefaultClockController import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants import com.android.systemui.statusbar.KeyguardIndicationController import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController import com.android.systemui.statusbar.phone.KeyguardBottomAreaView import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator import dagger.assisted.Assisted import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking /** Renders the preview of the lock screen. */ class KeyguardPreviewRenderer @OptIn(ExperimentalCoroutinesApi::class) @AssistedInject constructor( @Application private val context: Context, Loading @@ -99,6 +106,9 @@ constructor( @Assisted bundle: Bundle, private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel, private val keyguardBlueprintInteractor: KeyguardBlueprintInteractor, private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel, private val chipbarCoordinator: ChipbarCoordinator, private val keyguardStateController: KeyguardStateController, ) { val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN) Loading Loading @@ -130,11 +140,13 @@ constructor( init { if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) { keyguardRootViewModel.enablePreviewMode( keyguardRootViewModel.enablePreviewMode() quickAffordancesCombinedViewModel.enablePreviewMode( initiallySelectedSlotId = bundle.getString( KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID, ), ) ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance, ) } else { Loading Loading @@ -163,17 +175,8 @@ constructor( val rootView = FrameLayout(context) if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) { val keyguardRootView = KeyguardRootView(context, null) rootView.addView( keyguardRootView, FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, ), ) setupShortcuts(keyguardRootView) KeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) keyguardBlueprintInteractor.refreshBlueprint() setupKeyguardRootView(rootView) setupShortcuts(rootView) } else { setUpBottomArea(rootView) } Loading Loading @@ -325,10 +328,34 @@ constructor( ) } private fun setupShortcuts(keyguardRootView: KeyguardRootView) { @OptIn(ExperimentalCoroutinesApi::class) private fun setupKeyguardRootView(rootView: FrameLayout) { val keyguardRootView = KeyguardRootView(context, null) disposables.add( KeyguardRootViewBinder.bind( keyguardRootView, keyguardRootViewModel, featureFlags, occludingAppDeviceEntryMessageViewModel, chipbarCoordinator, keyguardStateController, ) ) rootView.addView( keyguardRootView, FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, ), ) KeyguardBlueprintViewBinder.bind(keyguardRootView, keyguardBlueprintViewModel) keyguardBlueprintInteractor.refreshBlueprint() } private fun setupShortcuts(rootView: FrameLayout) { shortcutsBindings.add( KeyguardQuickAffordanceViewBinder.bind( keyguardRootView.requireViewById(R.id.start_button), rootView.requireViewById(R.id.start_button), quickAffordancesCombinedViewModel.startButton, keyguardRootViewModel.alpha, falsingManager, Loading @@ -340,7 +367,7 @@ constructor( shortcutsBindings.add( KeyguardQuickAffordanceViewBinder.bind( keyguardRootView.requireViewById(R.id.end_button), rootView.requireViewById(R.id.end_button), quickAffordancesCombinedViewModel.endButton, keyguardRootViewModel.alpha, falsingManager, Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt +68 −36 Original line number Diff line number Diff line Loading @@ -18,22 +18,20 @@ package com.android.systemui.keyguard.ui.viewmodel import androidx.annotation.VisibleForTesting import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import javax.inject.Inject @OptIn(ExperimentalCoroutinesApi::class) class KeyguardQuickAffordancesCombinedViewModel Loading @@ -43,6 +41,18 @@ constructor( private val keyguardInteractor: KeyguardInteractor, ) { data class PreviewMode( val isInPreviewMode: Boolean = false, val shouldHighlightSelectedAffordance: Boolean = false, ) /** * Whether this view-model instance is powering the preview experience that renders exclusively * in the wallpaper picker application. This should _always_ be `false` for the real lock screen * experience. */ private val previewMode = MutableStateFlow(PreviewMode()) /** * ID of the slot that's currently selected in the preview that renders exclusively in the * wallpaper picker application. This is ignored for the actual, real lock screen experience. Loading Loading @@ -85,10 +95,34 @@ constructor( selectedPreviewSlotId.value = slotId } /** * Puts this view-model in "preview mode", which means it's being used for UI that is rendering * the lock screen preview in wallpaper picker / settings and not the real experience on the * lock screen. * * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one. * @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be * highlighted (while all others are dimmed to make the selected one stand out). */ fun enablePreviewMode( initiallySelectedSlotId: String?, shouldHighlightSelectedAffordance: Boolean, ) { val newPreviewMode = PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance, ) onPreviewSlotSelected( initiallySelectedSlotId ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) previewMode.value = newPreviewMode } private fun button( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceViewModel> { return keyguardInteractor.previewMode.flatMapLatest { previewMode -> return previewMode.flatMapLatest { previewMode -> combine( if (previewMode.isInPreviewMode) { quickAffordanceInteractor.quickAffordanceAlwaysVisible(position = position) Loading Loading @@ -167,8 +201,6 @@ constructor( // time, we don't want the number to be too close to 1.0 such that there is a chance that we // never treat the affordance UI as "fully opaque" as that would risk making it forever not // clickable. @VisibleForTesting const val AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD = 0.95f @VisibleForTesting const val AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD = 0.95f } }
packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +18 −24 Original line number Diff line number Diff line Loading @@ -19,29 +19,37 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import javax.inject.Inject @OptIn(ExperimentalCoroutinesApi::class) class KeyguardRootViewModel @Inject constructor( private val keyguardInteractor: KeyguardInteractor, private val keyguardQuickAffordancesCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel ) { ) { data class PreviewMode(val isInPreviewMode: Boolean = false) /** * Whether this view-model instance is powering the preview experience that renders exclusively * in the wallpaper picker application. This should _always_ be `false` for the real lock screen * experience. */ private val previewMode = MutableStateFlow(PreviewMode()) /** Represents the current state of the KeyguardRootView visibility */ val keyguardRootViewVisibilityState: Flow<KeyguardRootViewVisibilityState> = keyguardInteractor.keyguardRootViewVisibilityState /** An observable for the alpha level for the entire keyguard root view. */ val alpha: Flow<Float> = keyguardInteractor.previewMode.flatMapLatest { previewMode.flatMapLatest { if (it.isInPreviewMode) { flowOf(1f) } else { Loading @@ -53,23 +61,9 @@ constructor( * Puts this view-model in "preview mode", which means it's being used for UI that is rendering * the lock screen preview in wallpaper picker / settings and not the real experience on the * lock screen. * * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one. * @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be * highlighted (while all others are dimmed to make the selected one stand out). */ fun enablePreviewMode( initiallySelectedSlotId: String?, shouldHighlightSelectedAffordance: Boolean, ) { keyguardInteractor.previewMode.value = KeyguardInteractor.PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance, ) keyguardQuickAffordancesCombinedViewModel.onPreviewSlotSelected( initiallySelectedSlotId ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) fun enablePreviewMode() { val newPreviewMode = PreviewMode(true) previewMode.value = newPreviewMode } }
packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt +2 −10 Original line number Diff line number Diff line Loading @@ -281,11 +281,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { underTest.onPreviewSlotSelected( KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) keyguardInteractor.previewMode.value = KeyguardInteractor.PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = true, ) underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true) repository.setKeyguardShowing(false) val latest = collectLastValue(underTest.startButton) Loading Loading @@ -330,11 +326,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { underTest.onPreviewSlotSelected( KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ) keyguardInteractor.previewMode.value = KeyguardInteractor.PreviewMode( isInPreviewMode = true, shouldHighlightSelectedAffordance = true, ) underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true) repository.setKeyguardShowing(false) val endButton = collectLastValue(underTest.endButton) Loading