1 /*
2  * Copyright (C) 2023 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.biometrics
18 
19 import android.testing.TestableLooper
20 import android.view.View
21 import android.view.accessibility.AccessibilityNodeInfo
22 import androidx.test.ext.junit.runners.AndroidJUnit4
23 import androidx.test.filters.SmallTest
24 import com.android.keyguard.FaceAuthApiRequestReason
25 import com.android.keyguard.KeyguardUpdateMonitor
26 import com.android.systemui.SysuiTestCase
27 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
28 import com.android.systemui.util.mockito.any
29 import com.android.systemui.util.mockito.argumentCaptor
30 import com.android.systemui.util.mockito.eq
31 import com.android.systemui.util.mockito.whenever
32 import org.junit.Assert.assertEquals
33 import org.junit.Before
34 import org.junit.Test
35 import org.junit.runner.RunWith
36 import org.mockito.Mock
37 import org.mockito.Mockito.mock
38 import org.mockito.Mockito.never
39 import org.mockito.Mockito.verify
40 import org.mockito.MockitoAnnotations
41 
42 @RunWith(AndroidJUnit4::class)
43 @SmallTest
44 @TestableLooper.RunWithLooper
45 class FaceAuthAccessibilityDelegateTest : SysuiTestCase() {
46 
47     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
48     @Mock private lateinit var hostView: View
49     @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
50     private lateinit var underTest: FaceAuthAccessibilityDelegate
51 
52     @Before
53     fun setUp() {
54         MockitoAnnotations.initMocks(this)
55         underTest =
56             FaceAuthAccessibilityDelegate(
57                 context.resources,
58                 keyguardUpdateMonitor,
59                 faceAuthInteractor,
60             )
61     }
62 
63     @Test
64     fun shouldListenForFaceTrue_onInitializeAccessibilityNodeInfo_clickActionAdded() {
65         whenever(keyguardUpdateMonitor.shouldListenForFace()).thenReturn(true)
66 
67         // WHEN node is initialized
68         val mockedNodeInfo = mock(AccessibilityNodeInfo::class.java)
69         underTest.onInitializeAccessibilityNodeInfo(hostView, mockedNodeInfo)
70 
71         // THEN a11y action is added
72         val argumentCaptor = argumentCaptor<AccessibilityNodeInfo.AccessibilityAction>()
73         verify(mockedNodeInfo).addAction(argumentCaptor.capture())
74 
75         // AND the a11y action is a click action
76         assertEquals(
77             AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id,
78             argumentCaptor.value.id
79         )
80     }
81 
82     @Test
83     fun shouldListenForFaceFalse_onInitializeAccessibilityNodeInfo_clickActionNotAdded() {
84         whenever(keyguardUpdateMonitor.shouldListenForFace()).thenReturn(false)
85 
86         // WHEN node is initialized
87         val mockedNodeInfo = mock(AccessibilityNodeInfo::class.java)
88         underTest.onInitializeAccessibilityNodeInfo(hostView, mockedNodeInfo)
89 
90         // THEN a11y action is NOT added
91         verify(mockedNodeInfo, never())
92             .addAction(any(AccessibilityNodeInfo.AccessibilityAction::class.java))
93     }
94 
95     @Test
96     fun performAccessibilityAction_actionClick_retriesFaceAuth() {
97         whenever(keyguardUpdateMonitor.shouldListenForFace()).thenReturn(true)
98 
99         // WHEN click action is performed
100         underTest.performAccessibilityAction(
101             hostView,
102             AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id,
103             null
104         )
105 
106         // THEN retry face auth
107         verify(keyguardUpdateMonitor)
108             .requestFaceAuth(eq(FaceAuthApiRequestReason.ACCESSIBILITY_ACTION))
109         verify(faceAuthInteractor).onAccessibilityAction()
110     }
111 }
112