Merge "[flexiglass] Removes support for multiple containers." into udc-qpr-dev

This commit is contained in:
Ale Nijamkin
2023-07-28 20:30:50 +00:00
committed by Android (Google) Code Review
45 changed files with 339 additions and 953 deletions

View File

@@ -17,12 +17,10 @@
package com.android.systemui.scene.ui.composable
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerNames
import dagger.Module
import dagger.multibindings.Multibinds
import javax.inject.Named
@Module
interface SceneModule {
@Multibinds @Named(SceneContainerNames.SYSTEM_UI_DEFAULT) fun scenes(): Set<Scene>
@Multibinds fun scenes(): Set<Scene>
}

View File

@@ -16,35 +16,29 @@
package com.android.systemui.scene.ui.composable
import android.app.AlertDialog
import android.content.Context
import com.android.systemui.bouncer.ui.composable.BouncerScene
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
import com.android.systemui.bouncer.ui.composable.BouncerSceneDialogFactory
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.ui.composable.LockscreenScene
import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
import com.android.systemui.qs.ui.composable.QuickSettingsScene
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.shade.ui.composable.ShadeScene
import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel
import com.android.systemui.statusbar.phone.SystemUIDialog
import dagger.Module
import dagger.Provides
import javax.inject.Named
import kotlinx.coroutines.CoroutineScope
@Module
object SceneModule {
@Provides
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun scenes(
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT) bouncer: BouncerScene,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT) gone: GoneScene,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT) lockScreen: LockscreenScene,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT) qs: QuickSettingsScene,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT) shade: ShadeScene,
bouncer: BouncerScene,
gone: GoneScene,
lockScreen: LockscreenScene,
qs: QuickSettingsScene,
shade: ShadeScene,
): Set<Scene> {
return setOf(
bouncer,
@@ -57,70 +51,11 @@ object SceneModule {
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun bouncerScene(
@Application context: Context,
viewModelFactory: BouncerViewModel.Factory,
): BouncerScene {
return BouncerScene(
viewModel =
viewModelFactory.create(
containerName = SceneContainerNames.SYSTEM_UI_DEFAULT,
),
dialogFactory = { SystemUIDialog(context) },
)
}
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun goneScene(): GoneScene {
return GoneScene()
}
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun lockscreenScene(
@Application applicationScope: CoroutineScope,
viewModelFactory: LockscreenSceneViewModel.Factory,
): LockscreenScene {
return LockscreenScene(
applicationScope = applicationScope,
viewModel =
viewModelFactory.create(
containerName = SceneContainerNames.SYSTEM_UI_DEFAULT,
),
)
}
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun quickSettingsScene(
viewModelFactory: QuickSettingsSceneViewModel.Factory,
): QuickSettingsScene {
return QuickSettingsScene(
viewModel =
viewModelFactory.create(
containerName = SceneContainerNames.SYSTEM_UI_DEFAULT,
),
)
}
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun shadeScene(
@Application applicationScope: CoroutineScope,
viewModelFactory: ShadeSceneViewModel.Factory,
): ShadeScene {
return ShadeScene(
applicationScope = applicationScope,
viewModel =
viewModelFactory.create(
containerName = SceneContainerNames.SYSTEM_UI_DEFAULT,
),
)
fun bouncerSceneDialogFactory(@Application context: Context): BouncerSceneDialogFactory {
return object : BouncerSceneDialogFactory {
override fun invoke(): AlertDialog {
return SystemUIDialog(context)
}
}
}
}

View File

@@ -52,24 +52,27 @@ import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.UserAction
import com.android.systemui.scene.ui.composable.ComposableScene
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** The bouncer scene displays authentication challenges like PIN, password, or pattern. */
class BouncerScene(
@SysUISingleton
class BouncerScene
@Inject
constructor(
private val viewModel: BouncerViewModel,
private val dialogFactory: () -> AlertDialog,
private val dialogFactory: BouncerSceneDialogFactory,
) : ComposableScene {
override val key = SceneKey.Bouncer
override fun destinationScenes(
containerName: String,
): StateFlow<Map<UserAction, SceneModel>> =
override fun destinationScenes(): StateFlow<Map<UserAction, SceneModel>> =
MutableStateFlow<Map<UserAction, SceneModel>>(
mapOf(
UserAction.Back to SceneModel(SceneKey.Lockscreen),
@@ -79,7 +82,6 @@ class BouncerScene(
@Composable
override fun Content(
containerName: String,
modifier: Modifier,
) = BouncerScene(viewModel, dialogFactory, modifier)
}
@@ -87,7 +89,7 @@ class BouncerScene(
@Composable
private fun BouncerScene(
viewModel: BouncerViewModel,
dialogFactory: () -> AlertDialog,
dialogFactory: BouncerSceneDialogFactory,
modifier: Modifier = Modifier,
) {
val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
@@ -175,3 +177,7 @@ private fun BouncerScene(
}
}
}
interface BouncerSceneDialogFactory {
operator fun invoke(): AlertDialog
}

View File

@@ -31,6 +31,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
import com.android.systemui.scene.shared.model.Direction
@@ -38,6 +39,7 @@ import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.UserAction
import com.android.systemui.scene.ui.composable.ComposableScene
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -45,15 +47,16 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** The lock screen scene shows when the device is locked. */
class LockscreenScene(
@SysUISingleton
class LockscreenScene
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
private val viewModel: LockscreenSceneViewModel,
) : ComposableScene {
override val key = SceneKey.Lockscreen
override fun destinationScenes(
containerName: String,
): StateFlow<Map<UserAction, SceneModel>> =
override fun destinationScenes(): StateFlow<Map<UserAction, SceneModel>> =
viewModel.upDestinationSceneKey
.map { pageKey -> destinationScenes(up = pageKey) }
.stateIn(
@@ -64,7 +67,6 @@ class LockscreenScene(
@Composable
override fun Content(
containerName: String,
modifier: Modifier,
) {
LockscreenScene(

View File

@@ -27,25 +27,28 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.UserAction
import com.android.systemui.scene.ui.composable.ComposableScene
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** The Quick Settings (AKA "QS") scene shows the quick setting tiles. */
class QuickSettingsScene(
@SysUISingleton
class QuickSettingsScene
@Inject
constructor(
private val viewModel: QuickSettingsSceneViewModel,
) : ComposableScene {
override val key = SceneKey.QuickSettings
override fun destinationScenes(
containerName: String,
): StateFlow<Map<UserAction, SceneModel>> =
override fun destinationScenes(): StateFlow<Map<UserAction, SceneModel>> =
MutableStateFlow<Map<UserAction, SceneModel>>(
mapOf(
UserAction.Swipe(Direction.UP) to SceneModel(SceneKey.Shade),
@@ -55,7 +58,6 @@ class QuickSettingsScene(
@Composable
override fun Content(
containerName: String,
modifier: Modifier,
) {
QuickSettingsScene(

View File

@@ -22,5 +22,5 @@ import com.android.systemui.scene.shared.model.Scene
/** Compose-capable extension of [Scene]. */
interface ComposableScene : Scene {
@Composable fun Content(containerName: String, modifier: Modifier)
@Composable fun Content(modifier: Modifier)
}

View File

@@ -23,10 +23,12 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.UserAction
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -35,12 +37,11 @@ import kotlinx.coroutines.flow.asStateFlow
* "Gone" is not a real scene but rather the absence of scenes when we want to skip showing any
* content from the scene framework.
*/
class GoneScene : ComposableScene {
@SysUISingleton
class GoneScene @Inject constructor() : ComposableScene {
override val key = SceneKey.Gone
override fun destinationScenes(
containerName: String,
): StateFlow<Map<UserAction, SceneModel>> =
override fun destinationScenes(): StateFlow<Map<UserAction, SceneModel>> =
MutableStateFlow<Map<UserAction, SceneModel>>(
mapOf(
UserAction.Swipe(Direction.DOWN) to SceneModel(SceneKey.Shade),
@@ -50,7 +51,6 @@ class GoneScene : ComposableScene {
@Composable
override fun Content(
containerName: String,
modifier: Modifier,
) {
/*

View File

@@ -75,7 +75,6 @@ fun SceneContainer(
if (key == currentSceneKey) {
Scene(
scene = composableScene,
containerName = viewModel.containerName,
onSceneChanged = viewModel::setCurrentScene,
modifier = Modifier.fillMaxSize(),
)
@@ -88,12 +87,10 @@ fun SceneContainer(
@Composable
private fun Scene(
scene: ComposableScene,
containerName: String,
onSceneChanged: (SceneModel) -> Unit,
modifier: Modifier = Modifier,
) {
val destinationScenes: Map<UserAction, SceneModel> by
scene.destinationScenes(containerName).collectAsState()
val destinationScenes: Map<UserAction, SceneModel> by scene.destinationScenes().collectAsState()
val swipeLeftDestinationScene = destinationScenes[UserAction.Swipe(Direction.LEFT)]
val swipeUpDestinationScene = destinationScenes[UserAction.Swipe(Direction.UP)]
val swipeRightDestinationScene = destinationScenes[UserAction.Swipe(Direction.RIGHT)]
@@ -107,7 +104,6 @@ private fun Scene(
modifier = Modifier.align(Alignment.Center),
) {
scene.Content(
containerName = containerName,
modifier = Modifier,
)

View File

@@ -26,6 +26,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.footer.ui.compose.QuickSettings
@@ -35,6 +36,7 @@ import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.UserAction
import com.android.systemui.scene.ui.composable.ComposableScene
import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -42,15 +44,16 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** The shade scene shows scrolling list of notifications and some of the quick setting tiles. */
class ShadeScene(
@SysUISingleton
class ShadeScene
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
private val viewModel: ShadeSceneViewModel,
) : ComposableScene {
override val key = SceneKey.Shade
override fun destinationScenes(
containerName: String,
): StateFlow<Map<UserAction, SceneModel>> =
override fun destinationScenes(): StateFlow<Map<UserAction, SceneModel>> =
viewModel.upDestinationSceneKey
.map { sceneKey -> destinationScenes(up = sceneKey) }
.stateIn(
@@ -61,7 +64,6 @@ class ShadeScene(
@Composable
override fun Content(
containerName: String,
modifier: Modifier,
) = ShadeScene(viewModel, modifier)

View File

@@ -81,7 +81,6 @@ import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.model.SceneContainerNames;
import com.android.systemui.scene.shared.model.SceneKey;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -476,7 +475,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
// When the scene framework transitions from bouncer to gone, we dismiss the keyguard.
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
mSceneInteractor.get().sceneTransitions(SceneContainerNames.SYSTEM_UI_DEFAULT),
mSceneInteractor.get().getTransitions(),
sceneTransitionModel -> {
if (sceneTransitionModel != null
&& sceneTransitionModel.getFrom() == SceneKey.Bouncer.INSTANCE

View File

@@ -24,6 +24,7 @@ import com.android.systemui.authentication.domain.interactor.AuthenticationInter
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
import com.android.systemui.bouncer.data.repository.BouncerRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -31,9 +32,7 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.kotlin.pairwise
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -44,8 +43,9 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
/** Encapsulates business logic and application state accessing use-cases. */
@SysUISingleton
class BouncerInteractor
@AssistedInject
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
@Application private val applicationContext: Context,
@@ -53,7 +53,6 @@ constructor(
private val authenticationInteractor: AuthenticationInteractor,
private val sceneInteractor: SceneInteractor,
featureFlags: FeatureFlags,
@Assisted private val containerName: String,
) {
/** The user-facing message to show in the bouncer. */
@@ -118,23 +117,19 @@ constructor(
/**
* Either shows the bouncer or unlocks the device, if the bouncer doesn't need to be shown.
*
* @param containerName The name of the scene container to show the bouncer in.
* @param message An optional message to show to the user in the bouncer.
*/
fun showOrUnlockDevice(
containerName: String,
message: String? = null,
) {
applicationScope.launch {
if (authenticationInteractor.isAuthenticationRequired()) {
repository.setMessage(message ?: promptMessage(getAuthenticationMethod()))
sceneInteractor.setCurrentScene(
containerName = containerName,
scene = SceneModel(SceneKey.Bouncer),
)
} else {
sceneInteractor.setCurrentScene(
containerName = containerName,
scene = SceneModel(SceneKey.Gone),
)
}
@@ -180,7 +175,6 @@ constructor(
if (isAuthenticated) {
sceneInteractor.setCurrentScene(
containerName = containerName,
scene = SceneModel(SceneKey.Gone),
)
} else {
@@ -228,11 +222,4 @@ constructor(
else -> ""
}
}
@AssistedFactory
interface Factory {
fun create(
containerName: String,
): BouncerInteractor
}
}

View File

@@ -22,13 +22,12 @@ import android.content.Context
import com.android.systemui.R
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.util.kotlin.pairwise
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
import kotlin.math.ceil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -45,17 +44,15 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
/** Holds UI state and handles user input on bouncer UIs. */
@SysUISingleton
class BouncerViewModel
@AssistedInject
@Inject
constructor(
@Application private val applicationContext: Context,
@Application private val applicationScope: CoroutineScope,
interactorFactory: BouncerInteractor.Factory,
private val interactor: BouncerInteractor,
featureFlags: FeatureFlags,
@Assisted containerName: String,
) {
private val interactor: BouncerInteractor = interactorFactory.create(containerName)
private val isInputEnabled: StateFlow<Boolean> =
interactor.isThrottled
.map { !it }
@@ -222,11 +219,4 @@ constructor(
*/
val isUpdateAnimated: Boolean,
)
@AssistedFactory
interface Factory {
fun create(
containerName: String,
): BouncerViewModel
}
}

View File

@@ -19,10 +19,9 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -30,17 +29,14 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Hosts business and application state accessing logic for the lockscreen scene. */
@SysUISingleton
class LockscreenSceneInteractor
@AssistedInject
@Inject
constructor(
@Application applicationScope: CoroutineScope,
private val authenticationInteractor: AuthenticationInteractor,
bouncerInteractorFactory: BouncerInteractor.Factory,
@Assisted private val containerName: String,
private val bouncerInteractor: BouncerInteractor,
) {
private val bouncerInteractor: BouncerInteractor =
bouncerInteractorFactory.create(containerName)
/** Whether the device is currently locked. */
val isDeviceLocked: StateFlow<Boolean> =
authenticationInteractor.isUnlocked
@@ -67,13 +63,6 @@ constructor(
/** Attempts to dismiss the lockscreen. This will cause the bouncer to show, if needed. */
fun dismissLockscreen() {
bouncerInteractor.showOrUnlockDevice(containerName = containerName)
}
@AssistedFactory
interface Factory {
fun create(
containerName: String,
): LockscreenSceneInteractor
bouncerInteractor.showOrUnlockDevice()
}
}

View File

@@ -19,12 +19,11 @@ package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.R
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.shared.model.SceneKey
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -32,15 +31,13 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Models UI state and handles user input for the lockscreen scene. */
@SysUISingleton
class LockscreenSceneViewModel
@AssistedInject
@Inject
constructor(
@Application applicationScope: CoroutineScope,
interactorFactory: LockscreenSceneInteractor.Factory,
@Assisted containerName: String,
private val interactor: LockscreenSceneInteractor,
) {
private val interactor: LockscreenSceneInteractor = interactorFactory.create(containerName)
/** The icon for the "lock" button on the lockscreen. */
val lockButtonIcon: StateFlow<Icon> =
interactor.isDeviceLocked
@@ -98,11 +95,4 @@ constructor(
)
)
}
@AssistedFactory
interface Factory {
fun create(
containerName: String,
): LockscreenSceneViewModel
}
}

View File

@@ -16,30 +16,19 @@
package com.android.systemui.qs.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
/** Models UI state and handles user input for the quick settings scene. */
@SysUISingleton
class QuickSettingsSceneViewModel
@AssistedInject
@Inject
constructor(
lockscreenSceneInteractorFactory: LockscreenSceneInteractor.Factory,
@Assisted containerName: String,
private val lockscreenSceneInteractor: LockscreenSceneInteractor,
) {
private val lockscreenSceneInteractor: LockscreenSceneInteractor =
lockscreenSceneInteractorFactory.create(containerName)
/** Notifies that some content in quick settings was clicked. */
fun onContentClicked() {
lockscreenSceneInteractor.dismissLockscreen()
}
@AssistedFactory
interface Factory {
fun create(
containerName: String,
): QuickSettingsSceneViewModel
}
}

View File

@@ -97,7 +97,6 @@ import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.model.SceneContainerNames;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
@@ -221,8 +220,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
// If scene framework is enabled, set the scene container window to
// visible and let the touch "slip" into that window.
if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
mSceneInteractor.get().setVisible(
SceneContainerNames.SYSTEM_UI_DEFAULT, true);
mSceneInteractor.get().setVisible(true);
} else {
centralSurfaces.onInputFocusTransfer(
mInputFocusTransferStarted, false /* cancel */,

View File

@@ -19,7 +19,6 @@ package com.android.systemui.scene
import com.android.systemui.scene.domain.startable.SceneContainerStartableModule
import com.android.systemui.scene.shared.model.SceneContainerConfigModule
import com.android.systemui.scene.ui.composable.SceneModule
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModelModule
import dagger.Module
@Module(
@@ -27,7 +26,6 @@ import dagger.Module
[
SceneContainerConfigModule::class,
SceneContainerStartableModule::class,
SceneContainerViewModelModule::class,
SceneModule::class,
],
)

View File

@@ -29,26 +29,20 @@ import kotlinx.coroutines.flow.asStateFlow
class SceneContainerRepository
@Inject
constructor(
private val containerConfigByName: Map<String, SceneContainerConfig>,
private val config: SceneContainerConfig,
) {
private val containerVisibilityByName: Map<String, MutableStateFlow<Boolean>> =
containerConfigByName
.map { (containerName, _) -> containerName to MutableStateFlow(true) }
.toMap()
private val currentSceneByContainerName: Map<String, MutableStateFlow<SceneModel>> =
containerConfigByName
.map { (containerName, config) ->
containerName to MutableStateFlow(SceneModel(config.initialSceneKey))
}
.toMap()
private val sceneTransitionProgressByContainerName: Map<String, MutableStateFlow<Float>> =
containerConfigByName
.map { (containerName, _) -> containerName to MutableStateFlow(1f) }
.toMap()
private val sceneTransitionByContainerName:
Map<String, MutableStateFlow<SceneTransitionModel?>> =
containerConfigByName.keys.associateWith { MutableStateFlow(null) }
private val _isVisible = MutableStateFlow(true)
val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
private val _currentScene = MutableStateFlow(SceneModel(config.initialSceneKey))
val currentScene: StateFlow<SceneModel> = _currentScene.asStateFlow()
private val _transitionProgress = MutableStateFlow(1f)
val transitionProgress: StateFlow<Float> = _transitionProgress.asStateFlow()
private val _transitions = MutableStateFlow<SceneTransitionModel?>(null)
val transitions: StateFlow<SceneTransitionModel?> = _transitions.asStateFlow()
/**
* Returns the keys to all scenes in the container with the given name.
@@ -56,100 +50,50 @@ constructor(
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
*/
fun allSceneKeys(containerName: String): List<SceneKey> {
return containerConfigByName[containerName]?.sceneKeys
?: error(noSuchContainerErrorMessage(containerName))
fun allSceneKeys(): List<SceneKey> {
return config.sceneKeys
}
/** Sets the current scene in the container with the given name. */
fun setCurrentScene(containerName: String, scene: SceneModel) {
check(allSceneKeys(containerName).contains(scene.key)) {
fun setCurrentScene(scene: SceneModel) {
check(allSceneKeys().contains(scene.key)) {
"""
Cannot set current scene key to "${scene.key}". The container "$containerName" does
not contain a scene with that key.
Cannot set current scene key to "${scene.key}". The configuration does not contain a
scene with that key.
"""
.trimIndent()
}
currentSceneByContainerName.setValue(containerName, scene)
_currentScene.value = scene
}
/** Sets the scene transition in the container with the given name. */
fun setSceneTransition(containerName: String, from: SceneKey, to: SceneKey) {
check(allSceneKeys(containerName).contains(from)) {
fun setSceneTransition(from: SceneKey, to: SceneKey) {
check(allSceneKeys().contains(from)) {
"""
Cannot set current scene key to "$from". The container "$containerName" does
not contain a scene with that key.
Cannot set current scene key to "$from". The configuration does not contain a scene
with that key.
"""
.trimIndent()
}
check(allSceneKeys(containerName).contains(to)) {
check(allSceneKeys().contains(to)) {
"""
Cannot set current scene key to "$to". The container "$containerName" does
not contain a scene with that key.
Cannot set current scene key to "$to". The configuration does not contain a scene
with that key.
"""
.trimIndent()
}
sceneTransitionByContainerName.setValue(
containerName,
SceneTransitionModel(from = from, to = to)
)
}
/** The current scene in the container with the given name. */
fun currentScene(containerName: String): StateFlow<SceneModel> {
return currentSceneByContainerName.mutableOrError(containerName).asStateFlow()
}
/**
* Scene transitions as pairs of keys. A new value is emitted exactly once, each time a scene
* transition occurs. The flow begins with a `null` value at first, because the initial scene is
* not something that we transition to from another scene.
*/
fun sceneTransitions(containerName: String): StateFlow<SceneTransitionModel?> {
return sceneTransitionByContainerName.mutableOrError(containerName).asStateFlow()
_transitions.value = SceneTransitionModel(from = from, to = to)
}
/** Sets whether the container with the given name is visible. */
fun setVisible(containerName: String, isVisible: Boolean) {
containerVisibilityByName.setValue(containerName, isVisible)
}
/** Whether the container with the given name should be visible. */
fun isVisible(containerName: String): StateFlow<Boolean> {
return containerVisibilityByName.mutableOrError(containerName).asStateFlow()
fun setVisible(isVisible: Boolean) {
_isVisible.value = isVisible
}
/** Sets scene transition progress to the current scene in the container with the given name. */
fun setSceneTransitionProgress(containerName: String, progress: Float) {
sceneTransitionProgressByContainerName.setValue(containerName, progress)
}
/** Progress of the transition into the current scene in the container with the given name. */
fun sceneTransitionProgress(containerName: String): StateFlow<Float> {
return sceneTransitionProgressByContainerName.mutableOrError(containerName).asStateFlow()
}
private fun <T> Map<String, MutableStateFlow<T>>.mutableOrError(
containerName: String,
): MutableStateFlow<T> {
return this[containerName] ?: error(noSuchContainerErrorMessage(containerName))
}
private fun <T> Map<String, MutableStateFlow<T>>.setValue(
containerName: String,
value: T,
) {
val mutable = mutableOrError(containerName)
mutable.value = value
}
private fun noSuchContainerErrorMessage(containerName: String): String {
return """
No container named "$containerName". Existing containers:
${containerConfigByName.values.joinToString(", ") { it.name }}
"""
.trimIndent()
fun setSceneTransitionProgress(progress: Float) {
_transitionProgress.value = progress
}
}

View File

@@ -30,12 +30,8 @@ import kotlinx.coroutines.flow.asStateFlow
/**
* Generic business logic and app state accessors for the scene framework.
*
* Note that scene container specific business logic does not belong in this class. Instead, it
* should be hoisted to a class that is specific to that scene container, for an example, please see
* [SystemUiDefaultSceneContainerStartable].
*
* Also note that this class should not depend on state or logic of other modules or features.
* Instead, other feature modules should depend on and call into this class when their parts of the
* Note that this class should not depend on state or logic of other modules or features. Instead,
* other feature modules should depend on and call into this class when their parts of the
* application state change.
*/
@SysUISingleton
@@ -51,50 +47,42 @@ constructor(
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
*/
fun allSceneKeys(containerName: String): List<SceneKey> {
return repository.allSceneKeys(containerName)
fun allSceneKeys(): List<SceneKey> {
return repository.allSceneKeys()
}
/** Sets the scene in the container with the given name. */
fun setCurrentScene(containerName: String, scene: SceneModel) {
val currentSceneKey = repository.currentScene(containerName).value.key
repository.setCurrentScene(containerName, scene)
repository.setSceneTransition(containerName, from = currentSceneKey, to = scene.key)
fun setCurrentScene(scene: SceneModel) {
val currentSceneKey = repository.currentScene.value.key
repository.setCurrentScene(scene)
repository.setSceneTransition(from = currentSceneKey, to = scene.key)
}
/** The current scene in the container with the given name. */
fun currentScene(containerName: String): StateFlow<SceneModel> {
return repository.currentScene(containerName)
}
val currentScene: StateFlow<SceneModel> = repository.currentScene
/** Sets the visibility of the container with the given name. */
fun setVisible(containerName: String, isVisible: Boolean) {
return repository.setVisible(containerName, isVisible)
fun setVisible(isVisible: Boolean) {
return repository.setVisible(isVisible)
}
/** Whether the container with the given name is visible. */
fun isVisible(containerName: String): StateFlow<Boolean> {
return repository.isVisible(containerName)
}
val isVisible: StateFlow<Boolean> = repository.isVisible
/** Sets scene transition progress to the current scene in the container with the given name. */
fun setSceneTransitionProgress(containerName: String, progress: Float) {
repository.setSceneTransitionProgress(containerName, progress)
fun setSceneTransitionProgress(progress: Float) {
repository.setSceneTransitionProgress(progress)
}
/** Progress of the transition into the current scene in the container with the given name. */
fun sceneTransitionProgress(containerName: String): StateFlow<Float> {
return repository.sceneTransitionProgress(containerName)
}
val transitionProgress: StateFlow<Float> = repository.transitionProgress
/**
* Scene transitions as pairs of keys. A new value is emitted exactly once, each time a scene
* transition occurs. The flow begins with a `null` value at first, because the initial scene is
* not something that we transition to from another scene.
*/
fun sceneTransitions(containerName: String): StateFlow<SceneTransitionModel?> {
return repository.sceneTransitions(containerName)
}
val transitions: StateFlow<SceneTransitionModel?> = repository.transitions
private val _remoteUserInput: MutableStateFlow<RemoteUserInput?> = MutableStateFlow(null)

View File

@@ -28,7 +28,6 @@ import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING
@@ -44,12 +43,11 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
/**
* Hooks up business logic that manipulates the state of the [SceneInteractor] for the default
* system UI scene container (the one named [SceneContainerNames.SYSTEM_UI_DEFAULT]) based on state
* from other systems.
* Hooks up business logic that manipulates the state of the [SceneInteractor] for the system UI
* scene container based on state from other systems.
*/
@SysUISingleton
class SystemUiDefaultSceneContainerStartable
class SceneContainerStartable
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
@@ -72,13 +70,10 @@ constructor(
/** Updates the visibility of the scene container based on the current scene. */
private fun hydrateVisibility() {
applicationScope.launch {
sceneInteractor
.currentScene(CONTAINER_NAME)
sceneInteractor.currentScene
.map { it.key }
.distinctUntilChanged()
.collect { sceneKey ->
sceneInteractor.setVisible(CONTAINER_NAME, sceneKey != SceneKey.Gone)
}
.collect { sceneKey -> sceneInteractor.setVisible(sceneKey != SceneKey.Gone) }
}
}
@@ -87,7 +82,7 @@ constructor(
applicationScope.launch {
authenticationInteractor.isUnlocked
.map { isUnlocked ->
val currentSceneKey = sceneInteractor.currentScene(CONTAINER_NAME).value.key
val currentSceneKey = sceneInteractor.currentScene.value.key
val isBypassEnabled = authenticationInteractor.isBypassEnabled()
when {
isUnlocked ->
@@ -135,8 +130,7 @@ constructor(
/** Keeps [SysUiState] up-to-date */
private fun hydrateSystemUiState() {
applicationScope.launch {
sceneInteractor
.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT)
sceneInteractor.currentScene
.map { it.key }
.distinctUntilChanged()
.collect { sceneKey ->
@@ -155,12 +149,7 @@ constructor(
private fun switchToScene(targetSceneKey: SceneKey) {
sceneInteractor.setCurrentScene(
containerName = CONTAINER_NAME,
scene = SceneModel(targetSceneKey),
)
}
companion object {
private const val CONTAINER_NAME = SceneContainerNames.SYSTEM_UI_DEFAULT
}
}

View File

@@ -27,6 +27,6 @@ interface SceneContainerStartableModule {
@Binds
@IntoMap
@ClassKey(SystemUiDefaultSceneContainerStartable::class)
fun bind(impl: SystemUiDefaultSceneContainerStartable): CoreStartable
@ClassKey(SceneContainerStartable::class)
fun bind(impl: SceneContainerStartable): CoreStartable
}

View File

@@ -27,8 +27,6 @@ import kotlinx.coroutines.flow.asStateFlow
* takes care of rendering the current scene and allowing scenes to be switched from one to another
* based on either user action (for example, swiping down while on the lock screen scene may switch
* to the shade scene).
*
* The framework also supports multiple containers, each one with its own configuration.
*/
interface Scene {
@@ -59,7 +57,7 @@ interface Scene {
* The API is designed such that it's possible to emit ever-changing values for each
* [UserAction] to enable, disable, or change the destination scene of a given user action.
*/
fun destinationScenes(containerName: String): StateFlow<Map<UserAction, SceneModel>> =
fun destinationScenes(): StateFlow<Map<UserAction, SceneModel>> =
MutableStateFlow(emptyMap<UserAction, SceneModel>()).asStateFlow()
}

View File

@@ -16,10 +16,8 @@
package com.android.systemui.scene.shared.model
/** Models the configuration of a single scene container. */
/** Models the configuration of the scene container. */
data class SceneContainerConfig(
/** Container name. Must be unique across all containers in System UI. */
val name: String,
/**
* The keys to all scenes in the container, sorted by z-order such that the last one renders on

View File

@@ -16,44 +16,27 @@
package com.android.systemui.scene.shared.model
import com.android.systemui.dagger.SysUISingleton
import dagger.Module
import dagger.Provides
import javax.inject.Named
@Module
object SceneContainerConfigModule {
@Provides
fun containerConfigs(): Map<String, SceneContainerConfig> {
return mapOf(
SceneContainerNames.SYSTEM_UI_DEFAULT to
SceneContainerConfig(
name = SceneContainerNames.SYSTEM_UI_DEFAULT,
// Note that this list is in z-order. The first one is the bottom-most and the
// last
// one is top-most.
sceneKeys =
listOf(
SceneKey.Gone,
SceneKey.Lockscreen,
SceneKey.Bouncer,
SceneKey.Shade,
SceneKey.QuickSettings,
),
initialSceneKey = SceneKey.Lockscreen,
fun containerConfig(): SceneContainerConfig {
return SceneContainerConfig(
// Note that this list is in z-order. The first one is the bottom-most and the
// last
// one is top-most.
sceneKeys =
listOf(
SceneKey.Gone,
SceneKey.Lockscreen,
SceneKey.Bouncer,
SceneKey.Shade,
SceneKey.QuickSettings,
),
initialSceneKey = SceneKey.Lockscreen,
)
}
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun provideDefaultSceneContainerConfig(
configs: Map<String, SceneContainerConfig>,
): SceneContainerConfig {
return checkNotNull(configs[SceneContainerNames.SYSTEM_UI_DEFAULT]) {
"No SceneContainerConfig named \"${SceneContainerNames.SYSTEM_UI_DEFAULT}\"."
}
}
}

View File

@@ -1,21 +0,0 @@
/*
* 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.scene.shared.model
object SceneContainerNames {
const val SYSTEM_UI_DEFAULT = "system_ui"
}

View File

@@ -17,16 +17,20 @@
package com.android.systemui.scene.ui.viewmodel
import android.view.MotionEvent
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.RemoteUserInput
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import javax.inject.Inject
import kotlinx.coroutines.flow.StateFlow
/** Models UI state for a single scene container. */
class SceneContainerViewModel(
/** Models UI state for the scene container. */
@SysUISingleton
class SceneContainerViewModel
@Inject
constructor(
private val interactor: SceneInteractor,
val containerName: String,
) {
/** A flow of motion events originating from outside of the scene framework. */
val remoteUserInput: StateFlow<RemoteUserInput?> = interactor.remoteUserInput
@@ -37,22 +41,22 @@ class SceneContainerViewModel(
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
*/
val allSceneKeys: List<SceneKey> = interactor.allSceneKeys(containerName)
val allSceneKeys: List<SceneKey> = interactor.allSceneKeys()
/** The current scene. */
val currentScene: StateFlow<SceneModel> = interactor.currentScene(containerName)
val currentScene: StateFlow<SceneModel> = interactor.currentScene
/** Whether the container is visible. */
val isVisible: StateFlow<Boolean> = interactor.isVisible(containerName)
val isVisible: StateFlow<Boolean> = interactor.isVisible
/** Requests a transition to the scene with the given key. */
fun setCurrentScene(scene: SceneModel) {
interactor.setCurrentScene(containerName, scene)
interactor.setCurrentScene(scene)
}
/** Notifies of the progress of a scene transition. */
fun setSceneTransitionProgress(progress: Float) {
interactor.setSceneTransitionProgress(containerName, progress)
interactor.setSceneTransitionProgress(progress)
}
/** Handles a [MotionEvent] representing remote user input. */

View File

@@ -1,40 +0,0 @@
/*
* 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.scene.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerNames
import dagger.Module
import dagger.Provides
import javax.inject.Named
@Module
object SceneContainerViewModelModule {
@Provides
@SysUISingleton
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
fun defaultSceneContainerViewModel(
interactor: SceneInteractor,
): SceneContainerViewModel {
return SceneContainerViewModel(
interactor = interactor,
containerName = SceneContainerNames.SYSTEM_UI_DEFAULT,
)
}
}

View File

@@ -36,7 +36,6 @@ import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.ui.view.SceneWindowRootView
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
@@ -73,11 +72,8 @@ abstract class ShadeViewProviderModule {
fun providesWindowRootView(
layoutInflater: LayoutInflater,
featureFlags: FeatureFlags,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
viewModelProvider: Provider<SceneContainerViewModel>,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
containerConfigProvider: Provider<SceneContainerConfig>,
@Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
layoutInsetController: NotificationInsetsController,
): WindowRootView {

View File

@@ -16,12 +16,11 @@
package com.android.systemui.shade.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.shared.model.SceneKey
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -29,32 +28,29 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Models UI state and handles user input for the shade scene. */
@SysUISingleton
class ShadeSceneViewModel
@AssistedInject
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
lockscreenSceneInteractorFactory: LockscreenSceneInteractor.Factory,
@Assisted private val containerName: String,
private val lockscreenSceneInteractor: LockscreenSceneInteractor,
) {
private val lockScreenInteractor: LockscreenSceneInteractor =
lockscreenSceneInteractorFactory.create(containerName)
/** The key of the scene we should switch to when swiping up. */
val upDestinationSceneKey: StateFlow<SceneKey> =
lockScreenInteractor.isDeviceLocked
lockscreenSceneInteractor.isDeviceLocked
.map { isLocked -> upDestinationSceneKey(isLocked = isLocked) }
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
initialValue =
upDestinationSceneKey(
isLocked = lockScreenInteractor.isDeviceLocked.value,
isLocked = lockscreenSceneInteractor.isDeviceLocked.value,
),
)
/** Notifies that some content in the shade was clicked. */
fun onContentClicked() {
lockScreenInteractor.dismissLockscreen()
lockscreenSceneInteractor.dismissLockscreen()
}
private fun upDestinationSceneKey(
@@ -62,11 +58,4 @@ constructor(
): SceneKey {
return if (isLocked) SceneKey.Lockscreen else SceneKey.Gone
}
@AssistedFactory
interface Factory {
fun create(
containerName: String,
): ShadeSceneViewModel
}
}

View File

@@ -30,7 +30,6 @@ import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.RemoteUserInput
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shade.ShadeViewController
@@ -183,7 +182,7 @@ class PhoneStatusBarViewController private constructor(
sceneInteractor.get()
.onRemoteUserInput(RemoteUserInput.translateMotionEvent(event))
// TODO(b/291965119): remove once view is expanded to cover the status bar
sceneInteractor.get().setVisible(SceneContainerNames.SYSTEM_UI_DEFAULT, true)
sceneInteractor.get().setVisible(true)
return false
}

View File

@@ -37,7 +37,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.model.SceneContainerNames;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -126,7 +125,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable {
if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
javaAdapter.get().alwaysCollectFlow(
sceneInteractor.get().isVisible(SceneContainerNames.SYSTEM_UI_DEFAULT),
sceneInteractor.get().isVisible(),
this::onShadeExpansionFullyChanged);
}

View File

@@ -733,29 +733,20 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// is
// not enough to trigger a dismissal of the keyguard.
underTest.onViewAttached()
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer, null)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null))
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
// While listening, going from the bouncer scene to the gone scene, does dismiss the
// keyguard.
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Gone, null)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null))
runCurrent()
verify(viewMediatorCallback).keyguardDone(anyBoolean(), anyInt())
// While listening, moving back to the bouncer scene does not dismiss the keyguard
// again.
clearInvocations(viewMediatorCallback)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer, null)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null))
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
@@ -763,18 +754,12 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// scene
// does not dismiss the keyguard while we're not listening.
underTest.onViewDetached()
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Gone, null)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null))
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
// While not listening, moving back to the bouncer does not dismiss the keyguard.
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer, null)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null))
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
@@ -782,10 +767,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// gone
// scene now does dismiss the keyguard again.
underTest.onViewAttached()
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Gone, null)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null))
runCurrent()
verify(viewMediatorCallback).keyguardDone(anyBoolean(), anyInt())
}

View File

@@ -69,13 +69,12 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
@@ -101,14 +100,13 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod_tryAutoConfirm_withAutoConfirmPin() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setAutoConfirmEnabled(true)
utils.authenticationRepository.setUnlocked(false)
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
underTest.clearMessage()
@@ -138,13 +136,12 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod_tryAutoConfirm_withoutAutoConfirmPin() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.clearMessage()
@@ -168,14 +165,13 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun passwordAuthMethod() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
@@ -201,14 +197,13 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun patternAuthMethod() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
@@ -239,13 +234,12 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
}
@@ -253,12 +247,11 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe)
utils.authenticationRepository.setUnlocked(false)
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
}
@@ -266,8 +259,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_customMessageShown() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
@@ -275,7 +267,7 @@ class BouncerInteractorTest : SysuiTestCase() {
utils.authenticationRepository.setUnlocked(false)
val customMessage = "Hello there!"
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1, customMessage)
underTest.showOrUnlockDevice(customMessage)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(customMessage)
@@ -287,11 +279,10 @@ class BouncerInteractorTest : SysuiTestCase() {
val isThrottled by collectLastValue(underTest.isThrottled)
val throttling by collectLastValue(underTest.throttling)
val message by collectLastValue(underTest.message)
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
runCurrent()
underTest.showOrUnlockDevice(SceneTestUtils.CONTAINER_1)
underTest.showOrUnlockDevice()
runCurrent()
assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
assertThat(isThrottled).isFalse()

View File

@@ -72,18 +72,14 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -96,18 +92,14 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPasswordInputChanged() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -122,16 +114,12 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_whenCorrect() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("password")
@@ -144,18 +132,14 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_whenWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("wrong")
@@ -170,18 +154,14 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_correctAfterWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("wrong")

View File

@@ -75,8 +75,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -84,10 +83,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -101,8 +97,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragStart() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -110,10 +105,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -129,18 +121,14 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_whenCorrect() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
@@ -180,8 +168,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_whenWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -189,10 +176,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
@@ -216,8 +200,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_correctAfterWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -225,10 +208,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()

View File

@@ -75,15 +75,11 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -96,16 +92,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPinButtonClicked() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -120,16 +112,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onBackspaceButtonClicked() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -146,15 +134,11 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPinEdit() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -172,16 +156,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onBackspaceButtonLongPressed() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -200,14 +180,10 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_whenCorrect() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -222,16 +198,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_whenWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPinButtonClicked(1)
@@ -250,16 +222,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_correctAfterWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPinButtonClicked(1)
@@ -286,15 +254,11 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAutoConfirm_whenCorrect() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAutoConfirmEnabled(true)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -307,17 +271,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAutoConfirm_whenWrong() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAutoConfirmEnabled(true)
sceneInteractor.setCurrentScene(
SceneTestUtils.CONTAINER_1,
SceneModel(SceneKey.Bouncer)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit ->

View File

@@ -21,7 +21,6 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.SceneTestUtils.Companion.CONTAINER_1
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
@@ -91,7 +90,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() {
@Test
fun dismissLockScreen_deviceLockedWithSecureAuthMethod_switchesToBouncer() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
@@ -104,7 +103,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() {
@Test
fun dismissLockScreen_deviceUnlocked_switchesToGone() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setUnlocked(true)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
@@ -117,7 +116,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() {
@Test
fun dismissLockScreen_deviceLockedWithInsecureAuthMethod_switchesToGone() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
@@ -131,11 +130,11 @@ class LockscreenSceneInteractorTest : SysuiTestCase() {
fun switchFromLockScreenToGone_authMethodNotSwipe_doesNotUnlockDevice() =
testScope.runTest {
val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Lockscreen))
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Lockscreen))
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
assertThat(isUnlocked).isFalse()
sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Gone))
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone))
assertThat(isUnlocked).isFalse()
}
@@ -145,13 +144,13 @@ class LockscreenSceneInteractorTest : SysuiTestCase() {
testScope.runTest {
val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
runCurrent()
sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Shade))
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade))
runCurrent()
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe)
runCurrent()
assertThat(isUnlocked).isFalse()
sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Gone))
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone))
assertThat(isUnlocked).isFalse()
}
@@ -159,10 +158,10 @@ class LockscreenSceneInteractorTest : SysuiTestCase() {
@Test
fun authMethodChangedToNone_notOnLockScreenScene_doesNotDismissLockScreen() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe)
runCurrent()
sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.QuickSettings))
sceneInteractor.setCurrentScene(SceneModel(SceneKey.QuickSettings))
runCurrent()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.QuickSettings))

View File

@@ -22,9 +22,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.SceneTestUtils.Companion.CONTAINER_1
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
@@ -51,20 +49,15 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
private val underTest =
LockscreenSceneViewModel(
applicationScope = testScope.backgroundScope,
interactorFactory =
object : LockscreenSceneInteractor.Factory {
override fun create(containerName: String): LockscreenSceneInteractor {
return utils.lockScreenSceneInteractor(
interactor =
utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
),
)
}
},
containerName = CONTAINER_1
sceneInteractor = sceneInteractor,
),
),
)
@Test
@@ -116,7 +109,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onLockButtonClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
@@ -129,7 +122,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -142,7 +135,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
@@ -155,7 +148,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onLockButtonClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()

View File

@@ -20,9 +20,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.SceneTestUtils.Companion.CONTAINER_1
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
@@ -48,26 +46,21 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
private val underTest =
QuickSettingsSceneViewModel(
lockscreenSceneInteractorFactory =
object : LockscreenSceneInteractor.Factory {
override fun create(containerName: String): LockscreenSceneInteractor {
return utils.lockScreenSceneInteractor(
lockscreenSceneInteractor =
utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
),
)
}
},
containerName = CONTAINER_1
sceneInteractor = sceneInteractor,
),
),
)
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -80,7 +73,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()

View File

@@ -41,7 +41,7 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
@Test
fun allSceneKeys() {
val underTest = utils.fakeSceneContainerRepository()
assertThat(underTest.allSceneKeys(SceneTestUtils.CONTAINER_1))
assertThat(underTest.allSceneKeys())
.isEqualTo(
listOf(
SceneKey.QuickSettings,
@@ -53,162 +53,79 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
)
}
@Test(expected = IllegalStateException::class)
fun allSceneKeys_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.allSceneKeys("nonExistingContainer")
}
@Test
fun currentScene() = runTest {
val underTest = utils.fakeSceneContainerRepository()
val currentScene by collectLastValue(underTest.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
underTest.setCurrentScene(SceneTestUtils.CONTAINER_1, SceneModel(SceneKey.Shade))
underTest.setCurrentScene(SceneModel(SceneKey.Shade))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
}
@Test(expected = IllegalStateException::class)
fun currentScene_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.currentScene("nonExistingContainer")
}
@Test(expected = IllegalStateException::class)
fun setCurrentScene_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.setCurrentScene("nonExistingContainer", SceneModel(SceneKey.Shade))
}
@Test(expected = IllegalStateException::class)
fun setCurrentScene_noSuchSceneInContainer_throws() {
val underTest =
utils.fakeSceneContainerRepository(
setOf(
utils.fakeSceneContainerConfig(SceneTestUtils.CONTAINER_1),
utils.fakeSceneContainerConfig(
SceneTestUtils.CONTAINER_2,
listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)
),
)
utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
)
underTest.setCurrentScene(SceneTestUtils.CONTAINER_2, SceneModel(SceneKey.Shade))
underTest.setCurrentScene(SceneModel(SceneKey.Shade))
}
@Test
fun isVisible() = runTest {
val underTest = utils.fakeSceneContainerRepository()
val isVisible by collectLastValue(underTest.isVisible(SceneTestUtils.CONTAINER_1))
val isVisible by collectLastValue(underTest.isVisible)
assertThat(isVisible).isTrue()
underTest.setVisible(SceneTestUtils.CONTAINER_1, false)
underTest.setVisible(false)
assertThat(isVisible).isFalse()
underTest.setVisible(SceneTestUtils.CONTAINER_1, true)
underTest.setVisible(true)
assertThat(isVisible).isTrue()
}
@Test(expected = IllegalStateException::class)
fun isVisible_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.isVisible("nonExistingContainer")
}
@Test(expected = IllegalStateException::class)
fun setVisible_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.setVisible("nonExistingContainer", false)
}
@Test
fun sceneTransitionProgress() = runTest {
fun transitionProgress() = runTest {
val underTest = utils.fakeSceneContainerRepository()
val sceneTransitionProgress by
collectLastValue(underTest.sceneTransitionProgress(SceneTestUtils.CONTAINER_1))
val sceneTransitionProgress by collectLastValue(underTest.transitionProgress)
assertThat(sceneTransitionProgress).isEqualTo(1f)
underTest.setSceneTransitionProgress(SceneTestUtils.CONTAINER_1, 0.1f)
underTest.setSceneTransitionProgress(0.1f)
assertThat(sceneTransitionProgress).isEqualTo(0.1f)
underTest.setSceneTransitionProgress(SceneTestUtils.CONTAINER_1, 0.9f)
underTest.setSceneTransitionProgress(0.9f)
assertThat(sceneTransitionProgress).isEqualTo(0.9f)
}
@Test(expected = IllegalStateException::class)
fun sceneTransitionProgress_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.sceneTransitionProgress("nonExistingContainer")
}
@Test
fun setSceneTransition() = runTest {
val underTest =
utils.fakeSceneContainerRepository(
setOf(
utils.fakeSceneContainerConfig(SceneTestUtils.CONTAINER_1),
utils.fakeSceneContainerConfig(
SceneTestUtils.CONTAINER_2,
listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)
),
)
)
val sceneTransition by
collectLastValue(underTest.sceneTransitions(SceneTestUtils.CONTAINER_2))
val underTest = utils.fakeSceneContainerRepository()
val sceneTransition by collectLastValue(underTest.transitions)
assertThat(sceneTransition).isNull()
underTest.setSceneTransition(
SceneTestUtils.CONTAINER_2,
SceneKey.Lockscreen,
SceneKey.QuickSettings
)
underTest.setSceneTransition(SceneKey.Lockscreen, SceneKey.QuickSettings)
assertThat(sceneTransition)
.isEqualTo(
SceneTransitionModel(from = SceneKey.Lockscreen, to = SceneKey.QuickSettings)
)
}
@Test(expected = IllegalStateException::class)
fun setSceneTransition_noSuchContainer_throws() {
val underTest = utils.fakeSceneContainerRepository()
underTest.setSceneTransition("nonExistingContainer", SceneKey.Lockscreen, SceneKey.Shade)
}
@Test(expected = IllegalStateException::class)
fun setSceneTransition_noFromSceneInContainer_throws() {
val underTest =
utils.fakeSceneContainerRepository(
setOf(
utils.fakeSceneContainerConfig(SceneTestUtils.CONTAINER_1),
utils.fakeSceneContainerConfig(
SceneTestUtils.CONTAINER_2,
listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)
),
)
utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
)
underTest.setSceneTransition(
SceneTestUtils.CONTAINER_2,
SceneKey.Shade,
SceneKey.Lockscreen
)
underTest.setSceneTransition(SceneKey.Shade, SceneKey.Lockscreen)
}
@Test(expected = IllegalStateException::class)
fun setSceneTransition_noToSceneInContainer_throws() {
val underTest =
utils.fakeSceneContainerRepository(
setOf(
utils.fakeSceneContainerConfig(SceneTestUtils.CONTAINER_1),
utils.fakeSceneContainerConfig(
SceneTestUtils.CONTAINER_2,
listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)
),
)
utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
)
underTest.setSceneTransition(
SceneTestUtils.CONTAINER_2,
SceneKey.Shade,
SceneKey.Lockscreen
)
underTest.setSceneTransition(SceneKey.Shade, SceneKey.Lockscreen)
}
}

View File

@@ -41,48 +41,46 @@ class SceneInteractorTest : SysuiTestCase() {
@Test
fun allSceneKeys() {
assertThat(underTest.allSceneKeys(SceneTestUtils.CONTAINER_1))
.isEqualTo(utils.fakeSceneKeys())
assertThat(underTest.allSceneKeys()).isEqualTo(utils.fakeSceneKeys())
}
@Test
fun currentScene() = runTest {
val currentScene by collectLastValue(underTest.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
underTest.setCurrentScene(SceneTestUtils.CONTAINER_1, SceneModel(SceneKey.Shade))
underTest.setCurrentScene(SceneModel(SceneKey.Shade))
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
}
@Test
fun sceneTransitionProgress() = runTest {
val progress by
collectLastValue(underTest.sceneTransitionProgress(SceneTestUtils.CONTAINER_1))
val progress by collectLastValue(underTest.transitionProgress)
assertThat(progress).isEqualTo(1f)
underTest.setSceneTransitionProgress(SceneTestUtils.CONTAINER_1, 0.55f)
underTest.setSceneTransitionProgress(0.55f)
assertThat(progress).isEqualTo(0.55f)
}
@Test
fun isVisible() = runTest {
val isVisible by collectLastValue(underTest.isVisible(SceneTestUtils.CONTAINER_1))
val isVisible by collectLastValue(underTest.isVisible)
assertThat(isVisible).isTrue()
underTest.setVisible(SceneTestUtils.CONTAINER_1, false)
underTest.setVisible(false)
assertThat(isVisible).isFalse()
underTest.setVisible(SceneTestUtils.CONTAINER_1, true)
underTest.setVisible(true)
assertThat(isVisible).isTrue()
}
@Test
fun sceneTransitions() = runTest {
val transitions by collectLastValue(underTest.sceneTransitions(SceneTestUtils.CONTAINER_1))
val transitions by collectLastValue(underTest.transitions)
assertThat(transitions).isNull()
val initialSceneKey = underTest.currentScene(SceneTestUtils.CONTAINER_1).value.key
underTest.setCurrentScene(SceneTestUtils.CONTAINER_1, SceneModel(SceneKey.Shade))
val initialSceneKey = underTest.currentScene.value.key
underTest.setCurrentScene(SceneModel(SceneKey.Shade))
assertThat(transitions)
.isEqualTo(
SceneTransitionModel(
@@ -91,7 +89,7 @@ class SceneInteractorTest : SysuiTestCase() {
)
)
underTest.setCurrentScene(SceneTestUtils.CONTAINER_1, SceneModel(SceneKey.QuickSettings))
underTest.setCurrentScene(SceneModel(SceneKey.QuickSettings))
assertThat(transitions)
.isEqualTo(
SceneTransitionModel(

View File

@@ -28,7 +28,6 @@ import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.mockito.mock
@@ -47,7 +46,7 @@ import org.mockito.Mockito.verify
@SmallTest
@RunWith(JUnit4::class)
class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
class SceneContainerStartableTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
@@ -66,7 +65,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
private val sysUiState: SysUiState = mock()
private val underTest =
SystemUiDefaultSceneContainerStartable(
SceneContainerStartable(
applicationScope = testScope.backgroundScope,
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
@@ -84,14 +83,8 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateVisibility_featureEnabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val isVisible by
collectLastValue(sceneInteractor.isVisible(SceneContainerNames.SYSTEM_UI_DEFAULT))
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
val isVisible by collectLastValue(sceneInteractor.isVisible)
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = true,
@@ -104,24 +97,15 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
assertThat(isVisible).isFalse()
sceneInteractor.setCurrentScene(
SceneContainerNames.SYSTEM_UI_DEFAULT,
SceneModel(SceneKey.Shade)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade))
assertThat(isVisible).isTrue()
}
@Test
fun hydrateVisibility_featureDisabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val isVisible by
collectLastValue(sceneInteractor.isVisible(SceneContainerNames.SYSTEM_UI_DEFAULT))
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
val isVisible by collectLastValue(sceneInteractor.isVisible)
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = true,
@@ -133,28 +117,17 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
underTest.start()
assertThat(isVisible).isTrue()
sceneInteractor.setCurrentScene(
SceneContainerNames.SYSTEM_UI_DEFAULT,
SceneModel(SceneKey.Gone)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone))
assertThat(isVisible).isTrue()
sceneInteractor.setCurrentScene(
SceneContainerNames.SYSTEM_UI_DEFAULT,
SceneModel(SceneKey.Shade)
)
sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade))
assertThat(isVisible).isTrue()
}
@Test
fun switchToLockscreenWhenDeviceLocks_featureEnabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = true,
@@ -171,12 +144,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceLocks_featureDisabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -193,12 +161,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromBouncerToGoneWhenDeviceUnlocked_featureEnabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = false,
@@ -215,12 +178,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromBouncerToGoneWhenDeviceUnlocked_featureDisabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -237,12 +195,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOn() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isBypassEnabled = true,
@@ -259,12 +212,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOff() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isBypassEnabled = false,
@@ -281,12 +229,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOff_bypassOn() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isBypassEnabled = true,
@@ -303,12 +246,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceSleepsUnlocked_featureEnabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = true,
@@ -325,12 +263,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceSleepsUnlocked_featureDisabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = true,
@@ -347,12 +280,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceSleepsLocked_featureEnabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = false,
@@ -369,12 +297,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceSleepsLocked_featureDisabled() =
testScope.runTest {
val currentSceneKey by
collectLastValue(
sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
it.key
}
)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -403,10 +326,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
SceneKey.QuickSettings,
)
.forEachIndexed { index, sceneKey ->
sceneInteractor.setCurrentScene(
SceneContainerNames.SYSTEM_UI_DEFAULT,
SceneModel(sceneKey),
)
sceneInteractor.setCurrentScene(SceneModel(sceneKey))
runCurrent()
verify(sysUiState, times(index + 1)).commitUpdate(Display.DEFAULT_DISPLAY)
@@ -422,9 +342,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
featureFlags.set(Flags.SCENE_CONTAINER, isFeatureEnabled)
authenticationRepository.setUnlocked(isDeviceUnlocked)
keyguardRepository.setBypassEnabled(isBypassEnabled)
initialSceneKey?.let {
sceneInteractor.setCurrentScene(SceneContainerNames.SYSTEM_UI_DEFAULT, SceneModel(it))
}
initialSceneKey?.let { sceneInteractor.setCurrentScene(SceneModel(it)) }
}
companion object {

View File

@@ -45,7 +45,6 @@ class SceneContainerViewModelTest : SysuiTestCase() {
private val underTest =
SceneContainerViewModel(
interactor = interactor,
containerName = SceneTestUtils.CONTAINER_1,
)
@Test
@@ -53,10 +52,10 @@ class SceneContainerViewModelTest : SysuiTestCase() {
val isVisible by collectLastValue(underTest.isVisible)
assertThat(isVisible).isTrue()
interactor.setVisible(SceneTestUtils.CONTAINER_1, false)
interactor.setVisible(false)
assertThat(isVisible).isFalse()
interactor.setVisible(SceneTestUtils.CONTAINER_1, true)
interactor.setVisible(true)
assertThat(isVisible).isTrue()
}

View File

@@ -20,7 +20,6 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
@@ -48,20 +47,15 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
private val underTest =
ShadeSceneViewModel(
applicationScope = testScope.backgroundScope,
lockscreenSceneInteractorFactory =
object : LockscreenSceneInteractor.Factory {
override fun create(containerName: String): LockscreenSceneInteractor {
return utils.lockScreenSceneInteractor(
lockscreenSceneInteractor =
utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
),
)
}
},
containerName = SceneTestUtils.CONTAINER_1
sceneInteractor = sceneInteractor,
),
),
)
@Test
@@ -87,8 +81,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -101,8 +94,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
val currentScene by
collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
val currentScene by collectLastValue(sceneInteractor.currentScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()

View File

@@ -41,7 +41,6 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.RemoteUserInput
import com.android.systemui.scene.shared.model.RemoteUserInputAction
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.data.repository.UserRepository
@@ -96,13 +95,9 @@ class SceneTestUtils(
private val context = test.context
fun fakeSceneContainerRepository(
containerConfigurations: Set<SceneContainerConfig> =
setOf(
fakeSceneContainerConfig(CONTAINER_1),
fakeSceneContainerConfig(CONTAINER_2),
)
containerConfig: SceneContainerConfig = fakeSceneContainerConfig(),
): SceneContainerRepository {
return SceneContainerRepository(containerConfigurations.associateBy { it.name })
return SceneContainerRepository(containerConfig)
}
fun fakeSceneKeys(): List<SceneKey> {
@@ -116,11 +111,9 @@ class SceneTestUtils(
}
fun fakeSceneContainerConfig(
name: String,
sceneKeys: List<SceneKey> = fakeSceneKeys(),
): SceneContainerConfig {
return SceneContainerConfig(
name = name,
sceneKeys = sceneKeys,
initialSceneKey = SceneKey.Lockscreen,
)
@@ -174,7 +167,6 @@ class SceneTestUtils(
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
featureFlags = featureFlags,
containerName = CONTAINER_1,
)
}
@@ -184,14 +176,8 @@ class SceneTestUtils(
return BouncerViewModel(
applicationContext = context,
applicationScope = applicationScope(),
interactorFactory =
object : BouncerInteractor.Factory {
override fun create(containerName: String): BouncerInteractor {
return bouncerInteractor
}
},
interactor = bouncerInteractor,
featureFlags = featureFlags,
containerName = CONTAINER_1,
)
}
@@ -202,13 +188,7 @@ class SceneTestUtils(
return LockscreenSceneInteractor(
applicationScope = applicationScope(),
authenticationInteractor = authenticationInteractor,
bouncerInteractorFactory =
object : BouncerInteractor.Factory {
override fun create(containerName: String): BouncerInteractor {
return bouncerInteractor
}
},
containerName = CONTAINER_1,
bouncerInteractor = bouncerInteractor,
)
}
@@ -217,9 +197,6 @@ class SceneTestUtils(
}
companion object {
const val CONTAINER_1 = SceneContainerNames.SYSTEM_UI_DEFAULT
const val CONTAINER_2 = "container2"
val REMOTE_INPUT_DOWN_GESTURE =
listOf(
RemoteUserInput(10f, 10f, RemoteUserInputAction.DOWN),