1 /*
2  * Copyright (C) 2016 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 junit.framework.TestCase.assertEquals;
20 import static junit.framework.TestCase.assertFalse;
21 import static junit.framework.TestCase.assertTrue;
22 
23 import static org.mockito.Matchers.anyInt;
24 import static org.mockito.Matchers.anyLong;
25 import static org.mockito.Matchers.anyObject;
26 import static org.mockito.Matchers.eq;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.verifyZeroInteractions;
31 import static org.mockito.Mockito.when;
32 import static org.mockito.hamcrest.MockitoHamcrest.argThat;
33 
34 import android.content.Context;
35 import android.os.Handler;
36 import android.os.IPowerManager;
37 import android.os.IThermalService;
38 import android.os.Looper;
39 import android.os.Message;
40 import android.os.PowerManager;
41 import android.os.RemoteException;
42 import android.view.Display;
43 import android.view.KeyEvent;
44 
45 import androidx.test.InstrumentationRegistry;
46 import androidx.test.runner.AndroidJUnit4;
47 
48 import com.android.server.accessibility.KeyEventDispatcher.KeyEventFilter;
49 import com.android.server.accessibility.test.MessageCapturingHandler;
50 import com.android.server.policy.WindowManagerPolicy;
51 
52 import org.hamcrest.Description;
53 import org.hamcrest.TypeSafeMatcher;
54 import org.junit.After;
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.junit.runner.RunWith;
58 import org.mockito.ArgumentCaptor;
59 
60 import java.util.Arrays;
61 import java.util.Collections;
62 
63 /**
64  * Tests for KeyEventDispatcher
65  */
66 @RunWith(AndroidJUnit4.class)
67 public class KeyEventDispatcherTest {
68     private static final int SEND_FRAMEWORK_KEY_EVENT = 4;
69 
70     private final KeyEvent mKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, 0x40);
71     private final KeyEvent mOtherKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, 0x50);
72     private final Object mLock = new Object();
73     private MessageCapturingHandler mInputEventsHandler;
74     private KeyEventDispatcher mKeyEventDispatcher;
75     private KeyEventFilter mKeyEventFilter1;
76     private KeyEventFilter mKeyEventFilter2;
77     private IPowerManager mMockPowerManagerService;
78     private IThermalService mMockThermalService;
79     private MessageCapturingHandler mMessageCapturingHandler;
80     private ArgumentCaptor<Integer> mFilter1SequenceCaptor = ArgumentCaptor.forClass(Integer.class);
81     private ArgumentCaptor<Integer> mFilter2SequenceCaptor = ArgumentCaptor.forClass(Integer.class);
82 
83     @Before
setUp()84     public void setUp() {
85         Looper looper = InstrumentationRegistry.getContext().getMainLooper();
86         mInputEventsHandler = new MessageCapturingHandler(looper, null);
87         mMockPowerManagerService = mock(IPowerManager.class);
88         mMockThermalService = mock(IThermalService.class);
89         // TODO: It would be better to mock PowerManager rather than its binder, but the class is
90         // final.
91         PowerManager powerManager =
92                 new PowerManager(mock(Context.class), mMockPowerManagerService, mMockThermalService,
93                         new Handler(looper));
94         mMessageCapturingHandler = new MessageCapturingHandler(looper, null);
95         mKeyEventDispatcher = new KeyEventDispatcher(mInputEventsHandler, SEND_FRAMEWORK_KEY_EVENT,
96                 mLock, powerManager, mMessageCapturingHandler);
97 
98         mKeyEventFilter1 = mock(KeyEventFilter.class);
99         when(mKeyEventFilter1.onKeyEvent((KeyEvent) anyObject(),
100                 mFilter1SequenceCaptor.capture().intValue()))
101                 .thenReturn(true);
102 
103         mKeyEventFilter2 = mock(KeyEventFilter.class);
104         when(mKeyEventFilter2.onKeyEvent((KeyEvent) anyObject(),
105                 mFilter2SequenceCaptor.capture().intValue()))
106                 .thenReturn(true);
107     }
108 
109     @After
tearDown()110     public void tearDown() {
111         mInputEventsHandler.removeAllMessages();
112         mMessageCapturingHandler.removeAllMessages();
113     }
114 
115 
116     @Test
testNotifyKeyEvent_withNoBoundServices_shouldReturnFalse()117     public void testNotifyKeyEvent_withNoBoundServices_shouldReturnFalse() {
118         assertFalse(mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Collections.EMPTY_LIST));
119         assertFalse(isTimeoutPending(mMessageCapturingHandler));
120     }
121 
122     @Test
testNotifyKeyEvent_boundServiceDoesntProcessEvents_shouldReturnFalse()123     public void testNotifyKeyEvent_boundServiceDoesntProcessEvents_shouldReturnFalse() {
124         KeyEventFilter keyEventFilter = mock(KeyEventFilter.class);
125         when(keyEventFilter.onKeyEvent((KeyEvent) anyObject(), anyInt())).thenReturn(false);
126         assertFalse(mKeyEventDispatcher
127                 .notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(keyEventFilter)));
128         assertFalse(isTimeoutPending(mMessageCapturingHandler));
129     }
130 
131     @Test
testNotifyKeyEvent_withOneValidService_shouldNotifyService()132     public void testNotifyKeyEvent_withOneValidService_shouldNotifyService()
133             throws RemoteException {
134         assertTrue(mKeyEventDispatcher
135                 .notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1)));
136         verify(mKeyEventFilter1, times(1)).onKeyEvent(argThat(new KeyEventMatcher(mKeyEvent)),
137                 anyInt());
138     }
139 
140     @Test
testNotifyKeyEvent_withTwoValidService_shouldNotifyBoth()141     public void testNotifyKeyEvent_withTwoValidService_shouldNotifyBoth() throws RemoteException {
142         assertTrue(mKeyEventDispatcher.notifyKeyEventLocked(
143                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2)));
144         verify(mKeyEventFilter1, times(1)).onKeyEvent(argThat(new KeyEventMatcher(mKeyEvent)),
145                 anyInt());
146         verify(mKeyEventFilter2, times(1)).onKeyEvent(argThat(new KeyEventMatcher(mKeyEvent)),
147                 anyInt());
148     }
149 
150     /*
151      * Results from services
152      */
153     @Test
testSetOnKeyResult_eventNotHandled_shouldPassEventToFramework()154     public void testSetOnKeyResult_eventNotHandled_shouldPassEventToFramework() {
155         mKeyEventDispatcher
156                 .notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
157 
158         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
159                 mFilter1SequenceCaptor.getValue());
160 
161         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
162         verifyZeroInteractions(mMockPowerManagerService);
163         assertFalse(isTimeoutPending(mMessageCapturingHandler));
164     }
165 
166     @Test
testSetOnKeyResult_eventHandled_shouldNotPassEventToFramework()167     public void testSetOnKeyResult_eventHandled_shouldNotPassEventToFramework()
168             throws RemoteException {
169         mKeyEventDispatcher
170                 .notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
171 
172         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
173                 mFilter1SequenceCaptor.getValue());
174 
175         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
176         verify(mMockPowerManagerService, times(1)).userActivity(eq(Display.DEFAULT_DISPLAY),
177                 anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
178         assertFalse(isTimeoutPending(mMessageCapturingHandler));
179     }
180 
181     @Test
testSetOnKeyResult_twoServicesReturnsFalse_shouldPassEventToFramework()182     public void testSetOnKeyResult_twoServicesReturnsFalse_shouldPassEventToFramework() {
183         mKeyEventDispatcher.notifyKeyEventLocked(
184                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
185 
186         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
187                 mFilter1SequenceCaptor.getValue());
188         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
189                 mFilter2SequenceCaptor.getValue());
190 
191         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
192         verifyZeroInteractions(mMockPowerManagerService);
193         assertFalse(isTimeoutPending(mMessageCapturingHandler));
194     }
195 
196     @Test
testSetOnKeyResult_twoServicesReturnsTrue_shouldNotPassEventToFramework()197     public void testSetOnKeyResult_twoServicesReturnsTrue_shouldNotPassEventToFramework()
198             throws RemoteException {
199         mKeyEventDispatcher.notifyKeyEventLocked(
200                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
201 
202         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
203                 mFilter1SequenceCaptor.getValue());
204         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, true,
205                 mFilter2SequenceCaptor.getValue());
206 
207         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
208         verify(mMockPowerManagerService, times(1)).userActivity(eq(Display.DEFAULT_DISPLAY),
209                 anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
210         assertFalse(isTimeoutPending(mMessageCapturingHandler));
211     }
212 
213     @Test
testSetOnKeyResult_firstOfTwoServicesReturnsTrue_shouldNotPassEventToFramework()214     public void testSetOnKeyResult_firstOfTwoServicesReturnsTrue_shouldNotPassEventToFramework()
215             throws RemoteException {
216         mKeyEventDispatcher.notifyKeyEventLocked(
217                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
218 
219         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
220                 mFilter1SequenceCaptor.getValue());
221         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
222                 mFilter2SequenceCaptor.getValue());
223 
224         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
225         verify(mMockPowerManagerService, times(1)).userActivity(eq(Display.DEFAULT_DISPLAY),
226                 anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
227         assertFalse(isTimeoutPending(mMessageCapturingHandler));
228     }
229 
230     @Test
testSetOnKeyResult_secondOfTwoServicesReturnsTrue_shouldNotPassEventToFramework()231     public void testSetOnKeyResult_secondOfTwoServicesReturnsTrue_shouldNotPassEventToFramework()
232             throws RemoteException {
233         mKeyEventDispatcher.notifyKeyEventLocked(
234                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
235 
236         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
237                 mFilter1SequenceCaptor.getValue());
238         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, true,
239                 mFilter2SequenceCaptor.getValue());
240 
241         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
242         verify(mMockPowerManagerService, times(1)).userActivity(eq(Display.DEFAULT_DISPLAY),
243                 anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
244         assertFalse(isTimeoutPending(mMessageCapturingHandler));
245     }
246 
247     // Each event should have its result set only once, but if it's set twice, we should ignore
248     // the second time.
249     @Test
testSetOnKeyResult_firstServiceReturnsTwice_secondShouldBeIgnored()250     public void testSetOnKeyResult_firstServiceReturnsTwice_secondShouldBeIgnored() {
251         mKeyEventDispatcher.notifyKeyEventLocked(
252                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
253 
254         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
255                 mFilter1SequenceCaptor.getValue());
256         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
257                 mFilter1SequenceCaptor.getValue());
258         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
259 
260         // Verify event is sent properly when other service responds
261         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
262                 mFilter2SequenceCaptor.getValue());
263         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
264         verifyZeroInteractions(mMockPowerManagerService);
265         assertFalse(isTimeoutPending(mMessageCapturingHandler));
266     }
267 
268 
269     /*
270      * Timeouts
271      */
272     @Test
testEventTimesOut_shouldPassToFramework()273     public void testEventTimesOut_shouldPassToFramework() throws RemoteException {
274         mKeyEventDispatcher.notifyKeyEventLocked(
275                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
276 
277         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
278         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
279 
280         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
281         verifyZeroInteractions(mMockPowerManagerService);
282     }
283 
284     @Test
testEventTimesOut_afterOneServiceReturnsFalse_shouldPassToFramework()285     public void testEventTimesOut_afterOneServiceReturnsFalse_shouldPassToFramework() {
286         mKeyEventDispatcher.notifyKeyEventLocked(
287                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
288 
289         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
290                 mFilter1SequenceCaptor.getValue());
291 
292         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
293         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
294 
295         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
296         verifyZeroInteractions(mMockPowerManagerService);
297     }
298 
299     @Test
testEventTimesOut_afterOneServiceReturnsTrue_shouldNotPassToFramework()300     public void testEventTimesOut_afterOneServiceReturnsTrue_shouldNotPassToFramework()
301             throws RemoteException {
302         mKeyEventDispatcher.notifyKeyEventLocked(
303                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
304 
305         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
306                 mFilter1SequenceCaptor.getValue());
307 
308         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
309         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
310 
311         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
312         verify(mMockPowerManagerService, times(1)).userActivity(eq(Display.DEFAULT_DISPLAY),
313                 anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
314     }
315 
316     @Test
testEventTimesOut_thenServiceReturnsFalse_shouldPassToFrameworkOnce()317     public void testEventTimesOut_thenServiceReturnsFalse_shouldPassToFrameworkOnce() {
318         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
319         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
320 
321         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
322         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
323         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
324 
325         mInputEventsHandler.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
326         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
327                 mFilter1SequenceCaptor.getValue());
328 
329         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
330         verifyZeroInteractions(mMockPowerManagerService);
331     }
332 
333     @Test
testEventTimesOut_afterServiceReturnsFalse_shouldPassToFrameworkOnce()334     public void testEventTimesOut_afterServiceReturnsFalse_shouldPassToFrameworkOnce() {
335         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
336         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
337 
338         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
339                 mFilter1SequenceCaptor.getValue());
340         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
341 
342         mInputEventsHandler.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
343         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
344         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
345 
346         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
347         verifyZeroInteractions(mMockPowerManagerService);
348     }
349 
350     @Test
testEventTimesOut_afterServiceReturnsTrue_shouldNotPassToFramework()351     public void testEventTimesOut_afterServiceReturnsTrue_shouldNotPassToFramework()
352             throws RemoteException {
353         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
354 
355         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
356                 mFilter1SequenceCaptor.getValue());
357         assertEquals(1, mMessageCapturingHandler.timedMessages.size());
358         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
359 
360         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
361         verify(mMockPowerManagerService, times(1)).userActivity(eq(Display.DEFAULT_DISPLAY),
362                 anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY), eq(0));
363     }
364 
365     /*
366      * Flush services
367      */
368     @Test
testFlushService_withPendingEvent_shouldPassToFramework()369     public void testFlushService_withPendingEvent_shouldPassToFramework() {
370         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
371         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
372 
373         mKeyEventDispatcher.flush(mKeyEventFilter1);
374 
375         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
376     }
377 
378     @Test
testFlushTwpServices_withPendingEvent_shouldPassToFramework()379     public void testFlushTwpServices_withPendingEvent_shouldPassToFramework() {
380         mKeyEventDispatcher.notifyKeyEventLocked(
381                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
382 
383         mKeyEventDispatcher.flush(mKeyEventFilter1);
384         mKeyEventDispatcher.flush(mKeyEventFilter2);
385 
386         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
387     }
388 
389     @Test
testFlushOneService_thenOtherReturnsTrue_shouldNotPassToFramework()390     public void testFlushOneService_thenOtherReturnsTrue_shouldNotPassToFramework() {
391         mKeyEventDispatcher.notifyKeyEventLocked(
392                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
393 
394         mKeyEventDispatcher.flush(mKeyEventFilter1);
395         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, true,
396                 mFilter2SequenceCaptor.getValue());
397 
398         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
399     }
400 
401     @Test
testFlushOneService_thenOtherReturnsFalse_shouldPassToFramework()402     public void testFlushOneService_thenOtherReturnsFalse_shouldPassToFramework() {
403         mKeyEventDispatcher.notifyKeyEventLocked(
404                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
405 
406         mKeyEventDispatcher.flush(mKeyEventFilter1);
407         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
408                 mFilter2SequenceCaptor.getValue());
409 
410         assertTrue(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
411     }
412 
413     @Test
testFlushServiceWithNoEvents_shouldNotCrash()414     public void testFlushServiceWithNoEvents_shouldNotCrash() {
415         mKeyEventDispatcher.flush(mKeyEventFilter1);
416     }
417 
418     /*
419      * Multiple Events
420      */
421     @Test
twoEvents_serviceReturnsFalse_sentToFramework()422     public void twoEvents_serviceReturnsFalse_sentToFramework() {
423         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
424         mKeyEventDispatcher
425                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
426         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
427 
428         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
429                 mFilter1SequenceCaptor.getAllValues().get(0));
430         mInputEventsHandler.removeMessages(SEND_FRAMEWORK_KEY_EVENT);
431         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
432                 mFilter1SequenceCaptor.getAllValues().get(1));
433 
434         assertTwoKeyEventsSentToFrameworkInOrder(mKeyEvent, mOtherKeyEvent);
435     }
436 
437     @Test
twoEvents_serviceReturnsTrue_notSentToFramework()438     public void twoEvents_serviceReturnsTrue_notSentToFramework() {
439         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
440         mKeyEventDispatcher
441                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
442         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
443 
444         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
445                 mFilter1SequenceCaptor.getAllValues().get(0));
446         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
447                 mFilter1SequenceCaptor.getAllValues().get(1));
448 
449         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
450     }
451 
452     @Test
twoEvents_serviceHandlesFirst_otherSentToFramework()453     public void twoEvents_serviceHandlesFirst_otherSentToFramework() {
454         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
455         mKeyEventDispatcher
456                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
457         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
458 
459         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
460                 mFilter1SequenceCaptor.getAllValues().get(0));
461         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
462                 mFilter1SequenceCaptor.getAllValues().get(1));
463 
464         assertOneKeyEventSentToFramework(mOtherKeyEvent);
465     }
466 
467     @Test
twoEvents_serviceHandlesSecond_otherSentToFramework()468     public void twoEvents_serviceHandlesSecond_otherSentToFramework() {
469         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
470         mKeyEventDispatcher
471                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
472         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
473 
474         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
475                 mFilter1SequenceCaptor.getAllValues().get(0));
476         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
477                 mFilter1SequenceCaptor.getAllValues().get(1));
478 
479         assertOneKeyEventSentToFramework(mKeyEvent);
480     }
481 
482     @Test
twoEvents_firstTimesOutThenServiceHandlesBoth_firstSentToFramework()483     public void twoEvents_firstTimesOutThenServiceHandlesBoth_firstSentToFramework() {
484         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
485         mKeyEventDispatcher
486                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
487         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
488 
489         mKeyEventDispatcher.handleMessage(getTimedMessage(mMessageCapturingHandler, 0));
490         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
491                 mFilter1SequenceCaptor.getAllValues().get(0));
492         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, true,
493                 mFilter1SequenceCaptor.getAllValues().get(1));
494 
495         assertOneKeyEventSentToFramework(mKeyEvent);
496     }
497 
498     @Test
addServiceBetweenTwoEvents_neitherEventHandled_bothSentToFramework()499     public void addServiceBetweenTwoEvents_neitherEventHandled_bothSentToFramework() {
500         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
501         mKeyEventDispatcher.notifyKeyEventLocked(
502                 mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
503         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
504 
505         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
506                 mFilter2SequenceCaptor.getValue());
507         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
508                 mFilter1SequenceCaptor.getAllValues().get(0));
509         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
510                 mFilter1SequenceCaptor.getAllValues().get(1));
511 
512         assertTwoKeyEventsSentToFrameworkInOrder(mKeyEvent, mOtherKeyEvent);
513     }
514 
515     @Test
removeServiceBetweenTwoEvents_neitherEventHandled_bothSentToFramework()516     public void removeServiceBetweenTwoEvents_neitherEventHandled_bothSentToFramework() {
517         mKeyEventDispatcher.notifyKeyEventLocked(
518                 mKeyEvent, 0, Arrays.asList(mKeyEventFilter1, mKeyEventFilter2));
519         mKeyEventDispatcher.flush(mKeyEventFilter1);
520         mKeyEventDispatcher.notifyKeyEventLocked(
521                 mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter2));
522         assertFalse(mInputEventsHandler.hasMessages(SEND_FRAMEWORK_KEY_EVENT));
523 
524         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
525                 mFilter2SequenceCaptor.getAllValues().get(0));
526         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter2, false,
527                 mFilter2SequenceCaptor.getAllValues().get(1));
528 
529         assertTwoKeyEventsSentToFrameworkInOrder(mKeyEvent, mOtherKeyEvent);
530     }
531 
532     /*
533      * Misc
534      */
535     @Test
twoEvents_serviceReturnsFalseOutOfOrder_sentToFramework()536     public void twoEvents_serviceReturnsFalseOutOfOrder_sentToFramework() {
537         mKeyEventDispatcher.notifyKeyEventLocked(mKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
538         mKeyEventDispatcher
539                 .notifyKeyEventLocked(mOtherKeyEvent, 0, Arrays.asList(mKeyEventFilter1));
540 
541         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
542                 mFilter1SequenceCaptor.getAllValues().get(1));
543         mKeyEventDispatcher.setOnKeyEventResult(mKeyEventFilter1, false,
544                 mFilter1SequenceCaptor.getAllValues().get(0));
545 
546         // Order doesn't really matter since this is really checking that we don't do something
547         // really bad, but we'll send them in the order they are reported
548         assertTwoKeyEventsSentToFrameworkInOrder(mOtherKeyEvent, mKeyEvent);
549     }
550 
assertOneKeyEventSentToFramework(KeyEvent event)551     private void assertOneKeyEventSentToFramework(KeyEvent event) {
552         assertEquals(1, mInputEventsHandler.timedMessages.size());
553 
554         Message m = getTimedMessage(mInputEventsHandler, 0);
555         assertEquals(SEND_FRAMEWORK_KEY_EVENT, m.what);
556         assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER, m.arg1);
557         assertTrue(new KeyEventMatcher(event).matches(m.obj));
558     }
559 
assertTwoKeyEventsSentToFrameworkInOrder(KeyEvent first, KeyEvent second)560     private void assertTwoKeyEventsSentToFrameworkInOrder(KeyEvent first, KeyEvent second) {
561         assertEquals(2, mInputEventsHandler.timedMessages.size());
562 
563         Message m0 = getTimedMessage(mInputEventsHandler, 0);
564         assertEquals(SEND_FRAMEWORK_KEY_EVENT, m0.what);
565         assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER, m0.arg1);
566         assertTrue(new KeyEventMatcher(first).matches(m0.obj));
567 
568         Message m1 = getTimedMessage(mInputEventsHandler, 1);
569         assertEquals(SEND_FRAMEWORK_KEY_EVENT, m1.what);
570         assertEquals(WindowManagerPolicy.FLAG_PASS_TO_USER, m1.arg1);
571         assertTrue(new KeyEventMatcher(second).matches(m1.obj));
572     }
573 
getTimedMessage(MessageCapturingHandler handler, int i)574     private static Message getTimedMessage(MessageCapturingHandler handler, int i) {
575         return handler.timedMessages.get(i).first;
576     }
577 
isTimeoutPending(MessageCapturingHandler handler)578     private static boolean isTimeoutPending(MessageCapturingHandler handler) {
579         return handler.hasMessages(KeyEventDispatcher.MSG_ON_KEY_EVENT_TIMEOUT);
580     }
581 
582     private class KeyEventMatcher extends TypeSafeMatcher<KeyEvent> {
583         private KeyEvent mEventToMatch;
584 
KeyEventMatcher(KeyEvent eventToMatch)585         KeyEventMatcher(KeyEvent eventToMatch) {
586             mEventToMatch = eventToMatch;
587         }
588 
589         @Override
matchesSafely(KeyEvent keyEvent)590         public boolean matchesSafely(KeyEvent keyEvent) {
591             return (mEventToMatch.getAction() == keyEvent.getAction())
592                     && (mEventToMatch.getKeyCode() == keyEvent.getKeyCode());
593         }
594 
595         @Override
describeTo(Description description)596         public void describeTo(Description description) {
597             description.appendText("Key event matcher");
598         }
599     }
600 }
601