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 package com.android.systemui.deviceentry.domain.ui.binder
18 
19 import android.content.packageManager
20 import android.content.pm.PackageManager
21 import android.hardware.Sensor
22 import android.hardware.TriggerEventListener
23 import android.testing.TestableLooper
24 import androidx.test.ext.junit.runners.AndroidJUnit4
25 import androidx.test.filters.SmallTest
26 import com.android.systemui.SysuiTestCase
27 import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
28 import com.android.systemui.deviceentry.ui.binder.liftToRunFaceAuthBinder
29 import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
30 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
31 import com.android.systemui.kosmos.testScope
32 import com.android.systemui.power.data.repository.fakePowerRepository
33 import com.android.systemui.testKosmos
34 import com.android.systemui.util.mockito.any
35 import com.android.systemui.util.mockito.capture
36 import com.android.systemui.util.mockito.whenever
37 import com.android.systemui.util.sensors.asyncSensorManager
38 import kotlinx.coroutines.ExperimentalCoroutinesApi
39 import kotlinx.coroutines.test.runCurrent
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.ArgumentCaptor
45 import org.mockito.Captor
46 import org.mockito.Mock
47 import org.mockito.Mockito.clearInvocations
48 import org.mockito.Mockito.never
49 import org.mockito.Mockito.verify
50 import org.mockito.MockitoAnnotations
51 
52 @ExperimentalCoroutinesApi
53 @SmallTest
54 @RunWith(AndroidJUnit4::class)
55 @TestableLooper.RunWithLooper(setAsMainLooper = true)
56 class LiftToRunFaceAuthBinderTest : SysuiTestCase() {
57     private val kosmos = testKosmos()
58     private val testScope = kosmos.testScope
59     private val sensorManager = kosmos.asyncSensorManager
60     private val powerRepository = kosmos.fakePowerRepository
61     private val keyguardRepository = kosmos.fakeKeyguardRepository
62     private val bouncerRepository = kosmos.keyguardBouncerRepository
63     private val biometricSettingsRepository = kosmos.biometricSettingsRepository
64     private val packageManager = kosmos.packageManager
65 
66     @Captor private lateinit var triggerEventListenerCaptor: ArgumentCaptor<TriggerEventListener>
67     @Mock private lateinit var mockSensor: Sensor
68 
<lambda>null69     private val underTest by lazy { kosmos.liftToRunFaceAuthBinder }
70 
71     @Before
setupnull72     fun setup() {
73         MockitoAnnotations.initMocks(this)
74         whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true)
75         whenever(sensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)).thenReturn(mockSensor)
76     }
77 
78     @Test
doNotListenForGesturenull79     fun doNotListenForGesture() =
80         testScope.runTest {
81             start()
82             verifyNeverRequestsTriggerSensor()
83         }
84 
85     @Test
awakeKeyguard_listenForGesturenull86     fun awakeKeyguard_listenForGesture() =
87         testScope.runTest {
88             start()
89             givenAwakeKeyguard(true)
90             runCurrent()
91             verifyRequestTriggerSensor()
92         }
93 
94     @Test
faceNotEnrolled_listenForGesturenull95     fun faceNotEnrolled_listenForGesture() =
96         testScope.runTest {
97             start()
98             givenAwakeKeyguard(true)
99             biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(false)
100             runCurrent()
101             verifyNeverRequestsTriggerSensor()
102         }
103 
104     @Test
notInteractive_doNotListenForGesturenull105     fun notInteractive_doNotListenForGesture() =
106         testScope.runTest {
107             start()
108             givenAwakeKeyguard(true)
109             powerRepository.setInteractive(false)
110             runCurrent()
111             verifyNeverRequestsTriggerSensor()
112         }
113 
114     @Test
primaryBouncer_listenForGesturenull115     fun primaryBouncer_listenForGesture() =
116         testScope.runTest {
117             start()
118             givenAwakeKeyguard(false)
119             givenPrimaryBouncerShowing()
120             runCurrent()
121             verifyRequestTriggerSensor()
122         }
123 
124     @Test
alternateBouncer_listenForGesturenull125     fun alternateBouncer_listenForGesture() =
126         testScope.runTest {
127             start()
128             givenAwakeKeyguard(false)
129             givenAlternateBouncerShowing()
130             runCurrent()
131             verifyRequestTriggerSensor()
132         }
133 
134     @Test
restartListeningForGestureAfterSensorTriggernull135     fun restartListeningForGestureAfterSensorTrigger() =
136         testScope.runTest {
137             start()
138             givenAwakeKeyguard(true)
139             runCurrent()
140             verifyRequestTriggerSensor()
141             clearInvocations(sensorManager)
142 
143             triggerEventListenerCaptor.value.onTrigger(null)
144             runCurrent()
145             verifyRequestTriggerSensor()
146         }
147 
148     @Test
cancelTriggerSensor_keyguardNotAwakeAnymorenull149     fun cancelTriggerSensor_keyguardNotAwakeAnymore() =
150         testScope.runTest {
151             start()
152             givenAwakeKeyguard(true)
153             runCurrent()
154             verifyRequestTriggerSensor()
155 
156             givenAwakeKeyguard(false)
157             runCurrent()
158             verifyCancelTriggerSensor()
159         }
160 
startnull161     private fun start() {
162         underTest.start()
163         biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
164         givenAwakeKeyguard(false)
165         givenBouncerNotShowing()
166     }
167 
givenAwakeKeyguardnull168     private fun givenAwakeKeyguard(isAwake: Boolean) {
169         powerRepository.setInteractive(isAwake)
170         keyguardRepository.setKeyguardShowing(isAwake)
171         keyguardRepository.setKeyguardOccluded(false)
172     }
173 
givenPrimaryBouncerShowingnull174     private fun givenPrimaryBouncerShowing() {
175         bouncerRepository.setPrimaryShow(true)
176         bouncerRepository.setAlternateVisible(false)
177     }
178 
givenBouncerNotShowingnull179     private fun givenBouncerNotShowing() {
180         bouncerRepository.setPrimaryShow(false)
181         bouncerRepository.setAlternateVisible(false)
182     }
183 
givenAlternateBouncerShowingnull184     private fun givenAlternateBouncerShowing() {
185         bouncerRepository.setPrimaryShow(false)
186         bouncerRepository.setAlternateVisible(true)
187     }
188 
verifyRequestTriggerSensornull189     private fun verifyRequestTriggerSensor() {
190         verify(sensorManager).requestTriggerSensor(capture(triggerEventListenerCaptor), any())
191     }
192 
verifyNeverRequestsTriggerSensornull193     private fun verifyNeverRequestsTriggerSensor() {
194         verify(sensorManager, never()).requestTriggerSensor(any(), any())
195     }
196 
verifyCancelTriggerSensornull197     private fun verifyCancelTriggerSensor() {
198         verify(sensorManager).cancelTriggerSensor(any(), any())
199     }
200 }
201