diff options
| author | 2023-10-05 20:58:29 +0000 | |
|---|---|---|
| committer | 2023-10-05 20:58:29 +0000 | |
| commit | d2b850dd61db199140901c39bb6507792be8f134 (patch) | |
| tree | 517ee5a717ec55cdf900b8374ab940ef247e31ca | |
| parent | e58722b03454367cd00f2402d234c90c9b5a4d89 (diff) | |
| parent | 9f25cb02b5e44cbde1657533fa53f0f75e938134 (diff) | |
Merge "Introduce NICViewModel#animationsEnabled" into main
37 files changed, 1868 insertions, 484 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java index c0ee71cf0dc8..0dfaf0f4318d 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java @@ -18,8 +18,15 @@ package com.android.systemui.classifier; import android.view.MotionEvent; +import javax.inject.Inject; + /** */ public class FalsingCollectorFake implements FalsingCollector { + + @Inject + public FalsingCollectorFake() { + } + @Override public void onSuccessfulUnlock() { } diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt index ac8333ae84ad..e487a6fb9617 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt @@ -19,7 +19,11 @@ package com.android.systemui.shade.domain.interactor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.DozeStateModel +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState +import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.ObservableTransitionState @@ -27,8 +31,9 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor +import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository -import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository import com.android.systemui.user.domain.interactor.UserInteractor import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject @@ -56,13 +61,16 @@ class ShadeInteractor @Inject constructor( @Application scope: CoroutineScope, + deviceProvisioningRepository: DeviceProvisioningRepository, disableFlagsRepository: DisableFlagsRepository, + dozeParams: DozeParameters, sceneContainerFlags: SceneContainerFlags, // TODO(b/300258424) convert to direct reference instead of provider sceneInteractorProvider: Provider<SceneInteractor>, keyguardRepository: KeyguardRepository, + keyguardTransitionInteractor: KeyguardTransitionInteractor, + powerInteractor: PowerInteractor, userSetupRepository: UserSetupRepository, - deviceProvisionedController: DeviceProvisionedController, userInteractor: UserInteractor, sharedNotificationContainerInteractor: SharedNotificationContainerInteractor, repository: ShadeRepository, @@ -187,6 +195,26 @@ constructor( combine(isUserInteractingWithShade, isUserInteractingWithShade) { shade, qs -> shade || qs } .distinctUntilChanged() + /** Are touches allowed on the notification panel? */ + val isShadeTouchable: Flow<Boolean> = + combine( + powerInteractor.isAsleep, + keyguardTransitionInteractor.isInTransitionToStateWhere { it == KeyguardState.AOD }, + keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING }, + deviceProvisioningRepository.isFactoryResetProtectionActive, + ) { isAsleep, goingToSleep, isPulsing, isFrpActive -> + when { + // Touches are disabled when Factory Reset Protection is active + isFrpActive -> false + // If the device is going to sleep, only accept touches if we're still + // animating + goingToSleep -> dozeParams.shouldControlScreenOff() + // If the device is asleep, only accept touches if there's a pulse + isAsleep -> isPulsing + else -> true + } + } + /** Emits true if the shade can be expanded from QQS to QS and false otherwise. */ val isExpandToQsEnabled: Flow<Boolean> = combine( @@ -194,8 +222,9 @@ constructor( isShadeEnabled, keyguardRepository.isDozing, userSetupRepository.isUserSetupFlow, - ) { disableFlags, isShadeEnabled, isDozing, isUserSetup -> - deviceProvisionedController.isDeviceProvisioned && + deviceProvisioningRepository.isDeviceProvisioned, + ) { disableFlags, isShadeEnabled, isDozing, isUserSetup, isDeviceProvisioned -> + isDeviceProvisioned && // Disallow QS during setup if it's a simple user switcher. (The user intends to // use the lock screen user switcher, QS is not needed.) (isUserSetup || !userInteractor.isSimpleUserSwitcher) && diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt index 5cc5e751ca8e..a77e67b6908d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt @@ -118,7 +118,6 @@ constructor( private var aodIcons: NotificationIconContainer? = null private var aodBindJob: DisposableHandle? = null private var aodIconAppearTranslation = 0 - private var animationsEnabled = false private var aodIconTint = 0 private var aodIconsVisible = false private var showLowPriority = true @@ -157,9 +156,12 @@ constructor( } this.aodIcons = aodIcons this.aodIcons!!.setOnLockScreen(true) - aodBindJob = NotificationIconContainerViewBinder.bind(aodIcons, aodIconsViewModel) + aodBindJob = + NotificationIconContainerViewBinder.bind( + aodIcons, + aodIconsViewModel, + ) updateAodIconsVisibility(animate = false, forceUpdate = changed) - updateAnimations() if (changed) { updateAodNotificationIcons() } @@ -171,7 +173,10 @@ constructor( override fun setShelfIcons(icons: NotificationIconContainer) { if (shelfRefactor.expectEnabled()) { - NotificationIconContainerViewBinder.bind(icons, shelfIconsViewModel) + NotificationIconContainerViewBinder.bind( + icons, + shelfIconsViewModel, + ) shelfIcons = icons } } @@ -252,14 +257,10 @@ constructor( aodIcons!!.setDozing(isDozing, animate, 0) } - override fun setAnimationsEnabled(enabled: Boolean) { - animationsEnabled = enabled - updateAnimations() - } + override fun setAnimationsEnabled(enabled: Boolean) = unsupported override fun onStateChanged(newState: Int) { updateAodIconsVisibility(animate = false, forceUpdate = false) - updateAnimations() } override fun onThemeChanged() { @@ -348,7 +349,10 @@ constructor( val layoutInflater = LayoutInflater.from(context) notificationIconArea = inflateIconArea(layoutInflater) notificationIcons = notificationIconArea?.findViewById(R.id.notificationIcons) - NotificationIconContainerViewBinder.bind(notificationIcons!!, statusBarIconsViewModel) + NotificationIconContainerViewBinder.bind( + notificationIcons!!, + statusBarIconsViewModel, + ) } private fun updateIconLayoutParams(context: Context) { @@ -598,14 +602,6 @@ constructor( v.setDecorColor(tint) } - private fun updateAnimations() { - val inShade = statusBarStateController.state == StatusBarState.SHADE - if (aodIcons != null) { - aodIcons!!.setAnimationsEnabled(animationsEnabled && !inShade) - } - notificationIcons!!.setAnimationsEnabled(animationsEnabled && inShade) - } - private fun animateInAodIconTranslation() { if (!statusViewMigrated) { aodIcons!! @@ -702,7 +698,12 @@ constructor( companion object { private const val AOD_ICONS_APPEAR_DURATION: Long = 200 - @ColorInt private val DEFAULT_AOD_ICON_COLOR = -0x1 + + val unsupported: Nothing + get() = + error( + "Code path not supported when NOTIFICATION_ICON_CONTAINER_REFACTOR is disabled" + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt index 8293bb329a01..f8ff3e393033 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt @@ -21,6 +21,7 @@ import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel import com.android.systemui.statusbar.phone.NotificationIconContainer import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.launch /** Binds a [NotificationIconContainer] to its [view model][NotificationIconContainerViewModel]. */ object NotificationIconContainerViewBinder { @@ -28,6 +29,10 @@ object NotificationIconContainerViewBinder { view: NotificationIconContainer, viewModel: NotificationIconContainerViewModel, ): DisposableHandle { - return view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) {} } + return view.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt index f68b0ef79638..90507fc82a79 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt @@ -15,8 +15,24 @@ */ package com.android.systemui.statusbar.notification.icon.ui.viewmodel +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.shade.domain.interactor.ShadeInteractor import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine /** View-model for the row of notification icons displayed on the always-on display. */ -class NotificationIconContainerAlwaysOnDisplayViewModel @Inject constructor() : - NotificationIconContainerViewModel +class NotificationIconContainerAlwaysOnDisplayViewModel +@Inject +constructor( + keyguardInteractor: KeyguardInteractor, + shadeInteractor: ShadeInteractor, +) : NotificationIconContainerViewModel { + override val animationsEnabled: Flow<Boolean> = + combine( + shadeInteractor.isShadeTouchable, + keyguardInteractor.isKeyguardVisible, + ) { panelTouchesEnabled, isKeyguardVisible -> + panelTouchesEnabled && isKeyguardVisible + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt index 933c76f19aee..49f262de8f4a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt @@ -16,7 +16,11 @@ package com.android.systemui.statusbar.notification.icon.ui.viewmodel import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf /** View-model for the overflow row of notification icons displayed in the notification shade. */ class NotificationIconContainerShelfViewModel @Inject constructor() : - NotificationIconContainerViewModel + NotificationIconContainerViewModel { + override val animationsEnabled: Flow<Boolean> = flowOf(true) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt index 2217646e6022..ee57b780b8c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt @@ -15,8 +15,24 @@ */ package com.android.systemui.statusbar.notification.icon.ui.viewmodel +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.shade.domain.interactor.ShadeInteractor import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine /** View-model for the row of notification icons displayed in the status bar, */ -class NotificationIconContainerStatusBarViewModel @Inject constructor() : - NotificationIconContainerViewModel +class NotificationIconContainerStatusBarViewModel +@Inject +constructor( + keyguardInteractor: KeyguardInteractor, + shadeInteractor: ShadeInteractor, +) : NotificationIconContainerViewModel { + override val animationsEnabled: Flow<Boolean> = + combine( + shadeInteractor.isShadeTouchable, + keyguardInteractor.isKeyguardShowing, + ) { panelTouchesEnabled, isKeyguardShowing -> + panelTouchesEnabled && !isKeyguardShowing + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt index 892b2be9ed6e..6f8ce4b1db4b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt @@ -15,8 +15,13 @@ */ package com.android.systemui.statusbar.notification.icon.ui.viewmodel +import kotlinx.coroutines.flow.Flow + /** * View-model for the row of notification icons displayed in the NotificationShelf, StatusBar, and * AOD. */ -interface NotificationIconContainerViewModel +interface NotificationIconContainerViewModel { + /** Are changes to the icon container animated? */ + val animationsEnabled: Flow<Boolean> +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 3e2f10dd1a0c..31762220a5dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -2688,7 +2688,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { !mDozeServiceHost.isPulsing(), mDeviceProvisionedController.isFrpActive()); mShadeSurface.setTouchAndAnimationDisabled(disabled); - mNotificationIconAreaController.setAnimationsEnabled(!disabled); + if (!mFeatureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) { + mNotificationIconAreaController.setAnimationsEnabled(!disabled); + } } final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt index c302d6aeadbc..859e636a7714 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.policy import android.content.res.Resources import com.android.systemui.res.R +import javax.inject.Inject /** * Fake SplitShadeStateController @@ -24,7 +25,7 @@ import com.android.systemui.res.R * Identical behaviour to legacy implementation (that used LargeScreenUtils.kt) I.E., behaviour * based solely on resources, no extra flag logic. */ -class ResourcesSplitShadeStateController : SplitShadeStateController { +class ResourcesSplitShadeStateController @Inject constructor() : SplitShadeStateController { override fun shouldUseSplitNotificationShade(resources: Resources): Boolean { return resources.getBoolean(R.bool.config_use_split_notification_shade) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java index a77c69236946..818ba9512e15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java @@ -70,6 +70,7 @@ import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeControllerImpl; import com.android.systemui.statusbar.policy.bluetooth.BluetoothRepository; import com.android.systemui.statusbar.policy.bluetooth.BluetoothRepositoryImpl; +import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepositoryModule; import dagger.Binds; import dagger.Module; @@ -80,7 +81,7 @@ import java.util.concurrent.Executor; import javax.inject.Named; /** Dagger Module for code in the statusbar.policy package. */ -@Module +@Module(includes = { DeviceProvisioningRepositoryModule.class }) public interface StatusBarPolicyModule { String DEVICE_STATE_ROTATION_LOCK_DEFAULTS = "DEVICE_STATE_ROTATION_LOCK_DEFAULTS"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepository.kt new file mode 100644 index 000000000000..1160d657ba88 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepository.kt @@ -0,0 +1,73 @@ +/* + * 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.statusbar.policy.data.repository + +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import dagger.Binds +import dagger.Module +import javax.inject.Inject +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow + +/** Tracks state related to device provisioning. */ +interface DeviceProvisioningRepository { + /** + * Whether this device has been provisioned. + * + * @see android.provider.Settings.Global.DEVICE_PROVISIONED + */ + val isDeviceProvisioned: Flow<Boolean> + + /** Whether Factory Reset Protection (FRP) is currently active, locking the device. */ + val isFactoryResetProtectionActive: Flow<Boolean> +} + +@Module +interface DeviceProvisioningRepositoryModule { + @Binds fun bindsImpl(impl: DeviceProvisioningRepositoryImpl): DeviceProvisioningRepository +} + +class DeviceProvisioningRepositoryImpl +@Inject +constructor( + private val deviceProvisionedController: DeviceProvisionedController, +) : DeviceProvisioningRepository { + + override val isDeviceProvisioned: Flow<Boolean> = conflatedCallbackFlow { + val listener = + object : DeviceProvisionedController.DeviceProvisionedListener { + override fun onDeviceProvisionedChanged() { + trySend(deviceProvisionedController.isDeviceProvisioned) + } + } + deviceProvisionedController.addCallback(listener) + trySend(deviceProvisionedController.isDeviceProvisioned) + awaitClose { deviceProvisionedController.removeCallback(listener) } + } + + override val isFactoryResetProtectionActive: Flow<Boolean> = conflatedCallbackFlow { + val listener = + object : DeviceProvisionedController.DeviceProvisionedListener { + override fun onFrpActiveChanged() { + trySend(deviceProvisionedController.isFrpActive) + } + } + deviceProvisionedController.addCallback(listener) + trySend(deviceProvisionedController.isFrpActive) + awaitClose { deviceProvisionedController.removeCallback(listener) } + } +} diff --git a/packages/SystemUI/tests/src/com/android/TestMocksModule.kt b/packages/SystemUI/tests/src/com/android/TestMocksModule.kt index 8990583cf9de..c1be44ab8a85 100644 --- a/packages/SystemUI/tests/src/com/android/TestMocksModule.kt +++ b/packages/SystemUI/tests/src/com/android/TestMocksModule.kt @@ -18,61 +18,94 @@ package com.android import android.app.ActivityManager import android.app.admin.DevicePolicyManager import android.os.UserManager +import android.util.DisplayMetrics +import com.android.internal.logging.MetricsLogger import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.GuestResumeSessionReceiver import com.android.systemui.demomode.DemoModeController +import com.android.systemui.dump.DumpManager +import com.android.systemui.keyguard.ScreenLifecycle +import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.log.LogBuffer import com.android.systemui.log.dagger.BroadcastDispatcherLog import com.android.systemui.log.dagger.SceneFrameworkLog +import com.android.systemui.media.controls.ui.MediaHierarchyManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationListener +import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.NotificationMediaManager +import com.android.systemui.statusbar.NotificationShadeDepthController +import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator +import com.android.systemui.statusbar.notification.stack.AmbientState +import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController +import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.statusbar.phone.LSShadeTransitionLogger import com.android.systemui.statusbar.phone.ScreenOffAnimationController -import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.SplitShadeStateController import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.mockito.mock import com.android.wm.shell.bubbles.Bubbles +import dagger.Binds import dagger.Module import dagger.Provides import java.util.Optional -@Module +@Module(includes = [TestMocksModule.Bindings::class]) data class TestMocksModule( @get:Provides val activityStarter: ActivityStarter = mock(), + @get:Provides val ambientState: AmbientState = mock(), @get:Provides val bubbles: Optional<Bubbles> = Optional.of(mock()), - @get:Provides val configurationController: ConfigurationController = mock(), @get:Provides val darkIconDispatcher: DarkIconDispatcher = mock(), @get:Provides val demoModeController: DemoModeController = mock(), @get:Provides val deviceProvisionedController: DeviceProvisionedController = mock(), @get:Provides val dozeParameters: DozeParameters = mock(), + @get:Provides val dumpManager: DumpManager = mock(), @get:Provides val guestResumeSessionReceiver: GuestResumeSessionReceiver = mock(), @get:Provides val keyguardBypassController: KeyguardBypassController = mock(), @get:Provides val keyguardSecurityModel: KeyguardSecurityModel = mock(), @get:Provides val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock(), - @get:Provides val notifListener: NotificationListener = mock(), - @get:Provides val notifMediaManager: NotificationMediaManager = mock(), + @get:Provides val mediaHierarchyManager: MediaHierarchyManager = mock(), + @get:Provides val notificationListener: NotificationListener = mock(), + @get:Provides val notificationLockscreenUserManager: NotificationLockscreenUserManager = mock(), + @get:Provides val notificationMediaManager: NotificationMediaManager = mock(), + @get:Provides val notificationShadeDepthController: NotificationShadeDepthController = mock(), + @get:Provides + val notificationStackScrollLayoutController: NotificationStackScrollLayoutController = mock(), + @get:Provides val notificationStackSizeCalculator: NotificationStackSizeCalculator = mock(), + @get:Provides val notificationWakeUpCoordinator: NotificationWakeUpCoordinator = mock(), + @get:Provides val screenLifecycle: ScreenLifecycle = mock(), @get:Provides val screenOffAnimController: ScreenOffAnimationController = mock(), - @get:Provides val splitShadeStateController: SplitShadeStateController = mock(), - @get:Provides val statusBarStateController: StatusBarStateController = mock(), + @get:Provides val scrimController: ScrimController = mock(), + @get:Provides val statusBarStateController: SysuiStatusBarStateController = mock(), @get:Provides val statusBarWindowController: StatusBarWindowController = mock(), - @get:Provides val wakeUpCoordinator: NotificationWakeUpCoordinator = mock(), + @get:Provides val wakefulnessLifecycle: WakefulnessLifecycle = mock(), // log buffers @get:[Provides BroadcastDispatcherLog] val broadcastDispatcherLogger: LogBuffer = mock(), @get:[Provides SceneFrameworkLog] val sceneLogger: LogBuffer = mock(), + @get:Provides val lsShadeTransitionLogger: LSShadeTransitionLogger = mock(), // framework mocks @get:Provides val activityManager: ActivityManager = mock(), @get:Provides val devicePolicyManager: DevicePolicyManager = mock(), + @get:Provides val displayMetrics: DisplayMetrics = mock(), + @get:Provides val metricsLogger: MetricsLogger = mock(), @get:Provides val userManager: UserManager = mock(), -) +) { + @Module + interface Bindings { + @Binds + fun bindStatusBarStateController( + sysuiStatusBarStateController: SysuiStatusBarStateController, + ): StatusBarStateController + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt index 73654609ad7f..d68a3131da4c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt @@ -16,36 +16,18 @@ package com.android.systemui.biometrics -import android.app.ActivityManager -import android.os.UserManager import androidx.test.filters.SmallTest -import com.android.internal.logging.UiEventLogger -import com.android.keyguard.KeyguardUpdateMonitor +import com.android.SysUITestModule import com.android.systemui.SysuiTestCase -import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository -import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.flags.Flags -import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory -import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.scene.SceneTestUtils -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.shade.data.repository.FakeShadeRepository -import com.android.systemui.shade.domain.interactor.ShadeInteractor -import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository -import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor -import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository -import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController -import com.android.systemui.telephony.data.repository.FakeTelephonyRepository -import com.android.systemui.telephony.domain.interactor.TelephonyInteractor -import com.android.systemui.user.data.repository.FakeUserRepository -import com.android.systemui.user.domain.interactor.GuestUserInteractor -import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode -import com.android.systemui.user.domain.interactor.RefreshUsersScheduler -import com.android.systemui.user.domain.interactor.UserInteractor -import com.android.systemui.util.mockito.mock +import com.android.systemui.user.domain.UserDomainLayerModule +import dagger.BindsInstance +import dagger.Component import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -58,91 +40,27 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { - private val utils = SceneTestUtils(this) - private val testScope = utils.testScope - private val testDispatcher = utils.testDispatcher - private val disableFlagsRepository = FakeDisableFlagsRepository() - private val featureFlags = FakeFeatureFlags() - private val keyguardRepository = FakeKeyguardRepository() - private val shadeRepository = FakeShadeRepository() - private val sceneContainerFlags = FakeSceneContainerFlags() - private val sceneInteractor = utils.sceneInteractor() - private val userSetupRepository = FakeUserSetupRepository() - private val userRepository = FakeUserRepository() - private val configurationRepository = FakeConfigurationRepository() - private val sharedNotificationContainerInteractor = - SharedNotificationContainerInteractor( - configurationRepository, - mContext, - ResourcesSplitShadeStateController() - ) - - private lateinit var detector: AuthDialogPanelInteractionDetector - private lateinit var shadeInteractor: ShadeInteractor - private lateinit var userInteractor: UserInteractor + + private val testComponent: TestComponent = + DaggerAuthDialogPanelInteractionDetectorTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FACE_AUTH_REFACTOR, false) + set(Flags.FULL_SCREEN_USER_SWITCHER, true) + }, + ) @Mock private lateinit var action: Runnable - @Mock private lateinit var activityManager: ActivityManager - @Mock private lateinit var activityStarter: ActivityStarter - @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController - @Mock private lateinit var guestInteractor: GuestUserInteractor - @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode - @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor - @Mock private lateinit var manager: UserManager - @Mock private lateinit var uiEventLogger: UiEventLogger + + private val testScope = testComponent.testScope + private val shadeRepository = testComponent.shadeRepository + private val detector = testComponent.detector @Before fun setUp() { MockitoAnnotations.initMocks(this) - - featureFlags.set(Flags.FACE_AUTH_REFACTOR, false) - featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) - - val refreshUsersScheduler = - RefreshUsersScheduler( - applicationScope = testScope.backgroundScope, - mainDispatcher = testDispatcher, - repository = userRepository, - ) - userInteractor = - UserInteractor( - applicationContext = context, - repository = userRepository, - activityStarter = activityStarter, - keyguardInteractor = - KeyguardInteractorFactory.create(featureFlags = featureFlags) - .keyguardInteractor, - featureFlags = featureFlags, - manager = manager, - headlessSystemUserMode = headlessSystemUserMode, - applicationScope = testScope.backgroundScope, - telephonyInteractor = - TelephonyInteractor( - repository = FakeTelephonyRepository(), - ), - broadcastDispatcher = fakeBroadcastDispatcher, - keyguardUpdateMonitor = keyguardUpdateMonitor, - backgroundDispatcher = testDispatcher, - activityManager = activityManager, - refreshUsersScheduler = refreshUsersScheduler, - guestUserInteractor = guestInteractor, - uiEventLogger = uiEventLogger, - userRestrictionChecker = mock(), - ) - shadeInteractor = - ShadeInteractor( - testScope.backgroundScope, - disableFlagsRepository, - sceneContainerFlags, - { sceneInteractor }, - keyguardRepository, - userSetupRepository, - deviceProvisionedController, - userInteractor, - sharedNotificationContainerInteractor, - shadeRepository, - ) - detector = AuthDialogPanelInteractionDetector(testScope, { shadeInteractor }) } @Test @@ -215,4 +133,27 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { // Clean up job detector.disable() } + + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent { + + val detector: AuthDialogPanelInteractionDetector + val shadeRepository: FakeShadeRepository + val testScope: TestScope + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + ): TestComponent + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index 2ed20908ba2f..eb006100d535 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -47,18 +47,34 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; +import com.android.keyguard.KeyguardSecurityModel; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; +import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository; +import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; +import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FakeFeatureFlagsClassic; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.data.repository.FakeCommandQueue; import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository; +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository; +import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor; +import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.power.data.repository.FakePowerRepository; +import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.res.R; import com.android.systemui.scene.FakeWindowRootViewComponent; import com.android.systemui.scene.SceneTestUtils; +import com.android.systemui.scene.data.repository.SceneContainerRepository; +import com.android.systemui.scene.domain.interactor.SceneInteractor; import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; +import com.android.systemui.scene.shared.logger.SceneLogger; import com.android.systemui.shade.data.repository.FakeShadeRepository; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.StatusBarState; @@ -71,9 +87,9 @@ import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository; import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository; import com.android.systemui.user.domain.interactor.UserInteractor; import com.google.common.util.concurrent.MoreExecutors; @@ -109,6 +125,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { @Mock private SysuiColorExtractor mColorExtractor; @Mock ColorExtractor.GradientColors mGradientColors; @Mock private DumpManager mDumpManager; + @Mock private KeyguardSecurityModel mKeyguardSecurityModel; @Mock private KeyguardStateController mKeyguardStateController; @Mock private ScreenOffAnimationController mScreenOffAnimationController; @Mock private AuthController mAuthController; @@ -123,6 +140,8 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { private NotificationShadeWindowControllerImpl mNotificationShadeWindowController; private float mPreferredRefreshRate = -1; + private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor; + private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor; @Before public void setUp() { @@ -137,22 +156,86 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { when(mDozeParameters.getAlwaysOn()).thenReturn(true); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); + FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository(); + FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic(); + FakeShadeRepository shadeRepository = new FakeShadeRepository(); + FakePowerRepository powerRepository = new FakePowerRepository(); + + PowerInteractor powerInteractor = new PowerInteractor( + powerRepository, + new FalsingCollectorFake(), + mScreenOffAnimationController, + mStatusBarStateController); + + SceneInteractor sceneInteractor = new SceneInteractor( + mTestScope.getBackgroundScope(), + new SceneContainerRepository( + mTestScope.getBackgroundScope(), + mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())), + powerRepository, + mock(SceneLogger.class)); + + FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository(); + FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags(); + KeyguardInteractor keyguardInteractor = new KeyguardInteractor( + keyguardRepository, + new FakeCommandQueue(), + powerInteractor, + featureFlags, + sceneContainerFlags, + new FakeDeviceEntryRepository(), + new FakeKeyguardBouncerRepository(), + configurationRepository, + shadeRepository, + () -> sceneInteractor); + + FakeKeyguardTransitionRepository keyguardTransitionRepository = + new FakeKeyguardTransitionRepository(); + + KeyguardTransitionInteractor keyguardTransitionInteractor = + new KeyguardTransitionInteractor( + mTestScope.getBackgroundScope(), + keyguardTransitionRepository, + () -> keyguardInteractor, + () -> mFromLockscreenTransitionInteractor, + () -> mFromPrimaryBouncerTransitionInteractor); + + mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor( + keyguardTransitionRepository, + keyguardTransitionInteractor, + mTestScope.getBackgroundScope(), + keyguardInteractor, + featureFlags, + shadeRepository, + powerInteractor); + + mFromPrimaryBouncerTransitionInteractor = new FromPrimaryBouncerTransitionInteractor( + keyguardTransitionRepository, + keyguardTransitionInteractor, + mTestScope.getBackgroundScope(), + keyguardInteractor, + featureFlags, + mKeyguardSecurityModel, + powerInteractor); + mShadeInteractor = new ShadeInteractor( mTestScope.getBackgroundScope(), + new FakeDeviceProvisioningRepository(), new FakeDisableFlagsRepository(), - new FakeSceneContainerFlags(), - mUtils::sceneInteractor, - new FakeKeyguardRepository(), + mock(DozeParameters.class), + sceneContainerFlags, + () -> sceneInteractor, + keyguardRepository, + keyguardTransitionInteractor, + powerInteractor, new FakeUserSetupRepository(), - mock(DeviceProvisionedController.class), mock(UserInteractor.class), new SharedNotificationContainerInteractor( - new FakeConfigurationRepository(), + configurationRepository, mContext, new ResourcesSplitShadeStateController()), - new FakeShadeRepository() - ); + shadeRepository); mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl( mContext, diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java index 8138b328a3c5..65174bab7f63 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java @@ -32,23 +32,39 @@ import android.view.accessibility.AccessibilityManager; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; +import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardStatusView; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; +import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository; +import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; +import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FakeFeatureFlagsClassic; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.fragments.FragmentHostManager; +import com.android.systemui.keyguard.data.repository.FakeCommandQueue; import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository; +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository; +import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor; +import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.media.controls.pipeline.MediaDataManager; import com.android.systemui.media.controls.ui.MediaHierarchyManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QS; +import com.android.systemui.power.data.repository.FakePowerRepository; +import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.qs.QSFragmentLegacy; import com.android.systemui.res.R; import com.android.systemui.scene.SceneTestUtils; +import com.android.systemui.scene.data.repository.SceneContainerRepository; +import com.android.systemui.scene.domain.interactor.SceneInteractor; import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; +import com.android.systemui.scene.shared.logger.SceneLogger; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shade.data.repository.FakeShadeRepository; import com.android.systemui.shade.domain.interactor.ShadeInteractor; @@ -64,19 +80,21 @@ import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFl import com.android.systemui.statusbar.notification.stack.AmbientState; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor; +import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBottomAreaView; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardStatusBarView; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockscreenGestureLogger; +import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository; import com.android.systemui.user.domain.interactor.UserInteractor; import com.android.systemui.util.kotlin.JavaAdapter; @@ -103,8 +121,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { protected SceneTestUtils mUtils = new SceneTestUtils(this); protected TestScope mTestScope = mUtils.getTestScope(); - @Mock - protected Resources mResources; + @Mock protected Resources mResources; @Mock protected KeyguardBottomAreaView mQsFrame; @Mock protected KeyguardStatusBarView mKeyguardStatusBar; @Mock protected QS mQs; @@ -126,6 +143,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { @Mock protected NotificationShadeDepthController mNotificationShadeDepthController; @Mock protected ShadeHeaderController mShadeHeaderController; @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + @Mock protected DozeParameters mDozeParameters; @Mock protected KeyguardStateController mKeyguardStateController; @Mock protected KeyguardBypassController mKeyguardBypassController; @Mock protected KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -144,7 +162,6 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { @Mock protected DumpManager mDumpManager; @Mock protected UiEventLogger mUiEventLogger; @Mock protected CastController mCastController; - @Mock protected DeviceProvisionedController mDeviceProvisionedController; @Mock protected UserInteractor mUserInteractor; protected FakeDisableFlagsRepository mDisableFlagsRepository = new FakeDisableFlagsRepository(); @@ -161,6 +178,8 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { new ShadeExpansionStateManager(); protected FragmentHostManager.FragmentListener mFragmentListener; + private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor; + private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor; @Before public void setup() { @@ -169,21 +188,89 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager, mInteractionJankMonitor, mShadeExpansionStateManager); - when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true); + FakeDeviceProvisioningRepository deviceProvisioningRepository = + new FakeDeviceProvisioningRepository(); + deviceProvisioningRepository.setDeviceProvisioned(true); + FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic(); + FakePowerRepository powerRepository = new FakePowerRepository(); + FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository(); + + PowerInteractor powerInteractor = new PowerInteractor( + powerRepository, + new FalsingCollectorFake(), + mock(ScreenOffAnimationController.class), + mStatusBarStateController); + + SceneInteractor sceneInteractor = new SceneInteractor( + mTestScope.getBackgroundScope(), + new SceneContainerRepository( + mTestScope.getBackgroundScope(), + mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())), + powerRepository, + mock(SceneLogger.class)); + + FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags(); + KeyguardInteractor keyguardInteractor = new KeyguardInteractor( + mKeyguardRepository, + new FakeCommandQueue(), + powerInteractor, + featureFlags, + sceneContainerFlags, + new FakeDeviceEntryRepository(), + new FakeKeyguardBouncerRepository(), + configurationRepository, + mShadeRepository, + () -> sceneInteractor); + + FakeKeyguardTransitionRepository keyguardTransitionRepository = + new FakeKeyguardTransitionRepository(); + + KeyguardTransitionInteractor keyguardTransitionInteractor = + new KeyguardTransitionInteractor( + mTestScope.getBackgroundScope(), + keyguardTransitionRepository, + () -> keyguardInteractor, + () -> mFromLockscreenTransitionInteractor, + () -> mFromPrimaryBouncerTransitionInteractor); + + mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor( + keyguardTransitionRepository, + keyguardTransitionInteractor, + mTestScope.getBackgroundScope(), + keyguardInteractor, + featureFlags, + mShadeRepository, + powerInteractor); + + mFromPrimaryBouncerTransitionInteractor = new FromPrimaryBouncerTransitionInteractor( + keyguardTransitionRepository, + keyguardTransitionInteractor, + mTestScope.getBackgroundScope(), + keyguardInteractor, + featureFlags, + mock(KeyguardSecurityModel.class), + powerInteractor); + + ResourcesSplitShadeStateController splitShadeStateController = + new ResourcesSplitShadeStateController(); + mShadeInteractor = new ShadeInteractor( mTestScope.getBackgroundScope(), + deviceProvisioningRepository, mDisableFlagsRepository, - new FakeSceneContainerFlags(), - () -> mUtils.sceneInteractor(), + mDozeParameters, + sceneContainerFlags, + () -> sceneInteractor, mKeyguardRepository, + keyguardTransitionInteractor, + powerInteractor, new FakeUserSetupRepository(), - mDeviceProvisionedController, mUserInteractor, new SharedNotificationContainerInteractor( - new FakeConfigurationRepository(), + configurationRepository, mContext, - new ResourcesSplitShadeStateController()), + splitShadeStateController), mShadeRepository ); @@ -262,7 +349,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { mShadeInteractor, new JavaAdapter(mTestScope.getBackgroundScope()), mCastController, - new ResourcesSplitShadeStateController() + splitShadeStateController ); mQsController.init(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt index 2be1c09843c1..81382a44def6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt @@ -16,50 +16,52 @@ package com.android.systemui.shade.data.repository -import android.app.ActivityManager import android.app.StatusBarManager.DISABLE2_NONE import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import android.content.pm.UserInfo import android.os.UserManager import androidx.test.filters.SmallTest -import com.android.internal.logging.UiEventLogger -import com.android.keyguard.KeyguardUpdateMonitor +import com.android.SysUITestModule +import com.android.TestMocksModule import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.DozeStateModel +import com.android.systemui.keyguard.shared.model.DozeTransitionModel +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState -import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.shared.model.WakeSleepReason +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.res.R -import com.android.systemui.scene.SceneTestUtils -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags +import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository -import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor +import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository -import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController -import com.android.systemui.telephony.data.repository.FakeTelephonyRepository -import com.android.systemui.telephony.domain.interactor.TelephonyInteractor +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository import com.android.systemui.user.data.model.UserSwitcherSettingsModel import com.android.systemui.user.data.repository.FakeUserRepository -import com.android.systemui.user.domain.interactor.GuestUserInteractor -import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode -import com.android.systemui.user.domain.interactor.RefreshUsersScheduler -import com.android.systemui.user.domain.interactor.UserInteractor -import com.android.systemui.util.mockito.mock +import com.android.systemui.user.domain.UserDomainLayerModule import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import dagger.BindsInstance +import dagger.Component import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -70,50 +72,55 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) class ShadeInteractorTest : SysuiTestCase() { - private lateinit var underTest: ShadeInteractor - private val utils = SceneTestUtils(this) - private val testScope = utils.testScope - private val featureFlags = FakeFeatureFlags() - private val sceneContainerFlags = FakeSceneContainerFlags() - private val sceneInteractor = utils.sceneInteractor() - private val userSetupRepository = FakeUserSetupRepository() - private val userRepository = FakeUserRepository() - private val disableFlagsRepository = FakeDisableFlagsRepository() - private val keyguardRepository = FakeKeyguardRepository() - private val shadeRepository = FakeShadeRepository() - private val configurationRepository = FakeConfigurationRepository() - private val sharedNotificationContainerInteractor = - SharedNotificationContainerInteractor( - configurationRepository, - mContext, - ResourcesSplitShadeStateController() - ) - - @Mock private lateinit var manager: UserManager - @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode - @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController - @Mock private lateinit var activityStarter: ActivityStarter - @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor - @Mock private lateinit var activityManager: ActivityManager - @Mock private lateinit var uiEventLogger: UiEventLogger - @Mock private lateinit var guestInteractor: GuestUserInteractor - - private lateinit var userInteractor: UserInteractor + @Mock private lateinit var dozeParameters: DozeParameters + + private lateinit var testComponent: TestComponent + + private val configurationRepository + get() = testComponent.configurationRepository + private val deviceProvisioningRepository + get() = testComponent.deviceProvisioningRepository + private val disableFlagsRepository + get() = testComponent.disableFlagsRepository + private val keyguardRepository + get() = testComponent.keyguardRepository + private val keyguardTransitionRepository + get() = testComponent.keygaurdTransitionRepository + private val powerRepository + get() = testComponent.powerRepository + private val sceneInteractor + get() = testComponent.sceneInteractor + private val shadeRepository + get() = testComponent.shadeRepository + private val testScope + get() = testComponent.testScope + private val userRepository + get() = testComponent.userRepository + private val userSetupRepository + get() = testComponent.userSetupRepository + + private lateinit var underTest: ShadeInteractor @Before fun setUp() { MockitoAnnotations.initMocks(this) - featureFlags.set(Flags.FACE_AUTH_REFACTOR, false) - featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) - - val refreshUsersScheduler = - RefreshUsersScheduler( - applicationScope = testScope.backgroundScope, - mainDispatcher = utils.testDispatcher, - repository = userRepository, - ) + testComponent = + DaggerShadeInteractorTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FACE_AUTH_REFACTOR, false) + set(Flags.FULL_SCREEN_USER_SWITCHER, true) + }, + mocks = + TestMocksModule( + dozeParameters = dozeParameters, + ), + ) + underTest = testComponent.underTest runBlocking { val userInfos = @@ -131,44 +138,6 @@ class ShadeInteractorTest : SysuiTestCase() { userRepository.setUserInfos(userInfos) userRepository.setSelectedUserInfo(userInfos[0]) } - userInteractor = - UserInteractor( - applicationContext = context, - repository = userRepository, - activityStarter = activityStarter, - keyguardInteractor = - KeyguardInteractorFactory.create(featureFlags = featureFlags) - .keyguardInteractor, - featureFlags = featureFlags, - manager = manager, - headlessSystemUserMode = headlessSystemUserMode, - applicationScope = testScope.backgroundScope, - telephonyInteractor = - TelephonyInteractor( - repository = FakeTelephonyRepository(), - ), - broadcastDispatcher = fakeBroadcastDispatcher, - keyguardUpdateMonitor = keyguardUpdateMonitor, - backgroundDispatcher = utils.testDispatcher, - activityManager = activityManager, - refreshUsersScheduler = refreshUsersScheduler, - guestUserInteractor = guestInteractor, - uiEventLogger = uiEventLogger, - userRestrictionChecker = mock(), - ) - underTest = - ShadeInteractor( - testScope.backgroundScope, - disableFlagsRepository, - sceneContainerFlags, - { sceneInteractor }, - keyguardRepository, - userSetupRepository, - deviceProvisionedController, - userInteractor, - sharedNotificationContainerInteractor, - shadeRepository, - ) } @Test @@ -188,7 +157,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_deviceNotProvisioned_false() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(false) + deviceProvisioningRepository.setDeviceProvisioned(false) val actual by collectLastValue(underTest.isExpandToQsEnabled) @@ -198,7 +167,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_userNotSetupAndSimpleUserSwitcher_false() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(false) userRepository.setSettings(UserSwitcherSettingsModel(isSimpleUserSwitcher = true)) @@ -211,7 +180,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_shadeNotEnabled_false() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(true) disableFlagsRepository.disableFlags.value = @@ -227,7 +196,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_quickSettingsNotEnabled_false() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(true) disableFlagsRepository.disableFlags.value = @@ -242,7 +211,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_dozing_false() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(true) disableFlagsRepository.disableFlags.value = DisableFlagsModel( @@ -259,7 +228,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_userSetup_true() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = DisableFlagsModel( @@ -276,7 +245,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_notSimpleUserSwitcher_true() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = DisableFlagsModel( @@ -293,7 +262,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_respondsToDozingUpdates() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = DisableFlagsModel( @@ -321,7 +290,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_respondsToDisableUpdates() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = DisableFlagsModel( @@ -353,7 +322,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_respondsToUserUpdates() = testScope.runTest { - whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = DisableFlagsModel( @@ -1129,4 +1098,168 @@ class ShadeInteractorTest : SysuiTestCase() { // THEN interacting is false assertThat(interacting).isFalse() } + + @Test + fun isShadeTouchable_isFalse_whenFrpIsActive() = + testScope.runTest { + deviceProvisioningRepository.setFactoryResetProtectionActive(true) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + runCurrent() + assertThat(isShadeTouchable).isFalse() + } + + @Test + fun isShadeTouchable_isFalse_whenDeviceAsleepAndNotPulsing() = + testScope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + // goingToSleep == false + // TODO: remove? + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.LOCKSCREEN, + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_AOD, + ) + ) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + runCurrent() + assertThat(isShadeTouchable).isFalse() + } + + @Test + fun isShadeTouchable_isTrue_whenDeviceAsleepAndPulsing() = + testScope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + // goingToSleep == false + // TODO: remove? + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.LOCKSCREEN, + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_PULSING, + ) + ) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + runCurrent() + assertThat(isShadeTouchable).isTrue() + } + + @Test + fun isShadeTouchable_isFalse_whenStartingToSleepAndNotControlScreenOff() = + testScope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + // goingToSleep == true + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, + ) + ) + whenever(dozeParameters.shouldControlScreenOff()).thenReturn(false) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + runCurrent() + assertThat(isShadeTouchable).isFalse() + } + + @Test + fun isShadeTouchable_isTrue_whenStartingToSleepAndControlScreenOff() = + testScope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + // goingToSleep == true + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, + ) + ) + whenever(dozeParameters.shouldControlScreenOff()).thenReturn(true) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + runCurrent() + assertThat(isShadeTouchable).isTrue() + } + + @Test + fun isShadeTouchable_isTrue_whenNotAsleep() = + testScope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val isShadeTouchable by collectLastValue(underTest.isShadeTouchable) + runCurrent() + assertThat(isShadeTouchable).isTrue() + } + + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent { + + val underTest: ShadeInteractor + + val configurationRepository: FakeConfigurationRepository + val deviceProvisioningRepository: FakeDeviceProvisioningRepository + val disableFlagsRepository: FakeDisableFlagsRepository + val keyguardRepository: FakeKeyguardRepository + val keygaurdTransitionRepository: FakeKeyguardTransitionRepository + val powerRepository: FakePowerRepository + val sceneInteractor: SceneInteractor + val shadeRepository: FakeShadeRepository + val testScope: TestScope + val userRepository: FakeUserRepository + val userSetupRepository: FakeUserSetupRepository + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + mocks: TestMocksModule, + ): TestComponent + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index 14e58e5f570a..e8923a5baca8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -5,41 +5,32 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest +import com.android.SysUITestModule +import com.android.TestMocksModule import com.android.systemui.ExpandHelper -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase -import com.android.systemui.classifier.FalsingCollector -import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository -import com.android.systemui.dump.DumpManager -import com.android.systemui.keyguard.WakefulnessLifecycle -import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FakeFeatureFlagsClassicModule +import com.android.systemui.flags.Flags import com.android.systemui.media.controls.ui.MediaHierarchyManager -import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QS -import com.android.systemui.power.domain.interactor.PowerInteractorFactory -import com.android.systemui.scene.SceneTestUtils -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags +import com.android.systemui.res.R import com.android.systemui.shade.ShadeViewController -import com.android.systemui.shade.data.repository.FakeShadeRepository -import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.NotificationTestHelper -import com.android.systemui.statusbar.notification.stack.AmbientState import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController -import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.LSShadeTransitionLogger import com.android.systemui.statusbar.phone.ScrimController -import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository import com.android.systemui.statusbar.policy.FakeConfigurationController -import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController -import com.android.systemui.util.mockito.mock +import com.android.systemui.user.domain.UserDomainLayerModule +import dagger.BindsInstance +import dagger.Component import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import org.junit.After import org.junit.Assert.assertFalse @@ -60,9 +51,8 @@ import org.mockito.Mockito import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.verify -import org.mockito.Mockito.verifyZeroInteractions -import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever +import org.mockito.junit.MockitoJUnit private fun <T> anyObject(): T { return Mockito.anyObject<T>() @@ -73,68 +63,38 @@ private fun <T> anyObject(): T { @RunWith(AndroidTestingRunner::class) @OptIn(ExperimentalCoroutinesApi::class) class LockscreenShadeTransitionControllerTest : SysuiTestCase() { - private val utils = SceneTestUtils(this) - private val testScope = utils.testScope - lateinit var transitionController: LockscreenShadeTransitionController + private lateinit var testComponent: TestComponent + + private val transitionController + get() = testComponent.transitionController + private val configurationController + get() = testComponent.configurationController + private val disableFlagsRepository + get() = testComponent.disableFlagsRepository + private val testScope + get() = testComponent.testScope + lateinit var row: ExpandableNotificationRow - @Mock lateinit var statusbarStateController: SysuiStatusBarStateController - @Mock lateinit var logger: LSShadeTransitionLogger - @Mock lateinit var dumpManager: DumpManager + + @Mock lateinit var centralSurfaces: CentralSurfaces + @Mock lateinit var depthController: NotificationShadeDepthController + @Mock lateinit var expandHelperCallback: ExpandHelper.Callback @Mock lateinit var keyguardBypassController: KeyguardBypassController @Mock lateinit var lockScreenUserManager: NotificationLockscreenUserManager - @Mock lateinit var falsingCollector: FalsingCollector - @Mock lateinit var ambientState: AmbientState - @Mock lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock lateinit var mediaHierarchyManager: MediaHierarchyManager + @Mock lateinit var nsslController: NotificationStackScrollLayoutController + @Mock lateinit var qS: QS @Mock lateinit var scrimController: ScrimController - @Mock lateinit var falsingManager: FalsingManager @Mock lateinit var shadeViewController: ShadeViewController - @Mock lateinit var nsslController: NotificationStackScrollLayoutController - @Mock lateinit var depthController: NotificationShadeDepthController @Mock lateinit var stackscroller: NotificationStackScrollLayout - @Mock lateinit var expandHelperCallback: ExpandHelper.Callback - @Mock lateinit var mCentralSurfaces: CentralSurfaces - @Mock lateinit var qS: QS - @Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller - @Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller - @Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController - @Mock lateinit var activityStarter: ActivityStarter + @Mock lateinit var statusbarStateController: SysuiStatusBarStateController @Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback - private val sceneContainerFlags = FakeSceneContainerFlags() - private val sceneInteractor = utils.sceneInteractor() - private val disableFlagsRepository = FakeDisableFlagsRepository() - private val keyguardRepository = FakeKeyguardRepository() - private val configurationRepository = FakeConfigurationRepository() - private val sharedNotificationContainerInteractor = SharedNotificationContainerInteractor( - configurationRepository, - mContext, - ResourcesSplitShadeStateController() - ) - private val shadeInteractor = - ShadeInteractor( - testScope.backgroundScope, - disableFlagsRepository, - sceneContainerFlags, - { sceneInteractor }, - keyguardRepository, - userSetupRepository = FakeUserSetupRepository(), - deviceProvisionedController = mock(), - userInteractor = mock(), - sharedNotificationContainerInteractor, - repository = FakeShadeRepository(), - ) - private val powerInteractor = PowerInteractorFactory.create().powerInteractor - @JvmField @Rule val mockito = MockitoJUnit.rule() - private val configurationController = FakeConfigurationController() + @JvmField @Rule val mockito = MockitoJUnit.rule() @Before fun setup() { - // By default, have the shade enabled - disableFlagsRepository.disableFlags.value = DisableFlagsModel() - testScope.runCurrent() - val helper = NotificationTestHelper(mContext, mDependency, TestableLooper.get(this)) row = helper.createRow() context @@ -143,55 +103,9 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { context .getOrCreateTestableResources() .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100) - transitionController = - LockscreenShadeTransitionController( - statusBarStateController = statusbarStateController, - logger = logger, - keyguardBypassController = keyguardBypassController, - lockScreenUserManager = lockScreenUserManager, - falsingCollector = falsingCollector, - ambientState = ambientState, - mediaHierarchyManager = mediaHierarchyManager, - depthController = depthController, - wakefulnessLifecycle = wakefulnessLifecycle, - context = context, - configurationController = configurationController, - falsingManager = falsingManager, - dumpManager = dumpManager, - splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller }, - singleShadeOverScrollerFactory = { singleShadeOverScroller }, - scrimTransitionController = - LockscreenShadeScrimTransitionController( - scrimController, - context, - configurationController, - dumpManager, - ResourcesSplitShadeStateController() - ), - keyguardTransitionControllerFactory = { notificationPanelController -> - LockscreenShadeKeyguardTransitionController( - mediaHierarchyManager, - notificationPanelController, - context, - configurationController, - dumpManager, - ResourcesSplitShadeStateController() - ) - }, - qsTransitionControllerFactory = { qsTransitionController }, - activityStarter = activityStarter, - shadeRepository = FakeShadeRepository(), - shadeInteractor = shadeInteractor, - powerInteractor = powerInteractor, - splitShadeStateController = ResourcesSplitShadeStateController() - ) - transitionController.addCallback(transitionControllerCallback) + whenever(nsslController.view).thenReturn(stackscroller) whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback) - transitionController.shadeViewController = shadeViewController - transitionController.centralSurfaces = mCentralSurfaces - transitionController.qS = qS - transitionController.setStackScroller(nsslController) whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD) whenever(nsslController.isInLockedDownShade).thenReturn(false) whenever(qS.isFullyCollapsed).thenReturn(true) @@ -199,9 +113,36 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { .thenReturn(true) whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true) whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true) - whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false) whenever(keyguardBypassController.bypassEnabled).thenReturn(false) - clearInvocations(mCentralSurfaces) + + testComponent = + DaggerLockscreenShadeTransitionControllerTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FULL_SCREEN_USER_SWITCHER, false) + }, + mocks = + TestMocksModule( + notificationShadeDepthController = depthController, + keyguardBypassController = keyguardBypassController, + mediaHierarchyManager = mediaHierarchyManager, + notificationLockscreenUserManager = lockScreenUserManager, + notificationStackScrollLayoutController = nsslController, + scrimController = scrimController, + statusBarStateController = statusbarStateController, + ) + ) + + transitionController.addCallback(transitionControllerCallback) + transitionController.shadeViewController = shadeViewController + transitionController.centralSurfaces = centralSurfaces + transitionController.qS = qS + transitionController.setStackScroller(nsslController) + clearInvocations(centralSurfaces) + + testScope.runCurrent() } @After @@ -282,7 +223,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { transitionController.goToLockedShade(null) verify(statusbarStateController, never()).setState(anyInt()) verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true) - verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject()) + verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject()) } @Test @@ -318,7 +259,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat()) verify(transitionControllerCallback, never()) .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong()) - verify(qsTransitionController, never()).dragDownAmount = anyFloat() + verify(qS, never()).setTransitionToFullShadeProgress(anyBoolean(), anyFloat(), anyFloat()) } @Test @@ -329,7 +270,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat()) verify(transitionControllerCallback) .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong()) - verify(qsTransitionController).dragDownAmount = 10f + verify(qS).setTransitionToFullShadeProgress(eq(true), anyFloat(), anyFloat()) verify(depthController).transitionToFullShadeProgress = anyFloat() } @@ -532,8 +473,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { transitionController.dragDownAmount = 10f - verify(singleShadeOverScroller).expansionDragDownAmount = 10f - verifyZeroInteractions(splitShadeOverScroller) + verify(nsslController).setOverScrollAmount(0) + verify(scrimController, never()).setNotificationsOverScrollAmount(anyInt()) } @Test @@ -542,8 +483,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { transitionController.dragDownAmount = 10f - verify(splitShadeOverScroller).expansionDragDownAmount = 10f - verifyZeroInteractions(singleShadeOverScroller) + verify(nsslController).setOverScrollAmount(0) + verify(scrimController).setNotificationsOverScrollAmount(0) } @Test @@ -591,6 +532,32 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { progress: Float, lockScreenNotificationsProgress: Float ) { - scrimController.setTransitionToFullShadeProgress(progress, lockScreenNotificationsProgress) + setTransitionToFullShadeProgress(progress, lockScreenNotificationsProgress) + } + + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent { + + val transitionController: LockscreenShadeTransitionController + + val configurationController: FakeConfigurationController + val disableFlagsRepository: FakeDisableFlagsRepository + val testScope: TestScope + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + mocks: TestMocksModule, + ): TestComponent + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt new file mode 100644 index 000000000000..99c3b194a662 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt @@ -0,0 +1,282 @@ +/* + * 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. + */ +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.statusbar.notification.icon.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.SysUITestModule +import com.android.TestMocksModule +import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FakeFeatureFlagsClassicModule +import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.DozeStateModel +import com.android.systemui.keyguard.shared.model.DozeTransitionModel +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.shared.model.WakeSleepReason +import com.android.systemui.power.shared.model.WakefulnessState +import com.android.systemui.statusbar.phone.DozeParameters +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository +import com.android.systemui.user.domain.UserDomainLayerModule +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import dagger.BindsInstance +import dagger.Component +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidJUnit4::class) +class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { + + @Mock private lateinit var dozeParams: DozeParameters + + private lateinit var testComponent: TestComponent + private val underTest + get() = testComponent.underTest + private val deviceProvisioningRepository + get() = testComponent.deviceProvisioningRepository + private val keyguardRepository + get() = testComponent.keyguardRepository + private val keyguardTransitionRepository + get() = testComponent.keyguardTransitionRepository + private val powerRepository + get() = testComponent.powerRepository + private val scope + get() = testComponent.scope + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + + testComponent = + DaggerNotificationIconContainerAlwaysOnDisplayViewModelTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FACE_AUTH_REFACTOR, value = false) + set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) + }, + mocks = + TestMocksModule( + dozeParameters = dozeParams, + ), + ) + + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + deviceProvisioningRepository.setFactoryResetProtectionActive(false) + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.OTHER, + lastSleepReason = WakeSleepReason.OTHER, + ) + } + + @Test + fun animationsEnabled_isFalse_whenFrpIsActive() = + scope.runTest { + deviceProvisioningRepository.setFactoryResetProtectionActive(true) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() + } + + @Test + fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_AOD, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() + } + + @Test + fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_PULSING, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() + } + + @Test + fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, + ) + ) + whenever(dozeParams.shouldControlScreenOff()).thenReturn(false) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() + } + + @Test + fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, + ) + ) + whenever(dozeParams.shouldControlScreenOff()).thenReturn(true) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() + } + + @Test + fun animationsEnabled_isTrue_whenNotAsleep() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() + } + + @Test + fun animationsEnabled_isTrue_whenKeyguardIsShowing() = + scope.runTest { + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + runCurrent() + + assertThat(animationsEnabled).isTrue() + + keyguardRepository.setKeyguardOccluded(true) + runCurrent() + + assertThat(animationsEnabled).isFalse() + + keyguardRepository.setKeyguardShowing(false) + keyguardRepository.setKeyguardOccluded(true) + runCurrent() + + assertThat(animationsEnabled).isFalse() + } + + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + BiometricsDomainLayerModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent { + + val underTest: NotificationIconContainerAlwaysOnDisplayViewModel + + val deviceProvisioningRepository: FakeDeviceProvisioningRepository + val keyguardRepository: FakeKeyguardRepository + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val powerRepository: FakePowerRepository + val scope: TestScope + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + mocks: TestMocksModule, + featureFlags: FakeFeatureFlagsClassicModule, + ): TestComponent + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt new file mode 100644 index 000000000000..d1518f7e0d08 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt @@ -0,0 +1,274 @@ +/* + * 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. + */ +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.statusbar.notification.icon.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.SysUITestModule +import com.android.TestMocksModule +import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FakeFeatureFlagsClassicModule +import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.DozeStateModel +import com.android.systemui.keyguard.shared.model.DozeTransitionModel +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.shared.model.WakeSleepReason +import com.android.systemui.power.shared.model.WakefulnessState +import com.android.systemui.statusbar.phone.DozeParameters +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository +import com.android.systemui.user.domain.UserDomainLayerModule +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import dagger.BindsInstance +import dagger.Component +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidJUnit4::class) +class NotificationIconContainerStatusBarViewModelTest : SysuiTestCase() { + + @Mock lateinit var dozeParams: DozeParameters + + private lateinit var testComponent: TestComponent + private val underTest: NotificationIconContainerStatusBarViewModel + get() = testComponent.underTest + private val deviceProvisioningRepository + get() = testComponent.deviceProvisioningRepository + private val keyguardTransitionRepository + get() = testComponent.keyguardTransitionRepository + private val keyguardRepository + get() = testComponent.keyguardRepository + private val powerRepository + get() = testComponent.powerRepository + private val scope + get() = testComponent.scope + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + + testComponent = + DaggerNotificationIconContainerStatusBarViewModelTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FACE_AUTH_REFACTOR, value = false) + set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) + }, + mocks = + TestMocksModule( + dozeParameters = dozeParams, + ), + ) + + keyguardRepository.setKeyguardShowing(false) + deviceProvisioningRepository.setFactoryResetProtectionActive(false) + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.OTHER, + lastSleepReason = WakeSleepReason.OTHER, + ) + } + + @Test + fun animationsEnabled_isFalse_whenFrpIsActive() = + scope.runTest { + deviceProvisioningRepository.setFactoryResetProtectionActive(true) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() + } + + @Test + fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_AOD, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() + } + + @Test + fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_PULSING, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() + } + + @Test + fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, + ) + ) + whenever(dozeParams.shouldControlScreenOff()).thenReturn(false) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() + } + + @Test + fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, + ) + ) + whenever(dozeParams.shouldControlScreenOff()).thenReturn(true) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() + } + + @Test + fun animationsEnabled_isTrue_whenNotAsleep() = + scope.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() + } + + @Test + fun animationsEnabled_isTrue_whenKeyguardIsNotShowing() = + scope.runTest { + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + ) + ) + keyguardRepository.setKeyguardShowing(true) + runCurrent() + + assertThat(animationsEnabled).isFalse() + + keyguardRepository.setKeyguardShowing(false) + runCurrent() + + assertThat(animationsEnabled).isTrue() + } + + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + BiometricsDomainLayerModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent { + + val underTest: NotificationIconContainerStatusBarViewModel + + val deviceProvisioningRepository: FakeDeviceProvisioningRepository + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val keyguardRepository: FakeKeyguardRepository + val powerRepository: FakePowerRepository + val scope: TestScope + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + mocks: TestMocksModule, + featureFlags: FakeFeatureFlagsClassicModule, + ): TestComponent + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index e254dd085b2e..ac11ff29b83a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -19,36 +19,35 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.res.R +import com.android.SysUITestModule +import com.android.TestMocksModule import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.SharedNotificationContainerPosition import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FakeFeatureFlagsClassicModule +import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor -import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor -import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep -import com.android.systemui.scene.SceneTestUtils -import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags +import com.android.systemui.res.R import com.android.systemui.shade.data.repository.FakeShadeRepository -import com.android.systemui.shade.domain.interactor.ShadeInteractor -import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor -import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository -import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController -import com.android.systemui.user.domain.interactor.UserInteractor +import com.android.systemui.user.domain.UserDomainLayerModule import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import dagger.BindsInstance +import dagger.Component +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -60,29 +59,27 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class SharedNotificationContainerViewModelTest : SysuiTestCase() { - private val utils = SceneTestUtils(this) - - private val testScope = utils.testScope - - private val disableFlagsRepository = FakeDisableFlagsRepository() - private val userSetupRepository = FakeUserSetupRepository() - private val shadeRepository = FakeShadeRepository() - private val keyguardRepository = FakeKeyguardRepository() - private val sceneContainerFlags = FakeSceneContainerFlags() - private val sceneInteractor = utils.sceneInteractor() - - private lateinit var configurationRepository: FakeConfigurationRepository - private lateinit var sharedNotificationContainerInteractor: - SharedNotificationContainerInteractor - private lateinit var underTest: SharedNotificationContainerViewModel - private lateinit var keyguardInteractor: KeyguardInteractor - private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor - private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository - private lateinit var shadeInteractor: ShadeInteractor + + private lateinit var testComponent: TestComponent + + private val shadeRepository + get() = testComponent.shadeRepository + private val keyguardRepository + get() = testComponent.keyguardRepository + private val configurationRepository + get() = testComponent.configurationRepository + private val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor + get() = testComponent.sharedNotificationContainerInteractor + private val underTest: SharedNotificationContainerViewModel + get() = testComponent.underTest + private val keyguardInteractor: KeyguardInteractor + get() = testComponent.keyguardInteractor + private val keyguardTransitionRepository + get() = testComponent.keyguardTransitionRepository + private val testScope + get() = testComponent.testScope @Mock private lateinit var notificationStackSizeCalculator: NotificationStackSizeCalculator - @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController - @Mock private lateinit var userInteractor: UserInteractor @Mock private lateinit var notificationStackScrollLayoutController: NotificationStackScrollLayoutController @@ -94,43 +91,21 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { whenever(notificationStackScrollLayoutController.getView()).thenReturn(mock()) whenever(notificationStackScrollLayoutController.getShelfHeight()).thenReturn(0) - configurationRepository = FakeConfigurationRepository() - KeyguardTransitionInteractorFactory.create( - scope = testScope.backgroundScope, - ) - .also { - keyguardInteractor = it.keyguardInteractor - keyguardTransitionInteractor = it.keyguardTransitionInteractor - keyguardTransitionRepository = it.repository - } - sharedNotificationContainerInteractor = - SharedNotificationContainerInteractor( - configurationRepository, - mContext, - ResourcesSplitShadeStateController() - ) - shadeInteractor = - ShadeInteractor( - testScope.backgroundScope, - disableFlagsRepository, - sceneContainerFlags, - { sceneInteractor }, - keyguardRepository, - userSetupRepository, - deviceProvisionedController, - userInteractor, - sharedNotificationContainerInteractor, - shadeRepository, - ) - underTest = - SharedNotificationContainerViewModel( - sharedNotificationContainerInteractor, - keyguardInteractor, - keyguardTransitionInteractor, - notificationStackSizeCalculator, - notificationStackScrollLayoutController, - shadeInteractor - ) + testComponent = + DaggerSharedNotificationContainerViewModelTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FULL_SCREEN_USER_SWITCHER, true) + }, + mocks = + TestMocksModule( + notificationStackSizeCalculator = notificationStackSizeCalculator, + notificationStackScrollLayoutController = + notificationStackScrollLayoutController, + ) + ) } @Test @@ -404,4 +379,34 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { ) ) } + + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent { + + val underTest: SharedNotificationContainerViewModel + + val configurationRepository: FakeConfigurationRepository + val keyguardRepository: FakeKeyguardRepository + val keyguardInteractor: KeyguardInteractor + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val shadeRepository: FakeShadeRepository + val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor + val testScope: TestScope + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + mocks: TestMocksModule, + ): TestComponent + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index e33fa22bfc0c..e2efd258994f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -336,6 +336,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false); // Set default value to avoid IllegalStateException. mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false); + mFeatureFlags.setDefault(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR); // For the Shade to respond to Back gesture, we must enable the event routing mFeatureFlags.set(Flags.WM_SHADE_ALLOW_BACK_GESTURE, true); // For the Shade to animate during the Back gesture, we must enable the animation flag. diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt new file mode 100644 index 000000000000..12694ae998c1 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt @@ -0,0 +1,108 @@ +/* + * 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. + */ +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.statusbar.policy.data.repository + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.mockito.withArgCaptor +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidJUnit4::class) +class DeviceProvisioningRepositoryImplTest : SysuiTestCase() { + + @Mock lateinit var deviceProvisionedController: DeviceProvisionedController + + lateinit var underTest: DeviceProvisioningRepositoryImpl + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + underTest = + DeviceProvisioningRepositoryImpl( + deviceProvisionedController, + ) + } + + @Test + fun isDeviceProvisioned_reflectsCurrentControllerState() = runTest { + whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + val deviceProvisioned by collectLastValue(underTest.isDeviceProvisioned) + assertThat(deviceProvisioned).isTrue() + } + + @Test + fun isDeviceProvisioned_updatesWhenControllerStateChanges_toTrue() = runTest { + val deviceProvisioned by collectLastValue(underTest.isDeviceProvisioned) + runCurrent() + whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) + withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) } + .onDeviceProvisionedChanged() + assertThat(deviceProvisioned).isTrue() + } + + @Test + fun isDeviceProvisioned_updatesWhenControllerStateChanges_toFalse() = runTest { + val deviceProvisioned by collectLastValue(underTest.isDeviceProvisioned) + runCurrent() + whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(false) + withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) } + .onDeviceProvisionedChanged() + assertThat(deviceProvisioned).isFalse() + } + + @Test + fun isFrpActive_reflectsCurrentControllerState() = runTest { + whenever(deviceProvisionedController.isFrpActive).thenReturn(true) + val frpActive by collectLastValue(underTest.isFactoryResetProtectionActive) + assertThat(frpActive).isTrue() + } + + @Test + fun isFrpActive_updatesWhenControllerStateChanges_toTrue() = runTest { + val frpActive by collectLastValue(underTest.isFactoryResetProtectionActive) + runCurrent() + whenever(deviceProvisionedController.isFrpActive).thenReturn(true) + withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) } + .onFrpActiveChanged() + assertThat(frpActive).isTrue() + } + + @Test + fun isFrpActive_updatesWhenControllerStateChanges_toFalse() = runTest { + val frpActive by collectLastValue(underTest.isFactoryResetProtectionActive) + runCurrent() + whenever(deviceProvisionedController.isFrpActive).thenReturn(false) + withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) } + .onFrpActiveChanged() + assertThat(frpActive).isFalse() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index 409ba4801d0d..c8327029026d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -86,20 +86,36 @@ import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; +import com.android.keyguard.KeyguardSecurityModel; import com.android.launcher3.icons.BubbleIconFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; +import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository; +import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; +import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.FakeFeatureFlagsClassic; import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.keyguard.data.repository.FakeCommandQueue; import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository; +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository; +import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor; +import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.power.data.repository.FakePowerRepository; +import com.android.systemui.power.domain.interactor.PowerInteractor; import com.android.systemui.scene.FakeWindowRootViewComponent; import com.android.systemui.scene.SceneTestUtils; +import com.android.systemui.scene.data.repository.SceneContainerRepository; +import com.android.systemui.scene.domain.interactor.SceneInteractor; import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags; +import com.android.systemui.scene.shared.logger.SceneLogger; import com.android.systemui.settings.FakeDisplayTracker; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.NotificationShadeWindowControllerImpl; @@ -139,6 +155,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository; import com.android.systemui.user.domain.interactor.UserInteractor; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.WindowManagerShellWrapper; @@ -329,6 +346,8 @@ public class BubblesTest extends SysuiTestCase { private UserHandle mUser0; private FakeBubbleProperties mBubbleProperties; + private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor; + private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor; @Before public void setUp() throws Exception { @@ -350,21 +369,94 @@ public class BubblesTest extends SysuiTestCase { when(mNotificationShadeWindowView.getViewTreeObserver()) .thenReturn(mock(ViewTreeObserver.class)); - mShadeInteractor = new ShadeInteractor( + + FakeDeviceProvisioningRepository deviceProvisioningRepository = + new FakeDeviceProvisioningRepository(); + deviceProvisioningRepository.setDeviceProvisioned(true); + FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository(); + FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic(); + FakeShadeRepository shadeRepository = new FakeShadeRepository(); + FakePowerRepository powerRepository = new FakePowerRepository(); + FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository(); + + PowerInteractor powerInteractor = new PowerInteractor( + powerRepository, + new FalsingCollectorFake(), + mock(ScreenOffAnimationController.class), + mStatusBarStateController); + + SceneInteractor sceneInteractor = new SceneInteractor( mTestScope.getBackgroundScope(), - new FakeDisableFlagsRepository(), - new FakeSceneContainerFlags(), - mUtils::sceneInteractor, - new FakeKeyguardRepository(), - new FakeUserSetupRepository(), - mock(DeviceProvisionedController.class), - mock(UserInteractor.class), - new SharedNotificationContainerInteractor( - new FakeConfigurationRepository(), - mContext, - new ResourcesSplitShadeStateController()), - new FakeShadeRepository() - ); + new SceneContainerRepository( + mTestScope.getBackgroundScope(), + mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())), + powerRepository, + mock(SceneLogger.class)); + + FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags(); + KeyguardInteractor keyguardInteractor = new KeyguardInteractor( + keyguardRepository, + new FakeCommandQueue(), + powerInteractor, + featureFlags, + sceneContainerFlags, + new FakeDeviceEntryRepository(), + new FakeKeyguardBouncerRepository(), + configurationRepository, + shadeRepository, + () -> sceneInteractor); + + FakeKeyguardTransitionRepository keyguardTransitionRepository = + new FakeKeyguardTransitionRepository(); + + KeyguardTransitionInteractor keyguardTransitionInteractor = + new KeyguardTransitionInteractor( + mTestScope.getBackgroundScope(), + keyguardTransitionRepository, + () -> keyguardInteractor, + () -> mFromLockscreenTransitionInteractor, + () -> mFromPrimaryBouncerTransitionInteractor); + + mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor( + keyguardTransitionRepository, + keyguardTransitionInteractor, + mTestScope.getBackgroundScope(), + keyguardInteractor, + featureFlags, + shadeRepository, + powerInteractor); + + mFromPrimaryBouncerTransitionInteractor = new FromPrimaryBouncerTransitionInteractor( + keyguardTransitionRepository, + keyguardTransitionInteractor, + mTestScope.getBackgroundScope(), + keyguardInteractor, + featureFlags, + mock(KeyguardSecurityModel.class), + powerInteractor); + + ResourcesSplitShadeStateController splitShadeStateController = + new ResourcesSplitShadeStateController(); + + mShadeInteractor = + new ShadeInteractor( + mTestScope.getBackgroundScope(), + deviceProvisioningRepository, + new FakeDisableFlagsRepository(), + mDozeParameters, + sceneContainerFlags, + () -> sceneInteractor, + keyguardRepository, + keyguardTransitionInteractor, + powerInteractor, + new FakeUserSetupRepository(), + mock(UserInteractor.class), + new SharedNotificationContainerInteractor( + configurationRepository, + mContext, + splitShadeStateController), + new FakeShadeRepository() + ); mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl( mContext, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt index 0e594964bb30..813197b171ad 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt @@ -15,21 +15,27 @@ */ package com.android.systemui +import com.android.systemui.classifier.FakeClassifierModule import com.android.systemui.data.FakeSystemUiDataLayerModule import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.log.FakeUiEventLoggerModule import com.android.systemui.scene.FakeSceneModule import com.android.systemui.settings.FakeSettingsModule +import com.android.systemui.statusbar.policy.FakeConfigurationControllerModule +import com.android.systemui.statusbar.policy.FakeSplitShadeStateControllerModule import com.android.systemui.util.concurrency.FakeExecutorModule import dagger.Module @Module( includes = [ + FakeClassifierModule::class, + FakeConfigurationControllerModule::class, FakeExecutorModule::class, FakeFeatureFlagsClassicModule::class, - FakeSettingsModule::class, FakeSceneModule::class, + FakeSettingsModule::class, + FakeSplitShadeStateControllerModule::class, FakeSystemUiDataLayerModule::class, FakeUiEventLoggerModule::class, ] diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeClassifierModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeClassifierModule.kt new file mode 100644 index 000000000000..23bad39a262e --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeClassifierModule.kt @@ -0,0 +1,21 @@ +/* + * 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.classifier + +import dagger.Module + +@Module(includes = [FakeFalsingCollectorModule::class, FakeFalsingManagerModule::class]) +object FakeClassifierModule diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingCollectorModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingCollectorModule.kt new file mode 100644 index 000000000000..92acc9465bb0 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingCollectorModule.kt @@ -0,0 +1,25 @@ +/* + * 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.classifier + +import dagger.Binds +import dagger.Module + +@Module +interface FakeFalsingCollectorModule { + @Binds @FalsingCollectorActual fun bindFake(fake: FalsingCollectorFake): FalsingCollector + @Binds fun bindFakeLegacy(fake: FalsingCollectorFake): FalsingCollector +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingManagerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingManagerModule.kt new file mode 100644 index 000000000000..554fc75ec1db --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingManagerModule.kt @@ -0,0 +1,25 @@ +/* + * 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.classifier + +import com.android.systemui.plugins.FalsingManager +import dagger.Binds +import dagger.Module + +@Module +interface FakeFalsingManagerModule { + @Binds fun bindFake(fake: FalsingManagerFake): FalsingManager +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java index d47e88fc9385..5038285aef00 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -21,15 +21,19 @@ import static com.google.common.truth.Truth.assertWithMessage; import android.net.Uri; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.FalsingManager; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + /** * Simple Fake for testing where {@link FalsingManager} is required. */ +@SysUISingleton public class FalsingManagerFake implements FalsingManager { private boolean mIsFalseTouch; private boolean mIsSimpleTap; @@ -46,6 +50,10 @@ public class FalsingManagerFake implements FalsingManager { private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>(); private final List<FalsingTapListener> mTapListeners = new ArrayList<>(); + @Inject + public FalsingManagerFake() { + } + @Override public void onSuccessfulUnlock() { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt index f866932309bb..29fb52aabd39 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt @@ -17,6 +17,7 @@ package com.android.systemui.data import com.android.systemui.bouncer.data.repository.FakeBouncerDataLayerModule import com.android.systemui.common.ui.data.FakeCommonDataLayerModule +import com.android.systemui.deviceentry.data.FakeDeviceEntryDataLayerModule import com.android.systemui.keyguard.data.FakeKeyguardDataLayerModule import com.android.systemui.power.data.FakePowerDataLayerModule import com.android.systemui.shade.data.repository.FakeShadeDataLayerModule @@ -28,8 +29,9 @@ import dagger.Module @Module( includes = [ - FakeCommonDataLayerModule::class, FakeBouncerDataLayerModule::class, + FakeCommonDataLayerModule::class, + FakeDeviceEntryDataLayerModule::class, FakeKeyguardDataLayerModule::class, FakePowerDataLayerModule::class, FakeShadeDataLayerModule::class, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt new file mode 100644 index 000000000000..ef02bdd9c35c --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt @@ -0,0 +1,21 @@ +/* + * 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.deviceentry.data + +import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepositoryModule +import dagger.Module + +@Module(includes = [FakeDeviceEntryRepositoryModule::class]) object FakeDeviceEntryDataLayerModule diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt index 5e60a09e006b..26d95c0a0ea3 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt @@ -1,11 +1,16 @@ package com.android.systemui.deviceentry.data.repository +import com.android.systemui.dagger.SysUISingleton +import dagger.Binds +import dagger.Module +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow /** Fake implementation of [DeviceEntryRepository] */ -class FakeDeviceEntryRepository : DeviceEntryRepository { +@SysUISingleton +class FakeDeviceEntryRepository @Inject constructor() : DeviceEntryRepository { private var isInsecureLockscreenEnabled = true private var isBypassEnabled = false @@ -33,3 +38,8 @@ class FakeDeviceEntryRepository : DeviceEntryRepository { this.isBypassEnabled = isBypassEnabled } } + +@Module +interface FakeDeviceEntryRepositoryModule { + @Binds fun bindFake(fake: FakeDeviceEntryRepository): DeviceEntryRepository +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt index 1bec82b0875b..822edfc7f6cd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.data import com.android.systemui.statusbar.disableflags.data.FakeStatusBarDisableFlagsDataLayerModule import com.android.systemui.statusbar.pipeline.data.FakeStatusBarPipelineDataLayerModule +import com.android.systemui.statusbar.policy.data.FakeStatusBarPolicyDataLayerModule import dagger.Module @Module( @@ -24,6 +25,7 @@ import dagger.Module [ FakeStatusBarDisableFlagsDataLayerModule::class, FakeStatusBarPipelineDataLayerModule::class, + FakeStatusBarPolicyDataLayerModule::class, ] ) object FakeStatusBarDataLayerModule diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt index 16a326869562..23477d86807c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt @@ -1,9 +1,14 @@ package com.android.systemui.statusbar.policy import android.content.res.Configuration +import com.android.systemui.dagger.SysUISingleton +import dagger.Binds +import dagger.Module +import javax.inject.Inject /** Fake implementation of [ConfigurationController] for tests. */ -class FakeConfigurationController : ConfigurationController { +@SysUISingleton +class FakeConfigurationController @Inject constructor() : ConfigurationController { private var listeners = mutableListOf<ConfigurationController.ConfigurationListener>() @@ -33,3 +38,8 @@ class FakeConfigurationController : ConfigurationController { override fun isLayoutRtl(): Boolean = false } + +@Module +interface FakeConfigurationControllerModule { + @Binds fun bindFake(fake: FakeConfigurationController): ConfigurationController +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSplitShadeStateControllerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSplitShadeStateControllerModule.kt new file mode 100644 index 000000000000..14bab84e62b2 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSplitShadeStateControllerModule.kt @@ -0,0 +1,24 @@ +/* + * 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.statusbar.policy + +import dagger.Binds +import dagger.Module + +@Module +interface FakeSplitShadeStateControllerModule { + @Binds fun bindFake(fake: ResourcesSplitShadeStateController): SplitShadeStateController +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/FakeStatusBarPolicyDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/FakeStatusBarPolicyDataLayerModule.kt new file mode 100644 index 000000000000..5aece1bbbd31 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/FakeStatusBarPolicyDataLayerModule.kt @@ -0,0 +1,22 @@ +/* + * 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.statusbar.policy.data + +import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepositoryModule +import dagger.Module + +@Module(includes = [FakeDeviceProvisioningRepositoryModule::class]) +object FakeStatusBarPolicyDataLayerModule diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt new file mode 100644 index 000000000000..300229954044 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt @@ -0,0 +1,42 @@ +/* + * 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.statusbar.policy.data.repository + +import com.android.systemui.dagger.SysUISingleton +import dagger.Binds +import dagger.Module +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +@SysUISingleton +class FakeDeviceProvisioningRepository @Inject constructor() : DeviceProvisioningRepository { + private val _isDeviceProvisioned = MutableStateFlow(false) + override val isDeviceProvisioned: Flow<Boolean> = _isDeviceProvisioned + private val _isFactoryResetProtectionActive = MutableStateFlow(false) + override val isFactoryResetProtectionActive: Flow<Boolean> = _isFactoryResetProtectionActive + fun setDeviceProvisioned(isProvisioned: Boolean) { + _isDeviceProvisioned.value = isProvisioned + } + fun setFactoryResetProtectionActive(isActive: Boolean) { + _isFactoryResetProtectionActive.value = isActive + } +} + +@Module +interface FakeDeviceProvisioningRepositoryModule { + @Binds fun bindFake(fake: FakeDeviceProvisioningRepository): DeviceProvisioningRepository +} |