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.power.domain.interactor
19 
20 import android.os.PowerManager
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.filters.SmallTest
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.camera.cameraGestureHelper
25 import com.android.systemui.classifier.FalsingCollector
26 import com.android.systemui.coroutines.collectLastValue
27 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
28 import com.android.systemui.kosmos.testScope
29 import com.android.systemui.plugins.statusbar.StatusBarStateController
30 import com.android.systemui.power.data.repository.FakePowerRepository
31 import com.android.systemui.power.shared.model.WakeSleepReason
32 import com.android.systemui.power.shared.model.WakefulnessState
33 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
34 import com.android.systemui.testKosmos
35 import com.android.systemui.util.mockito.any
36 import com.android.systemui.util.mockito.whenever
37 import com.google.common.truth.Truth.assertThat
38 import junit.framework.Assert.assertFalse
39 import junit.framework.Assert.assertTrue
40 import kotlinx.coroutines.test.runTest
41 import org.junit.Before
42 import org.junit.Test
43 import org.junit.runner.RunWith
44 import org.mockito.Mock
45 import org.mockito.Mockito.verify
46 import org.mockito.MockitoAnnotations
47 
48 @SmallTest
49 @RunWith(AndroidJUnit4::class)
50 class PowerInteractorTest : SysuiTestCase() {
51     private val kosmos = testKosmos()
52     private val testScope = kosmos.testScope
53     private val cameraGestureHelper = kosmos.cameraGestureHelper
54 
55     private lateinit var underTest: PowerInteractor
56     private lateinit var repository: FakePowerRepository
57     private val keyguardRepository = FakeKeyguardRepository()
58     @Mock private lateinit var falsingCollector: FalsingCollector
59     @Mock private lateinit var screenOffAnimationController: ScreenOffAnimationController
60     @Mock private lateinit var statusBarStateController: StatusBarStateController
61 
62     @Before
setUpnull63     fun setUp() {
64         MockitoAnnotations.initMocks(this)
65 
66         repository = FakePowerRepository()
67         underTest =
68             PowerInteractor(
69                 repository,
70                 falsingCollector,
71                 screenOffAnimationController,
72                 statusBarStateController,
73                 { cameraGestureHelper },
74             )
75 
76         whenever(cameraGestureHelper.canCameraGestureBeLaunched(any())).thenReturn(true)
77     }
78 
79     @Test
isInteractive_screenTurnsOffnull80     fun isInteractive_screenTurnsOff() =
81         testScope.runTest {
82             repository.setInteractive(true)
83             val isInteractive by collectLastValue(underTest.isInteractive)
84 
85             repository.setInteractive(false)
86             assertThat(isInteractive).isFalse()
87         }
88 
89     @Test
isInteractive_becomesInteractivenull90     fun isInteractive_becomesInteractive() =
91         testScope.runTest {
92             repository.setInteractive(false)
93             val isInteractive by collectLastValue(underTest.isInteractive)
94 
95             repository.setInteractive(true)
96             assertThat(isInteractive).isTrue()
97         }
98 
99     @Test
wakeUpIfDozing_notDozing_notWokennull100     fun wakeUpIfDozing_notDozing_notWoken() {
101         whenever(statusBarStateController.isDozing).thenReturn(false)
102         whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(true)
103 
104         underTest.wakeUpIfDozing("why", PowerManager.WAKE_REASON_TAP)
105 
106         assertThat(repository.lastWakeWhy).isNull()
107         assertThat(repository.lastWakeReason).isNull()
108     }
109 
110     @Test
wakeUpIfDozing_notAllowed_notWokennull111     fun wakeUpIfDozing_notAllowed_notWoken() {
112         whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(false)
113         whenever(statusBarStateController.isDozing).thenReturn(true)
114 
115         underTest.wakeUpIfDozing("why", PowerManager.WAKE_REASON_TAP)
116 
117         assertThat(repository.lastWakeWhy).isNull()
118         assertThat(repository.lastWakeReason).isNull()
119     }
120 
121     @Test
wakeUpIfDozing_dozingAndAllowed_wokenAndFalsingNotifiednull122     fun wakeUpIfDozing_dozingAndAllowed_wokenAndFalsingNotified() {
123         whenever(statusBarStateController.isDozing).thenReturn(true)
124         whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(true)
125 
126         underTest.wakeUpIfDozing("testReason", PowerManager.WAKE_REASON_GESTURE)
127 
128         assertThat(repository.lastWakeWhy).isEqualTo("testReason")
129         assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_GESTURE)
130         verify(falsingCollector).onScreenOnFromTouch()
131     }
132 
133     @Test
wakeUpForFullScreenIntent_notGoingToSleepAndNotDozing_notWokennull134     fun wakeUpForFullScreenIntent_notGoingToSleepAndNotDozing_notWoken() {
135         underTest.onFinishedWakingUp()
136         whenever(statusBarStateController.isDozing).thenReturn(false)
137 
138         underTest.wakeUpForFullScreenIntent()
139 
140         assertThat(repository.lastWakeWhy).isNull()
141         assertThat(repository.lastWakeReason).isNull()
142     }
143 
144     @Test
wakeUpForFullScreenIntent_startingToSleep_wokennull145     fun wakeUpForFullScreenIntent_startingToSleep_woken() {
146         underTest.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_MIN)
147         whenever(statusBarStateController.isDozing).thenReturn(false)
148 
149         underTest.wakeUpForFullScreenIntent()
150 
151         assertThat(repository.lastWakeWhy).isNotNull()
152         assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_APPLICATION)
153     }
154 
155     @Test
wakeUpForFullScreenIntent_dozing_wokennull156     fun wakeUpForFullScreenIntent_dozing_woken() {
157         whenever(statusBarStateController.isDozing).thenReturn(true)
158         underTest.onFinishedWakingUp()
159         underTest.wakeUpForFullScreenIntent()
160 
161         assertThat(repository.lastWakeWhy).isNotNull()
162         assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_APPLICATION)
163     }
164 
165     @Test
wakeUpIfDreaming_dreaming_wokennull166     fun wakeUpIfDreaming_dreaming_woken() {
167         // GIVEN device is dreaming
168         whenever(statusBarStateController.isDreaming).thenReturn(true)
169 
170         // WHEN wakeUpIfDreaming is called
171         underTest.wakeUpIfDreaming("testReason", PowerManager.WAKE_REASON_GESTURE)
172 
173         // THEN device is woken up
174         assertThat(repository.lastWakeWhy).isEqualTo("testReason")
175         assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_GESTURE)
176     }
177 
178     @Test
wakeUpIfDreaming_notDreaming_notWokennull179     fun wakeUpIfDreaming_notDreaming_notWoken() {
180         // GIVEN device is not dreaming
181         whenever(statusBarStateController.isDreaming).thenReturn(false)
182 
183         // WHEN wakeUpIfDreaming is called
184         underTest.wakeUpIfDreaming("why", PowerManager.WAKE_REASON_TAP)
185 
186         // THEN device is not woken
187         assertThat(repository.lastWakeWhy).isNull()
188         assertThat(repository.lastWakeReason).isNull()
189     }
190 
191     @Test
onStartedGoingToSleep_clearsPowerButtonLaunchGestureTriggerednull192     fun onStartedGoingToSleep_clearsPowerButtonLaunchGestureTriggered() {
193         underTest.onStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON, true)
194 
195         assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
196 
197         underTest.onFinishedWakingUp()
198 
199         assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
200 
201         underTest.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
202 
203         assertFalse(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
204     }
205 
206     @Test
onCameraLaunchGestureDetected_isNotTrueWhenCannotLaunchnull207     fun onCameraLaunchGestureDetected_isNotTrueWhenCannotLaunch() {
208         whenever(cameraGestureHelper.canCameraGestureBeLaunched(any())).thenReturn(false)
209         underTest.onStartedWakingUp(
210             PowerManager.WAKE_REASON_POWER_BUTTON,
211             /*powerButtonLaunchGestureTriggeredDuringSleep= */ false
212         )
213         underTest.onFinishedWakingUp()
214         underTest.onCameraLaunchGestureDetected()
215 
216         assertThat(repository.wakefulness.value.internalWakefulnessState)
217             .isEqualTo(WakefulnessState.AWAKE)
218         assertThat(repository.wakefulness.value.lastWakeReason)
219             .isEqualTo(WakeSleepReason.POWER_BUTTON)
220         assertFalse(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
221     }
222 
223     @Test
onCameraLaunchGestureDetected_maintainsAllOtherStatenull224     fun onCameraLaunchGestureDetected_maintainsAllOtherState() {
225         underTest.onStartedWakingUp(
226             PowerManager.WAKE_REASON_POWER_BUTTON,
227             /*powerButtonLaunchGestureTriggeredDuringSleep= */ false
228         )
229         underTest.onFinishedWakingUp()
230         underTest.onCameraLaunchGestureDetected()
231 
232         assertThat(repository.wakefulness.value.internalWakefulnessState)
233             .isEqualTo(WakefulnessState.AWAKE)
234         assertThat(repository.wakefulness.value.lastWakeReason)
235             .isEqualTo(WakeSleepReason.POWER_BUTTON)
236         assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
237     }
238 
239     @Test
onCameraLaunchGestureDetected_stillTrue_ifGestureNotDetectedOnWakingUpnull240     fun onCameraLaunchGestureDetected_stillTrue_ifGestureNotDetectedOnWakingUp() {
241         underTest.onCameraLaunchGestureDetected()
242         // Ensure that the 'false' here does not clear the direct launch detection call earlier.
243         // This state should only be reset onStartedGoingToSleep.
244         underTest.onFinishedGoingToSleep(/* powerButtonLaunchGestureTriggeredDuringSleep= */ false)
245         underTest.onStartedWakingUp(
246             PowerManager.WAKE_REASON_POWER_BUTTON,
247             /*powerButtonLaunchGestureTriggeredDuringSleep= */ false
248         )
249         underTest.onFinishedWakingUp()
250 
251         assertThat(repository.wakefulness.value.internalWakefulnessState)
252             .isEqualTo(WakefulnessState.AWAKE)
253         assertThat(repository.wakefulness.value.lastWakeReason)
254             .isEqualTo(WakeSleepReason.POWER_BUTTON)
255         assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
256     }
257 
258     @Test
cameraLaunchDetectedOnGoingToSleep_stillTrue_ifGestureNotDetectedOnWakingUpnull259     fun cameraLaunchDetectedOnGoingToSleep_stillTrue_ifGestureNotDetectedOnWakingUp() {
260         underTest.onFinishedGoingToSleep(/* powerButtonLaunchGestureTriggeredDuringSleep= */ true)
261         // Ensure that the 'false' here does not clear the direct launch detection call earlier.
262         // This state should only be reset onStartedGoingToSleep.
263         underTest.onStartedWakingUp(
264             PowerManager.WAKE_REASON_POWER_BUTTON,
265             /*powerButtonLaunchGestureTriggeredDuringSleep= */ false
266         )
267         underTest.onFinishedWakingUp()
268 
269         assertThat(repository.wakefulness.value.internalWakefulnessState)
270             .isEqualTo(WakefulnessState.AWAKE)
271         assertThat(repository.wakefulness.value.lastWakeReason)
272             .isEqualTo(WakeSleepReason.POWER_BUTTON)
273         assertTrue(repository.wakefulness.value.powerButtonLaunchGestureTriggered)
274     }
275 }
276