1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.scene 18 19 import android.content.pm.UserInfo 20 import com.android.systemui.SysuiTestCase 21 import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel 22 import com.android.systemui.authentication.data.repository.AuthenticationRepository 23 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository 24 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor 25 import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel 26 import com.android.systemui.bouncer.data.repository.BouncerRepository 27 import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository 28 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor 29 import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel 30 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository 31 import com.android.systemui.flags.FakeFeatureFlags 32 import com.android.systemui.flags.Flags 33 import com.android.systemui.keyguard.data.repository.FakeCommandQueue 34 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository 35 import com.android.systemui.keyguard.data.repository.KeyguardRepository 36 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor 37 import com.android.systemui.keyguard.shared.model.WakeSleepReason 38 import com.android.systemui.keyguard.shared.model.WakefulnessModel 39 import com.android.systemui.keyguard.shared.model.WakefulnessState 40 import com.android.systemui.scene.data.repository.SceneContainerRepository 41 import com.android.systemui.scene.domain.interactor.SceneInteractor 42 import com.android.systemui.scene.shared.model.SceneContainerConfig 43 import com.android.systemui.scene.shared.model.SceneKey 44 import com.android.systemui.user.data.repository.FakeUserRepository 45 import com.android.systemui.user.data.repository.UserRepository 46 import com.android.systemui.util.mockito.mock 47 import com.android.systemui.util.mockito.whenever 48 import kotlinx.coroutines.CoroutineScope 49 import kotlinx.coroutines.ExperimentalCoroutinesApi 50 import kotlinx.coroutines.runBlocking 51 import kotlinx.coroutines.test.StandardTestDispatcher 52 import kotlinx.coroutines.test.TestScope 53 import kotlinx.coroutines.test.currentTime 54 55 /** 56 * Utilities for creating scene container framework related repositories, interactors, and 57 * view-models for tests. 58 */ 59 @OptIn(ExperimentalCoroutinesApi::class) 60 class SceneTestUtils( 61 test: SysuiTestCase, 62 ) { 63 val testDispatcher = StandardTestDispatcher() 64 val testScope = TestScope(testDispatcher) 65 val featureFlags = 66 FakeFeatureFlags().apply { 67 set(Flags.SCENE_CONTAINER, true) 68 set(Flags.FACE_AUTH_REFACTOR, false) 69 } 70 private val userRepository: UserRepository by lazy { 71 FakeUserRepository().apply { 72 val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0)) 73 setUserInfos(users) 74 runBlocking { setSelectedUserInfo(users.first()) } 75 } 76 } 77 78 val authenticationRepository: FakeAuthenticationRepository by lazy { 79 FakeAuthenticationRepository( 80 currentTime = { testScope.currentTime }, 81 ) 82 } 83 val keyguardRepository: FakeKeyguardRepository by lazy { 84 FakeKeyguardRepository().apply { 85 setWakefulnessModel( 86 WakefulnessModel( 87 WakefulnessState.AWAKE, 88 WakeSleepReason.OTHER, 89 WakeSleepReason.OTHER, 90 ) 91 ) 92 } 93 } 94 95 private val context = test.context 96 97 fun fakeSceneContainerRepository( 98 containerConfig: SceneContainerConfig = fakeSceneContainerConfig(), 99 ): SceneContainerRepository { 100 return SceneContainerRepository(applicationScope(), containerConfig) 101 } 102 103 fun fakeSceneKeys(): List<SceneKey> { 104 return listOf( 105 SceneKey.QuickSettings, 106 SceneKey.Shade, 107 SceneKey.Lockscreen, 108 SceneKey.Bouncer, 109 SceneKey.Gone, 110 ) 111 } 112 113 fun fakeSceneContainerConfig( 114 sceneKeys: List<SceneKey> = fakeSceneKeys(), 115 ): SceneContainerConfig { 116 return SceneContainerConfig( 117 sceneKeys = sceneKeys, 118 initialSceneKey = SceneKey.Lockscreen, 119 ) 120 } 121 122 fun sceneInteractor( 123 repository: SceneContainerRepository = fakeSceneContainerRepository() 124 ): SceneInteractor { 125 return SceneInteractor( 126 applicationScope = applicationScope(), 127 repository = repository, 128 logger = mock(), 129 ) 130 } 131 132 fun authenticationRepository(): FakeAuthenticationRepository { 133 return authenticationRepository 134 } 135 136 fun authenticationInteractor( 137 repository: AuthenticationRepository, 138 sceneInteractor: SceneInteractor = sceneInteractor(), 139 ): AuthenticationInteractor { 140 return AuthenticationInteractor( 141 applicationScope = applicationScope(), 142 repository = repository, 143 backgroundDispatcher = testDispatcher, 144 userRepository = userRepository, 145 keyguardRepository = keyguardRepository, 146 sceneInteractor = sceneInteractor, 147 clock = mock { whenever(elapsedRealtime()).thenAnswer { testScope.currentTime } } 148 ) 149 } 150 151 fun keyguardRepository(): FakeKeyguardRepository { 152 return keyguardRepository 153 } 154 155 fun keyguardInteractor(repository: KeyguardRepository): KeyguardInteractor { 156 return KeyguardInteractor( 157 repository = repository, 158 commandQueue = FakeCommandQueue(), 159 featureFlags = featureFlags, 160 bouncerRepository = FakeKeyguardBouncerRepository(), 161 configurationRepository = FakeConfigurationRepository() 162 ) 163 } 164 165 fun bouncerInteractor( 166 authenticationInteractor: AuthenticationInteractor, 167 sceneInteractor: SceneInteractor, 168 ): BouncerInteractor { 169 return BouncerInteractor( 170 applicationScope = applicationScope(), 171 applicationContext = context, 172 repository = BouncerRepository(), 173 authenticationInteractor = authenticationInteractor, 174 sceneInteractor = sceneInteractor, 175 featureFlags = featureFlags, 176 ) 177 } 178 179 fun bouncerViewModel( 180 bouncerInteractor: BouncerInteractor, 181 authenticationInteractor: AuthenticationInteractor, 182 ): BouncerViewModel { 183 return BouncerViewModel( 184 applicationContext = context, 185 applicationScope = applicationScope(), 186 bouncerInteractor = bouncerInteractor, 187 authenticationInteractor = authenticationInteractor, 188 featureFlags = featureFlags, 189 ) 190 } 191 192 private fun applicationScope(): CoroutineScope { 193 return testScope.backgroundScope 194 } 195 196 companion object { 197 fun DomainLayerAuthenticationMethodModel.toDataLayer(): DataLayerAuthenticationMethodModel { 198 return when (this) { 199 DomainLayerAuthenticationMethodModel.None -> DataLayerAuthenticationMethodModel.None 200 DomainLayerAuthenticationMethodModel.Swipe -> 201 DataLayerAuthenticationMethodModel.None 202 DomainLayerAuthenticationMethodModel.Pin -> DataLayerAuthenticationMethodModel.Pin 203 DomainLayerAuthenticationMethodModel.Password -> 204 DataLayerAuthenticationMethodModel.Password 205 DomainLayerAuthenticationMethodModel.Pattern -> 206 DataLayerAuthenticationMethodModel.Pattern 207 } 208 } 209 } 210 } 211