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.ambient.touch;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.eq;
21 import static org.mockito.Mockito.never;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.when;
25 
26 import android.platform.test.annotations.EnableFlags;
27 import android.testing.TestableLooper;
28 import android.view.Choreographer;
29 import android.view.GestureDetector;
30 import android.view.InputEvent;
31 import android.view.MotionEvent;
32 
33 import androidx.test.ext.junit.runners.AndroidJUnit4;
34 import androidx.test.filters.SmallTest;
35 
36 import com.android.systemui.Flags;
37 import com.android.systemui.SysuiTestCase;
38 import com.android.systemui.shared.system.InputChannelCompat;
39 import com.android.systemui.shared.system.InputMonitorCompat;
40 
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.Mock;
46 import org.mockito.Mockito;
47 import org.mockito.MockitoAnnotations;
48 
49 /**
50  * A test suite for exercising {@link InputSession}.
51  */
52 @SmallTest
53 @RunWith(AndroidJUnit4.class)
54 @TestableLooper.RunWithLooper()
55 public class InputSessionTest extends SysuiTestCase {
56     @Mock
57     InputMonitorCompat mInputMonitor;
58 
59     @Mock
60     GestureDetector mGestureDetector;
61 
62     @Mock
63     InputChannelCompat.InputEventListener mInputEventListener;
64 
65     TestableLooper mLooper;
66 
67     @Mock
68     Choreographer mChoreographer;
69 
70     @Mock
71     InputChannelCompat.InputEventReceiver mInputEventReceiver;
72 
73     InputSession mSession;
74 
75     InputChannelCompat.InputEventListener mEventListener;
76 
77 
78     @Before
setup()79     public void setup() {
80         MockitoAnnotations.initMocks(this);
81         mLooper = TestableLooper.get(this);
82     }
83 
createSession(boolean pilfer)84     private void createSession(boolean pilfer) {
85         when(mInputMonitor.getInputReceiver(any(), any(), any()))
86                 .thenReturn(mInputEventReceiver);
87         mSession = new InputSession(mInputMonitor, mGestureDetector,
88                 mInputEventListener, mChoreographer, mLooper.getLooper(), pilfer);
89         final ArgumentCaptor<InputChannelCompat.InputEventListener> listenerCaptor =
90                 ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
91         verify(mInputMonitor).getInputReceiver(any(), any(), listenerCaptor.capture());
92         mEventListener = listenerCaptor.getValue();
93     }
94 
95     /**
96      * Ensures consumed motion events are pilfered when option is set.
97      */
98     @Test
testPilferOnMotionEventGestureConsume()99     public void testPilferOnMotionEventGestureConsume() {
100         createSession(true);
101         final MotionEvent event = Mockito.mock(MotionEvent.class);
102         when(mGestureDetector.onTouchEvent(event)).thenReturn(true);
103         mEventListener.onInputEvent(event);
104         verify(mInputEventListener).onInputEvent(eq(event));
105         verify(mInputMonitor).pilferPointers();
106     }
107 
108     /**
109      * Ensures consumed motion events are not pilfered when option is not set.
110      */
111     @Test
testNoPilferOnMotionEventGestureConsume()112     public void testNoPilferOnMotionEventGestureConsume() {
113         createSession(false);
114         final MotionEvent event = Mockito.mock(MotionEvent.class);
115         when(mGestureDetector.onTouchEvent(event)).thenReturn(true);
116         mEventListener.onInputEvent(event);
117         verify(mInputEventListener).onInputEvent(eq(event));
118         verify(mInputMonitor, never()).pilferPointers();
119     }
120 
121     /**
122      * Ensures input events are never pilfered.
123      */
124     @Test
testNoPilferOnInputEvent()125     public void testNoPilferOnInputEvent() {
126         createSession(true);
127         final InputEvent event = Mockito.mock(InputEvent.class);
128         mEventListener.onInputEvent(event);
129         verify(mInputEventListener).onInputEvent(eq(event));
130         verify(mInputMonitor, never()).pilferPointers();
131     }
132 
133     @Test
134     @EnableFlags(Flags.FLAG_DREAM_INPUT_SESSION_PILFER_ONCE)
testPilferOnce()135     public void testPilferOnce() {
136         createSession(true);
137         final MotionEvent event = Mockito.mock(MotionEvent.class);
138         when(mGestureDetector.onTouchEvent(event)).thenReturn(true);
139         mEventListener.onInputEvent(event);
140         mEventListener.onInputEvent(event);
141         verify(mInputEventListener, times(2)).onInputEvent(eq(event));
142         verify(mInputMonitor, times(1)).pilferPointers();
143     }
144 
145     /**
146      * Ensures components are properly disposed.
147      */
148     @Test
testDispose()149     public void testDispose() {
150         createSession(true);
151         mSession.dispose();
152         verify(mInputMonitor).dispose();
153         verify(mInputEventReceiver).dispose();
154     }
155 }
156