1 /*
2  * Copyright (C) 2019 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.doze;
18 
19 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
20 
21 import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP;
22 import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
23 import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
24 
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertTrue;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.anyFloat;
30 import static org.mockito.ArgumentMatchers.anyInt;
31 import static org.mockito.ArgumentMatchers.eq;
32 import static org.mockito.Mockito.doAnswer;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.reset;
36 import static org.mockito.Mockito.times;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.when;
39 
40 import android.app.ActivityManager;
41 import android.content.res.Resources;
42 import android.database.ContentObserver;
43 import android.hardware.Sensor;
44 import android.hardware.display.AmbientDisplayConfiguration;
45 import android.testing.AndroidTestingRunner;
46 import android.testing.TestableLooper;
47 import android.testing.TestableLooper.RunWithLooper;
48 
49 import androidx.test.filters.SmallTest;
50 
51 import com.android.systemui.SysuiTestCase;
52 import com.android.systemui.biometrics.AuthController;
53 import com.android.systemui.doze.DozeSensors.TriggerSensor;
54 import com.android.systemui.plugins.SensorManagerPlugin;
55 import com.android.systemui.settings.UserTracker;
56 import com.android.systemui.statusbar.phone.DozeParameters;
57 import com.android.systemui.statusbar.policy.DevicePostureController;
58 import com.android.systemui.util.sensors.AsyncSensorManager;
59 import com.android.systemui.util.sensors.ProximitySensor;
60 import com.android.systemui.util.settings.FakeSettings;
61 import com.android.systemui.util.wakelock.WakeLock;
62 
63 import org.junit.Before;
64 import org.junit.Test;
65 import org.junit.runner.RunWith;
66 import org.mockito.ArgumentCaptor;
67 import org.mockito.Captor;
68 import org.mockito.Mock;
69 import org.mockito.MockitoAnnotations;
70 
71 import java.lang.reflect.Constructor;
72 import java.lang.reflect.Field;
73 import java.lang.reflect.Method;
74 import java.util.ArrayList;
75 import java.util.List;
76 import java.util.function.Consumer;
77 
78 @RunWith(AndroidTestingRunner.class)
79 @RunWithLooper
80 @SmallTest
81 public class DozeSensorsTest extends SysuiTestCase {
82     @Mock
83     private Resources mResources;
84     @Mock
85     private AsyncSensorManager mSensorManager;
86     @Mock
87     private DozeParameters mDozeParameters;
88     @Mock
89     private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
90     @Mock
91     private WakeLock mWakeLock;
92     @Mock
93     private DozeSensors.Callback mCallback;
94     @Mock
95     private Consumer<Boolean> mProxCallback;
96     @Mock
97     private TriggerSensor mTriggerSensor;
98     @Mock
99     private DozeLog mDozeLog;
100     @Mock
101     private AuthController mAuthController;
102     @Mock
103     private DevicePostureController mDevicePostureController;
104     @Mock
105     private UserTracker mUserTracker;
106     @Mock
107     private ProximitySensor mProximitySensor;
108 
109     // Capture listeners so that they can be used to send events
110     @Captor
111     private ArgumentCaptor<AuthController.Callback> mAuthControllerCallbackCaptor =
112             ArgumentCaptor.forClass(AuthController.Callback.class);
113     private AuthController.Callback mAuthControllerCallback;
114 
115     private FakeSettings mFakeSettings = new FakeSettings();
116     private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
117     private TestableLooper mTestableLooper;
118     private TestableDozeSensors mDozeSensors;
119     private TriggerSensor mSensorTap;
120 
121     @Before
setUp()122     public void setUp() {
123         MockitoAnnotations.initMocks(this);
124         mTestableLooper = TestableLooper.get(this);
125         when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
126         when(mAmbientDisplayConfiguration.tapSensorTypeMapping())
127                 .thenReturn(new String[]{"tapSensor"});
128         when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
129         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
130         when(mAmbientDisplayConfiguration.enabled(ActivityManager.getCurrentUser())).thenReturn(
131                 true);
132         doAnswer(invocation -> {
133             ((Runnable) invocation.getArgument(0)).run();
134             return null;
135         }).when(mWakeLock).wrap(any(Runnable.class));
136         mDozeSensors = new TestableDozeSensors();
137 
138         verify(mAuthController).addCallback(mAuthControllerCallbackCaptor.capture());
139         mAuthControllerCallback = mAuthControllerCallbackCaptor.getValue();
140     }
141 
142     @Test
testRegisterProx()143     public void testRegisterProx() {
144         assertFalse(mProximitySensor.isRegistered());
145         mDozeSensors.setProxListening(true);
146         verify(mProximitySensor).resume();
147     }
148 
149     @Test
testSensorDebounce()150     public void testSensorDebounce() {
151         mDozeSensors.setListening(true, true, true);
152 
153         mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
154         mTestableLooper.processAllMessages();
155         verify(mCallback).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH),
156                 anyFloat(), anyFloat(), eq(null));
157 
158         mDozeSensors.requestTemporaryDisable();
159         reset(mCallback);
160         mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
161         mTestableLooper.processAllMessages();
162         verify(mCallback, never()).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_REACH),
163                 anyFloat(), anyFloat(), eq(null));
164     }
165 
166     @Test
testSetListening_firstTrue_registerSettingsObserver()167     public void testSetListening_firstTrue_registerSettingsObserver() {
168         verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt());
169         mDozeSensors.setListening(true, true, true);
170 
171         verify(mTriggerSensor).registerSettingsObserver(any(ContentObserver.class));
172     }
173 
174     @Test
testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce()175     public void testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce() {
176         verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt());
177         mDozeSensors.setListening(true, true, true);
178         mDozeSensors.setListening(true, true, true);
179 
180         verify(mTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class));
181     }
182 
183     @Test
testDestroy()184     public void testDestroy() {
185         mDozeSensors.destroy();
186 
187         verify(mProximitySensor).destroy();
188         verify(mTriggerSensor).setListening(false);
189     }
190 
191     @Test
testRegisterSensorsUsingProx()192     public void testRegisterSensorsUsingProx() {
193         // GIVEN we only should register sensors using prox when not in low-powered mode / off
194         // and the single tap sensor uses the proximity sensor
195         when(mDozeParameters.getSelectivelyRegisterSensorsUsingProx()).thenReturn(true);
196         when(mDozeParameters.singleTapUsesProx(anyInt())).thenReturn(true);
197         TestableDozeSensors dozeSensors = new TestableDozeSensors();
198 
199         // THEN on initialization, the tap sensor isn't requested
200         assertFalse(mSensorTap.mRequested);
201 
202         // WHEN we're now in a low powered state
203         dozeSensors.setListeningWithPowerState(true, true, true, true);
204 
205         // THEN the tap sensor is registered
206         assertTrue(mSensorTap.mRequested);
207     }
208 
209     @Test
testDozeSensorSetListening()210     public void testDozeSensorSetListening() {
211         // GIVEN doze sensors enabled
212         when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true);
213 
214         // GIVEN a trigger sensor that's enabled by settings
215         Sensor mockSensor = mock(Sensor.class);
216         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorWithSettingEnabled(
217                 mockSensor,
218                 /* settingEnabled */ true
219         );
220         when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor)))
221                 .thenReturn(true);
222 
223         // WHEN we want to listen for the trigger sensor
224         triggerSensor.setListening(true);
225 
226         // THEN the sensor is registered
227         assertTrue(triggerSensor.mRegistered);
228     }
229 
230     @Test
testDozeSensorSettingDisabled()231     public void testDozeSensorSettingDisabled() {
232         // GIVEN doze sensors enabled
233         when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true);
234 
235         // GIVEN a trigger sensor that's not enabled by settings
236         Sensor mockSensor = mock(Sensor.class);
237         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorWithSettingEnabled(
238                 mockSensor,
239                 /* settingEnabled*/ false
240         );
241         when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor)))
242                 .thenReturn(true);
243 
244         // WHEN setListening is called
245         triggerSensor.setListening(true);
246 
247         // THEN the sensor is not registered
248         assertFalse(triggerSensor.mRegistered);
249     }
250 
251     @Test
testDozeSensorIgnoreSetting()252     public void testDozeSensorIgnoreSetting() {
253         // GIVEN doze sensors enabled
254         when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true);
255 
256         // GIVEN a trigger sensor that's not enabled by settings
257         Sensor mockSensor = mock(Sensor.class);
258         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorWithSettingEnabled(
259                 mockSensor,
260                 /* settingEnabled*/ false
261         );
262         when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor)))
263                 .thenReturn(true);
264 
265         // GIVEN sensor is listening
266         triggerSensor.setListening(true);
267 
268         // WHEN ignoreSetting is called
269         triggerSensor.ignoreSetting(true);
270 
271         // THEN the sensor is still registered since the setting is ignore
272         assertTrue(triggerSensor.mRegistered);
273     }
274 
275     @Test
testUpdateListeningAfterAlreadyRegistered()276     public void testUpdateListeningAfterAlreadyRegistered() {
277         // GIVEN doze sensors enabled
278         when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true);
279 
280         // GIVEN a trigger sensor
281         Sensor mockSensor = mock(Sensor.class);
282         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorWithSettingEnabled(
283                 mockSensor,
284                 /* settingEnabled*/ true
285         );
286         when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor)))
287                 .thenReturn(true);
288 
289         // WHEN setListening is called AND updateListening is called
290         triggerSensor.setListening(true);
291         triggerSensor.updateListening();
292 
293         // THEN the sensor is still registered
294         assertTrue(triggerSensor.mRegistered);
295     }
296 
297     @Test
testPostureStartStateClosed_registersCorrectSensor()298     public void testPostureStartStateClosed_registersCorrectSensor() throws Exception {
299         // GIVEN doze sensor that supports postures
300         Sensor closedSensor = createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
301         Sensor openedSensor = createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_LIGHT);
302         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorForPosture(
303                 new Sensor[] {
304                         null /* unknown */,
305                         closedSensor,
306                         null /* half-opened */,
307                         openedSensor},
308                 DevicePostureController.DEVICE_POSTURE_CLOSED);
309 
310         // WHEN trigger sensor requests listening
311         triggerSensor.setListening(true);
312 
313         // THEN the correct sensor is registered
314         verify(mSensorManager).requestTriggerSensor(eq(triggerSensor), eq(closedSensor));
315         verify(mSensorManager, never()).requestTriggerSensor(eq(triggerSensor), eq(openedSensor));
316     }
317 
318     @Test
testPostureChange_registersCorrectSensor()319     public void testPostureChange_registersCorrectSensor() throws Exception {
320         // GIVEN doze sensor that supports postures
321         Sensor closedSensor = createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
322         Sensor openedSensor = createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_LIGHT);
323         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorForPosture(
324                 new Sensor[] {
325                         null /* unknown */,
326                         closedSensor,
327                         null /* half-opened */,
328                         openedSensor},
329                 DevicePostureController.DEVICE_POSTURE_CLOSED);
330 
331         // GIVEN sensor is listening
332         when(mSensorManager.requestTriggerSensor(any(), any())).thenReturn(true);
333         triggerSensor.setListening(true);
334         reset(mSensorManager);
335         assertTrue(triggerSensor.mRegistered);
336 
337         // WHEN posture changes
338         boolean sensorChanged =
339                 triggerSensor.setPosture(DevicePostureController.DEVICE_POSTURE_OPENED);
340 
341         // THEN the correct sensor is registered
342         assertTrue(sensorChanged);
343         verify(mSensorManager).requestTriggerSensor(eq(triggerSensor), eq(openedSensor));
344         verify(mSensorManager, never()).requestTriggerSensor(eq(triggerSensor), eq(closedSensor));
345     }
346 
347     @Test
testPostureChange_noSensorChange()348     public void testPostureChange_noSensorChange() throws Exception {
349         // GIVEN doze sensor that supports postures
350         Sensor closedSensor = createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
351         Sensor openedSensor = createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_LIGHT);
352         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorForPosture(
353                 new Sensor[] {
354                         null /* unknown */,
355                         closedSensor,
356                         openedSensor /* half-opened uses the same sensor as opened*/,
357                         openedSensor},
358                 DevicePostureController.DEVICE_POSTURE_HALF_OPENED);
359 
360         // GIVEN sensor is listening
361         when(mSensorManager.requestTriggerSensor(any(), any())).thenReturn(true);
362         triggerSensor.setListening(true);
363         reset(mSensorManager);
364 
365         // WHEN posture changes
366         boolean sensorChanged =
367                 triggerSensor.setPosture(DevicePostureController.DEVICE_POSTURE_OPENED);
368 
369         // THEN no change in sensor
370         assertFalse(sensorChanged);
371         verify(mSensorManager, never()).requestTriggerSensor(eq(triggerSensor), any());
372     }
373 
374     @Test
testFindSensor()375     public void testFindSensor() throws Exception {
376         // GIVEN a prox sensor
377         List<Sensor> sensors = new ArrayList<>();
378         Sensor proxSensor =
379                 createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
380         sensors.add(proxSensor);
381 
382         when(mSensorManager.getSensorList(anyInt())).thenReturn(sensors);
383 
384         // WHEN we try to find the prox sensor with the same type and name
385         // THEN we find the added sensor
386         assertEquals(
387                 proxSensor,
388                 DozeSensors.findSensor(
389                         mSensorManager,
390                         Sensor.STRING_TYPE_PROXIMITY,
391                         proxSensor.getName()));
392 
393         // WHEN we try to find a prox sensor with a different name
394         // THEN no sensor is found
395         assertEquals(
396                 null,
397                 DozeSensors.findSensor(
398                         mSensorManager,
399                         Sensor.STRING_TYPE_PROXIMITY,
400                         "some other name"));
401     }
402 
403     @Test
testUdfpsEnrollmentChanged()404     public void testUdfpsEnrollmentChanged() throws Exception {
405         // GIVEN a UDFPS_LONG_PRESS trigger sensor that's not configured
406         Sensor mockSensor = mock(Sensor.class);
407         TriggerSensor triggerSensor = mDozeSensors.createDozeSensorForPosture(
408                 mockSensor,
409                 REASON_SENSOR_UDFPS_LONG_PRESS,
410                 /* configured */ false);
411         mDozeSensors.addSensor(triggerSensor);
412         when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor)))
413                 .thenReturn(true);
414 
415         // WHEN listening state is set to TRUE
416         mDozeSensors.setListening(true, true, true);
417 
418         // THEN mRegistered is still false b/c !mConfigured
419         assertFalse(triggerSensor.mConfigured);
420         assertFalse(triggerSensor.mRegistered);
421 
422         // WHEN enrollment changes to TRUE
423         when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
424         mAuthControllerCallback.onEnrollmentsChanged(TYPE_FINGERPRINT);
425 
426         // THEN mConfigured = TRUE
427         assertTrue(triggerSensor.mConfigured);
428 
429         // THEN mRegistered = TRUE
430         assertTrue(triggerSensor.mRegistered);
431     }
432 
433     @Test
testGesturesAllInitiallyRespectSettings()434     public void testGesturesAllInitiallyRespectSettings() {
435         DozeSensors dozeSensors = new DozeSensors(mResources, mSensorManager, mDozeParameters,
436                 mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
437                 mProximitySensor, mFakeSettings, mAuthController,
438                 mDevicePostureController, mUserTracker);
439 
440         for (TriggerSensor sensor : dozeSensors.mTriggerSensors) {
441             assertFalse(sensor.mIgnoresSetting);
442         }
443     }
444 
445     @Test
aodOnlySensor_onlyRegisteredWhenAodSensorsIncluded()446     public void aodOnlySensor_onlyRegisteredWhenAodSensorsIncluded() {
447         // GIVEN doze sensors enabled
448         when(mAmbientDisplayConfiguration.enabled(anyInt())).thenReturn(true);
449 
450         // GIVEN a trigger sensor that requires aod
451         Sensor mockSensor = mock(Sensor.class);
452         TriggerSensor aodOnlyTriggerSensor = mDozeSensors.createDozeSensorRequiringAod(mockSensor);
453         when(mSensorManager.requestTriggerSensor(eq(aodOnlyTriggerSensor), eq(mockSensor)))
454                 .thenReturn(true);
455         mDozeSensors.addSensor(aodOnlyTriggerSensor);
456 
457         // WHEN aod only sensors aren't included
458         mDozeSensors.setListening(/* listen */ true, /* includeTouchScreenSensors */true,
459                 /* includeAodOnlySensors */false);
460 
461         // THEN the sensor is not registered or requested
462         assertFalse(aodOnlyTriggerSensor.mRequested);
463         assertFalse(aodOnlyTriggerSensor.mRegistered);
464 
465         // WHEN aod only sensors ARE included
466         mDozeSensors.setListening(/* listen */ true, /* includeTouchScreenSensors */true,
467                 /* includeAodOnlySensors */true);
468 
469         // THEN the sensor is registered and requested
470         assertTrue(aodOnlyTriggerSensor.mRequested);
471         assertTrue(aodOnlyTriggerSensor.mRegistered);
472     }
473 
474     @Test
liftToWake_defaultSetting_configDefaultFalse()475     public void liftToWake_defaultSetting_configDefaultFalse() {
476         // WHEN the default lift to wake gesture setting is false
477         when(mResources.getBoolean(
478                 com.android.internal.R.bool.config_dozePickupGestureEnabled)).thenReturn(false);
479 
480         DozeSensors dozeSensors = new DozeSensors(mResources, mSensorManager, mDozeParameters,
481                 mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
482                 mProximitySensor, mFakeSettings, mAuthController,
483                 mDevicePostureController, mUserTracker);
484 
485         for (TriggerSensor sensor : dozeSensors.mTriggerSensors) {
486             // THEN lift to wake's TriggerSensor enabledBySettings is false
487             if (sensor.mPulseReason == DozeLog.REASON_SENSOR_PICKUP) {
488                 assertFalse(sensor.enabledBySetting());
489             }
490         }
491     }
492 
493     @Test
liftToWake_defaultSetting_configDefaultTrue()494     public void liftToWake_defaultSetting_configDefaultTrue() {
495         // WHEN the default lift to wake gesture setting is true
496         when(mResources.getBoolean(
497                 com.android.internal.R.bool.config_dozePickupGestureEnabled)).thenReturn(true);
498 
499         DozeSensors dozeSensors = new DozeSensors(mResources, mSensorManager, mDozeParameters,
500                 mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
501                 mProximitySensor, mFakeSettings, mAuthController,
502                 mDevicePostureController, mUserTracker);
503 
504         for (TriggerSensor sensor : dozeSensors.mTriggerSensors) {
505             // THEN lift to wake's TriggerSensor enabledBySettings is true
506             if (sensor.mPulseReason == DozeLog.REASON_SENSOR_PICKUP) {
507                 assertTrue(sensor.enabledBySetting());
508             }
509         }
510     }
511 
512     private class TestableDozeSensors extends DozeSensors {
TestableDozeSensors()513         TestableDozeSensors() {
514             super(mResources, mSensorManager, mDozeParameters,
515                     mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
516                     mProximitySensor, mFakeSettings, mAuthController,
517                     mDevicePostureController, mUserTracker);
518             for (TriggerSensor sensor : mTriggerSensors) {
519                 if (sensor instanceof PluginSensor
520                         && ((PluginSensor) sensor).mPluginSensor.getType()
521                         == TYPE_WAKE_LOCK_SCREEN) {
522                     mWakeLockScreenListener = (PluginSensor) sensor;
523                 } else if (sensor.mPulseReason == REASON_SENSOR_TAP) {
524                     mSensorTap = sensor;
525                 }
526             }
527             mTriggerSensors = new TriggerSensor[] {mTriggerSensor, mSensorTap};
528         }
529 
createDozeSensorWithSettingEnabled(Sensor sensor, boolean settingEnabled)530         public TriggerSensor createDozeSensorWithSettingEnabled(Sensor sensor,
531                 boolean settingEnabled) {
532             return new TriggerSensor(/* sensor */ sensor,
533                     /* setting name */ "test_setting",
534                     /* settingDefault */ settingEnabled,
535                     /* configured */ true,
536                     /* pulseReason*/ 0,
537                     /* reportsTouchCoordinate*/ false,
538                     /* requiresTouchscreen */ false,
539                     /* ignoresSetting */ false,
540                     /* requiresProx */ false,
541                     /* immediatelyReRegister */ true,
542                     /* requiresAod */false
543             );
544         }
545 
createDozeSensorForPosture( Sensor sensor, int pulseReason, boolean configured )546         public TriggerSensor createDozeSensorForPosture(
547                 Sensor sensor,
548                 int pulseReason,
549                 boolean configured
550         ) {
551             return new TriggerSensor(/* sensor */ sensor,
552                     /* setting name */ "test_setting",
553                     /* settingDefault */ true,
554                     /* configured */ configured,
555                     /* pulseReason*/ pulseReason,
556                     /* reportsTouchCoordinate*/ false,
557                     /* requiresTouchscreen */ false,
558                     /* ignoresSetting */ false,
559                     /* requiresTouchScreen */ false,
560                     /* immediatelyReRegister*/ true,
561                     false
562             );
563         }
564 
565         /**
566          * Create a doze sensor that requires Aod
567          */
createDozeSensorRequiringAod(Sensor sensor)568         public TriggerSensor createDozeSensorRequiringAod(Sensor sensor) {
569             return new TriggerSensor(/* sensor */ sensor,
570                     /* setting name */ "aod_requiring_sensor",
571                     /* settingDefault */ true,
572                     /* configured */ true,
573                     /* pulseReason*/ 0,
574                     /* reportsTouchCoordinate*/ false,
575                     /* requiresTouchscreen */ false,
576                     /* ignoresSetting */ false,
577                     /* requiresProx */ false,
578                     /* immediatelyReRegister */ true,
579                     /* requiresAoD */ true
580             );
581         }
582 
583         /**
584          * Create a doze sensor that supports postures and is enabled
585          */
createDozeSensorForPosture(Sensor[] sensors, int posture)586         public TriggerSensor createDozeSensorForPosture(Sensor[] sensors, int posture) {
587             return new TriggerSensor(/* sensor */ sensors,
588                     /* setting name */ "posture_test_setting",
589                     /* settingDefault */ true,
590                     /* configured */ true,
591                     /* pulseReason*/ 0,
592                     /* reportsTouchCoordinate*/ false,
593                     /* requiresTouchscreen */ false,
594                     /* ignoresSetting */ true,
595                     /* requiresProx */ false,
596                     /* immediatelyReRegister */ true,
597                     posture,
598                     /* requiresUi */ false
599             );
600         }
601 
addSensor(TriggerSensor sensor)602         public void addSensor(TriggerSensor sensor) {
603             TriggerSensor[] newArray = new TriggerSensor[mTriggerSensors.length + 1];
604             for (int i = 0; i < mTriggerSensors.length; i++) {
605                 newArray[i] = mTriggerSensors[i];
606             }
607             newArray[mTriggerSensors.length] = sensor;
608             mTriggerSensors = newArray;
609         }
610     }
611 
setSensorType(Sensor sensor, int type, String strType)612     public static void setSensorType(Sensor sensor, int type, String strType) throws Exception {
613         Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
614         setter.setAccessible(true);
615         setter.invoke(sensor, type);
616         if (strType != null) {
617             Field f = sensor.getClass().getDeclaredField("mStringType");
618             f.setAccessible(true);
619             f.set(sensor, strType);
620         }
621     }
622 
createSensor(int type, String strType)623     public static Sensor createSensor(int type, String strType) throws Exception {
624         Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
625         constr.setAccessible(true);
626         Sensor sensor = constr.newInstance();
627         setSensorType(sensor, type, strType);
628         return sensor;
629     }
630 }
631