• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.systemui.dreams.touch;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyBoolean;
23 import static org.mockito.ArgumentMatchers.anyInt;
24 import static org.mockito.ArgumentMatchers.eq;
25 import static org.mockito.Mockito.doAnswer;
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.graphics.Rect;
31 import android.graphics.Region;
32 import android.testing.AndroidTestingRunner;
33 import android.util.Pair;
34 import android.view.GestureDetector;
35 import android.view.InputEvent;
36 import android.view.MotionEvent;
37 
38 import androidx.lifecycle.DefaultLifecycleObserver;
39 import androidx.lifecycle.Lifecycle;
40 import androidx.lifecycle.LifecycleObserver;
41 import androidx.lifecycle.LifecycleOwner;
42 import androidx.test.filters.SmallTest;
43 
44 import com.android.systemui.SysuiTestCase;
45 import com.android.systemui.dreams.touch.dagger.InputSessionComponent;
46 import com.android.systemui.shared.system.InputChannelCompat;
47 import com.android.systemui.util.concurrency.FakeExecutor;
48 import com.android.systemui.util.display.DisplayHelper;
49 import com.android.systemui.util.time.FakeSystemClock;
50 
51 import com.google.common.util.concurrent.ListenableFuture;
52 
53 import org.junit.Before;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 import org.mockito.ArgumentCaptor;
57 import org.mockito.Mockito;
58 import org.mockito.MockitoAnnotations;
59 
60 import java.util.HashSet;
61 import java.util.Set;
62 import java.util.concurrent.ExecutionException;
63 import java.util.function.Consumer;
64 import java.util.stream.Collectors;
65 import java.util.stream.Stream;
66 
67 @SmallTest
68 @RunWith(AndroidTestingRunner.class)
69 public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
70     @Before
setup()71     public void setup() {
72         MockitoAnnotations.initMocks(this);
73     }
74 
75     private static class Environment {
76         private final InputSessionComponent.Factory mInputFactory;
77         private final InputSession mInputSession;
78         private final Lifecycle mLifecycle;
79         private final LifecycleOwner mLifecycleOwner;
80         private final DreamOverlayTouchMonitor mMonitor;
81         private final DefaultLifecycleObserver mLifecycleObserver;
82         private final InputChannelCompat.InputEventListener mEventListener;
83         private final GestureDetector.OnGestureListener mGestureListener;
84         private final DisplayHelper mDisplayHelper;
85         private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
86         private final Rect mDisplayBounds = Mockito.mock(Rect.class);
87 
Environment(Set<DreamTouchHandler> handlers)88         Environment(Set<DreamTouchHandler> handlers) {
89             mLifecycle = Mockito.mock(Lifecycle.class);
90             mLifecycleOwner = Mockito.mock(LifecycleOwner.class);
91 
92             mInputFactory = Mockito.mock(InputSessionComponent.Factory.class);
93             final InputSessionComponent inputComponent = Mockito.mock(InputSessionComponent.class);
94             mInputSession = Mockito.mock(InputSession.class);
95 
96             when(mInputFactory.create(any(), any(), any(), anyBoolean()))
97                     .thenReturn(inputComponent);
98             when(inputComponent.getInputSession()).thenReturn(mInputSession);
99 
100             mDisplayHelper = Mockito.mock(DisplayHelper.class);
101             when(mDisplayHelper.getMaxBounds(anyInt(), anyInt()))
102                     .thenReturn(mDisplayBounds);
103             mMonitor = new DreamOverlayTouchMonitor(mExecutor, mLifecycle, mInputFactory,
104                     mDisplayHelper, handlers);
105             mMonitor.init();
106 
107             final ArgumentCaptor<LifecycleObserver> lifecycleObserverCaptor =
108                     ArgumentCaptor.forClass(LifecycleObserver.class);
109             verify(mLifecycle).addObserver(lifecycleObserverCaptor.capture());
110             assertThat(lifecycleObserverCaptor.getValue() instanceof DefaultLifecycleObserver)
111                     .isTrue();
112             mLifecycleObserver = (DefaultLifecycleObserver) lifecycleObserverCaptor.getValue();
113 
114             updateLifecycle(observer -> observer.first.onResume(observer.second));
115 
116             // Capture creation request.
117             final ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
118                     ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
119             final ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
120                     ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
121             verify(mInputFactory).create(any(), inputEventListenerCaptor.capture(),
122                     gestureListenerCaptor.capture(),
123                     eq(true));
124             mEventListener = inputEventListenerCaptor.getValue();
125             mGestureListener = gestureListenerCaptor.getValue();
126         }
127 
getDisplayBounds()128         public Rect getDisplayBounds() {
129             return mDisplayBounds;
130         }
131 
executeAll()132         void executeAll() {
133             mExecutor.runAllReady();
134         }
135 
publishInputEvent(InputEvent event)136         void publishInputEvent(InputEvent event) {
137             mEventListener.onInputEvent(event);
138         }
139 
publishGestureEvent(Consumer<GestureDetector.OnGestureListener> listenerConsumer)140         void publishGestureEvent(Consumer<GestureDetector.OnGestureListener> listenerConsumer) {
141             listenerConsumer.accept(mGestureListener);
142         }
143 
updateLifecycle(Consumer<Pair<DefaultLifecycleObserver, LifecycleOwner>> consumer)144         void updateLifecycle(Consumer<Pair<DefaultLifecycleObserver, LifecycleOwner>> consumer) {
145             consumer.accept(Pair.create(mLifecycleObserver, mLifecycleOwner));
146         }
147 
verifyInputSessionDispose()148         void verifyInputSessionDispose() {
149             verify(mInputSession).dispose();
150             Mockito.clearInvocations(mInputSession);
151         }
152     }
153 
154     @Test
testReportedDisplayBounds()155     public void testReportedDisplayBounds() {
156         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
157         final Environment environment = new Environment(Stream.of(touchHandler)
158                 .collect(Collectors.toCollection(HashSet::new)));
159 
160         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
161         when(initialEvent.getX()).thenReturn(0.0f);
162         when(initialEvent.getY()).thenReturn(0.0f);
163         environment.publishInputEvent(initialEvent);
164 
165         // Verify display bounds passed into TouchHandler#getTouchInitiationRegion
166         verify(touchHandler).getTouchInitiationRegion(eq(environment.getDisplayBounds()), any());
167         final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
168                 ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
169         verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
170 
171         // Verify that display bounds provided from TouchSession#getBounds
172         assertThat(touchSessionArgumentCaptor.getValue().getBounds())
173                 .isEqualTo(environment.getDisplayBounds());
174     }
175 
176     @Test
testEntryTouchZone()177     public void testEntryTouchZone() {
178         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
179         final Rect touchArea = new Rect(4, 4, 8 , 8);
180 
181         doAnswer(invocation -> {
182             final Region region = (Region) invocation.getArguments()[1];
183             region.set(touchArea);
184             return null;
185         }).when(touchHandler).getTouchInitiationRegion(any(), any());
186 
187         final Environment environment = new Environment(Stream.of(touchHandler)
188                 .collect(Collectors.toCollection(HashSet::new)));
189 
190         // Ensure touch outside specified region is not delivered.
191         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
192         when(initialEvent.getX()).thenReturn(0.0f);
193         when(initialEvent.getY()).thenReturn(1.0f);
194         environment.publishInputEvent(initialEvent);
195         verify(touchHandler, never()).onSessionStart(any());
196 
197         // Make sure touch inside region causes session start.
198         when(initialEvent.getX()).thenReturn(5.0f);
199         when(initialEvent.getY()).thenReturn(5.0f);
200         environment.publishInputEvent(initialEvent);
201         verify(touchHandler).onSessionStart(any());
202     }
203 
204     @Test
testSessionCount()205     public void testSessionCount() {
206         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
207         final Rect touchArea = new Rect(4, 4, 8 , 8);
208 
209         final DreamTouchHandler unzonedTouchHandler = Mockito.mock(DreamTouchHandler.class);
210         doAnswer(invocation -> {
211             final Region region = (Region) invocation.getArguments()[1];
212             region.set(touchArea);
213             return null;
214         }).when(touchHandler).getTouchInitiationRegion(any(), any());
215 
216         final Environment environment = new Environment(Stream.of(touchHandler, unzonedTouchHandler)
217                 .collect(Collectors.toCollection(HashSet::new)));
218 
219         // Ensure touch outside specified region is delivered to unzoned touch handler.
220         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
221         when(initialEvent.getX()).thenReturn(0.0f);
222         when(initialEvent.getY()).thenReturn(1.0f);
223         environment.publishInputEvent(initialEvent);
224 
225         ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionCaptor = ArgumentCaptor.forClass(
226                 DreamTouchHandler.TouchSession.class);
227 
228         // Make sure only one active session.
229         {
230             verify(unzonedTouchHandler).onSessionStart(touchSessionCaptor.capture());
231             final DreamTouchHandler.TouchSession touchSession = touchSessionCaptor.getValue();
232             assertThat(touchSession.getActiveSessionCount()).isEqualTo(1);
233             touchSession.pop();
234             environment.executeAll();
235         }
236 
237         // Make sure touch inside the touch region.
238         when(initialEvent.getX()).thenReturn(5.0f);
239         when(initialEvent.getY()).thenReturn(5.0f);
240         environment.publishInputEvent(initialEvent);
241 
242         // Make sure there are two active sessions.
243         {
244             verify(touchHandler).onSessionStart(touchSessionCaptor.capture());
245             final DreamTouchHandler.TouchSession touchSession = touchSessionCaptor.getValue();
246             assertThat(touchSession.getActiveSessionCount()).isEqualTo(2);
247             touchSession.pop();
248         }
249     }
250 
251     @Test
testInputEventPropagation()252     public void testInputEventPropagation() {
253         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
254 
255         final Environment environment = new Environment(Stream.of(touchHandler)
256                 .collect(Collectors.toCollection(HashSet::new)));
257 
258         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
259         environment.publishInputEvent(initialEvent);
260 
261         // Ensure session started
262         final InputChannelCompat.InputEventListener eventListener =
263                 registerInputEventListener(touchHandler);
264 
265         // First event will be missed since we register after the execution loop,
266         final InputEvent event = Mockito.mock(InputEvent.class);
267         environment.publishInputEvent(event);
268         verify(eventListener).onInputEvent(eq(event));
269     }
270 
271     @Test
testInputGesturePropagation()272     public void testInputGesturePropagation() {
273         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
274 
275         final Environment environment = new Environment(Stream.of(touchHandler)
276                 .collect(Collectors.toCollection(HashSet::new)));
277 
278         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
279         environment.publishInputEvent(initialEvent);
280 
281         // Ensure session started
282         final GestureDetector.OnGestureListener gestureListener =
283                 registerGestureListener(touchHandler);
284 
285         final MotionEvent event = Mockito.mock(MotionEvent.class);
286         environment.publishGestureEvent(onGestureListener -> onGestureListener.onShowPress(event));
287         verify(gestureListener).onShowPress(eq(event));
288     }
289 
290     @Test
testGestureConsumption()291     public void testGestureConsumption() {
292         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
293 
294         final Environment environment = new Environment(Stream.of(touchHandler)
295                 .collect(Collectors.toCollection(HashSet::new)));
296 
297         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
298         environment.publishInputEvent(initialEvent);
299 
300         // Ensure session started
301         final GestureDetector.OnGestureListener gestureListener =
302                 registerGestureListener(touchHandler);
303 
304         when(gestureListener.onDown(any())).thenReturn(true);
305         final MotionEvent event = Mockito.mock(MotionEvent.class);
306         environment.publishGestureEvent(onGestureListener -> {
307             assertThat(onGestureListener.onDown(event)).isTrue();
308         });
309 
310         verify(gestureListener).onDown(eq(event));
311     }
312 
313     @Test
testBroadcast()314     public void testBroadcast() {
315         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
316         final DreamTouchHandler touchHandler2 = Mockito.mock(DreamTouchHandler.class);
317 
318         final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2)
319                 .collect(Collectors.toCollection(HashSet::new)));
320 
321         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
322         environment.publishInputEvent(initialEvent);
323 
324         final HashSet<InputChannelCompat.InputEventListener> inputListeners = new HashSet<>();
325 
326         inputListeners.add(registerInputEventListener(touchHandler));
327         inputListeners.add(registerInputEventListener(touchHandler));
328         inputListeners.add(registerInputEventListener(touchHandler2));
329 
330         final MotionEvent event = Mockito.mock(MotionEvent.class);
331         environment.publishInputEvent(event);
332 
333         inputListeners
334                 .stream()
335                 .forEach(inputEventListener -> verify(inputEventListener).onInputEvent(event));
336     }
337 
338     @Test
testPush()339     public void testPush() throws InterruptedException, ExecutionException {
340         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
341 
342         final Environment environment = new Environment(Stream.of(touchHandler)
343                 .collect(Collectors.toCollection(HashSet::new)));
344 
345         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
346         environment.publishInputEvent(initialEvent);
347 
348         final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
349         final InputChannelCompat.InputEventListener eventListener =
350                 registerInputEventListener(session);
351 
352         final ListenableFuture<DreamTouchHandler.TouchSession> frontSessionFuture = session.push();
353         environment.executeAll();
354         final DreamTouchHandler.TouchSession frontSession = frontSessionFuture.get();
355         final InputChannelCompat.InputEventListener frontEventListener =
356                 registerInputEventListener(frontSession);
357 
358         final MotionEvent event = Mockito.mock(MotionEvent.class);
359         environment.publishInputEvent(event);
360 
361         verify(frontEventListener).onInputEvent(eq(event));
362         verify(eventListener, never()).onInputEvent(any());
363 
364         Mockito.clearInvocations(eventListener, frontEventListener);
365 
366         ListenableFuture<DreamTouchHandler.TouchSession> sessionFuture = frontSession.pop();
367         environment.executeAll();
368 
369         DreamTouchHandler.TouchSession returnedSession = sessionFuture.get();
370         assertThat(session == returnedSession).isTrue();
371 
372         environment.executeAll();
373 
374         final MotionEvent followupEvent = Mockito.mock(MotionEvent.class);
375         environment.publishInputEvent(followupEvent);
376 
377         verify(eventListener).onInputEvent(eq(followupEvent));
378         verify(frontEventListener, never()).onInputEvent(any());
379     }
380 
381     @Test
testPop()382     public void testPop() {
383         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
384         final DreamTouchHandler.TouchSession.Callback callback =
385                 Mockito.mock(DreamTouchHandler.TouchSession.Callback.class);
386 
387         final Environment environment = new Environment(Stream.of(touchHandler)
388                 .collect(Collectors.toCollection(HashSet::new)));
389 
390         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
391         environment.publishInputEvent(initialEvent);
392 
393         final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
394         session.registerCallback(callback);
395         session.pop();
396         environment.executeAll();
397 
398         verify(callback).onRemoved();
399     }
400 
401     @Test
testPauseWithNoActiveSessions()402     public void testPauseWithNoActiveSessions() {
403         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
404 
405         final Environment environment = new Environment(Stream.of(touchHandler)
406                 .collect(Collectors.toCollection(HashSet::new)));
407 
408         environment.updateLifecycle(observerOwnerPair -> {
409             observerOwnerPair.first.onPause(observerOwnerPair.second);
410         });
411 
412         environment.verifyInputSessionDispose();
413     }
414 
415     @Test
testDeferredPauseWithActiveSessions()416     public void testDeferredPauseWithActiveSessions() {
417         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
418 
419         final Environment environment = new Environment(Stream.of(touchHandler)
420                 .collect(Collectors.toCollection(HashSet::new)));
421 
422         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
423         environment.publishInputEvent(initialEvent);
424 
425         // Ensure session started
426         final InputChannelCompat.InputEventListener eventListener =
427                 registerInputEventListener(touchHandler);
428 
429         // First event will be missed since we register after the execution loop,
430         final InputEvent event = Mockito.mock(InputEvent.class);
431         environment.publishInputEvent(event);
432         verify(eventListener).onInputEvent(eq(event));
433 
434         final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
435                 ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
436 
437         verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
438 
439         environment.updateLifecycle(observerOwnerPair -> {
440             observerOwnerPair.first.onPause(observerOwnerPair.second);
441         });
442 
443         verify(environment.mInputSession, never()).dispose();
444 
445         // End session
446         touchSessionArgumentCaptor.getValue().pop();
447         environment.executeAll();
448 
449         // Check to make sure the input session is now disposed.
450         environment.verifyInputSessionDispose();
451     }
452 
453     @Test
testDestroyWithActiveSessions()454     public void testDestroyWithActiveSessions() {
455         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
456 
457         final Environment environment = new Environment(Stream.of(touchHandler)
458                 .collect(Collectors.toCollection(HashSet::new)));
459 
460         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
461         environment.publishInputEvent(initialEvent);
462 
463         // Ensure session started
464         final InputChannelCompat.InputEventListener eventListener =
465                 registerInputEventListener(touchHandler);
466 
467         // First event will be missed since we register after the execution loop,
468         final InputEvent event = Mockito.mock(InputEvent.class);
469         environment.publishInputEvent(event);
470         verify(eventListener).onInputEvent(eq(event));
471 
472         final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
473                 ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
474 
475         verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
476 
477         environment.updateLifecycle(observerOwnerPair -> {
478             observerOwnerPair.first.onDestroy(observerOwnerPair.second);
479         });
480 
481         // Check to make sure the input session is now disposed.
482         environment.verifyInputSessionDispose();
483     }
484 
485 
486     @Test
testPilfering()487     public void testPilfering() {
488         final DreamTouchHandler touchHandler1 = Mockito.mock(DreamTouchHandler.class);
489         final DreamTouchHandler touchHandler2 = Mockito.mock(DreamTouchHandler.class);
490 
491         final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2)
492                 .collect(Collectors.toCollection(HashSet::new)));
493 
494         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
495         environment.publishInputEvent(initialEvent);
496 
497         final DreamTouchHandler.TouchSession session1 = captureSession(touchHandler1);
498         final GestureDetector.OnGestureListener gestureListener1 =
499                 registerGestureListener(session1);
500 
501         final DreamTouchHandler.TouchSession session2 = captureSession(touchHandler2);
502         final GestureDetector.OnGestureListener gestureListener2 =
503                 registerGestureListener(session2);
504         when(gestureListener2.onDown(any())).thenReturn(true);
505 
506         final MotionEvent gestureEvent = Mockito.mock(MotionEvent.class);
507         environment.publishGestureEvent(
508                 onGestureListener -> onGestureListener.onDown(gestureEvent));
509 
510         Mockito.clearInvocations(gestureListener1, gestureListener2);
511 
512         final MotionEvent followupEvent = Mockito.mock(MotionEvent.class);
513         environment.publishGestureEvent(
514                 onGestureListener -> onGestureListener.onDown(followupEvent));
515 
516         verify(gestureListener1, never()).onDown(any());
517         verify(gestureListener2).onDown(eq(followupEvent));
518     }
519 
520     @Test
testOnRemovedCallbackOnStopMonitoring()521     public void testOnRemovedCallbackOnStopMonitoring() {
522         final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
523         final DreamTouchHandler.TouchSession.Callback callback =
524                 Mockito.mock(DreamTouchHandler.TouchSession.Callback.class);
525 
526         final Environment environment = new Environment(Stream.of(touchHandler)
527                 .collect(Collectors.toCollection(HashSet::new)));
528 
529         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
530         environment.publishInputEvent(initialEvent);
531 
532         final DreamTouchHandler.TouchSession session = captureSession(touchHandler);
533         session.registerCallback(callback);
534 
535         environment.executeAll();
536 
537         environment.updateLifecycle(observerOwnerPair -> {
538             observerOwnerPair.first.onDestroy(observerOwnerPair.second);
539         });
540 
541         environment.executeAll();
542 
543         verify(callback).onRemoved();
544     }
545 
registerGestureListener(DreamTouchHandler handler)546     public GestureDetector.OnGestureListener registerGestureListener(DreamTouchHandler handler) {
547         final GestureDetector.OnGestureListener gestureListener = Mockito.mock(
548                 GestureDetector.OnGestureListener.class);
549         final ArgumentCaptor<DreamTouchHandler.TouchSession> sessionCaptor =
550                 ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
551         verify(handler).onSessionStart(sessionCaptor.capture());
552         sessionCaptor.getValue().registerGestureListener(gestureListener);
553 
554         return gestureListener;
555     }
556 
registerGestureListener( DreamTouchHandler.TouchSession session)557     public GestureDetector.OnGestureListener registerGestureListener(
558             DreamTouchHandler.TouchSession session) {
559         final GestureDetector.OnGestureListener gestureListener = Mockito.mock(
560                 GestureDetector.OnGestureListener.class);
561         session.registerGestureListener(gestureListener);
562 
563         return gestureListener;
564     }
565 
registerInputEventListener( DreamTouchHandler.TouchSession session)566     public InputChannelCompat.InputEventListener registerInputEventListener(
567             DreamTouchHandler.TouchSession session) {
568         final InputChannelCompat.InputEventListener eventListener = Mockito.mock(
569                 InputChannelCompat.InputEventListener.class);
570         session.registerInputListener(eventListener);
571 
572         return eventListener;
573     }
574 
captureSession(DreamTouchHandler handler)575     public DreamTouchHandler.TouchSession captureSession(DreamTouchHandler handler) {
576         final ArgumentCaptor<DreamTouchHandler.TouchSession> sessionCaptor =
577                 ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
578         verify(handler).onSessionStart(sessionCaptor.capture());
579         return sessionCaptor.getValue();
580     }
581 
registerInputEventListener( DreamTouchHandler handler)582     public InputChannelCompat.InputEventListener registerInputEventListener(
583             DreamTouchHandler handler) {
584         return registerInputEventListener(captureSession(handler));
585     }
586 }
587