• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.classifier;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.argThat;
21 import static org.mockito.Mockito.inOrder;
22 import static org.mockito.Mockito.never;
23 import static org.mockito.Mockito.reset;
24 import static org.mockito.Mockito.times;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27 
28 import android.testing.AndroidTestingRunner;
29 import android.view.MotionEvent;
30 
31 import androidx.test.filters.SmallTest;
32 
33 import com.android.keyguard.KeyguardUpdateMonitor;
34 import com.android.systemui.SysuiTestCase;
35 import com.android.systemui.dock.DockManager;
36 import com.android.systemui.dock.DockManagerFake;
37 import com.android.systemui.plugins.statusbar.StatusBarStateController;
38 import com.android.systemui.shade.ShadeExpansionStateManager;
39 import com.android.systemui.statusbar.StatusBarState;
40 import com.android.systemui.statusbar.SysuiStatusBarStateController;
41 import com.android.systemui.statusbar.policy.BatteryController;
42 import com.android.systemui.statusbar.policy.KeyguardStateController;
43 import com.android.systemui.util.concurrency.FakeExecutor;
44 import com.android.systemui.util.sensors.ProximitySensor;
45 import com.android.systemui.util.sensors.ThresholdSensor;
46 import com.android.systemui.util.time.FakeSystemClock;
47 
48 import org.junit.Before;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.InOrder;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55 
56 @SmallTest
57 @RunWith(AndroidTestingRunner.class)
58 public class FalsingCollectorImplTest extends SysuiTestCase {
59 
60     private FalsingCollectorImpl mFalsingCollector;
61     @Mock
62     private FalsingDataProvider mFalsingDataProvider;
63     private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
64     @Mock
65     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
66     @Mock
67     private HistoryTracker mHistoryTracker;
68     @Mock
69     private ProximitySensor mProximitySensor;
70     @Mock
71     private SysuiStatusBarStateController mStatusBarStateController;
72     @Mock
73     private KeyguardStateController mKeyguardStateController;
74     @Mock
75     private ShadeExpansionStateManager mShadeExpansionStateManager;
76     @Mock
77     private BatteryController mBatteryController;
78     private final DockManagerFake mDockManager = new DockManagerFake();
79     private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
80     private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
81 
82     @Before
setUp()83     public void setUp() {
84         MockitoAnnotations.initMocks(this);
85 
86         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
87         when(mKeyguardStateController.isShowing()).thenReturn(true);
88 
89         mFalsingCollector = new FalsingCollectorImpl(mFalsingDataProvider, mFalsingManager,
90                 mKeyguardUpdateMonitor, mHistoryTracker, mProximitySensor,
91                 mStatusBarStateController, mKeyguardStateController, mShadeExpansionStateManager,
92                 mBatteryController,
93                 mDockManager, mFakeExecutor, mFakeSystemClock);
94     }
95 
96     @Test
testRegisterSensor()97     public void testRegisterSensor() {
98         mFalsingCollector.onScreenTurningOn();
99         verify(mProximitySensor).register(any(ThresholdSensor.Listener.class));
100     }
101 
102     @Test
testNoProximityWhenWirelessCharging()103     public void testNoProximityWhenWirelessCharging() {
104         ArgumentCaptor<BatteryController.BatteryStateChangeCallback> batteryCallbackCaptor =
105                 ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback.class);
106         verify(mBatteryController).addCallback(batteryCallbackCaptor.capture());
107         batteryCallbackCaptor.getValue().onWirelessChargingChanged(true);
108         verify(mProximitySensor).pause();
109     }
110 
111     @Test
testProximityWhenOffWirelessCharging()112     public void testProximityWhenOffWirelessCharging() {
113         ArgumentCaptor<BatteryController.BatteryStateChangeCallback> batteryCallbackCaptor =
114                 ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback.class);
115         verify(mBatteryController).addCallback(batteryCallbackCaptor.capture());
116         batteryCallbackCaptor.getValue().onWirelessChargingChanged(false);
117         verify(mProximitySensor).resume();
118     }
119 
120     @Test
testNoProximityWhenDocked()121     public void testNoProximityWhenDocked() {
122         mDockManager.setDockEvent(DockManager.STATE_DOCKED);
123         verify(mProximitySensor).pause();
124     }
125 
126     @Test
testProximityWhenUndocked()127     public void testProximityWhenUndocked() {
128         mDockManager.setDockEvent(DockManager.STATE_NONE);
129         verify(mProximitySensor).resume();
130     }
131 
132     @Test
testUnregisterSensor()133     public void testUnregisterSensor() {
134         mFalsingCollector.onScreenTurningOn();
135         reset(mProximitySensor);
136         mFalsingCollector.onScreenOff();
137         verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
138     }
139 
140     @Test
testUnregisterSensor_QS()141     public void testUnregisterSensor_QS() {
142         mFalsingCollector.onScreenTurningOn();
143         reset(mProximitySensor);
144         mFalsingCollector.onQsExpansionChanged(true);
145         verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
146         mFalsingCollector.onQsExpansionChanged(false);
147         verify(mProximitySensor).register(any(ThresholdSensor.Listener.class));
148     }
149 
150     @Test
testUnregisterSensor_Bouncer()151     public void testUnregisterSensor_Bouncer() {
152         mFalsingCollector.onScreenTurningOn();
153         reset(mProximitySensor);
154         mFalsingCollector.onBouncerShown();
155         verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
156         mFalsingCollector.onBouncerHidden();
157         verify(mProximitySensor).register(any(ThresholdSensor.Listener.class));
158     }
159 
160     @Test
testUnregisterSensor_StateTransition()161     public void testUnregisterSensor_StateTransition() {
162         ArgumentCaptor<StatusBarStateController.StateListener> stateListenerArgumentCaptor =
163                 ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
164         verify(mStatusBarStateController).addCallback(stateListenerArgumentCaptor.capture());
165 
166         mFalsingCollector.onScreenTurningOn();
167         reset(mProximitySensor);
168         stateListenerArgumentCaptor.getValue().onStateChanged(StatusBarState.SHADE);
169         verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
170     }
171 
172     @Test
testPassThroughGesture()173     public void testPassThroughGesture() {
174         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
175         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
176 
177         // Nothing passed initially
178         mFalsingCollector.onTouchEvent(down);
179         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
180 
181         // Up event flushes the down event.
182         mFalsingCollector.onTouchEvent(up);
183         InOrder orderedCalls = inOrder(mFalsingDataProvider);
184         // We can't simply use "eq" or similar because the collector makes a copy of "down".
185         orderedCalls.verify(mFalsingDataProvider).onMotionEvent(
186                 argThat(argument -> argument.getActionMasked() == MotionEvent.ACTION_DOWN));
187         orderedCalls.verify(mFalsingDataProvider).onMotionEvent(up);
188     }
189 
190     @Test
testAvoidGesture()191     public void testAvoidGesture() {
192         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
193         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
194 
195         // Nothing passed initially
196         mFalsingCollector.onTouchEvent(down);
197         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
198 
199         mFalsingCollector.avoidGesture();
200         // Up event would flush, but we were told to avoid.
201         mFalsingCollector.onTouchEvent(up);
202         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
203     }
204 
205     @Test
testIgnoreActionOutside()206     public void testIgnoreActionOutside() {
207         MotionEvent outside = MotionEvent.obtain(0, 0, MotionEvent.ACTION_OUTSIDE, 0, 0, 0);
208         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
209 
210         // Nothing passed initially. The outside event will be completely ignored.
211         mFalsingCollector.onTouchEvent(outside);
212         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
213 
214         // Up event flushes, and the outside event isn't passed through.
215         mFalsingCollector.onTouchEvent(up);
216         verify(mFalsingDataProvider).onMotionEvent(up);
217     }
218 
219     @Test
testAvoidUnlocked()220     public void testAvoidUnlocked() {
221         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
222         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
223 
224         when(mKeyguardStateController.isShowing()).thenReturn(false);
225 
226         // Nothing passed initially
227         mFalsingCollector.onTouchEvent(down);
228         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
229 
230         // Up event would normally flush the up event, but doesn't.
231         mFalsingCollector.onTouchEvent(up);
232         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
233     }
234 
235     @Test
testGestureWhenDozing()236     public void testGestureWhenDozing() {
237         // We check the FalsingManager for taps during the transition to AoD (dozing=true,
238         // pulsing=false), so the FalsingCollector needs to continue to analyze events that occur
239         // while the device is dozing.
240         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
241         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
242 
243         when(mStatusBarStateController.isDozing()).thenReturn(true);
244 
245         // Nothing passed initially
246         mFalsingCollector.onTouchEvent(down);
247         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
248 
249         // Up event flushes
250         mFalsingCollector.onTouchEvent(up);
251         verify(mFalsingDataProvider, times(2)).onMotionEvent(any(MotionEvent.class));
252     }
253 
254     @Test
testGestureWhenPulsing()255     public void testGestureWhenPulsing() {
256         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
257         MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
258 
259         when(mStatusBarStateController.isDozing()).thenReturn(true);
260         when(mStatusBarStateController.isPulsing()).thenReturn(true);
261 
262         // Nothing passed initially
263         mFalsingCollector.onTouchEvent(down);
264         verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
265 
266         // Up event would flushes
267         mFalsingCollector.onTouchEvent(up);
268         verify(mFalsingDataProvider, times(2)).onMotionEvent(any(MotionEvent.class));
269     }
270 
271     @Test
testOnA11yAction()272     public void testOnA11yAction() {
273         mFalsingCollector.onA11yAction();
274         verify(mFalsingDataProvider).onA11yAction();
275     }
276 }
277