diff options
20 files changed, 316 insertions, 194 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 5fbffbed7965..c23a49c68363 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -208,6 +208,13 @@ flag { } flag { + name: "compose_bouncer" + namespace: "systemui" + description: "Use the new compose bouncer in SystemUI" + bug: "310005730" +} + +flag { name: "media_in_scene_container" namespace: "systemui" description: "Enable media in the scene container framework" diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt index fd04b5ee0d9c..f4ffb3c66219 100644 --- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt +++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt @@ -22,6 +22,8 @@ import android.view.View import android.view.WindowInsets import androidx.activity.ComponentActivity import androidx.lifecycle.LifecycleOwner +import com.android.systemui.bouncer.ui.BouncerDialogFactory +import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.people.ui.viewmodel.PeopleViewModel import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel @@ -85,6 +87,12 @@ object ComposeFacade : BaseComposeFacade { throwComposeUnavailableError() } + override fun createBouncer( + context: Context, + viewModel: BouncerViewModel, + dialogFactory: BouncerDialogFactory, + ): View = throwComposeUnavailableError() + private fun throwComposeUnavailableError(): Nothing { error( "Compose is not available. Make sure to check isComposeAvailable() before calling any" + diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt index d31547bd0d64..43745f9bf027 100644 --- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt +++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt @@ -28,6 +28,9 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.LifecycleOwner import com.android.compose.theme.PlatformTheme import com.android.compose.ui.platform.DensityAwareComposeView +import com.android.systemui.bouncer.ui.BouncerDialogFactory +import com.android.systemui.bouncer.ui.composable.BouncerContent +import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation import com.android.systemui.common.ui.compose.windowinsets.DisplayCutout import com.android.systemui.common.ui.compose.windowinsets.DisplayCutoutProvider @@ -171,4 +174,14 @@ object ComposeFacade : BaseComposeFacade { private fun Int.toDp(context: Context): Dp { return (this.toFloat() / context.resources.displayMetrics.density).dp } + + override fun createBouncer( + context: Context, + viewModel: BouncerViewModel, + dialogFactory: BouncerDialogFactory, + ): View { + return ComposeView(context).apply { + setContent { PlatformTheme { BouncerContent(viewModel, dialogFactory) } } + } + } } diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt index 1860c9f1656e..2b1268e40f00 100644 --- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt +++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt @@ -16,34 +16,14 @@ package com.android.systemui.scene -import android.app.AlertDialog -import android.content.Context -import com.android.systemui.bouncer.ui.composable.BouncerDialogFactory import com.android.systemui.bouncer.ui.composable.BouncerScene -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.scene.shared.model.Scene -import com.android.systemui.statusbar.phone.SystemUIDialog import dagger.Binds import dagger.Module -import dagger.Provides import dagger.multibindings.IntoSet @Module interface BouncerSceneModule { @Binds @IntoSet fun bouncerScene(scene: BouncerScene): Scene - - companion object { - - @Provides - @SysUISingleton - fun bouncerSceneDialogFactory(@Application context: Context): BouncerDialogFactory { - return object : BouncerDialogFactory { - override fun invoke(): AlertDialog { - return SystemUIDialog(context) - } - } - } - } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt index 6591543f44fe..d9493961e3ed 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt @@ -81,6 +81,7 @@ import com.android.compose.animation.scene.transitions import com.android.compose.modifiers.thenIf import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel +import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel @@ -824,10 +825,6 @@ private fun UserSwitcherDropdownMenu( } } -interface BouncerDialogFactory { - operator fun invoke(): AlertDialog -} - /** * Calculates an alpha for the user switcher and bouncer such that it's at `1` when the offset of * the two reaches a stopping point but `0` in the middle of the transition. 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 d638ffe11abe..428bc39c7632 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 @@ -24,6 +24,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneScope +import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.scene.shared.model.Direction diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt index ee46f76a94e4..63f6c2033ee1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt @@ -16,10 +16,10 @@ package com.android.systemui.bouncer.domain.interactor -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.testing.TestableResources import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor @@ -60,7 +60,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWithLooper(setAsMainLooper = true) -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class PrimaryBouncerInteractorTest : SysuiTestCase() { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var repository: KeyguardBouncerRepository diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt index c2a1d8fe26c3..d0ff1858a1c9 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt @@ -20,6 +20,7 @@ import android.os.Build import android.util.Log import com.android.systemui.biometrics.shared.SideFpsControllerRefactor import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN +import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -90,6 +91,9 @@ interface KeyguardBouncerRepository { val alternateBouncerUIAvailable: StateFlow<Boolean> val sideFpsShowing: StateFlow<Boolean> + /** Action that should be run right after the bouncer is dismissed. */ + var bouncerDismissActionModel: BouncerDismissActionModel? + var lastAlternateBouncerVisibleTime: Long fun setPrimaryScrimmed(isScrimmed: Boolean) @@ -134,6 +138,8 @@ constructor( @Application private val applicationScope: CoroutineScope, @BouncerTableLog private val buffer: TableLogBuffer, ) : KeyguardBouncerRepository { + override var bouncerDismissActionModel: BouncerDismissActionModel? = null + /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */ private val _primaryBouncerShow = MutableStateFlow(false) override val primaryBouncerShow = _primaryBouncerShow.asStateFlow() diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt index 654fa220d491..8c87b0c78ea7 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt @@ -28,10 +28,12 @@ import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.DejankUtils +import com.android.systemui.Flags import com.android.systemui.biometrics.shared.SideFpsControllerRefactor import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN +import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel import com.android.systemui.bouncer.ui.BouncerView import com.android.systemui.classifier.FalsingCollector @@ -154,12 +156,12 @@ constructor( /** Show the bouncer if necessary and set the relevant states. */ @JvmOverloads fun show(isScrimmed: Boolean) { - if (primaryBouncerView.delegate == null) { + if (primaryBouncerView.delegate == null && !Flags.composeBouncer()) { Log.d( TAG, "PrimaryBouncerInteractor#show is being called before the " + - "primaryBouncerDelegate is set. Let's exit early so we don't set the wrong " + - "primaryBouncer state." + "primaryBouncerDelegate is set. Let's exit early so we don't " + + "set the wrong primaryBouncer state." ) return } @@ -272,15 +274,24 @@ constructor( repository.setShowMessage(BouncerShowMessageModel(message, colorStateList)) } + val bouncerDismissAction: BouncerDismissActionModel? + get() = repository.bouncerDismissActionModel + /** * Sets actions to the bouncer based on how the bouncer is dismissed. If the bouncer is - * unlocked, we will run the onDismissAction. If the bouncer is existed before unlocking, we - * call cancelAction. + * unlocked, we will run the onDismissAction. If the bouncer is exited before unlocking, we call + * cancelAction. */ fun setDismissAction( onDismissAction: ActivityStarter.OnDismissAction?, cancelAction: Runnable? ) { + repository.bouncerDismissActionModel = + if (onDismissAction != null && cancelAction != null) { + BouncerDismissActionModel(onDismissAction, cancelAction) + } else { + null + } primaryBouncerView.delegate?.setDismissAction(onDismissAction, cancelAction) } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerDismissActionModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerDismissActionModel.kt new file mode 100644 index 000000000000..02b444f5a69f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerDismissActionModel.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 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.bouncer.shared.model + +import com.android.systemui.plugins.ActivityStarter + +/** Represents the action that needs to be performed after bouncer is dismissed. */ +data class BouncerDismissActionModel( + /** If the bouncer is unlocked, [onDismissAction] will be run. */ + val onDismissAction: ActivityStarter.OnDismissAction?, + /** If the bouncer is exited before unlocking, [onCancel] will be invoked. */ + val onCancel: Runnable? +) diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerDialogFactory.kt new file mode 100644 index 000000000000..5defe4754073 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerDialogFactory.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 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.bouncer.ui + +import android.app.AlertDialog + +/** Factory to create alert dialogs for use in bouncer component. */ +interface BouncerDialogFactory { + operator fun invoke(): AlertDialog +} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt index 7f3b794e2ac3..f3903ded7cf4 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerViewModule.kt @@ -16,9 +16,15 @@ package com.android.systemui.bouncer.ui +import android.app.AlertDialog +import android.content.Context import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModelModule +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.statusbar.phone.SystemUIDialog import dagger.Binds import dagger.Module +import dagger.Provides @Module( includes = @@ -29,4 +35,17 @@ import dagger.Module interface BouncerViewModule { /** Binds BouncerView to BouncerViewImpl and makes it injectable. */ @Binds fun bindBouncerView(bouncerViewImpl: BouncerViewImpl): BouncerView + + companion object { + + @Provides + @SysUISingleton + fun bouncerDialogFactory(@Application context: Context): BouncerDialogFactory { + return object : BouncerDialogFactory { + override fun invoke(): AlertDialog { + return SystemUIDialog(context) + } + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt new file mode 100644 index 000000000000..dd253a8f6eff --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt @@ -0,0 +1,89 @@ +package com.android.systemui.bouncer.ui.binder + +import android.view.ViewGroup +import com.android.keyguard.KeyguardMessageAreaController +import com.android.keyguard.ViewMediatorCallback +import com.android.keyguard.dagger.KeyguardBouncerComponent +import com.android.systemui.Flags +import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor +import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor +import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor +import com.android.systemui.bouncer.ui.BouncerDialogFactory +import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel +import com.android.systemui.compose.ComposeFacade +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.Flags.COMPOSE_BOUNCER_ENABLED +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel +import com.android.systemui.log.BouncerLogger +import com.android.systemui.user.domain.interactor.SelectedUserInteractor +import dagger.Lazy +import javax.inject.Inject + +/** Helper data class that allows to lazy load all the dependencies of the legacy bouncer. */ +@SysUISingleton +data class LegacyBouncerDependencies +@Inject +constructor( + val viewModel: KeyguardBouncerViewModel, + val primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel, + val componentFactory: KeyguardBouncerComponent.Factory, + val messageAreaControllerFactory: KeyguardMessageAreaController.Factory, + val bouncerMessageInteractor: BouncerMessageInteractor, + val bouncerLogger: BouncerLogger, + val selectedUserInteractor: SelectedUserInteractor, +) + +/** Helper data class that allows to lazy load all the dependencies of the compose based bouncer. */ +@SysUISingleton +data class ComposeBouncerDependencies +@Inject +constructor( + val legacyInteractor: PrimaryBouncerInteractor, + val viewModel: BouncerViewModel, + val dialogFactory: BouncerDialogFactory, + val authenticationInteractor: AuthenticationInteractor, + val viewMediatorCallback: ViewMediatorCallback?, + val selectedUserInteractor: SelectedUserInteractor, +) + +/** + * Toggles between the compose and non compose version of the bouncer, instantiating only the + * dependencies required for each. + */ +@SysUISingleton +class BouncerViewBinder +@Inject +constructor( + private val legacyBouncerDependencies: Lazy<LegacyBouncerDependencies>, + private val composeBouncerDependencies: Lazy<ComposeBouncerDependencies>, +) { + fun bind(view: ViewGroup) { + if ( + ComposeFacade.isComposeAvailable() && Flags.composeBouncer() && COMPOSE_BOUNCER_ENABLED + ) { + val deps = composeBouncerDependencies.get() + ComposeBouncerViewBinder.bind( + view, + deps.legacyInteractor, + deps.viewModel, + deps.dialogFactory, + deps.authenticationInteractor, + deps.selectedUserInteractor, + deps.viewMediatorCallback, + ) + } else { + val deps = legacyBouncerDependencies.get() + KeyguardBouncerViewBinder.bind( + view, + deps.viewModel, + deps.primaryBouncerToGoneTransitionViewModel, + deps.componentFactory, + deps.messageAreaControllerFactory, + deps.bouncerMessageInteractor, + deps.bouncerLogger, + deps.selectedUserInteractor, + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt new file mode 100644 index 000000000000..7b053956091e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt @@ -0,0 +1,75 @@ +package com.android.systemui.bouncer.ui.binder + +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle +import com.android.keyguard.ViewMediatorCallback +import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor +import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor +import com.android.systemui.bouncer.ui.BouncerDialogFactory +import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel +import com.android.systemui.compose.ComposeFacade +import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.user.domain.interactor.SelectedUserInteractor +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +/** View binder responsible for binding the compose version of the bouncer. */ +object ComposeBouncerViewBinder { + fun bind( + view: ViewGroup, + legacyInteractor: PrimaryBouncerInteractor, + viewModel: BouncerViewModel, + dialogFactory: BouncerDialogFactory, + authenticationInteractor: AuthenticationInteractor, + selectedUserInteractor: SelectedUserInteractor, + viewMediatorCallback: ViewMediatorCallback?, + ) { + view.addView( + ComposeFacade.createBouncer( + view.context, + viewModel, + dialogFactory, + ) + ) + view.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + launch { + legacyInteractor.isShowing.collectLatest { bouncerShowing -> + view.isVisible = bouncerShowing + } + } + + launch { + authenticationInteractor.onAuthenticationResult.collectLatest { + authenticationSucceeded -> + if (authenticationSucceeded) { + // Some dismiss actions require that keyguard be dismissed right away or + // deferred until something else later on dismisses keyguard (eg. end of + // a hide animation). + val deferKeyguardDone = + legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss() + legacyInteractor.setDismissAction(null, null) + + viewMediatorCallback?.let { + val selectedUserId = selectedUserInteractor.getSelectedUserId() + if (deferKeyguardDone == true) { + it.keyguardDonePending(selectedUserId) + } else { + it.keyguardDone(selectedUserId) + } + } + } + } + } + launch { + legacyInteractor.startingDisappearAnimation.collectLatest { + it.run() + legacyInteractor.hide() + } + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt index 3a927396527c..acbdecc5d514 100644 --- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt +++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt @@ -22,6 +22,8 @@ import android.view.View import android.view.WindowInsets import androidx.activity.ComponentActivity import androidx.lifecycle.LifecycleOwner +import com.android.systemui.bouncer.ui.BouncerDialogFactory +import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.people.ui.viewmodel.PeopleViewModel import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel @@ -88,6 +90,13 @@ interface BaseComposeFacade { viewModel: BaseCommunalViewModel, ): View + /** Create a [View] to represent the [BouncerViewModel]. */ + fun createBouncer( + context: Context, + viewModel: BouncerViewModel, + dialogFactory: BouncerDialogFactory, + ): View + /** Creates a container that hosts the communal UI and handles gesture transitions. */ fun createCommunalContainer(context: Context, viewModel: BaseCommunalViewModel): View } diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 7876a6f74293..846736c04d98 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -476,6 +476,13 @@ object Flags { // TODO(b/283300105): Tracking Bug @JvmField val SCENE_CONTAINER_ENABLED = false + /** + * Whether the compose bouncer is enabled. This ensures ProGuard can + * remove unused code from our APK at compile time. + */ + // TODO(b/280877228): Tracking Bug + @JvmField val COMPOSE_BOUNCER_ENABLED = false + // 1900 @JvmField val NOTE_TASKS = releasedFlag("keycode_flag") diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index cde2a62f9ae9..8c852cd04738 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -31,16 +31,12 @@ import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.AuthKeyguardMessageArea; -import com.android.keyguard.KeyguardMessageAreaController; import com.android.keyguard.LockIconViewController; -import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.Dumpable; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; -import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor; import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; -import com.android.systemui.bouncer.ui.binder.KeyguardBouncerViewBinder; -import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel; +import com.android.systemui.bouncer.ui.binder.BouncerViewBinder; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; @@ -56,8 +52,6 @@ import com.android.systemui.keyguard.shared.model.TransitionState; import com.android.systemui.keyguard.shared.model.TransitionStep; import com.android.systemui.keyguard.ui.binder.AlternateBouncerViewBinder; import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies; -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel; -import com.android.systemui.log.BouncerLogger; import com.android.systemui.res.R; import com.android.systemui.shared.animation.DisableSubpixelTextTransitionListener; import com.android.systemui.statusbar.DragDownHelper; @@ -77,7 +71,6 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.window.StatusBarWindowStateController; import com.android.systemui.unfold.UnfoldTransitionProgressProvider; -import com.android.systemui.user.domain.interactor.SelectedUserInteractor; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.time.SystemClock; @@ -183,24 +176,18 @@ public class NotificationShadeWindowViewController implements Dumpable { DumpManager dumpManager, PulsingGestureListener pulsingGestureListener, LockscreenHostedDreamGestureListener lockscreenHostedDreamGestureListener, - KeyguardBouncerViewModel keyguardBouncerViewModel, - KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory, - KeyguardMessageAreaController.Factory messageAreaControllerFactory, KeyguardTransitionInteractor keyguardTransitionInteractor, - PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel, GlanceableHubContainerController glanceableHubContainerController, NotificationLaunchAnimationInteractor notificationLaunchAnimationInteractor, FeatureFlagsClassic featureFlagsClassic, SystemClock clock, - BouncerMessageInteractor bouncerMessageInteractor, - BouncerLogger bouncerLogger, SysUIKeyEventHandler sysUIKeyEventHandler, QuickSettingsController quickSettingsController, PrimaryBouncerInteractor primaryBouncerInteractor, AlternateBouncerInteractor alternateBouncerInteractor, - SelectedUserInteractor selectedUserInteractor, Lazy<JavaAdapter> javaAdapter, - Lazy<AlternateBouncerDependencies> alternateBouncerDependencies) { + Lazy<AlternateBouncerDependencies> alternateBouncerDependencies, + BouncerViewBinder bouncerViewBinder) { mLockscreenShadeTransitionController = transitionController; mFalsingCollector = falsingCollector; mStatusBarStateController = statusBarStateController; @@ -234,15 +221,7 @@ public class NotificationShadeWindowViewController implements Dumpable { // This view is not part of the newly inflated expanded status bar. mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container); mDisableSubpixelTextTransitionListener = new DisableSubpixelTextTransitionListener(mView); - KeyguardBouncerViewBinder.bind( - mView.findViewById(R.id.keyguard_bouncer_container), - keyguardBouncerViewModel, - primaryBouncerToGoneTransitionViewModel, - keyguardBouncerComponentFactory, - messageAreaControllerFactory, - bouncerMessageInteractor, - bouncerLogger, - selectedUserInteractor); + bouncerViewBinder.bind(mView.findViewById(R.id.keyguard_bouncer_container)); if (DeviceEntryUdfpsRefactor.isEnabled()) { AlternateBouncerViewBinder.bind( diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index ee7c6c89e4a3..a11839c56b0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -17,7 +17,6 @@ package com.android.systemui.shade import android.content.Context -import android.os.Handler import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.KeyEvent @@ -25,50 +24,29 @@ import android.view.MotionEvent import android.view.View import android.view.ViewGroup import androidx.test.filters.SmallTest -import com.android.keyguard.KeyguardMessageAreaController import com.android.keyguard.KeyguardSecurityContainerController -import com.android.keyguard.KeyguardSecurityModel -import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.LockIconViewController import com.android.keyguard.dagger.KeyguardBouncerComponent import com.android.systemui.Flags import com.android.systemui.SysuiTestCase -import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository -import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl -import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor -import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor -import com.android.systemui.bouncer.domain.interactor.CountDownTimerUtil -import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor -import com.android.systemui.bouncer.ui.BouncerView -import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel -import com.android.systemui.classifier.FalsingCollector +import com.android.systemui.bouncer.ui.binder.BouncerViewBinder import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.compose.ComposeFacade.isComposeAvailable import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager -import com.android.systemui.log.logcatLogBuffer import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED import com.android.systemui.flags.Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION import com.android.systemui.flags.Flags.TRACKPAD_GESTURE_COMMON import com.android.systemui.flags.Flags.TRACKPAD_GESTURE_FEATURES -import com.android.systemui.flags.SystemPropertiesHelper import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler -import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.KeyguardUnlockAnimationController -import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository -import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository -import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository -import com.android.systemui.keyguard.data.repository.FakeTrustRepository -import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel -import com.android.systemui.log.BouncerLogger import com.android.systemui.res.R import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler import com.android.systemui.statusbar.DragDownHelper @@ -86,16 +64,15 @@ import com.android.systemui.statusbar.phone.DozeScrimController import com.android.systemui.statusbar.phone.DozeServiceHost import com.android.systemui.statusbar.phone.PhoneStatusBarViewController import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager -import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.window.StatusBarWindowStateController import com.android.systemui.unfold.UnfoldTransitionProgressProvider -import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.kotlin.JavaAdapter import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat +import java.util.Optional import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.test.TestScope @@ -110,9 +87,8 @@ import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import java.util.Optional import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -133,7 +109,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock private lateinit var shadeLogger: ShadeLogger @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var ambientState: AmbientState - @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel @Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager @Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController @@ -156,8 +131,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor @Mock lateinit var dragDownHelper: DragDownHelper @Mock lateinit var mSelectedUserInteractor: SelectedUserInteractor - @Mock - lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel @Mock lateinit var sysUIKeyEventHandler: SysUIKeyEventHandler @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor @@ -224,55 +197,18 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { dumpManager, pulsingGestureListener, mLockscreenHostedDreamGestureListener, - keyguardBouncerViewModel, - keyguardBouncerComponentFactory, - mock(KeyguardMessageAreaController.Factory::class.java), keyguardTransitionInteractor, - primaryBouncerToGoneTransitionViewModel, mGlanceableHubContainerController, notificationLaunchAnimationInteractor, featureFlagsClassic, fakeClock, - BouncerMessageInteractor( - repository = BouncerMessageRepositoryImpl(), - userRepository = FakeUserRepository(), - countDownTimerUtil = mock(CountDownTimerUtil::class.java), - updateMonitor = mock(KeyguardUpdateMonitor::class.java), - biometricSettingsRepository = FakeBiometricSettingsRepository(), - applicationScope = testScope.backgroundScope, - trustRepository = FakeTrustRepository(), - systemPropertiesHelper = mock(SystemPropertiesHelper::class.java), - primaryBouncerInteractor = - PrimaryBouncerInteractor( - FakeKeyguardBouncerRepository(), - mock(BouncerView::class.java), - mock(Handler::class.java), - mock(KeyguardStateController::class.java), - mock(KeyguardSecurityModel::class.java), - mock(PrimaryBouncerCallbackInteractor::class.java), - mock(FalsingCollector::class.java), - mock(DismissCallbackRegistry::class.java), - context, - mock(KeyguardUpdateMonitor::class.java), - FakeTrustRepository(), - testScope.backgroundScope, - mSelectedUserInteractor, - mock(DeviceEntryFaceAuthInteractor::class.java) - ), - facePropertyRepository = FakeFacePropertyRepository(), - deviceEntryFingerprintAuthRepository = - FakeDeviceEntryFingerprintAuthRepository(), - faceAuthRepository = FakeDeviceEntryFaceAuthRepository(), - securityModel = mock(KeyguardSecurityModel::class.java), - ), - BouncerLogger(logcatLogBuffer("BouncerLog")), sysUIKeyEventHandler, quickSettingsController, primaryBouncerInteractor, alternateBouncerInteractor, - mSelectedUserInteractor, - { mock (JavaAdapter::class.java )}, + { mock(JavaAdapter::class.java) }, { mock(AlternateBouncerDependencies::class.java) }, + mock(BouncerViewBinder::class.java) ) underTest.setupExpandedStatusBar() underTest.setDragDownHelper(dragDownHelper) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt index 33d60ea9f45c..0c4bf8120d25 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt @@ -15,51 +15,28 @@ */ package com.android.systemui.shade -import android.os.Handler import android.os.SystemClock import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.MotionEvent import android.widget.FrameLayout import androidx.test.filters.SmallTest -import com.android.keyguard.KeyguardMessageAreaController import com.android.keyguard.KeyguardSecurityContainerController -import com.android.keyguard.KeyguardSecurityModel -import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.LockIconViewController import com.android.keyguard.dagger.KeyguardBouncerComponent import com.android.systemui.Flags as AConfigFlags import com.android.systemui.SysuiTestCase -import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository -import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl -import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor -import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor -import com.android.systemui.bouncer.domain.interactor.CountDownTimerUtil -import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor -import com.android.systemui.bouncer.ui.BouncerView -import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel -import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags -import com.android.systemui.flags.SystemPropertiesHelper import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler -import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.KeyguardUnlockAnimationController -import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository -import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository -import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository -import com.android.systemui.keyguard.data.repository.FakeTrustRepository import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel -import com.android.systemui.log.BouncerLogger -import com.android.systemui.log.logcatLogBuffer -import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler import com.android.systemui.statusbar.DragDownHelper @@ -77,11 +54,8 @@ import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.DozeScrimController import com.android.systemui.statusbar.phone.DozeServiceHost import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager -import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.window.StatusBarWindowStateController import com.android.systemui.unfold.UnfoldTransitionProgressProvider -import com.android.systemui.user.data.repository.FakeUserRepository -import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.kotlin.JavaAdapter import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock @@ -137,7 +111,6 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { @Mock private lateinit var pulsingGestureListener: PulsingGestureListener @Mock private lateinit var mLockscreenHostedDreamGestureListener: LockscreenHostedDreamGestureListener - @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel @Mock private lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory @Mock private lateinit var keyguardBouncerComponent: KeyguardBouncerComponent @Mock @@ -150,10 +123,6 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor - @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor - @Mock - private lateinit var primaryBouncerToGoneTransitionViewModel: - PrimaryBouncerToGoneTransitionViewModel @Captor private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler> @@ -217,55 +186,18 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { dumpManager, pulsingGestureListener, mLockscreenHostedDreamGestureListener, - keyguardBouncerViewModel, - keyguardBouncerComponentFactory, - Mockito.mock(KeyguardMessageAreaController.Factory::class.java), keyguardTransitionInteractor, - primaryBouncerToGoneTransitionViewModel, mGlanceableHubContainerController, NotificationLaunchAnimationInteractor(NotificationLaunchAnimationRepository()), featureFlags, FakeSystemClock(), - BouncerMessageInteractor( - repository = BouncerMessageRepositoryImpl(), - userRepository = FakeUserRepository(), - countDownTimerUtil = Mockito.mock(CountDownTimerUtil::class.java), - updateMonitor = Mockito.mock(KeyguardUpdateMonitor::class.java), - biometricSettingsRepository = FakeBiometricSettingsRepository(), - applicationScope = testScope.backgroundScope, - trustRepository = FakeTrustRepository(), - systemPropertiesHelper = Mockito.mock(SystemPropertiesHelper::class.java), - primaryBouncerInteractor = - PrimaryBouncerInteractor( - FakeKeyguardBouncerRepository(), - Mockito.mock(BouncerView::class.java), - Mockito.mock(Handler::class.java), - Mockito.mock(KeyguardStateController::class.java), - Mockito.mock(KeyguardSecurityModel::class.java), - Mockito.mock(PrimaryBouncerCallbackInteractor::class.java), - Mockito.mock(FalsingCollector::class.java), - Mockito.mock(DismissCallbackRegistry::class.java), - context, - Mockito.mock(KeyguardUpdateMonitor::class.java), - FakeTrustRepository(), - testScope.backgroundScope, - mSelectedUserInteractor, - mock(), - ), - facePropertyRepository = FakeFacePropertyRepository(), - deviceEntryFingerprintAuthRepository = - FakeDeviceEntryFingerprintAuthRepository(), - faceAuthRepository = FakeDeviceEntryFaceAuthRepository(), - securityModel = Mockito.mock(KeyguardSecurityModel::class.java), - ), - BouncerLogger(logcatLogBuffer("BouncerLog")), Mockito.mock(SysUIKeyEventHandler::class.java), quickSettingsController, primaryBouncerInteractor, alternateBouncerInteractor, - mSelectedUserInteractor, { Mockito.mock(JavaAdapter::class.java) }, { Mockito.mock(AlternateBouncerDependencies::class.java) }, + mock() ) controller.setupExpandedStatusBar() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt index ff5179a7042c..8010261934b1 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt @@ -2,6 +2,7 @@ package com.android.systemui.bouncer.data.repository import com.android.systemui.biometrics.shared.SideFpsControllerRefactor import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants +import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel import com.android.systemui.dagger.SysUISingleton import dagger.Binds @@ -53,6 +54,7 @@ class FakeKeyguardBouncerRepository @Inject constructor() : KeyguardBouncerRepos override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow() private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false) override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow() + override var bouncerDismissActionModel: BouncerDismissActionModel? = null override fun setPrimaryScrimmed(isScrimmed: Boolean) { _primaryBouncerScrimmed.value = isScrimmed |