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 com.android.cts.util.TimeoutReq;
20 
21 import junit.framework.Assert;
22 
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.hardware.Sensor;
26 import android.hardware.SensorEvent;
27 import android.hardware.SensorEventListener;
28 import android.hardware.SensorEventListener2;
29 import android.hardware.SensorManager;
30 import android.hardware.TriggerEvent;
31 import android.hardware.TriggerEventListener;
32 import android.hardware.cts.helpers.SensorCtsHelper;
33 import android.hardware.cts.helpers.SensorNotSupportedException;
34 import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
35 import android.hardware.cts.helpers.TestSensorEnvironment;
36 import android.hardware.cts.helpers.TestSensorEventListener;
37 import android.hardware.cts.helpers.TestSensorManager;
38 import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
39 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
40 import android.hardware.cts.helpers.sensorverification.EventGapVerification;
41 import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
42 import android.hardware.cts.helpers.sensorverification.EventTimestampSynchronizationVerification;
43 import android.os.Handler;
44 import android.os.HandlerThread;
45 import android.os.PowerManager;
46 import android.os.SystemClock;
47 import android.util.Log;
48 
49 import java.util.ArrayList;
50 import java.util.List;
51 import java.util.Random;
52 import java.util.concurrent.CountDownLatch;
53 import java.util.concurrent.TimeUnit;
54 
55 public class SensorTest extends SensorTestCase {
56     private static final String TAG = "SensorTest";
57 
58     // Test only SDK defined sensors. Any sensors with type > 100 are ignored.
59     private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;
60 
61     private PowerManager.WakeLock mWakeLock;
62     private SensorManager mSensorManager;
63     private TestSensorManager mTestSensorManager;
64     private NullTriggerEventListener mNullTriggerEventListener;
65     private NullSensorEventListener mNullSensorEventListener;
66     private Sensor mTriggerSensor;
67     private List<Sensor> mSensorList;
68 
69     @Override
setUp()70     protected void setUp() throws Exception {
71         Context context = getContext();
72         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
73         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
74 
75         mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
76         mNullTriggerEventListener = new NullTriggerEventListener();
77         mNullSensorEventListener = new NullSensorEventListener();
78 
79         mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
80         assertNotNull("SensorList was null.", mSensorList);
81         if (mSensorList.isEmpty()) {
82             // several devices will not have sensors, so we need to skip the tests in those cases
83             throw new SensorTestStateNotSupportedException(
84                     "Sensors are not available in the system.");
85         }
86 
87         mWakeLock.acquire();
88     }
89 
90     @Override
tearDown()91     protected void tearDown(){
92         if (mSensorManager != null) {
93             // SensorManager will check listener and status, so just unregister listener
94             mSensorManager.unregisterListener(mNullSensorEventListener);
95             if (mTriggerSensor != null) {
96                 mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
97                 mTriggerSensor = null;
98             }
99         }
100 
101         if (mTestSensorManager != null) {
102             mTestSensorManager.unregisterListener();
103             mTestSensorManager = null;
104         }
105 
106         if (mWakeLock != null && mWakeLock.isHeld()) {
107             mWakeLock.release();
108         }
109     }
110 
111     @SuppressWarnings("deprecation")
testSensorOperations()112     public void testSensorOperations() {
113         // Because we can't know every sensors unit details, so we can't assert
114         // get values with specified values.
115         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
116         boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
117                 PackageManager.FEATURE_SENSOR_ACCELEROMETER);
118         // accelerometer sensor is optional
119         if (hasAccelerometer) {
120             assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
121             assertSensorValues(sensor);
122         } else {
123             assertNull(sensor);
124         }
125 
126         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
127         boolean hasStepCounter = getContext().getPackageManager().hasSystemFeature(
128                 PackageManager.FEATURE_SENSOR_STEP_COUNTER);
129         // stepcounter sensor is optional
130         if (hasStepCounter) {
131             assertEquals(Sensor.TYPE_STEP_COUNTER, sensor.getType());
132             assertSensorValues(sensor);
133         } else {
134             assertNull(sensor);
135         }
136 
137         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
138         boolean hasStepDetector = getContext().getPackageManager().hasSystemFeature(
139                 PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
140         // stepdetector sensor is optional
141         if (hasStepDetector) {
142             assertEquals(Sensor.TYPE_STEP_DETECTOR, sensor.getType());
143             assertSensorValues(sensor);
144         } else {
145             assertNull(sensor);
146         }
147 
148         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
149         boolean hasHeartRate = getContext().getPackageManager().hasSystemFeature(
150                 PackageManager.FEATURE_SENSOR_HEART_RATE);
151         // heartrate sensor is optional
152         if (hasHeartRate) {
153             assertEquals(Sensor.TYPE_HEART_RATE, sensor.getType());
154             assertSensorValues(sensor);
155         } else {
156             assertNull(sensor);
157         }
158 
159         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
160         boolean hasCompass = getContext().getPackageManager().hasSystemFeature(
161                 PackageManager.FEATURE_SENSOR_COMPASS);
162         // compass sensor is optional
163         if (hasCompass) {
164             assertEquals(Sensor.TYPE_MAGNETIC_FIELD, sensor.getType());
165             assertSensorValues(sensor);
166         } else {
167             assertNull(sensor);
168         }
169 
170         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
171         // orientation sensor is required if the device can physically implement it
172         if (hasCompass && hasAccelerometer) {
173             assertEquals(Sensor.TYPE_ORIENTATION, sensor.getType());
174             assertSensorValues(sensor);
175         }
176 
177         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE);
178         // temperature sensor is optional
179         if (sensor != null) {
180             assertEquals(Sensor.TYPE_TEMPERATURE, sensor.getType());
181             assertSensorValues(sensor);
182         }
183     }
184 
testValuesForAllSensors()185     public void testValuesForAllSensors() {
186         for (Sensor sensor : mSensorList) {
187             assertSensorValues(sensor);
188         }
189     }
190 
hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors)191     private void hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors) {
192         if (sensors == null || sensors.isEmpty()) return;
193         if (sensors.size() > 1) {
194             fail("More than one " + sensors.get(0).getName() + " defined.");
195             return;
196         }
197         assertTrue(sensors.get(0).getName() + " defined as non-wake-up sensor",
198                 sensors.get(0).isWakeUpSensor());
199     }
200 
201     // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
202     // default. Check if the wake-up flag is set correctly.
testWakeUpFlags()203     public void testWakeUpFlags() {
204         final int TYPE_WAKE_GESTURE = 23;
205         final int TYPE_GLANCE_GESTURE = 24;
206         final int TYPE_PICK_UP_GESTURE = 25;
207 
208         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_SIGNIFICANT_MOTION));
209         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_WAKE_GESTURE));
210         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
211         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));
212 
213         List<Sensor> proximity_sensors = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY);
214         if (proximity_sensors.isEmpty()) return;
215         boolean hasWakeUpProximitySensor = false;
216         for (Sensor sensor : proximity_sensors) {
217             if (sensor.isWakeUpSensor()) {
218                 hasWakeUpProximitySensor = true;
219                 break;
220             }
221         }
222         assertTrue("No wake-up proximity sensors implemented", hasWakeUpProximitySensor);
223     }
224 
testGetDefaultSensorWithWakeUpFlag()225     public void testGetDefaultSensorWithWakeUpFlag() {
226         // With wake-up flags set to false, the sensor returned should be a non wake-up sensor.
227         for (Sensor sensor : mSensorList) {
228             Sensor curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), false);
229             if (curr_sensor != null) {
230                 assertFalse("getDefaultSensor wakeup=false returns a wake-up sensor" +
231                         curr_sensor.getName(),
232                         curr_sensor.isWakeUpSensor());
233             }
234 
235             curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), true);
236             if (curr_sensor != null) {
237                 assertTrue("getDefaultSensor wake-up returns non wake sensor" +
238                         curr_sensor.getName(),
239                         curr_sensor.isWakeUpSensor());
240             }
241         }
242     }
243 
testSensorStringTypes()244     public void testSensorStringTypes() {
245         for (Sensor sensor : mSensorList) {
246             if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE &&
247                     !sensor.getStringType().startsWith("android.sensor.")) {
248                 fail("StringType not set correctly for android defined sensor " +
249                         sensor.getName() + " " + sensor.getStringType());
250             }
251         }
252     }
253 
testRequestTriggerWithNonTriggerSensor()254     public void testRequestTriggerWithNonTriggerSensor() {
255         mTriggerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
256         if (mTriggerSensor == null) {
257             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
258         }
259         boolean  result = mSensorManager.requestTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
260         assertFalse(result);
261     }
262 
testCancelTriggerWithNonTriggerSensor()263     public void testCancelTriggerWithNonTriggerSensor() {
264         mTriggerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
265         if (mTriggerSensor == null) {
266             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
267         }
268         boolean result = mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, mTriggerSensor);
269         assertFalse(result);
270     }
271 
testRegisterWithTriggerSensor()272     public void testRegisterWithTriggerSensor() {
273         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
274         if (sensor == null) {
275             throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
276         }
277         boolean result = mSensorManager.registerListener(
278                 mNullSensorEventListener,
279                 sensor,
280                 SensorManager.SENSOR_DELAY_NORMAL);
281         assertFalse(result);
282     }
283 
testRegisterTwiceWithSameSensor()284     public void testRegisterTwiceWithSameSensor() {
285         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
286         if (sensor == null) {
287             throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
288         }
289 
290         boolean result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
291                 SensorManager.SENSOR_DELAY_NORMAL);
292         assertTrue(result);
293 
294         result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
295                 SensorManager.SENSOR_DELAY_NORMAL);
296         assertFalse(result);
297     }
298 
299     // TODO: remove when parametized tests are supported and EventTimestampSynchronization
300     //       verification is added to default verifications
301     @TimeoutReq(minutes=60)
testSensorTimeStamps()302     public void testSensorTimeStamps() throws Exception {
303         ArrayList<Throwable> errorsFound = new ArrayList<>();
304         for (Sensor sensor : mSensorList) {
305             // test both continuous and batching mode sensors
306             verifyLongActivation(sensor, 0 /* maxReportLatencyUs */, errorsFound);
307             verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10), errorsFound);
308         }
309         assertOnErrors(errorsFound);
310     }
311 
312     // TODO: remove when parameterized tests are supported (see SensorBatchingTests.java)
313     @TimeoutReq(minutes=20)
testBatchAndFlush()314     public void testBatchAndFlush() throws Exception {
315         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
316         ArrayList<Throwable> errorsFound = new ArrayList<>();
317         for (Sensor sensor : mSensorList) {
318             verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound);
319         }
320         assertOnErrors(errorsFound);
321     }
322 
323     /**
324      * Verifies that sensor events arrive in the given message queue (Handler).
325      */
326     @TimeoutReq(minutes=10)
testBatchAndFlushWithHandler()327     public void testBatchAndFlushWithHandler() throws Exception {
328         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
329         Sensor sensor = null;
330         for (Sensor s : mSensorList) {
331             if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
332                 sensor = s;
333                 break;
334             }
335         }
336         if (sensor == null) {
337             throw new SensorTestStateNotSupportedException(
338                     "There are no Continuous sensors in the device.");
339         }
340 
341         TestSensorEnvironment environment = new TestSensorEnvironment(
342                 getContext(),
343                 sensor,
344                 SensorManager.SENSOR_DELAY_FASTEST,
345                 (int) TimeUnit.SECONDS.toMicros(5));
346         mTestSensorManager = new TestSensorManager(environment);
347 
348         HandlerThread handlerThread = new HandlerThread("sensorThread");
349         handlerThread.start();
350         Handler handler = new Handler(handlerThread.getLooper());
351         TestSensorEventListener listener = new TestSensorEventListener(environment, handler);
352 
353         CountDownLatch eventLatch = mTestSensorManager.registerListener(listener, 1);
354         listener.waitForEvents(eventLatch, 1, true);
355         CountDownLatch flushLatch = mTestSensorManager.requestFlush();
356         listener.waitForFlushComplete(flushLatch, true);
357         listener.assertEventsReceivedInHandler();
358     }
359 
360     /**
361      *  Explicit testing the SensorManager.registerListener(SensorEventListener, Sensor, int, int).
362      */
363     @TimeoutReq(minutes=10)
testBatchAndFlushUseDefaultHandler()364     public void testBatchAndFlushUseDefaultHandler() throws Exception {
365         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
366         Sensor sensor = null;
367         for (Sensor s : mSensorList) {
368             if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
369                 sensor = s;
370                 break;
371             }
372         }
373         if (sensor == null) {
374             throw new SensorTestStateNotSupportedException(
375                     "There are no Continuous sensors in the device.");
376         }
377 
378         TestSensorEnvironment environment = new TestSensorEnvironment(
379                 getContext(),
380                 sensor,
381                 SensorManager.SENSOR_DELAY_FASTEST,
382                 (int) TimeUnit.SECONDS.toMicros(5));
383         mTestSensorManager = new TestSensorManager(environment);
384 
385         TestSensorEventListener listener = new TestSensorEventListener(environment, null);
386 
387         // specifyHandler <= false, use the SensorManager API without Handler parameter
388         CountDownLatch eventLatch = mTestSensorManager.registerListener(listener, 1, false);
389         listener.waitForEvents(eventLatch, 1, true);
390         CountDownLatch flushLatch = mTestSensorManager.requestFlush();
391         listener.waitForFlushComplete(flushLatch, true);
392         listener.assertEventsReceivedInHandler();
393     }
394 
395     // TODO: after L release move to SensorBatchingTests and run in all sensors with default
396     //       verifications enabled
testBatchAndFlushWithMultipleSensors()397     public void testBatchAndFlushWithMultipleSensors() throws Exception {
398         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
399         final int maxSensors = 3;
400         final int maxReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(10);
401         List<Sensor> sensorsToTest = new ArrayList<Sensor>();
402         for (Sensor sensor : mSensorList) {
403             if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
404                 sensorsToTest.add(sensor);
405                 if (sensorsToTest.size()  == maxSensors) break;
406             }
407         }
408         final int numSensorsToTest = sensorsToTest.size();
409         if (numSensorsToTest == 0) {
410             return;
411         }
412 
413         StringBuilder builder = new StringBuilder();
414         ParallelSensorOperation parallelSensorOperation = new ParallelSensorOperation();
415         for (Sensor sensor : sensorsToTest) {
416             TestSensorEnvironment environment = new TestSensorEnvironment(
417                     getContext(),
418                     sensor,
419                     shouldEmulateSensorUnderLoad(),
420                     SensorManager.SENSOR_DELAY_FASTEST,
421                     maxReportLatencyUs);
422             FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */);
423             parallelSensorOperation.add(new TestSensorOperation(environment, executor));
424             builder.append(sensor.getName()).append(", ");
425         }
426 
427         Log.i(TAG, "Testing batch/flush for sensors: " + builder);
428         parallelSensorOperation.execute(getCurrentTestNode());
429     }
430 
assertSensorValues(Sensor sensor)431     private void assertSensorValues(Sensor sensor) {
432         assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
433                 + " " + sensor.getName(), sensor.getMaximumRange() >= 0);
434         assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " +
435                 sensor.getName(), sensor.getPower() >= 0);
436         assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
437                 " " + sensor.getName(), sensor.getResolution() >= 0);
438         assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
439         assertTrue("Version must be positive version=" + sensor.getVersion() + " " +
440                 sensor.getName(), sensor.getVersion() > 0);
441         int fifoMaxEventCount = sensor.getFifoMaxEventCount();
442         int fifoReservedEventCount = sensor.getFifoReservedEventCount();
443         assertTrue(fifoMaxEventCount >= 0);
444         assertTrue(fifoReservedEventCount >= 0);
445         assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
446         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
447             assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
448                     sensor.getFifoMaxEventCount() == 0);
449             assertTrue("One shot sensors should have zero FIFO Size "  + sensor.getName(),
450                     sensor.getFifoReservedEventCount() == 0);
451         }
452     }
453 
454     @SuppressWarnings("deprecation")
testLegacySensorOperations()455     public void testLegacySensorOperations() {
456         final SensorManager mSensorManager =
457                 (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
458 
459         // We expect the set of sensors reported by the new and legacy APIs to be consistent.
460         int sensors = 0;
461         if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
462             sensors |= SensorManager.SENSOR_ACCELEROMETER;
463         }
464         if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
465             sensors |= SensorManager.SENSOR_MAGNETIC_FIELD;
466         }
467         if (mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION) != null) {
468             sensors |= SensorManager.SENSOR_ORIENTATION | SensorManager.SENSOR_ORIENTATION_RAW;
469         }
470         assertEquals(sensors, mSensorManager.getSensors());
471     }
472 
473     /**
474      * Verifies that a continuous sensor produces events that have timestamps synchronized with
475      * {@link SystemClock#elapsedRealtimeNanos()}.
476      */
verifyLongActivation( Sensor sensor, int maxReportLatencyUs, ArrayList<Throwable> errorsFound)477     private void verifyLongActivation(
478             Sensor sensor,
479             int maxReportLatencyUs,
480             ArrayList<Throwable> errorsFound) throws InterruptedException {
481         if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
482             return;
483         }
484 
485         try {
486             TestSensorEnvironment environment = new TestSensorEnvironment(
487                     getContext(),
488                     sensor,
489                     shouldEmulateSensorUnderLoad(),
490                     SensorManager.SENSOR_DELAY_FASTEST,
491                     maxReportLatencyUs);
492             TestSensorOperation operation =
493                     TestSensorOperation.createOperation(environment, 20, TimeUnit.SECONDS);
494             operation.addVerification(EventGapVerification.getDefault(environment));
495             operation.addVerification(EventOrderingVerification.getDefault(environment));
496             operation.addVerification(
497                     EventTimestampSynchronizationVerification.getDefault(environment));
498 
499             Log.i(TAG, "Running timestamp test on: " + sensor.getName());
500             operation.execute(getCurrentTestNode());
501         } catch (InterruptedException e) {
502             // propagate so the test can stop
503             throw e;
504         } catch (Throwable e) {
505             errorsFound.add(e);
506             Log.e(TAG, e.getMessage());
507         }
508     }
509 
510     /**
511      * Verifies that a client can listen for events, and that
512      * {@link SensorManager#flush(SensorEventListener)} will trigger the appropriate notification
513      * for {@link SensorEventListener2#onFlushCompleted(Sensor)}.
514      */
verifyRegisterListenerCallFlush( Sensor sensor, Handler handler, ArrayList<Throwable> errorsFound)515     private void verifyRegisterListenerCallFlush(
516             Sensor sensor,
517             Handler handler,
518             ArrayList<Throwable> errorsFound)
519             throws InterruptedException {
520         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
521             return;
522         }
523 
524         try {
525             TestSensorEnvironment environment = new TestSensorEnvironment(
526                     getContext(),
527                     sensor,
528                     shouldEmulateSensorUnderLoad(),
529                     SensorManager.SENSOR_DELAY_FASTEST,
530                     (int) TimeUnit.SECONDS.toMicros(10));
531             FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */);
532             TestSensorOperation operation = new TestSensorOperation(environment, executor, handler);
533 
534             Log.i(TAG, "Running flush test on: " + sensor.getName());
535             operation.execute(getCurrentTestNode());
536         } catch (InterruptedException e) {
537             // propagate so the test can stop
538             throw e;
539         } catch (Throwable e) {
540             errorsFound.add(e);
541             Log.e(TAG, e.getMessage());
542         }
543     }
544 
assertOnErrors(List<Throwable> errorsFound)545     private void assertOnErrors(List<Throwable> errorsFound) {
546         if (!errorsFound.isEmpty()) {
547             StringBuilder builder = new StringBuilder();
548             for (Throwable error : errorsFound) {
549                 builder.append(error.getMessage()).append("\n");
550             }
551             Assert.fail(builder.toString());
552         }
553     }
554 
555     /**
556      * A delegate that drives the execution of Batch/Flush tests.
557      * It performs several operations in order:
558      * - registration
559      * - for continuous sensors it first ensures that the FIFO is filled
560      *      - if events do not arrive on time, an assert will be triggered
561      * - requests flush of sensor data
562      * - waits for {@link SensorEventListener2#onFlushCompleted(Sensor)}
563      *      - if the event does not arrive, an assert will be triggered
564      */
565     private class FlushExecutor implements TestSensorOperation.Executor {
566         private final TestSensorEnvironment mEnvironment;
567         private final int mEventCount;
568 
FlushExecutor(TestSensorEnvironment environment, int eventCount)569         public FlushExecutor(TestSensorEnvironment environment, int eventCount) {
570             mEnvironment = environment;
571             mEventCount = eventCount;
572         }
573 
574         /**
575          * Consider only continuous mode sensors for testing register listener.
576          *
577          * For on-change sensors, we only use
578          * {@link TestSensorManager#registerListener(TestSensorEventListener)} to associate the
579          * listener with the sensor. So that {@link TestSensorManager#requestFlush()} can be
580          * invoked on it.
581          */
582         @Override
execute(TestSensorManager sensorManager, TestSensorEventListener listener)583         public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
584                 throws InterruptedException {
585             int sensorReportingMode = mEnvironment.getSensor().getReportingMode();
586             try {
587                 CountDownLatch eventLatch = sensorManager.registerListener(listener, mEventCount);
588                 if (sensorReportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
589                     listener.waitForEvents(eventLatch, mEventCount, true);
590                 }
591                 CountDownLatch flushLatch = sensorManager.requestFlush();
592                 listener.waitForFlushComplete(flushLatch, true);
593             } finally {
594                 sensorManager.unregisterListener();
595             }
596         }
597     }
598 
599     private class NullTriggerEventListener extends TriggerEventListener {
600         @Override
onTrigger(TriggerEvent event)601         public void onTrigger(TriggerEvent event) {}
602     }
603 
604     private class NullSensorEventListener implements SensorEventListener {
605         @Override
onSensorChanged(SensorEvent event)606         public void onSensorChanged(SensorEvent event) {}
607 
608         @Override
onAccuracyChanged(Sensor sensor, int accuracy)609         public void onAccuracyChanged(Sensor sensor, int accuracy) {}
610     }
611 
612 }
613