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