xref: /aosp_15_r20/cts/tests/sensor/src/android/hardware/cts/SensorTest.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2008 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 android.hardware.cts;
18 
19 import android.content.Context;
20 import android.content.pm.PackageManager;
21 import android.hardware.Sensor;
22 import android.hardware.SensorEvent;
23 import android.hardware.SensorEventListener;
24 import android.hardware.SensorEventListener2;
25 import android.hardware.SensorManager;
26 import android.hardware.TriggerEvent;
27 import android.hardware.TriggerEventListener;
28 import android.hardware.cts.helpers.SensorCtsHelper;
29 import android.hardware.cts.helpers.SensorNotSupportedException;
30 import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
31 import android.hardware.cts.helpers.TestSensorEnvironment;
32 import android.hardware.cts.helpers.TestSensorEventListener;
33 import android.hardware.cts.helpers.TestSensorManager;
34 import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
35 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
36 import android.hardware.cts.helpers.sensorverification.ContinuousEventSanitizedVerification;
37 import android.hardware.cts.helpers.sensorverification.EventGapVerification;
38 import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
39 import android.hardware.cts.helpers.sensorverification.EventTimestampSynchronizationVerification;
40 import android.os.Build.VERSION_CODES;
41 import android.os.Handler;
42 import android.os.HandlerThread;
43 import android.os.PowerManager;
44 import android.os.SystemClock;
45 import android.platform.test.annotations.AppModeFull;
46 import android.platform.test.annotations.Presubmit;
47 import android.util.Log;
48 
49 import com.android.compatibility.common.util.CddTest;
50 import com.android.compatibility.common.util.PropertyUtil;
51 
52 import com.google.common.collect.ArrayListMultimap;
53 import com.google.common.collect.Multimap;
54 
55 import junit.framework.Assert;
56 
57 import java.util.ArrayList;
58 import java.util.List;
59 import java.util.concurrent.CountDownLatch;
60 import java.util.concurrent.TimeUnit;
61 
62 public class SensorTest extends SensorTestCase {
63     private static final String TAG = "SensorTest";
64 
65     // Test only SDK defined sensors. Any sensors with type > 100 are ignored.
66     private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;
67 
68     private PowerManager.WakeLock mWakeLock;
69     private SensorManager mSensorManager;
70     private TestSensorManager mTestSensorManager;
71     private NullTriggerEventListener mNullTriggerEventListener;
72     private NullSensorEventListener mNullSensorEventListener;
73     private Sensor mTriggerSensor;
74     private List<Sensor> mSensorList;
75     private List<Sensor> mAndroidSensorList;
76 
77     @Override
setUp()78     protected void setUp() throws Exception {
79         Context context = getContext();
80         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
81         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
82 
83         mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
84         mNullTriggerEventListener = new NullTriggerEventListener();
85         mNullSensorEventListener = new NullSensorEventListener();
86 
87         mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
88         assertNotNull("SensorList was null.", mSensorList);
89         if (mSensorList.isEmpty()) {
90             // several devices will not have sensors, so we need to skip the tests in those cases
91             throw new SensorTestStateNotSupportedException(
92                     "Sensors are not available in the system.");
93         }
94 
95         mAndroidSensorList = new ArrayList<>();
96         for (Sensor s : mSensorList) {
97             if (s.getType() < Sensor.TYPE_DEVICE_PRIVATE_BASE &&
98                     (!context.getPackageManager().isInstantApp() || s.getType() != Sensor.TYPE_HEART_RATE)) {
99                 mAndroidSensorList.add(s);
100             }
101         }
102 
103         mWakeLock.acquire();
104     }
105 
106     @Override
tearDown()107     protected void tearDown() {
108         if (mSensorManager != null) {
109             // SensorManager will check listener and status, so just unregister listener
110             mSensorManager.unregisterListener(mNullSensorEventListener);
111             if (mTriggerSensor != null) {
112                 mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
113                 mTriggerSensor = null;
114             }
115         }
116 
117         if (mTestSensorManager != null) {
118             mTestSensorManager.unregisterListener();
119             mTestSensorManager = null;
120         }
121 
122         if (mWakeLock != null && mWakeLock.isHeld()) {
123             mWakeLock.release();
124         }
125     }
126 
127     /**
128      * testSensorOperations
129      *
130      * Because we can't know every sensors unit details, so we can't assert
131      * get values with specified values.
132      */
133     @CddTest(requirement = "7.3.1/C-2-1")
testSensorOperations_accelerometer()134     public void testSensorOperations_accelerometer() {
135         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
136         boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
137                 PackageManager.FEATURE_SENSOR_ACCELEROMETER);
138         // accelerometer sensor is optional
139         if (hasAccelerometer) {
140             assertNotNull(sensor);
141             assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
142             assertSensorValues(sensor);
143         } else {
144             assertNull(sensor);
145         }
146     }
147 
testSensorOperations_stepCounter()148     public void testSensorOperations_stepCounter() {
149         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
150         boolean hasStepCounter = getContext().getPackageManager().hasSystemFeature(
151                 PackageManager.FEATURE_SENSOR_STEP_COUNTER);
152         // stepcounter sensor is optional
153         if (hasStepCounter) {
154             assertNotNull(sensor);
155             assertEquals(Sensor.TYPE_STEP_COUNTER, sensor.getType());
156             assertSensorValues(sensor);
157         } else {
158             assertNull(sensor);
159         }
160     }
161 
testSensorOperations_stepDetector()162     public void testSensorOperations_stepDetector() {
163         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
164         boolean hasStepDetector = getContext().getPackageManager().hasSystemFeature(
165                 PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
166         // stepdetector sensor is optional
167         if (hasStepDetector) {
168             assertNotNull(sensor);
169             assertEquals(Sensor.TYPE_STEP_DETECTOR, sensor.getType());
170             assertSensorValues(sensor);
171         } else {
172             assertNull(sensor);
173         }
174     }
175 
testSensorOperations_magneticField()176     public void testSensorOperations_magneticField() {
177         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
178         boolean hasCompass = getContext().getPackageManager().hasSystemFeature(
179                 PackageManager.FEATURE_SENSOR_COMPASS);
180         // compass sensor is optional
181         if (hasCompass) {
182             assertNotNull(sensor);
183             assertEquals(Sensor.TYPE_MAGNETIC_FIELD, sensor.getType());
184             assertSensorValues(sensor);
185         } else {
186             assertNull(sensor);
187         }
188     }
189 
190     @CddTest(requirement = "7.3.4/C-2-1")
testSensorOperations_gyroscope()191     public void testSensorOperations_gyroscope() {
192         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
193         boolean hasGyroscope = getContext().getPackageManager().hasSystemFeature(
194                 PackageManager.FEATURE_SENSOR_GYROSCOPE);
195         // gyroscope sensor is optional
196         if (hasGyroscope) {
197             assertNotNull(sensor);
198             assertEquals(Sensor.TYPE_GYROSCOPE, sensor.getType());
199             assertSensorValues(sensor);
200         } else {
201             assertNull(sensor);
202         }
203     }
204 
testSensorOperations_pressure()205     public void testSensorOperations_pressure() {
206         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
207         boolean hasPressure = getContext().getPackageManager().hasSystemFeature(
208                 PackageManager.FEATURE_SENSOR_BAROMETER);
209         // pressure sensor is optional
210         if (hasPressure) {
211             assertNotNull(sensor);
212             assertEquals(Sensor.TYPE_PRESSURE, sensor.getType());
213             assertSensorValues(sensor);
214         } else {
215             assertNull(sensor);
216         }
217     }
218 
219     @SuppressWarnings("deprecation")
testSensorOperations_orientation()220     public void testSensorOperations_orientation() {
221         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
222         // Note: orientation sensor is deprecated.
223         if (sensor != null) {
224             assertEquals(Sensor.TYPE_ORIENTATION, sensor.getType());
225             assertSensorValues(sensor);
226         }
227     }
228 
229     @SuppressWarnings("deprecation")
testSensorOperations_temperature()230     public void testSensorOperations_temperature() {
231         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE);
232         // temperature sensor is optional
233         if (sensor != null) {
234             assertEquals(Sensor.TYPE_TEMPERATURE, sensor.getType());
235             assertSensorValues(sensor);
236         }
237     }
238 
testSensorOperations_hingeAngle()239     public void testSensorOperations_hingeAngle() {
240         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE);
241         boolean hasHingeAngle = getContext().getPackageManager().hasSystemFeature(
242                 PackageManager.FEATURE_SENSOR_HINGE_ANGLE);
243 
244         if (hasHingeAngle) {
245             assertNotNull(sensor);
246             assertEquals(Sensor.TYPE_HINGE_ANGLE, sensor.getType());
247             assertSensorValues(sensor);
248             assertTrue("Max range must not be larger than 360. Range=" + sensor.getMaximumRange()
249                 + " " + sensor.getName(), sensor.getMaximumRange() <= 360);
250         } else {
251             assertNull(sensor);
252         }
253     }
254 
255     @CddTest(requirement = "7.3.1/C-3-1")
testSensorOperations_accelerometerLimitedAxes()256     public void testSensorOperations_accelerometerLimitedAxes() {
257         validateLimitedAxesImuSensorType(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES,
258                 PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES);
259     }
260 
testSensorOperations_gyroscopeLimitedAxes()261     public void testSensorOperations_gyroscopeLimitedAxes() {
262         validateLimitedAxesImuSensorType(Sensor.TYPE_GYROSCOPE_LIMITED_AXES,
263                 PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES);
264     }
265 
266     @CddTest(requirement = "7.3.4/C-3-1")
testSensorOperations_accelerometerLimitedAxesUncalibrated()267     public void testSensorOperations_accelerometerLimitedAxesUncalibrated() {
268         validateLimitedAxesImuSensorType(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED,
269                 PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED);
270     }
271 
testSensorOperations_gyroscopeLimitedAxesUncalibrated()272     public void testSensorOperations_gyroscopeLimitedAxesUncalibrated() {
273         validateLimitedAxesImuSensorType(Sensor.TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED,
274                 PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES_UNCALIBRATED);
275     }
276 
validateLimitedAxesImuSensorType(int sensorType, String systemFeature)277     private void validateLimitedAxesImuSensorType(int sensorType, String systemFeature) {
278         Sensor sensor = mSensorManager.getDefaultSensor(sensorType);
279         boolean hasSensorFeature = getContext().getPackageManager().hasSystemFeature(systemFeature);
280         if (hasSensorFeature) {
281             assertNotNull(sensor);
282             assertEquals(sensorType, sensor.getType());
283             assertSensorValues(sensor);
284         } else {
285             assertNull(sensor);
286         }
287     }
288 
testSensorOperations_heading()289     public void testSensorOperations_heading() {
290         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEADING);
291         boolean hasHeadingSensor = getContext().getPackageManager().hasSystemFeature(
292                 PackageManager.FEATURE_SENSOR_HEADING);
293         boolean isAutomotive = mContext.getPackageManager().hasSystemFeature(
294                 PackageManager.FEATURE_AUTOMOTIVE);
295         if (isAutomotive && hasHeadingSensor) {
296             assertNotNull(sensor);
297             assertEquals(Sensor.TYPE_HEADING, sensor.getType());
298             assertSensorValues(sensor);
299             assertTrue("Max range must not be greater or equal to 360. Range="
300                     + sensor.getMaximumRange() + " " + sensor.getName(),
301                     sensor.getMaximumRange() < 360);
302         } else if (isAutomotive) {
303             assertNull(sensor);
304         } else {
305             // There isn't good test coverage for heading, particularly for non-automotive devices.
306             // So if a non-automotive device wants to implement this, requirements for the sensor
307             // and how to test for those requirements should be re-discussed.
308             assertNull("If the heading sensor is being implemented on a non-automotive device, "
309                     + "the team would love to hear from you. Please reach out!", sensor);
310         }
311     }
312 
313     @AppModeFull(reason = "Instant apps cannot access body sensors")
testBodySensorOperations()314     public void testBodySensorOperations() {
315         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
316         boolean hasHeartRate = getContext().getPackageManager().hasSystemFeature(
317                 PackageManager.FEATURE_SENSOR_HEART_RATE);
318         // heartrate sensor is optional
319         if (hasHeartRate) {
320             assertEquals(Sensor.TYPE_HEART_RATE, sensor.getType());
321             assertSensorValues(sensor);
322         } else {
323             assertNull(sensor);
324         }
325     }
326 
assertAllSensorsNameUniqueness()327     private void assertAllSensorsNameUniqueness() {
328         Multimap<Integer, String> sensorTypeNameMap = ArrayListMultimap.create();
329 
330         for (Sensor sensor : mSensorList) {
331             assertFalse("Duplicate sensor name " + sensor.getName() + " for type " + sensor.getType(),
332                         sensorTypeNameMap.containsEntry(sensor.getType(), sensor.getName()));
333             sensorTypeNameMap.put(sensor.getType(), sensor.getName());
334         }
335     }
336 
testValuesForAllSensors()337     public void testValuesForAllSensors() {
338         for (Sensor sensor : mSensorList) {
339             assertSensorValues(sensor);
340         }
341         assertAllSensorsNameUniqueness();
342     }
343 
hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors)344     private void hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors) {
345         if (sensors == null || sensors.isEmpty()) return;
346         if (sensors.size() > 1) {
347             fail("More than one " + sensors.get(0).getName() + " defined.");
348             return;
349         }
350         assertTrue(sensors.get(0).getName() + " defined as non-wake-up sensor",
351                 sensors.get(0).isWakeUpSensor());
352     }
353 
hasDefaultWakeupSensorOrEmpty(int sensorType, String sensorName)354     private void hasDefaultWakeupSensorOrEmpty(int sensorType, String sensorName) {
355         Sensor sensor = mSensorManager.getDefaultSensor(sensorType);
356         if (sensor == null) return;
357 
358         assertTrue("Default " + sensorName + " sensor is not a wake-up sensor", sensor.isWakeUpSensor());
359     }
360 
361     // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
362     // default. Check if the wake-up flag is set correctly.
363     @Presubmit
testWakeUpFlags()364     public void testWakeUpFlags() {
365         final int TYPE_WAKE_GESTURE = 23;
366         final int TYPE_GLANCE_GESTURE = 24;
367         final int TYPE_PICK_UP_GESTURE = 25;
368 
369         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_SIGNIFICANT_MOTION));
370         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_WAKE_GESTURE));
371         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
372         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));
373 
374         hasDefaultWakeupSensorOrEmpty(Sensor.TYPE_PROXIMITY, "proximity");
375         hasDefaultWakeupSensorOrEmpty(Sensor.TYPE_HINGE_ANGLE, "hinge");
376     }
377 
testGetDefaultSensorWithWakeUpFlag()378     public void testGetDefaultSensorWithWakeUpFlag() {
379         // With wake-up flags set to false, the sensor returned should be a non wake-up sensor.
380         for (Sensor sensor : mSensorList) {
381             Sensor curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), false);
382             if (curr_sensor != null) {
383                 assertFalse("getDefaultSensor wakeup=false returns a wake-up sensor" +
384                         curr_sensor.getName(),
385                         curr_sensor.isWakeUpSensor());
386             }
387 
388             curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), true);
389             if (curr_sensor != null) {
390                 assertTrue("getDefaultSensor wake-up returns non wake sensor" +
391                         curr_sensor.getName(),
392                         curr_sensor.isWakeUpSensor());
393             }
394         }
395     }
396 
397     @Presubmit
testSensorStringTypes()398     public void testSensorStringTypes() {
399         for (Sensor sensor : mSensorList) {
400             if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE &&
401                     !sensor.getStringType().startsWith("android.sensor.")) {
402                 fail("StringType not set correctly for android defined sensor " +
403                         sensor.getName() + " " + sensor.getStringType());
404             }
405         }
406     }
407 
testRequestTriggerWithNonTriggerSensor()408     public void testRequestTriggerWithNonTriggerSensor() {
409         mTriggerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
410         if (mTriggerSensor == null) {
411             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
412         }
413         boolean  result =
414             mSensorManager.requestTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
415         assertFalse(result);
416     }
417 
testCancelTriggerWithNonTriggerSensor()418     public void testCancelTriggerWithNonTriggerSensor() {
419         mTriggerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
420         if (mTriggerSensor == null) {
421             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
422         }
423         boolean result =
424             mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
425         assertFalse(result);
426     }
427 
testRegisterWithTriggerSensor()428     public void testRegisterWithTriggerSensor() {
429         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
430         if (sensor == null) {
431             throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
432         }
433         boolean result = mSensorManager.registerListener(
434                 mNullSensorEventListener,
435                 sensor,
436                 SensorManager.SENSOR_DELAY_NORMAL);
437         assertFalse(result);
438     }
439 
testRegisterTwiceWithSameSensor()440     public void testRegisterTwiceWithSameSensor() {
441         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
442         if (sensor == null) {
443             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
444         }
445 
446         boolean result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
447                 SensorManager.SENSOR_DELAY_NORMAL);
448         assertTrue(result);
449 
450         result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
451                 SensorManager.SENSOR_DELAY_NORMAL);
452         assertFalse(result);
453     }
454 
455     /**
456      * Verifies that if the UID is idle the continuous events are being reported
457      * but sanitized - all events are the same as the first one delivered except
458      * for their timestamps. From the point of view of an idle app these events are
459      * being properly generated but the sensor reading does not change - privacy.
460      */
461     // TODO: remove when parametrized tests are supported and EventTimestampSynchronization
testSanitizedContinuousEventsUidIdle()462     public void testSanitizedContinuousEventsUidIdle() throws Exception {
463         ArrayList<Throwable> errorsFound = new ArrayList<>();
464         for (Sensor sensor : mAndroidSensorList) {
465             // If the UID is active no sanitization should be performed
466             verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
467                     5 /* duration */, TimeUnit.SECONDS, "continuous event",
468                     false /* sanitized */, errorsFound);
469             verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
470                     5 /* duration */, TimeUnit.SECONDS, "continuous event",
471                     false /* sanitized */, errorsFound);
472 
473             // If the UID is idle sanitization should be performed
474 
475             SensorCtsHelper.makeMyPackageIdle();
476             try {
477                 verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
478                         5 /* duration */, TimeUnit.SECONDS, "continuous event",
479                         true /* sanitized */, errorsFound);
480                 verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
481                         5 /* duration */, TimeUnit.SECONDS, "continuous event",
482                         true /* sanitized */, errorsFound);
483             } finally {
484                 SensorCtsHelper.makeMyPackageActive();
485             }
486 
487             // If the UID is active no sanitization should be performed
488             verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
489                     5 /* duration */, TimeUnit.SECONDS, "continuous event",
490                     false /* sanitized */, errorsFound);
491             verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
492                     5 /* duration */, TimeUnit.SECONDS, "continuous event",
493                     false /* sanitized */, errorsFound);
494         }
495         assertOnErrors(errorsFound);
496     }
497 
498     // TODO: remove when parametrized tests are supported and EventTimestampSynchronization
499     //       verification is added to default verifications
testSensorTimeStamps()500     public void testSensorTimeStamps() throws Exception {
501         ArrayList<Throwable> errorsFound = new ArrayList<>();
502         for (Sensor sensor : mAndroidSensorList) {
503             // test both continuous and batching mode sensors
504             verifyLongActivation(sensor, 0 /* maxReportLatencyUs */,
505                     20 /* duration */, TimeUnit.SECONDS, "timestamp", false
506                     /* sanitized */, errorsFound);
507             verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10),
508                     20 /* duration */, TimeUnit.SECONDS, "timestamp",
509                     false /* sanitized */, errorsFound);
510         }
511         assertOnErrors(errorsFound);
512     }
513 
514     // TODO: remove when parameterized tests are supported (see SensorBatchingTests.java)
testBatchAndFlush()515     public void testBatchAndFlush() throws Exception {
516         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
517         ArrayList<Throwable> errorsFound = new ArrayList<>();
518         for (Sensor sensor : mAndroidSensorList) {
519             verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound,
520                     false /* flushWhileIdle */);
521         }
522         assertOnErrors(errorsFound);
523     }
524 
525     /**
526      * Verifies that if the UID is idle flush events are reported. Since
527      * these events have no payload with private data they are working as
528      * for a non-idle UID.
529      */
530     // TODO: remove when parametized tests are supported and EventTimestampSynchronization
testBatchAndFlushUidIdle()531     public void testBatchAndFlushUidIdle() throws Exception {
532         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
533         ArrayList<Throwable> errorsFound = new ArrayList<>();
534         for (Sensor sensor : mAndroidSensorList) {
535             verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound,
536                     true /* flushWhileIdle */);
537         }
538         assertOnErrors(errorsFound);
539     }
540 
541     /**
542      * Verifies that sensor events arrive in the given message queue (Handler).
543      */
testBatchAndFlushWithHandler()544     public void testBatchAndFlushWithHandler() throws Exception {
545         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
546         Sensor sensor = null;
547         for (Sensor s : mAndroidSensorList) {
548             if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
549                 sensor = s;
550                 break;
551             }
552         }
553         if (sensor == null) {
554             throw new SensorTestStateNotSupportedException(
555                     "There are no Continuous sensors in the device.");
556         }
557 
558         TestSensorEnvironment environment = new TestSensorEnvironment(
559                 getContext(),
560                 sensor,
561                 SensorManager.SENSOR_DELAY_FASTEST,
562                 (int) TimeUnit.SECONDS.toMicros(5));
563         mTestSensorManager = new TestSensorManager(environment);
564 
565         HandlerThread handlerThread = new HandlerThread("sensorThread");
566         handlerThread.start();
567         Handler handler = new Handler(handlerThread.getLooper());
568         TestSensorEventListener listener = new TestSensorEventListener(environment, handler);
569 
570         CountDownLatch eventLatch = mTestSensorManager.registerListener(listener, 1);
571         listener.waitForEvents(eventLatch, 1, true);
572         CountDownLatch flushLatch = mTestSensorManager.requestFlush();
573         listener.waitForFlushComplete(flushLatch, true);
574         listener.assertEventsReceivedInHandler();
575     }
576 
577     /**
578      *  Explicit testing the SensorManager.registerListener(SensorEventListener, Sensor, int, int).
579      */
testBatchAndFlushUseDefaultHandler()580     public void testBatchAndFlushUseDefaultHandler() throws Exception {
581         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
582         Sensor sensor = null;
583         for (Sensor s : mAndroidSensorList) {
584             if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
585                 sensor = s;
586                 break;
587             }
588         }
589         if (sensor == null) {
590             throw new SensorTestStateNotSupportedException(
591                     "There are no Continuous sensors in the device.");
592         }
593 
594         TestSensorEnvironment environment = new TestSensorEnvironment(
595                 getContext(),
596                 sensor,
597                 SensorManager.SENSOR_DELAY_FASTEST,
598                 (int) TimeUnit.SECONDS.toMicros(5));
599         mTestSensorManager = new TestSensorManager(environment);
600 
601         TestSensorEventListener listener = new TestSensorEventListener(environment, null);
602 
603         // specifyHandler <= false, use the SensorManager API without Handler parameter
604         CountDownLatch eventLatch = mTestSensorManager.registerListener(listener, 1, false);
605         listener.waitForEvents(eventLatch, 1, true);
606         CountDownLatch flushLatch = mTestSensorManager.requestFlush();
607         listener.waitForFlushComplete(flushLatch, true);
608         listener.assertEventsReceivedInHandler();
609     }
610 
611     // TODO: after L release move to SensorBatchingTests and run in all sensors with default
612     //       verifications enabled
testBatchAndFlushWithMultipleSensors()613     public void testBatchAndFlushWithMultipleSensors() throws Exception {
614         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
615         final int maxSensors = 3;
616         final int maxReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(10);
617         List<Sensor> sensorsToTest = new ArrayList<Sensor>();
618         for (Sensor sensor : mAndroidSensorList) {
619             if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
620                 sensorsToTest.add(sensor);
621                 if (sensorsToTest.size()  == maxSensors) break;
622             }
623         }
624         final int numSensorsToTest = sensorsToTest.size();
625         if (numSensorsToTest == 0) {
626             return;
627         }
628 
629         StringBuilder builder = new StringBuilder();
630         ParallelSensorOperation parallelSensorOperation = new ParallelSensorOperation();
631         for (Sensor sensor : sensorsToTest) {
632             TestSensorEnvironment environment = new TestSensorEnvironment(
633                     getContext(),
634                     sensor,
635                     shouldEmulateSensorUnderLoad(),
636                     SensorManager.SENSOR_DELAY_FASTEST,
637                     maxReportLatencyUs);
638             FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */,
639                     false /* flushWhileIdle */);
640             parallelSensorOperation.add(new TestSensorOperation(environment, executor));
641             builder.append(sensor.getName()).append(", ");
642         }
643 
644         Log.i(TAG, "Testing batch/flush for sensors: " + builder);
645         parallelSensorOperation.execute(getCurrentTestNode());
646     }
647 
assertSensorValues(Sensor sensor)648     private void assertSensorValues(Sensor sensor) {
649         assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
650                 + " " + sensor.getName(), sensor.getMaximumRange() >= 0);
651         assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " +
652                 sensor.getName(), sensor.getPower() >= 0);
653 
654         // Only assert sensor resolution is non-zero for official sensor types since that's what's
655         // required by the CDD.
656         if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE) {
657             assertTrue("Max resolution must be non-zero and positive. Resolution=" + sensor.getResolution() +
658                     " " + sensor.getName(), sensor.getResolution() > 0);
659         } else {
660             assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
661                     " " + sensor.getName(), sensor.getResolution() >= 0);
662         }
663 
664         boolean hasHifiSensors = getContext().getPackageManager().hasSystemFeature(
665                 PackageManager.FEATURE_HIFI_SENSORS);
666         if (SensorCtsHelper.hasMaxResolutionRequirement(sensor, hasHifiSensors)) {
667             float maxResolution = SensorCtsHelper.getRequiredMaxResolutionForSensor(sensor);
668             assertTrue("Resolution must be <= " + maxResolution + ". Resolution=" +
669                     sensor.getResolution() + " " + sensor.getName(),
670                     sensor.getResolution() <= maxResolution);
671         }
672 
673         // The minimum resolution requirement was introduced to the CDD in R so
674         // it's only possible to assert compliance for devices that release with
675         // R or later.
676         if (PropertyUtil.getFirstApiLevel() >= VERSION_CODES.R &&
677                 SensorCtsHelper.hasMinResolutionRequirement(sensor)) {
678             float minResolution = SensorCtsHelper.getRequiredMinResolutionForSensor(sensor);
679             assertTrue("Resolution must be >= " + minResolution + ". Resolution =" +
680                     sensor.getResolution() + " " + sensor.getName(),
681                     sensor.getResolution() >= minResolution);
682         }
683 
684         assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
685         assertTrue("Version must be positive version=" + sensor.getVersion() + " " +
686                 sensor.getName(), sensor.getVersion() > 0);
687         int fifoMaxEventCount = sensor.getFifoMaxEventCount();
688         int fifoReservedEventCount = sensor.getFifoReservedEventCount();
689         assertTrue(fifoMaxEventCount >= 0);
690         assertTrue(fifoReservedEventCount >= 0);
691         assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
692         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
693             assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
694                     sensor.getFifoMaxEventCount() == 0);
695             assertTrue("One shot sensors should have zero FIFO Size "  + sensor.getName(),
696                     sensor.getFifoReservedEventCount() == 0);
697         }
698     }
699 
700     @SuppressWarnings("deprecation")
testLegacySensorOperations()701     public void testLegacySensorOperations() {
702         final SensorManager mSensorManager =
703                 (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
704 
705         // We expect the set of sensors reported by the new and legacy APIs to be consistent.
706         int sensors = 0;
707         if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
708             sensors |= SensorManager.SENSOR_ACCELEROMETER;
709         }
710         if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
711             sensors |= SensorManager.SENSOR_MAGNETIC_FIELD;
712         }
713         if (mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION) != null) {
714             sensors |= SensorManager.SENSOR_ORIENTATION | SensorManager.SENSOR_ORIENTATION_RAW;
715         }
716         assertEquals(sensors, mSensorManager.getSensors());
717     }
718 
719     /**
720      * Verifies that a continuous sensor produces events that have timestamps synchronized with
721      * {@link SystemClock#elapsedRealtimeNanos()} and that the events are sanitized/non-sanitized.
722      */
verifyLongActivation( Sensor sensor, int maxReportLatencyUs, long duration, TimeUnit durationTimeUnit, String testType, boolean sanitized, ArrayList<Throwable> errorsFound)723     private void verifyLongActivation(
724             Sensor sensor,
725             int maxReportLatencyUs,
726             long duration,
727             TimeUnit durationTimeUnit,
728             String testType,
729             boolean sanitized,
730             ArrayList<Throwable> errorsFound) throws InterruptedException {
731         if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
732             return;
733         }
734 
735         try {
736             TestSensorEnvironment environment = new TestSensorEnvironment(
737                     getContext(),
738                     sensor,
739                     shouldEmulateSensorUnderLoad(),
740                     SensorManager.SENSOR_DELAY_FASTEST,
741                     maxReportLatencyUs);
742             TestSensorOperation operation = TestSensorOperation.createOperation(
743                     environment, duration, durationTimeUnit);
744             if (sanitized) {
745                 final long verificationDelayNano = TimeUnit.NANOSECONDS.convert(
746                         maxReportLatencyUs, TimeUnit.MICROSECONDS) * 2;
747                 operation.addVerification(ContinuousEventSanitizedVerification
748                         .getDefault(environment, verificationDelayNano));
749             } else {
750                 operation.addVerification(EventGapVerification.getDefault(environment));
751                 operation.addVerification(EventOrderingVerification.getDefault(environment));
752                 operation.addVerification(EventTimestampSynchronizationVerification
753                         .getDefault(environment));
754             }
755             Log.i(TAG, "Running " + testType + " test on: " + sensor.getName());
756             operation.execute(getCurrentTestNode());
757         } catch (InterruptedException e) {
758             // propagate so the test can stop
759             throw e;
760         } catch (Throwable e) {
761             errorsFound.add(e);
762             Log.e(TAG, e.getMessage());
763         }
764     }
765 
766     /**
767      * Verifies that a client can listen for events, and that
768      * {@link SensorManager#flush(SensorEventListener)} will trigger the appropriate notification
769      * for {@link SensorEventListener2#onFlushCompleted(Sensor)}.
770      */
verifyRegisterListenerCallFlush( Sensor sensor, Handler handler, ArrayList<Throwable> errorsFound, boolean flushWhileIdle)771     private void verifyRegisterListenerCallFlush(
772             Sensor sensor,
773             Handler handler,
774             ArrayList<Throwable> errorsFound,
775             boolean flushWhileIdle)
776             throws InterruptedException {
777         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
778             return;
779         }
780 
781         try {
782             TestSensorEnvironment environment = new TestSensorEnvironment(
783                     getContext(),
784                     sensor,
785                     shouldEmulateSensorUnderLoad(),
786                     SensorManager.SENSOR_DELAY_FASTEST,
787                     (int) TimeUnit.SECONDS.toMicros(10));
788             FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */,
789                     flushWhileIdle);
790             TestSensorOperation operation = new TestSensorOperation(environment, executor, handler);
791 
792             Log.i(TAG, "Running flush test on: " + sensor.getName());
793             operation.execute(getCurrentTestNode());
794         } catch (InterruptedException e) {
795             // propagate so the test can stop
796             throw e;
797         } catch (Throwable e) {
798             errorsFound.add(e);
799             Log.e(TAG, e.getMessage());
800         }
801     }
802 
assertOnErrors(List<Throwable> errorsFound)803     private void assertOnErrors(List<Throwable> errorsFound) {
804         if (!errorsFound.isEmpty()) {
805             StringBuilder builder = new StringBuilder();
806             for (Throwable error : errorsFound) {
807                 builder.append(error.getMessage()).append("\n");
808             }
809             Assert.fail(builder.toString());
810         }
811     }
812 
813     /**
814      * A delegate that drives the execution of Batch/Flush tests.
815      * It performs several operations in order:
816      * - registration
817      * - for continuous sensors it first ensures that the FIFO is filled
818      *      - if events do not arrive on time, an assert will be triggered
819      * - requests flush of sensor data
820      * - waits for {@link SensorEventListener2#onFlushCompleted(Sensor)}
821      *      - if the event does not arrive, an assert will be triggered
822      */
823     private class FlushExecutor implements TestSensorOperation.Executor {
824         private final TestSensorEnvironment mEnvironment;
825         private final int mEventCount;
826         private final boolean mFlushWhileIdle;
827 
FlushExecutor(TestSensorEnvironment environment, int eventCount, boolean flushWhileIdle)828         public FlushExecutor(TestSensorEnvironment environment, int eventCount,
829                 boolean flushWhileIdle) {
830             mEnvironment = environment;
831             mEventCount = eventCount;
832             mFlushWhileIdle = flushWhileIdle;
833         }
834 
835         /**
836          * Consider only continuous mode sensors for testing register listener.
837          *
838          * For on-change sensors, we only use
839          * {@link TestSensorManager#registerListener(TestSensorEventListener)} to associate the
840          * listener with the sensor. So that {@link TestSensorManager#requestFlush()} can be
841          * invoked on it.
842          */
843         @Override
execute(TestSensorManager sensorManager, TestSensorEventListener listener)844         public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
845                 throws Exception {
846             int sensorReportingMode = mEnvironment.getSensor().getReportingMode();
847             try {
848                 CountDownLatch eventLatch = sensorManager.registerListener(listener, mEventCount);
849                 if (sensorReportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
850                     listener.waitForEvents(eventLatch, mEventCount, true);
851                 }
852                 if (mFlushWhileIdle) {
853                     SensorCtsHelper.makeMyPackageIdle();
854                     sensorManager.assertFlushFail();
855                 } else {
856                     CountDownLatch flushLatch = sensorManager.requestFlush();
857                     listener.waitForFlushComplete(flushLatch, true);
858                 }
859             } finally {
860                 sensorManager.unregisterListener();
861                 if (mFlushWhileIdle) {
862                     SensorCtsHelper.makeMyPackageActive();
863                 }
864             }
865         }
866     }
867 
868     private class NullTriggerEventListener extends TriggerEventListener {
869         @Override
onTrigger(TriggerEvent event)870         public void onTrigger(TriggerEvent event) {}
871     }
872 
873     private class NullSensorEventListener implements SensorEventListener {
874         @Override
onSensorChanged(SensorEvent event)875         public void onSensorChanged(SensorEvent event) {}
876 
877         @Override
onAccuracyChanged(Sensor sensor, int accuracy)878         public void onAccuracyChanged(Sensor sensor, int accuracy) {}
879     }
880 
881 }
882