1 /*
2  * Copyright (C) 2017 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.server.accessibility;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.mockito.Matchers.anyBoolean;
22 import static org.mockito.Matchers.anyInt;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.verifyNoMoreInteractions;
26 import static org.mockito.Mockito.when;
27 
28 import android.accessibilityservice.FingerprintGestureController;
29 import android.content.res.Resources;
30 import android.hardware.fingerprint.IFingerprintService;
31 import android.view.KeyEvent;
32 
33 import com.android.server.accessibility.FingerprintGestureDispatcher.FingerprintGestureClient;
34 import com.android.server.accessibility.test.MessageCapturingHandler;
35 
36 import org.junit.After;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.mockito.Mock;
40 import org.mockito.MockitoAnnotations;
41 
42 import java.util.Arrays;
43 import java.util.Collections;
44 
45 /**
46  * Tests for FingerprintGestureDispatcher
47  */
48 public class FingerprintGestureDispatcherTest {
49 
50     private @Mock IFingerprintService mMockFingerprintService;
51     private @Mock FingerprintGestureClient mNonGestureCapturingClient;
52     private @Mock FingerprintGestureClient mGestureCapturingClient;
53     private @Mock Resources mMockResources;
54 
55     private MessageCapturingHandler mMessageCapturingHandler;
56     private FingerprintGestureDispatcher mFingerprintGestureDispatcher;
57 
58     @Before
setup()59     public void setup() {
60         MockitoAnnotations.initMocks(this);
61         // For most tests, we support fingerprint gestures
62         when(mMockResources.getBoolean(anyInt())).thenReturn(true);
63         mMessageCapturingHandler = new MessageCapturingHandler(
64                 msg -> mFingerprintGestureDispatcher.handleMessage(msg));
65         mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(mMockFingerprintService,
66                 mMockResources, new Object(), mMessageCapturingHandler);
67         when(mNonGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(false);
68         when(mGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(true);
69     }
70 
71     @After
tearDown()72     public void tearDown() {
73         mMessageCapturingHandler.removeAllMessages();
74     }
75 
76 
77     @Test
testNoServices_doesNotCrashOrConsumeGestures()78     public void testNoServices_doesNotCrashOrConsumeGestures() {
79         mFingerprintGestureDispatcher.onClientActiveChanged(true);
80         mFingerprintGestureDispatcher.onClientActiveChanged(false);
81         assertFalse(mFingerprintGestureDispatcher.onFingerprintGesture(
82                 KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP));
83     }
84 
85     @Test
testOneNonCapturingService_doesNotCrashOrConsumeGestures()86     public void testOneNonCapturingService_doesNotCrashOrConsumeGestures() {
87         mFingerprintGestureDispatcher.updateClientList(
88                 Arrays.asList(mNonGestureCapturingClient));
89         mFingerprintGestureDispatcher.onClientActiveChanged(true);
90         mFingerprintGestureDispatcher.onClientActiveChanged(false);
91         assertFalse(mFingerprintGestureDispatcher.onFingerprintGesture(
92                 KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP));
93         verify(mNonGestureCapturingClient, times(0))
94                 .onFingerprintGestureDetectionActiveChanged(anyBoolean());
95         verify(mNonGestureCapturingClient, times(0)).onFingerprintGesture(anyInt());
96     }
97 
98     @Test
testOneCapturingService_notifiesClientOfActivityChanges()99     public void testOneCapturingService_notifiesClientOfActivityChanges() {
100         mFingerprintGestureDispatcher.updateClientList(
101                 Arrays.asList(mGestureCapturingClient));
102         mFingerprintGestureDispatcher.onClientActiveChanged(true);
103         // Client active means gesture detection isn't.
104         verify(mGestureCapturingClient, times(1)).onFingerprintGestureDetectionActiveChanged(false);
105         verify(mGestureCapturingClient, times(0)).onFingerprintGestureDetectionActiveChanged(true);
106         mFingerprintGestureDispatcher.onClientActiveChanged(false);
107         verify(mGestureCapturingClient, times(1)).onFingerprintGestureDetectionActiveChanged(false);
108         verify(mGestureCapturingClient, times(1)).onFingerprintGestureDetectionActiveChanged(true);
109     }
110 
111     @Test
testOneCapturingService_consumesGesturesAndPassesThemAlong()112     public void testOneCapturingService_consumesGesturesAndPassesThemAlong() {
113         mFingerprintGestureDispatcher.updateClientList(
114                 Arrays.asList(mGestureCapturingClient));
115         assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
116                 KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP));
117         verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
118                 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_UP);
119         assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
120                 KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN));
121         verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
122                 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN);
123         assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
124                 KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT));
125         verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
126                 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_LEFT);
127         assertTrue(mFingerprintGestureDispatcher.onFingerprintGesture(
128                 KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT));
129         verify(mGestureCapturingClient, times(1)).onFingerprintGesture(
130                 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_RIGHT);
131     }
132 
133     @Test
testInvalidKeyCodes_areNotCaptured()134     public void testInvalidKeyCodes_areNotCaptured() {
135         mFingerprintGestureDispatcher.updateClientList(
136                 Arrays.asList(mGestureCapturingClient));
137         assertFalse(mFingerprintGestureDispatcher.onFingerprintGesture(
138                 KeyEvent.KEYCODE_SPACE));
139         verify(mGestureCapturingClient, times(0)).onFingerprintGesture(anyInt());
140     }
141 
142     @Test
testWithCapturingService_registersForFingerprintUpdates()143     public void testWithCapturingService_registersForFingerprintUpdates() throws Exception {
144         verifyNoMoreInteractions(mMockFingerprintService);
145         mFingerprintGestureDispatcher.updateClientList(
146                 Arrays.asList(mGestureCapturingClient));
147         mMessageCapturingHandler.sendOneMessage();
148         verify(mMockFingerprintService).addClientActiveCallback(mFingerprintGestureDispatcher);
149     }
150 
151     @Test
testWhenCapturingServiceStops_unregistersForFingerprintUpdates()152     public void testWhenCapturingServiceStops_unregistersForFingerprintUpdates() throws Exception {
153         verifyNoMoreInteractions(mMockFingerprintService);
154         mFingerprintGestureDispatcher.updateClientList(
155                 Arrays.asList(mGestureCapturingClient));
156         mMessageCapturingHandler.sendOneMessage();
157         mFingerprintGestureDispatcher.updateClientList(Collections.emptyList());
158         mMessageCapturingHandler.sendOneMessage();
159         verify(mMockFingerprintService).removeClientActiveCallback(mFingerprintGestureDispatcher);
160     }
161 
162     @Test
testIsGestureDetectionAvailable_dependsOnFingerprintService()163     public void testIsGestureDetectionAvailable_dependsOnFingerprintService() throws Exception {
164         when(mMockFingerprintService.isClientActive()).thenReturn(true);
165         assertFalse(mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable());
166         when(mMockFingerprintService.isClientActive()).thenReturn(false);
167         assertTrue(mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable());
168     }
169 
170     @Test
ifGestureDetectionNotSupported_neverSaysAvailable()171     public void ifGestureDetectionNotSupported_neverSaysAvailable() throws Exception {
172         when(mMockResources.getBoolean(anyInt())).thenReturn(false);
173         // Need to create a new dispatcher, since it picks up the resource value in its
174         // constructor. This is fine since hardware config values don't change dynamically.
175         FingerprintGestureDispatcher fingerprintGestureDispatcher =
176                 new FingerprintGestureDispatcher(mMockFingerprintService, mMockResources,
177                         new Object(), mMessageCapturingHandler);
178 
179         when(mMockFingerprintService.isClientActive()).thenReturn(false);
180         assertFalse(fingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable());
181     }
182 }
183