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.keyguard.data.quickaffordance
19 
20 import android.content.Context
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.filters.SmallTest
23 import com.android.systemui.R
24 import com.android.systemui.RoboPilotTest
25 import com.android.systemui.common.shared.model.Icon
26 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
27 import com.android.systemui.statusbar.policy.FlashlightController
28 import com.android.systemui.utils.leaks.FakeFlashlightController
29 import com.android.systemui.utils.leaks.LeakCheckedTest
30 import kotlinx.coroutines.ExperimentalCoroutinesApi
31 import kotlinx.coroutines.flow.toList
32 import kotlinx.coroutines.launch
33 import kotlinx.coroutines.test.UnconfinedTestDispatcher
34 import kotlinx.coroutines.test.runTest
35 import org.junit.Assert.assertEquals
36 import org.junit.Assert.assertTrue
37 import org.junit.Before
38 import org.junit.Test
39 import org.junit.runner.RunWith
40 import org.mockito.Mock
41 import org.mockito.MockitoAnnotations
42 
43 @OptIn(ExperimentalCoroutinesApi::class)
44 @SmallTest
45 @RoboPilotTest
46 @RunWith(AndroidJUnit4::class)
47 class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
48 
49     @Mock private lateinit var context: Context
50     private lateinit var flashlightController: FakeFlashlightController
51     private lateinit var underTest: FlashlightQuickAffordanceConfig
52 
53     @Before
54     fun setUp() {
55         injectLeakCheckedDependency(FlashlightController::class.java)
56         MockitoAnnotations.initMocks(this)
57 
58         flashlightController =
59             SysuiLeakCheck().getLeakChecker(FlashlightController::class.java)
60                 as FakeFlashlightController
61         underTest = FlashlightQuickAffordanceConfig(context, flashlightController)
62     }
63 
64     @Test
65     fun flashlightIsOff_triggered_iconIsOnAndActive() = runTest {
66         // given
67         flashlightController.isEnabled = false
68         flashlightController.isAvailable = true
69         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
70         val job = launch(UnconfinedTestDispatcher()) { underTest.lockScreenState.toList(values) }
71 
72         // when
73         underTest.onTriggered(null)
74         val lastValue = values.last()
75 
76         // then
77         assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
78         assertEquals(
79             R.drawable.qs_flashlight_icon_on,
80             ((lastValue as KeyguardQuickAffordanceConfig.LockScreenState.Visible).icon
81                     as? Icon.Resource)
82                 ?.res
83         )
84         job.cancel()
85     }
86 
87     @Test
88     fun flashlightIsOn_triggered_iconIsOffAndInactive() = runTest {
89         // given
90         flashlightController.isEnabled = true
91         flashlightController.isAvailable = true
92         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
93         val job = launch(UnconfinedTestDispatcher()) { underTest.lockScreenState.toList(values) }
94 
95         // when
96         underTest.onTriggered(null)
97         val lastValue = values.last()
98 
99         // then
100         assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
101         assertEquals(
102             R.drawable.qs_flashlight_icon_off,
103             ((lastValue as KeyguardQuickAffordanceConfig.LockScreenState.Visible).icon
104                     as? Icon.Resource)
105                 ?.res
106         )
107         job.cancel()
108     }
109 
110     @Test
111     fun flashlightIsOn_receivesError_iconIsOffAndInactive() = runTest {
112         // given
113         flashlightController.isEnabled = true
114         flashlightController.isAvailable = false
115         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
116         val job = launch(UnconfinedTestDispatcher()) { underTest.lockScreenState.toList(values) }
117 
118         // when
119         flashlightController.onFlashlightError()
120         val lastValue = values.last()
121 
122         // then
123         assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
124         assertEquals(
125             R.drawable.qs_flashlight_icon_off,
126             ((lastValue as KeyguardQuickAffordanceConfig.LockScreenState.Visible).icon
127                     as? Icon.Resource)
128                 ?.res
129         )
130         job.cancel()
131     }
132 
133     @Test
134     fun flashlightAvailabilityNowOff_hidden() = runTest {
135         // given
136         flashlightController.isEnabled = true
137         flashlightController.isAvailable = false
138         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
139         val job = launch(UnconfinedTestDispatcher()) { underTest.lockScreenState.toList(values) }
140 
141         // when
142         flashlightController.onFlashlightAvailabilityChanged(false)
143         val lastValue = values.last()
144 
145         // then
146         assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
147         job.cancel()
148     }
149 
150     @Test
151     fun flashlightAvailabilityNowOn_flashlightOn_inactiveAndIconOff() = runTest {
152         // given
153         flashlightController.isEnabled = true
154         flashlightController.isAvailable = false
155         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
156         val job = launch(UnconfinedTestDispatcher()) { underTest.lockScreenState.toList(values) }
157 
158         // when
159         flashlightController.onFlashlightAvailabilityChanged(true)
160         val lastValue = values.last()
161 
162         // then
163         assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
164         assertTrue(
165             (lastValue as KeyguardQuickAffordanceConfig.LockScreenState.Visible).activationState
166                 is ActivationState.Active
167         )
168         assertEquals(R.drawable.qs_flashlight_icon_on, (lastValue.icon as? Icon.Resource)?.res)
169         job.cancel()
170     }
171 
172     @Test
173     fun flashlightAvailabilityNowOn_flashlightOff_inactiveAndIconOff() = runTest {
174         // given
175         flashlightController.isEnabled = false
176         flashlightController.isAvailable = false
177         val values = mutableListOf<KeyguardQuickAffordanceConfig.LockScreenState>()
178         val job = launch(UnconfinedTestDispatcher()) { underTest.lockScreenState.toList(values) }
179 
180         // when
181         flashlightController.onFlashlightAvailabilityChanged(true)
182         val lastValue = values.last()
183 
184         // then
185         assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
186         assertTrue(
187             (lastValue as KeyguardQuickAffordanceConfig.LockScreenState.Visible).activationState
188                 is ActivationState.Inactive
189         )
190         assertEquals(R.drawable.qs_flashlight_icon_off, (lastValue.icon as? Icon.Resource)?.res)
191         job.cancel()
192     }
193 
194     @Test
195     fun flashlightAvailable_pickerStateDefault() = runTest {
196         // given
197         flashlightController.isAvailable = true
198 
199         // when
200         val result = underTest.getPickerScreenState()
201 
202         // then
203         assertTrue(result is KeyguardQuickAffordanceConfig.PickerScreenState.Default)
204     }
205 
206     @Test
207     fun flashlightNotAvailable_pickerStateUnavailable() = runTest {
208         // given
209         flashlightController.isAvailable = false
210 
211         // when
212         val result = underTest.getPickerScreenState()
213 
214         // then
215         assertTrue(result is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
216     }
217 }
218