1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 @file:OptIn(ExperimentalCoroutinesApi::class)
18 
19 package com.android.systemui.scene.domain.resolver
20 
21 import com.android.compose.animation.scene.SceneKey
22 import com.android.systemui.dagger.SysUISingleton
23 import com.android.systemui.dagger.qualifiers.Application
24 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
25 import com.android.systemui.scene.shared.model.SceneFamilies
26 import com.android.systemui.scene.shared.model.Scenes
27 import dagger.Binds
28 import dagger.Module
29 import dagger.multibindings.IntoSet
30 import javax.inject.Inject
31 import kotlinx.coroutines.CoroutineScope
32 import kotlinx.coroutines.ExperimentalCoroutinesApi
33 import kotlinx.coroutines.flow.SharingStarted
34 import kotlinx.coroutines.flow.StateFlow
35 import kotlinx.coroutines.flow.combine
36 import kotlinx.coroutines.flow.stateIn
37 
38 /**
39  * Resolver for [SceneFamilies.Home]. The "home" scene family resolves to the scene that is
40  * currently underneath any "overlay" scene, such as shades or bouncer.
41  */
42 @SysUISingleton
43 class HomeSceneFamilyResolver
44 @Inject
45 constructor(
46     @Application private val applicationScope: CoroutineScope,
47     deviceEntryInteractor: DeviceEntryInteractor,
48 ) : SceneResolver {
49     override val targetFamily: SceneKey = SceneFamilies.Home
50 
51     override val resolvedScene: StateFlow<SceneKey> =
52         combine(
53                 deviceEntryInteractor.canSwipeToEnter,
54                 deviceEntryInteractor.isDeviceEntered,
55                 deviceEntryInteractor.isUnlocked,
56                 transform = ::homeScene,
57             )
58             .stateIn(
59                 scope = applicationScope,
60                 started = SharingStarted.Eagerly,
61                 initialValue =
62                     homeScene(
63                         deviceEntryInteractor.canSwipeToEnter.value,
64                         deviceEntryInteractor.isDeviceEntered.value,
65                         deviceEntryInteractor.isUnlocked.value,
66                     )
67             )
68 
includesScenenull69     override fun includesScene(scene: SceneKey): Boolean = scene in homeScenes
70 
71     private fun homeScene(
72         canSwipeToEnter: Boolean?,
73         isDeviceEntered: Boolean,
74         isUnlocked: Boolean,
75     ): SceneKey =
76         when {
77             canSwipeToEnter == true -> Scenes.Lockscreen
78             !isDeviceEntered -> Scenes.Lockscreen
79             !isUnlocked -> Scenes.Lockscreen
80             else -> Scenes.Gone
81         }
82 
83     companion object {
84         val homeScenes =
85             setOf(
86                 Scenes.Gone,
87                 Scenes.Lockscreen,
88             )
89     }
90 }
91 
92 @Module
93 interface HomeSceneFamilyResolverModule {
provideSceneResolvernull94     @Binds @IntoSet fun provideSceneResolver(interactor: HomeSceneFamilyResolver): SceneResolver
95 }
96