1 /*
2  * Copyright (C) 2022 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 
18 package com.android.systemui.controls.settings
19 
20 import android.content.pm.UserInfo
21 import android.provider.Settings
22 import androidx.test.filters.SmallTest
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.user.data.repository.FakeUserRepository
25 import com.android.systemui.util.settings.FakeSettings
26 import com.google.common.truth.Truth.assertThat
27 import kotlinx.coroutines.ExperimentalCoroutinesApi
28 import kotlinx.coroutines.flow.toList
29 import kotlinx.coroutines.launch
30 import kotlinx.coroutines.test.TestScope
31 import kotlinx.coroutines.test.UnconfinedTestDispatcher
32 import kotlinx.coroutines.test.runTest
33 import org.junit.Before
34 import org.junit.Test
35 import org.junit.runner.RunWith
36 import org.junit.runners.JUnit4
37 
38 @SmallTest
39 @RunWith(JUnit4::class)
40 @OptIn(ExperimentalCoroutinesApi::class)
41 class ControlsSettingsRepositoryImplTest : SysuiTestCase() {
42 
43     companion object {
44         private const val LOCKSCREEN_SHOW = Settings.Secure.LOCKSCREEN_SHOW_CONTROLS
45         private const val LOCKSCREEN_ACTION = Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS
46 
47         private fun createUser(id: Int): UserInfo {
48             return UserInfo(id, "user_$id", 0)
49         }
50 
51         private val ALL_USERS = (0..1).map { it to createUser(it) }.toMap()
52     }
53 
54     private lateinit var underTest: ControlsSettingsRepository
55 
56     private lateinit var testScope: TestScope
57     private lateinit var secureSettings: FakeSettings
58     private lateinit var userRepository: FakeUserRepository
59 
60     @Before
61     fun setUp() {
62         secureSettings = FakeSettings()
63         userRepository = FakeUserRepository()
64         userRepository.setUserInfos(ALL_USERS.values.toList())
65 
66         val coroutineDispatcher = UnconfinedTestDispatcher()
67         testScope = TestScope(coroutineDispatcher)
68 
69         underTest =
70             ControlsSettingsRepositoryImpl(
71                 scope = testScope.backgroundScope,
72                 backgroundDispatcher = coroutineDispatcher,
73                 userRepository = userRepository,
74                 secureSettings = secureSettings,
75             )
76     }
77 
78     @Test
79     fun showInLockScreen() =
80         testScope.runTest {
81             setUser(0)
82             val values = mutableListOf<Boolean>()
83             val job =
84                 launch(UnconfinedTestDispatcher()) {
85                     underTest.canShowControlsInLockscreen.toList(values)
86                 }
87             assertThat(values.last()).isFalse()
88 
89             secureSettings.putBool(LOCKSCREEN_SHOW, true)
90             assertThat(values.last()).isTrue()
91 
92             secureSettings.putBool(LOCKSCREEN_SHOW, false)
93             assertThat(values.last()).isFalse()
94 
95             secureSettings.putBoolForUser(LOCKSCREEN_SHOW, true, 1)
96             assertThat(values.last()).isFalse()
97 
98             setUser(1)
99             assertThat(values.last()).isTrue()
100 
101             job.cancel()
102         }
103 
104     @Test
105     fun showInLockScreen_changesInOtherUsersAreNotQueued() =
106         testScope.runTest {
107             setUser(0)
108 
109             val values = mutableListOf<Boolean>()
110             val job =
111                 launch(UnconfinedTestDispatcher()) {
112                     underTest.canShowControlsInLockscreen.toList(values)
113                 }
114 
115             secureSettings.putBoolForUser(LOCKSCREEN_SHOW, true, 1)
116             secureSettings.putBoolForUser(LOCKSCREEN_SHOW, false, 1)
117 
118             setUser(1)
119             assertThat(values.last()).isFalse()
120             assertThat(values).containsNoneIn(listOf(true))
121 
122             job.cancel()
123         }
124 
125     @Test
126     fun actionInLockScreen() =
127         testScope.runTest {
128             setUser(0)
129             val values = mutableListOf<Boolean>()
130             val job =
131                 launch(UnconfinedTestDispatcher()) {
132                     underTest.allowActionOnTrivialControlsInLockscreen.toList(values)
133                 }
134             assertThat(values.last()).isFalse()
135 
136             secureSettings.putBool(LOCKSCREEN_ACTION, true)
137             assertThat(values.last()).isTrue()
138 
139             secureSettings.putBool(LOCKSCREEN_ACTION, false)
140             assertThat(values.last()).isFalse()
141 
142             secureSettings.putBoolForUser(LOCKSCREEN_ACTION, true, 1)
143             assertThat(values.last()).isFalse()
144 
145             setUser(1)
146             assertThat(values.last()).isTrue()
147 
148             job.cancel()
149         }
150 
151     @Test
152     fun actionInLockScreen_changesInOtherUsersAreNotQueued() =
153         testScope.runTest {
154             setUser(0)
155 
156             val values = mutableListOf<Boolean>()
157             val job =
158                 launch(UnconfinedTestDispatcher()) {
159                     underTest.allowActionOnTrivialControlsInLockscreen.toList(values)
160                 }
161 
162             secureSettings.putBoolForUser(LOCKSCREEN_ACTION, true, 1)
163             secureSettings.putBoolForUser(LOCKSCREEN_ACTION, false, 1)
164 
165             setUser(1)
166             assertThat(values.last()).isFalse()
167             assertThat(values).containsNoneIn(listOf(true))
168 
169             job.cancel()
170         }
171 
172     @Test
173     fun valueIsUpdatedWhenNotSubscribed() =
174         testScope.runTest {
175             setUser(0)
176             assertThat(underTest.canShowControlsInLockscreen.value).isFalse()
177 
178             secureSettings.putBool(LOCKSCREEN_SHOW, true)
179 
180             assertThat(underTest.canShowControlsInLockscreen.value).isTrue()
181         }
182 
183     private suspend fun setUser(id: Int) {
184         secureSettings.userId = id
185         userRepository.setSelectedUserInfo(ALL_USERS[id]!!)
186     }
187 }
188