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