Home | History | Annotate | Download | only in cts
      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 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.os.Handler;
     31 import android.os.HandlerThread;
     32 import android.os.PowerManager;
     33 import android.os.SystemClock;
     34 import android.util.Log;
     35 
     36 import java.util.List;
     37 import java.util.concurrent.CountDownLatch;
     38 import java.util.concurrent.TimeUnit;
     39 
     40 public class SensorTest extends SensorTestCase {
     41     private SensorManager mSensorManager;
     42     private TriggerListener mTriggerListener;
     43     private SensorListener mSensorListener;
     44     private List<Sensor> mSensorList;
     45     private static final String TAG = "SensorTest";
     46     // Test only SDK defined sensors. Any sensors with type > 100 are ignored.
     47     private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;
     48     private static final long TIMEOUT_TOLERANCE_US = TimeUnit.SECONDS.toMicros(5);
     49     private static final double MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE = 0.9;
     50     private PowerManager.WakeLock mWakeLock;
     51 
     52     @Override
     53     protected void setUp() throws Exception {
     54         super.setUp();
     55         mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
     56         mTriggerListener = new TriggerListener();
     57         mSensorListener = new SensorListener();
     58         mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
     59         PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
     60         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
     61     }
     62 
     63     public void testSensorOperations() {
     64         // Because we can't know every sensors unit details, so we can't assert
     65         // get values with specified values.
     66         List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
     67         assertNotNull(sensors);
     68         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
     69         boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
     70                 PackageManager.FEATURE_SENSOR_ACCELEROMETER);
     71         // accelerometer sensor is optional
     72         if (hasAccelerometer) {
     73             assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
     74             assertSensorValues(sensor);
     75         } else {
     76             assertNull(sensor);
     77         }
     78 
     79         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
     80         boolean hasStepCounter = getContext().getPackageManager().hasSystemFeature(
     81                 PackageManager.FEATURE_SENSOR_STEP_COUNTER);
     82         // stepcounter sensor is optional
     83         if (hasStepCounter) {
     84             assertEquals(Sensor.TYPE_STEP_COUNTER, sensor.getType());
     85             assertSensorValues(sensor);
     86         } else {
     87             assertNull(sensor);
     88         }
     89 
     90         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
     91         boolean hasStepDetector = getContext().getPackageManager().hasSystemFeature(
     92                 PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
     93         // stepdetector sensor is optional
     94         if (hasStepDetector) {
     95             assertEquals(Sensor.TYPE_STEP_DETECTOR, sensor.getType());
     96             assertSensorValues(sensor);
     97         } else {
     98             assertNull(sensor);
     99         }
    100 
    101         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
    102         boolean hasHeartRate = getContext().getPackageManager().hasSystemFeature(
    103                 PackageManager.FEATURE_SENSOR_HEART_RATE);
    104         // heartrate sensor is optional
    105         if (hasHeartRate) {
    106             assertEquals(Sensor.TYPE_HEART_RATE, sensor.getType());
    107             assertSensorValues(sensor);
    108         } else {
    109             assertNull(sensor);
    110         }
    111 
    112         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    113         boolean hasCompass = getContext().getPackageManager().hasSystemFeature(
    114                 PackageManager.FEATURE_SENSOR_COMPASS);
    115         // compass sensor is optional
    116         if (hasCompass) {
    117             assertEquals(Sensor.TYPE_MAGNETIC_FIELD, sensor.getType());
    118             assertSensorValues(sensor);
    119         } else {
    120             assertNull(sensor);
    121         }
    122 
    123         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    124         // orientation sensor is required if the device can physically implement it
    125         if (hasCompass && hasAccelerometer) {
    126             assertEquals(Sensor.TYPE_ORIENTATION, sensor.getType());
    127             assertSensorValues(sensor);
    128         }
    129 
    130         sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE);
    131         // temperature sensor is optional
    132         if (sensor != null) {
    133             assertEquals(Sensor.TYPE_TEMPERATURE, sensor.getType());
    134             assertSensorValues(sensor);
    135         }
    136     }
    137 
    138     public void testValuesForAllSensors() {
    139         for (Sensor sensor : mSensorList) {
    140             assertSensorValues(sensor);
    141         }
    142     }
    143 
    144     private void hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors) {
    145         if (sensors == null || sensors.isEmpty()) return;
    146         if (sensors.size() > 1) {
    147             fail("More than one " + sensors.get(0).getName() + " defined.");
    148             return;
    149         }
    150         assertTrue(sensors.get(0).getName() + " defined as non-wake-up sensor",
    151                 sensors.get(0).isWakeUpSensor());
    152         return;
    153     }
    154 
    155     // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
    156     // default. Check if the wake-up flag is set correctly.
    157     public void testWakeUpFlags() {
    158         final int TYPE_WAKE_GESTURE = 23;
    159         final int TYPE_GLANCE_GESTURE = 24;
    160         final int TYPE_PICK_UP_GESTURE = 25;
    161 
    162         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_SIGNIFICANT_MOTION));
    163         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_WAKE_GESTURE));
    164         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
    165         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));
    166 
    167         List<Sensor> proximity_sensors = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY);
    168         if (proximity_sensors.isEmpty()) return;
    169         boolean hasWakeUpProximitySensor = false;
    170         for (Sensor sensor : proximity_sensors) {
    171             if (sensor.isWakeUpSensor()) {
    172                 hasWakeUpProximitySensor = true;
    173                 break;
    174             }
    175         }
    176         assertTrue("No wake-up proximity sensors implemented", hasWakeUpProximitySensor);
    177     }
    178 
    179     public void testGetDefaultSensorWithWakeUpFlag() {
    180         // With wake-up flags set to false, the sensor returned should be a non wake-up sensor.
    181         for (Sensor sensor : mSensorList) {
    182             Sensor curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), false);
    183             if (curr_sensor != null) {
    184                 assertFalse("getDefaultSensor wakeup=false returns a wake-up sensor" +
    185                         curr_sensor.getName(),
    186                         curr_sensor.isWakeUpSensor());
    187             }
    188 
    189             curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), true);
    190             if (curr_sensor != null) {
    191                 assertTrue("getDefaultSensor wake-up returns non wake sensor" +
    192                         curr_sensor.getName(),
    193                         curr_sensor.isWakeUpSensor());
    194             }
    195         }
    196     }
    197 
    198     public void testSensorStringTypes() {
    199         for (Sensor sensor : mSensorList) {
    200             if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE &&
    201                     !sensor.getStringType().startsWith("android.sensor.")) {
    202                 fail("StringType not set correctly for android defined sensor " +
    203                         sensor.getName() + " " + sensor.getStringType());
    204             }
    205         }
    206     }
    207 
    208     public void testRequestTriggerWithNonTriggerSensor() {
    209         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    210         boolean result;
    211         if (sensor != null) {
    212             result = mSensorManager.requestTriggerSensor(mTriggerListener, sensor);
    213             assertFalse(result);
    214         }
    215     }
    216 
    217     public void testCancelTriggerWithNonTriggerSensor() {
    218         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    219         boolean result;
    220         if (sensor != null) {
    221             result = mSensorManager.cancelTriggerSensor(mTriggerListener, sensor);
    222             assertFalse(result);
    223         }
    224     }
    225 
    226     public void testRegisterWithTriggerSensor() {
    227         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
    228         boolean result;
    229         if (sensor != null) {
    230             result = mSensorManager.registerListener(mSensorListener, sensor,
    231                     SensorManager.SENSOR_DELAY_NORMAL);
    232             assertFalse(result);
    233         }
    234     }
    235 
    236     public void testRegisterTwiceWithSameSensor() {
    237         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    238         boolean result;
    239         if (sensor != null) {
    240             result = mSensorManager.registerListener(mSensorListener, sensor,
    241                     SensorManager.SENSOR_DELAY_NORMAL);
    242             assertTrue(result);
    243             result = mSensorManager.registerListener(mSensorListener, sensor,
    244                     SensorManager.SENSOR_DELAY_NORMAL);
    245             assertFalse(result);
    246         }
    247     }
    248 
    249     class SensorEventTimeStampListener implements SensorEventListener {
    250         SensorEventTimeStampListener(long eventReportLatencyNs, CountDownLatch latch) {
    251             mEventReportLatencyNs = eventReportLatencyNs;
    252             mPrevTimeStampNs = -1;
    253             mLatch = latch;
    254             numErrors = 0;
    255         }
    256 
    257         @Override
    258         public void onSensorChanged(SensorEvent event) {
    259             if (mPrevTimeStampNs == -1) {
    260                 mPrevTimeStampNs = event.timestamp;
    261                 return;
    262             }
    263             long currTimeStampNs = event.timestamp;
    264             if (currTimeStampNs <= mPrevTimeStampNs) {
    265                 Log.w(TAG, "Timestamps not monotonically increasing curr_ts_ns=" +
    266                         event.timestamp + " prev_ts_ns=" + mPrevTimeStampNs);
    267                 numErrors++;
    268                 mPrevTimeStampNs = currTimeStampNs;
    269                 return;
    270             }
    271             mLatch.countDown();
    272 
    273             final long elapsedRealtimeNs = SystemClock.elapsedRealtimeNanos();
    274 
    275             if (elapsedRealtimeNs <= currTimeStampNs) {
    276                 Log.w(TAG, "Timestamps into the future curr elapsedRealTimeNs=" + elapsedRealtimeNs
    277                          + " current sensor ts_ns=" + currTimeStampNs);
    278                 ++numErrors;
    279             } else if (elapsedRealtimeNs-currTimeStampNs > SYNC_TOLERANCE + mEventReportLatencyNs) {
    280                 Log.w(TAG, "Timestamp sync error elapsedRealTimeNs=" + elapsedRealtimeNs +
    281                         " curr_ts_ns=" + currTimeStampNs +
    282                         " diff_ns=" + (elapsedRealtimeNs - currTimeStampNs) +
    283                         " SYNC_TOLERANCE_NS=" + SYNC_TOLERANCE +
    284                         " eventReportLatencyNs=" + mEventReportLatencyNs);
    285                 ++numErrors;
    286             }
    287             mPrevTimeStampNs = currTimeStampNs;
    288         }
    289 
    290         public int getNumErrors() {
    291             return numErrors;
    292         }
    293 
    294         @Override
    295         public void onAccuracyChanged(Sensor sensor, int accuracy) {
    296         }
    297 
    298         private int numErrors;
    299         private long mEventReportLatencyNs;
    300         private long mPrevTimeStampNs;
    301         private final CountDownLatch mLatch;
    302         private final long SYNC_TOLERANCE = 500000000L; // 500 milli seconds approx.
    303     }
    304 
    305     // Register for each sensor and compare the timestamps of SensorEvents that you get with
    306     // elapsedRealTimeNano.
    307     @TimeoutReq(minutes=60)
    308     public void testSensorTimeStamps() throws Exception {
    309         final int numEvents = 2000;
    310         try {
    311             mWakeLock.acquire();
    312             int numErrors = 0;
    313             for (Sensor sensor : mSensorList) {
    314                 // Skip OEM defined sensors and non continuous sensors.
    315                 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
    316                     continue;
    317                 }
    318 
    319                 for (int iterations = 0; iterations < 2; ++iterations) {
    320                     // Test in both batch mode and non-batch mode for every sensor.
    321                     long maxBatchReportLatencyNs = 10000000000L; // 10 secs
    322                     if (iterations % 2 == 0) maxBatchReportLatencyNs = 0;
    323 
    324                     final long samplingPeriodNs = (long)(TimeUnit.MICROSECONDS.toNanos(
    325                             sensor.getMinDelay())/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE);
    326                     // If there is a FIFO and a wake-lock is held, events will be reported when
    327                     // the batch timeout expires or when the FIFO is full which ever occurs
    328                     // earlier.
    329                     final long eventReportLatencyNs = Math.min(maxBatchReportLatencyNs,
    330                             sensor.getFifoMaxEventCount() * samplingPeriodNs);
    331 
    332                     final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
    333                     SensorEventTimeStampListener listener = new SensorEventTimeStampListener(
    334                             eventReportLatencyNs, eventsRemaining);
    335 
    336                     Log.i(TAG, "Running timeStamp test on " + sensor.getName());
    337                     boolean result = mSensorManager.registerListener(listener, sensor,
    338                             SensorManager.SENSOR_DELAY_FASTEST,
    339                             (int)maxBatchReportLatencyNs/1000);
    340                     assertTrue("Sensor registerListener failed ", result);
    341 
    342                     long timeToWaitUs = samplingPeriodNs/1000 + eventReportLatencyNs/1000 +
    343                             TIMEOUT_TOLERANCE_US;
    344                     long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
    345                             (int)(eventReportLatencyNs/1000), eventsRemaining);
    346 
    347                     mSensorManager.unregisterListener(listener);
    348                     if (eventsRemaining.getCount() > 0) {
    349                         failTimedOut(sensor.getName(), (double) totalTimeWaitedUs/1000,
    350                                 numEvents, (double) sensor.getMinDelay()/1000,
    351                                 eventsRemaining.getCount(),
    352                                 numEvents - eventsRemaining.getCount());
    353                     }
    354                     if (listener.getNumErrors() > 5) {
    355                         fail("Check logcat. Timestamp test failed. numErrors=" +
    356                                 listener.getNumErrors() + " " + sensor.getName() +
    357                                 " maxBatchReportLatencyNs=" + maxBatchReportLatencyNs +
    358                                 " samplingPeriodNs=" + sensor.getMinDelay());
    359                         numErrors += listener.getNumErrors();
    360                     } else {
    361                         Log.i(TAG, "TimeStamp test PASS'd on " + sensor.getName());
    362                     }
    363                 }
    364             }
    365         } finally {
    366             mWakeLock.release();
    367         }
    368     }
    369 
    370     private void failTimedOut(String sensorName, double totalTimeWaitedMs, int numEvents,
    371             double minDelayMs, long eventsRemaining, long eventsReceived) {
    372         final String TIMED_OUT_FORMAT = "Timed out waiting for events from %s " +
    373                 "waited for time=%.1fms to receive totalEvents=%d at samplingRate=%.1fHz" +
    374                 " remainingEvents=%d  received events=%d";
    375         fail(String.format(TIMED_OUT_FORMAT, sensorName, totalTimeWaitedMs, numEvents,
    376                 1000/minDelayMs, eventsRemaining, eventsReceived));
    377     }
    378 
    379     // Register for updates from each continuous mode sensor, wait for N events, call flush and
    380     // wait for flushCompleteEvent before unregistering for the sensor.
    381     @TimeoutReq(minutes=20)
    382     public void testBatchAndFlush() throws Exception {
    383         try {
    384             mWakeLock.acquire();
    385             for (Sensor sensor : mSensorList) {
    386                 // Skip ONLY one-shot sensors.
    387                 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
    388                     registerListenerCallFlush(sensor, null);
    389                 }
    390             }
    391         } finally {
    392             mWakeLock.release();
    393         }
    394     }
    395 
    396     // Same as testBatchAndFlush but using Handler version of the API to register for sensors.
    397     // onSensorChanged is now called on a background thread.
    398     @TimeoutReq(minutes=10)
    399     public void testBatchAndFlushWithHandler() throws Exception {
    400         try {
    401             mWakeLock.acquire();
    402             HandlerThread handlerThread = new HandlerThread("sensorThread");
    403             handlerThread.start();
    404             Handler handler = new Handler(handlerThread.getLooper());
    405             for (Sensor sensor : mSensorList) {
    406                 // Skip ONLY one-shot sensors.
    407                 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
    408                     registerListenerCallFlush(sensor, handler);
    409                 }
    410             }
    411         }  finally {
    412             mWakeLock.release();
    413         }
    414     }
    415 
    416     private void registerListenerCallFlush(Sensor sensor, Handler handler)
    417             throws InterruptedException {
    418         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
    419             return;
    420         }
    421         final int numEvents = 500;
    422         final int rateUs = 0; // DELAY_FASTEST
    423         final int maxBatchReportLatencyUs = 10000000;
    424         final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
    425         final CountDownLatch flushReceived = new CountDownLatch(1);
    426         SensorEventListener2 listener = new SensorEventListener2() {
    427             @Override
    428             public void onSensorChanged(SensorEvent event) {
    429                 eventsRemaining.countDown();
    430             }
    431 
    432             @Override
    433             public void onAccuracyChanged(Sensor sensor, int accuracy) {
    434             }
    435 
    436             @Override
    437             public void onFlushCompleted(Sensor sensor) {
    438                 flushReceived.countDown();
    439             }
    440         };
    441         // Consider only continuous mode sensors for testing registerListener.
    442         // For on-change sensors, call registerListener() so that the listener is associated
    443         // with the sensor so that flush(listener) can be called on it.
    444         try {
    445             Log.i(TAG, "testBatch " + sensor.getName());
    446             boolean result = mSensorManager.registerListener(listener, sensor,
    447                     rateUs, maxBatchReportLatencyUs, handler);
    448             assertTrue("registerListener failed " + sensor.getName(), result);
    449 
    450             // Wait for 500 events or N seconds before the test times out.
    451             if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
    452                 // Wait for approximately the time required to generate these events + a tolerance
    453                 // of 10 seconds.
    454                 long timeToWaitUs =
    455                   numEvents*(long)(sensor.getMinDelay()/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE)
    456                         + maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
    457 
    458                 long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
    459                         maxBatchReportLatencyUs, eventsRemaining);
    460                 if (eventsRemaining.getCount() > 0) {
    461                     failTimedOut(sensor.getName(), (double)totalTimeWaitedUs/1000, numEvents,
    462                             (double)sensor.getMinDelay()/1000,
    463                             eventsRemaining.getCount(), numEvents - eventsRemaining.getCount());
    464                 }
    465             }
    466             Log.i(TAG, "testFlush " + sensor.getName());
    467             result = mSensorManager.flush(listener);
    468             assertTrue("flush failed " + sensor.getName(), result);
    469             boolean collectedAllEvents = flushReceived.await(TIMEOUT_TOLERANCE_US,
    470                     TimeUnit.MICROSECONDS);
    471             if (!collectedAllEvents) {
    472                 fail("Timed out waiting for flushCompleteEvent from " + sensor.getName() +
    473                         " waitedFor="+ TIMEOUT_TOLERANCE_US/1000 + "ms");
    474             }
    475             Log.i(TAG, "testBatchAndFlush PASS " + sensor.getName());
    476         } finally {
    477             mSensorManager.unregisterListener(listener);
    478         }
    479     }
    480 
    481     // Wait till the CountDownLatch counts down to zero. If the events are not delivered within
    482     // timetoWaitUs, wait an additional maxReportLantencyUs and check if the sensor is streaming
    483     // data or not. If the sensor is not streaming at all, fail the test or else wait in increments
    484     // of maxReportLantencyUs to collect sensor events.
    485     private long waitToCollectAllEvents(long timeToWaitUs, int maxReportLatencyUs,
    486             CountDownLatch eventsRemaining)
    487             throws InterruptedException {
    488         boolean collectedAllEvents = false;
    489         long totalTimeWaitedUs = 0;
    490         long remainingEvents;
    491         final long INCREMENTAL_WAIT_US = maxReportLatencyUs + TimeUnit.SECONDS.toMicros(1);
    492         do {
    493             totalTimeWaitedUs += timeToWaitUs;
    494             remainingEvents = eventsRemaining.getCount();
    495             collectedAllEvents = eventsRemaining.await(timeToWaitUs, TimeUnit.MICROSECONDS);
    496             timeToWaitUs = INCREMENTAL_WAIT_US;
    497         } while (!collectedAllEvents &&
    498                 (remainingEvents - eventsRemaining.getCount() >=(long)INCREMENTAL_WAIT_US/1000000));
    499         return totalTimeWaitedUs;
    500     }
    501 
    502     // Call registerListener for multiple sensors at a time and call flush.
    503     public void testBatchAndFlushWithMutipleSensors() throws Exception {
    504         final int MAX_SENSORS = 3;
    505         int numSensors = mSensorList.size() < MAX_SENSORS ? mSensorList.size() : MAX_SENSORS;
    506         if (numSensors == 0) {
    507             return;
    508         }
    509         final int numEvents = 500;
    510         int rateUs = 0; // DELAY_FASTEST
    511         final int maxBatchReportLatencyUs = 10000000;
    512         final CountDownLatch eventsRemaining = new CountDownLatch(numSensors * numEvents);
    513         final CountDownLatch flushReceived = new CountDownLatch(numSensors);
    514         SensorEventListener2 listener = new SensorEventListener2() {
    515             @Override
    516             public void onSensorChanged(SensorEvent event) {
    517                 eventsRemaining.countDown();
    518             }
    519 
    520             @Override
    521             public void onAccuracyChanged(Sensor sensor, int accuracy) {
    522             }
    523 
    524             @Override
    525             public void onFlushCompleted(Sensor sensor) {
    526                 flushReceived.countDown();
    527             }
    528         };
    529 
    530         try {
    531             mWakeLock.acquire();
    532             StringBuilder registeredSensors = new StringBuilder(30);
    533             for (Sensor sensor : mSensorList) {
    534                 // Skip all non-continuous sensors.
    535                 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
    536                     continue;
    537                 }
    538                 rateUs = Math.max(sensor.getMinDelay(), rateUs);
    539                 boolean result = mSensorManager.registerListener(listener, sensor,
    540                         SensorManager.SENSOR_DELAY_FASTEST, maxBatchReportLatencyUs);
    541                 assertTrue("registerListener failed for " + sensor.getName(), result);
    542                 registeredSensors.append(sensor.getName());
    543                 registeredSensors.append(" ");
    544                 if (--numSensors == 0) {
    545                     break;
    546                 }
    547             }
    548             if (registeredSensors.toString().isEmpty()) {
    549                 return;
    550             }
    551 
    552             Log.i(TAG, "testBatchAndFlushWithMutipleSensors " + registeredSensors);
    553             long timeToWaitUs =
    554                     numEvents*(long)(rateUs/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE) +
    555                     maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
    556             long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs, maxBatchReportLatencyUs,
    557                     eventsRemaining);
    558             if (eventsRemaining.getCount() > 0) {
    559                 failTimedOut(registeredSensors.toString(), (double)totalTimeWaitedUs/1000,
    560                         numEvents, (double)rateUs/1000, eventsRemaining.getCount(),
    561                         numEvents - eventsRemaining.getCount());
    562             }
    563             boolean result = mSensorManager.flush(listener);
    564             assertTrue("flush failed " + registeredSensors.toString(), result);
    565             boolean collectedFlushEvent =
    566                     flushReceived.await(TIMEOUT_TOLERANCE_US, TimeUnit.MICROSECONDS);
    567             if (!collectedFlushEvent) {
    568                 fail("Timed out waiting for flushCompleteEvent from " +
    569                       registeredSensors.toString() + " waited for=" + timeToWaitUs/1000 + "ms");
    570             }
    571             Log.i(TAG, "testBatchAndFlushWithMutipleSensors PASS'd");
    572         } finally {
    573             mSensorManager.unregisterListener(listener);
    574             mWakeLock.release();
    575         }
    576     }
    577 
    578     private void assertSensorValues(Sensor sensor) {
    579         assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
    580                 + " " + sensor.getName(), sensor.getMaximumRange() >= 0);
    581         assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " +
    582                 sensor.getName(), sensor.getPower() >= 0);
    583         assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
    584                 " " + sensor.getName(), sensor.getResolution() >= 0);
    585         assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
    586         assertTrue("Version must be positive version="  + sensor.getVersion() + " " +
    587                     sensor.getName(), sensor.getVersion() > 0);
    588         int fifoMaxEventCount = sensor.getFifoMaxEventCount();
    589         int fifoReservedEventCount = sensor.getFifoReservedEventCount();
    590         assertTrue(fifoMaxEventCount >= 0);
    591         assertTrue(fifoReservedEventCount >= 0);
    592         assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
    593         if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
    594             assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
    595                     sensor.getFifoMaxEventCount() == 0);
    596             assertTrue("One shot sensors should have zero FIFO Size "  + sensor.getName(),
    597                     sensor.getFifoReservedEventCount() == 0);
    598         }
    599     }
    600 
    601     @SuppressWarnings("deprecation")
    602     public void testLegacySensorOperations() {
    603         final SensorManager mSensorManager =
    604                 (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
    605 
    606         // We expect the set of sensors reported by the new and legacy APIs to be consistent.
    607         int sensors = 0;
    608         if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
    609             sensors |= SensorManager.SENSOR_ACCELEROMETER;
    610         }
    611         if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    612             sensors |= SensorManager.SENSOR_MAGNETIC_FIELD;
    613         }
    614         if (mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION) != null) {
    615             sensors |= SensorManager.SENSOR_ORIENTATION | SensorManager.SENSOR_ORIENTATION_RAW;
    616         }
    617         assertEquals(sensors, mSensorManager.getSensors());
    618     }
    619 
    620     class TriggerListener extends TriggerEventListener {
    621         @Override
    622         public void onTrigger(TriggerEvent event) {
    623         }
    624     }
    625 
    626     class SensorListener implements SensorEventListener {
    627         @Override
    628         public void onSensorChanged(SensorEvent event) {
    629         }
    630 
    631         @Override
    632         public void onAccuracyChanged(Sensor sensor, int accuracy) {
    633         }
    634     }
    635 }
    636