1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware.cts; 18 19 import android.content.Context; 20 import android.hardware.HardwareBuffer; 21 import android.hardware.Sensor; 22 import android.hardware.SensorDirectChannel; 23 import android.hardware.SensorEvent; 24 import android.hardware.SensorEventListener; 25 import android.hardware.SensorManager; 26 import android.hardware.cts.helpers.SensorCtsHelper; 27 import android.hardware.cts.helpers.SensorCtsHelper.TestResultCollector; 28 import android.os.MemoryFile; 29 import android.os.SystemClock; 30 import android.util.Log; 31 32 import java.io.IOException; 33 import java.io.UncheckedIOException; 34 import java.nio.ByteBuffer; 35 import java.nio.ByteOrder; 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.List; 39 import java.util.concurrent.TimeUnit; 40 41 /** 42 * Checks Sensor Direct Report functionality 43 * 44 * This testcase tests operation of: 45 * - SensorManager.createDirectChannel() 46 * - SensorDirectChannel.* 47 * - Sensor.getHighestDirectReportRateLevel() 48 * - Sensor.isDirectChannelTypeSupported() 49 * 50 * Tests: 51 * - test<Sensor><SharedMemoryType><RateLevel> 52 * tests basic operation of sensor in direct report mode at various rate level specification. 53 * - testRateIndependency<Sensor1><Sensor2>SingleChannel 54 * tests if two sensors in the same direct channel are able to run at different rates. 55 * - testRateIndependency<Sensor>MultiChannel 56 * tests if a sensor is able to be configured to different rate levels for multiple channels. 57 * - testRateIndependency<Sensor>MultiMode 58 * tests if a sensor is able to report at different rates in direct report mode and traditional 59 * report mode (polling). 60 * - testTimestamp<Sensor> 61 * tests if the timestamp is correct both in absolute sense and relative to traditional report. 62 * - testAtomicCounter<Sensor> 63 * test if atomic counter is increased as specified and if sensor event content is fully updated 64 * before update of atomic counter. 65 * - testRegisterMultipleChannels 66 * test scenarios when multiple channels are registered simultaneously. 67 * - testReconfigure 68 * test channel reconfiguration (configure to a rate level; configure to stop; configure to 69 * another rate level) 70 * - testRegisterMultipleChannelsUsingSameMemory 71 * test a negative case when the same memory is being used twice for registering sensor direct 72 * channel 73 * - testCloseWithoutConfigStop 74 * test a common mistake in API usage and make sure no negative effect is made to system. 75 */ 76 public class SensorDirectReportTest extends SensorTestCase { 77 private static final String TAG = "SensorDirectReportTest"; 78 // nominal rates of each rate level supported 79 private static final float RATE_NORMAL_NOMINAL = 50; 80 private static final float RATE_FAST_NOMINAL = 200; 81 private static final float RATE_VERY_FAST_NOMINAL = 800; 82 83 // actuall value is allowed to be 55% to 220% of nominal value 84 private static final float FREQ_LOWER_BOUND = 0.55f; 85 private static final float FREQ_UPPER_BOUND = 2.2f; 86 87 // actuall value is allowed to be 90% to 200% of nominal value in poll() interface 88 private static final float FREQ_LOWER_BOUND_POLL = 0.90f; 89 private static final float FREQ_UPPER_BOUND_POLL = 2.00f; 90 91 // sensor reading assumption 92 private static final float GRAVITY_MIN = 9.81f - 1.0f; 93 private static final float GRAVITY_MAX = 9.81f + 1.0f; 94 private static final float GYRO_NORM_MAX = 0.1f; 95 96 // test constants 97 public static final int REST_PERIOD_BEFORE_TEST_MILLISEC = 3000; 98 private static final int TEST_RUN_TIME_PERIOD_MILLISEC = 5000; 99 private static final int ALLOWED_SENSOR_INIT_TIME_MILLISEC = 500; 100 private static final int SENSORS_EVENT_SIZE = 104; 101 private static final int ATOMIC_COUNTER_OFFSET = 12; 102 private static final int ATOMIC_COUNTER_SIZE = 4; 103 private static final int SENSORS_EVENT_COUNT = 10240; // 800Hz * 2.2 * 5 sec + extra 104 private static final int SHARED_MEMORY_SIZE = SENSORS_EVENT_COUNT * SENSORS_EVENT_SIZE; 105 private static final float MERCY_FACTOR = 0.1f; 106 private static final boolean CHECK_ABSOLUTE_LATENCY = false; 107 108 // list of rate levels being tested 109 private static final int[] POSSIBLE_RATE_LEVELS = new int[] { 110 SensorDirectChannel.RATE_NORMAL, 111 SensorDirectChannel.RATE_FAST, 112 SensorDirectChannel.RATE_VERY_FAST 113 }; 114 115 // list of channel types being tested 116 private static final int[] POSSIBLE_CHANNEL_TYPES = new int [] { 117 SensorDirectChannel.TYPE_MEMORY_FILE, 118 SensorDirectChannel.TYPE_HARDWARE_BUFFER 119 }; 120 121 // list of sensor types being tested 122 private static final int[] POSSIBLE_SENSOR_TYPES = new int [] { 123 Sensor.TYPE_ACCELEROMETER, 124 Sensor.TYPE_GYROSCOPE, 125 Sensor.TYPE_MAGNETIC_FIELD 126 }; 127 128 // list of sampling period being tested 129 private static final int[] POSSIBLE_SAMPLE_PERIOD_US = new int [] { 130 200_000, // Normal 5 Hz 131 66_667, // UI 15 Hz 132 20_000, // Game 50 Hz 133 5_000, // 200Hz 134 0 // fastest 135 }; 136 137 private static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder(); 138 nativeReadHardwareBuffer(HardwareBuffer hardwareBuffer, byte[] buffer, int srcOffset, int destOffset, int count)139 private static native boolean nativeReadHardwareBuffer(HardwareBuffer hardwareBuffer, 140 byte[] buffer, int srcOffset, int destOffset, int count); 141 142 private boolean mNeedMemoryFile; 143 private MemoryFile mMemoryFile; 144 private MemoryFile mMemoryFileSecondary; 145 private boolean mNeedHardwareBuffer; 146 private HardwareBuffer mHardwareBuffer; 147 private HardwareBuffer mHardwareBufferSecondary; 148 private ByteBuffer mByteBuffer; 149 private byte[] mBuffer; 150 151 private SensorManager mSensorManager; 152 private SensorDirectChannel mChannel; 153 private SensorDirectChannel mChannelSecondary; 154 155 private EventPool mEventPool; 156 157 static { 158 System.loadLibrary("cts-sensors-ndk-jni"); 159 } 160 161 @Override setUp()162 protected void setUp() throws Exception { 163 super.setUp(); 164 165 mByteBuffer = ByteBuffer.allocate(SHARED_MEMORY_SIZE); 166 mBuffer = mByteBuffer.array(); 167 mByteBuffer.order(ByteOrder.nativeOrder()); 168 169 mEventPool = new EventPool(10 * SENSORS_EVENT_COUNT); 170 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); 171 172 mNeedMemoryFile = isMemoryTypeNeeded(SensorDirectChannel.TYPE_MEMORY_FILE); 173 mNeedHardwareBuffer = isMemoryTypeNeeded(SensorDirectChannel.TYPE_HARDWARE_BUFFER); 174 175 allocateSharedMemory(); 176 } 177 178 @Override tearDown()179 protected void tearDown() throws Exception { 180 if (mChannel != null) { 181 mChannel.close(); 182 mChannel = null; 183 } 184 185 if (mChannelSecondary != null) { 186 mChannelSecondary.close(); 187 mChannelSecondary = null; 188 } 189 190 freeSharedMemory(); 191 super.tearDown(); 192 } 193 testSharedMemoryAllocation()194 public void testSharedMemoryAllocation() throws AssertionError { 195 assertTrue("allocating MemoryFile returned null: " 196 + (mMemoryFile == null) + ", " + (mMemoryFileSecondary == null), 197 !mNeedMemoryFile || (mMemoryFile != null && mMemoryFileSecondary != null)); 198 assertTrue("allocating HardwareBuffer returned null: " 199 + (mHardwareBuffer == null) + ", " + (mHardwareBufferSecondary == null), 200 !mNeedHardwareBuffer || 201 (mHardwareBuffer != null && mHardwareBufferSecondary != null)); 202 } 203 testAccelerometerAshmemNormal()204 public void testAccelerometerAshmemNormal() { 205 runSensorDirectReportTest( 206 Sensor.TYPE_ACCELEROMETER, 207 SensorDirectChannel.TYPE_MEMORY_FILE, 208 SensorDirectChannel.RATE_NORMAL); 209 } 210 testAccelerometerAshmemNormalUidIdle()211 public void testAccelerometerAshmemNormalUidIdle() { 212 runSensorDirectReportUidIdleTest( 213 Sensor.TYPE_ACCELEROMETER, 214 SensorDirectChannel.TYPE_MEMORY_FILE, 215 SensorDirectChannel.RATE_NORMAL); 216 } 217 testGyroscopeAshmemNormal()218 public void testGyroscopeAshmemNormal() { 219 runSensorDirectReportTest( 220 Sensor.TYPE_GYROSCOPE, 221 SensorDirectChannel.TYPE_MEMORY_FILE, 222 SensorDirectChannel.RATE_NORMAL); 223 } 224 testGyroscopeAshmemNormalUidIdle()225 public void testGyroscopeAshmemNormalUidIdle() { 226 runSensorDirectReportUidIdleTest( 227 Sensor.TYPE_GYROSCOPE, 228 SensorDirectChannel.TYPE_MEMORY_FILE, 229 SensorDirectChannel.RATE_NORMAL); 230 } 231 testMagneticFieldAshmemNormal()232 public void testMagneticFieldAshmemNormal() { 233 runSensorDirectReportTest( 234 Sensor.TYPE_MAGNETIC_FIELD, 235 SensorDirectChannel.TYPE_MEMORY_FILE, 236 SensorDirectChannel.RATE_NORMAL); 237 } 238 testMagneticFieldAshmemNormalUidIdle()239 public void testMagneticFieldAshmemNormalUidIdle() { 240 runSensorDirectReportUidIdleTest( 241 Sensor.TYPE_MAGNETIC_FIELD, 242 SensorDirectChannel.TYPE_MEMORY_FILE, 243 SensorDirectChannel.RATE_NORMAL); 244 } 245 testAccelerometerAshmemFast()246 public void testAccelerometerAshmemFast() { 247 runSensorDirectReportTest( 248 Sensor.TYPE_ACCELEROMETER, 249 SensorDirectChannel.TYPE_MEMORY_FILE, 250 SensorDirectChannel.RATE_FAST); 251 } 252 testAccelerometerAshmemFastUidIdle()253 public void testAccelerometerAshmemFastUidIdle() { 254 runSensorDirectReportUidIdleTest( 255 Sensor.TYPE_ACCELEROMETER, 256 SensorDirectChannel.TYPE_MEMORY_FILE, 257 SensorDirectChannel.RATE_FAST); 258 } 259 testGyroscopeAshmemFast()260 public void testGyroscopeAshmemFast() { 261 runSensorDirectReportTest( 262 Sensor.TYPE_GYROSCOPE, 263 SensorDirectChannel.TYPE_MEMORY_FILE, 264 SensorDirectChannel.RATE_FAST); 265 } 266 testGyroscopeAshmemFastUidIdle()267 public void testGyroscopeAshmemFastUidIdle() { 268 runSensorDirectReportUidIdleTest( 269 Sensor.TYPE_GYROSCOPE, 270 SensorDirectChannel.TYPE_MEMORY_FILE, 271 SensorDirectChannel.RATE_FAST); 272 } 273 testMagneticFieldAshmemFast()274 public void testMagneticFieldAshmemFast() { 275 runSensorDirectReportTest( 276 Sensor.TYPE_MAGNETIC_FIELD, 277 SensorDirectChannel.TYPE_MEMORY_FILE, 278 SensorDirectChannel.RATE_FAST); 279 } 280 testMagneticFieldAshmemFastUidIdle()281 public void testMagneticFieldAshmemFastUidIdle() { 282 runSensorDirectReportUidIdleTest( 283 Sensor.TYPE_MAGNETIC_FIELD, 284 SensorDirectChannel.TYPE_MEMORY_FILE, 285 SensorDirectChannel.RATE_FAST); 286 } 287 testAccelerometerAshmemVeryFast()288 public void testAccelerometerAshmemVeryFast() { 289 runSensorDirectReportTest( 290 Sensor.TYPE_ACCELEROMETER, 291 SensorDirectChannel.TYPE_MEMORY_FILE, 292 SensorDirectChannel.RATE_VERY_FAST); 293 } 294 testAccelerometerAshmemVeryFastUidIdle()295 public void testAccelerometerAshmemVeryFastUidIdle() { 296 runSensorDirectReportUidIdleTest( 297 Sensor.TYPE_ACCELEROMETER, 298 SensorDirectChannel.TYPE_MEMORY_FILE, 299 SensorDirectChannel.RATE_VERY_FAST); 300 } 301 testGyroscopeAshmemVeryFast()302 public void testGyroscopeAshmemVeryFast() { 303 runSensorDirectReportTest( 304 Sensor.TYPE_GYROSCOPE, 305 SensorDirectChannel.TYPE_MEMORY_FILE, 306 SensorDirectChannel.RATE_VERY_FAST); 307 } 308 testGyroscopeAshmemVeryFastUidIdle()309 public void testGyroscopeAshmemVeryFastUidIdle() { 310 runSensorDirectReportUidIdleTest( 311 Sensor.TYPE_GYROSCOPE, 312 SensorDirectChannel.TYPE_MEMORY_FILE, 313 SensorDirectChannel.RATE_VERY_FAST); 314 } 315 testMagneticFieldAshmemVeryFast()316 public void testMagneticFieldAshmemVeryFast() { 317 runSensorDirectReportTest( 318 Sensor.TYPE_MAGNETIC_FIELD, 319 SensorDirectChannel.TYPE_MEMORY_FILE, 320 SensorDirectChannel.RATE_VERY_FAST); 321 } 322 testMagneticFieldAshmemVeryFastUidIdle()323 public void testMagneticFieldAshmemVeryFastUidIdle() { 324 runSensorDirectReportUidIdleTest( 325 Sensor.TYPE_MAGNETIC_FIELD, 326 SensorDirectChannel.TYPE_MEMORY_FILE, 327 SensorDirectChannel.RATE_VERY_FAST); 328 } 329 testAccelerometerHardwareBufferNormal()330 public void testAccelerometerHardwareBufferNormal() { 331 runSensorDirectReportTest( 332 Sensor.TYPE_ACCELEROMETER, 333 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 334 SensorDirectChannel.RATE_NORMAL); 335 } 336 testAccelerometerHardwareBufferNormalUidIdle()337 public void testAccelerometerHardwareBufferNormalUidIdle() { 338 runSensorDirectReportUidIdleTest( 339 Sensor.TYPE_ACCELEROMETER, 340 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 341 SensorDirectChannel.RATE_NORMAL); 342 } 343 testGyroscopeHardwareBufferNormal()344 public void testGyroscopeHardwareBufferNormal() { 345 runSensorDirectReportTest( 346 Sensor.TYPE_GYROSCOPE, 347 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 348 SensorDirectChannel.RATE_NORMAL); 349 } 350 testGyroscopeHardwareBufferNormalUidIdle()351 public void testGyroscopeHardwareBufferNormalUidIdle() { 352 runSensorDirectReportUidIdleTest( 353 Sensor.TYPE_GYROSCOPE, 354 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 355 SensorDirectChannel.RATE_NORMAL); 356 } 357 testMagneticFieldHardwareBufferNormal()358 public void testMagneticFieldHardwareBufferNormal() { 359 runSensorDirectReportTest( 360 Sensor.TYPE_MAGNETIC_FIELD, 361 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 362 SensorDirectChannel.RATE_NORMAL); 363 } 364 testMagneticFieldHardwareBufferNormalUidIdle()365 public void testMagneticFieldHardwareBufferNormalUidIdle() { 366 runSensorDirectReportUidIdleTest( 367 Sensor.TYPE_MAGNETIC_FIELD, 368 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 369 SensorDirectChannel.RATE_NORMAL); 370 } 371 testAccelerometerHardwareBufferFast()372 public void testAccelerometerHardwareBufferFast() { 373 runSensorDirectReportTest( 374 Sensor.TYPE_ACCELEROMETER, 375 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 376 SensorDirectChannel.RATE_FAST); 377 } 378 testAccelerometerHardwareBufferFastUidIdle()379 public void testAccelerometerHardwareBufferFastUidIdle() { 380 runSensorDirectReportUidIdleTest( 381 Sensor.TYPE_ACCELEROMETER, 382 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 383 SensorDirectChannel.RATE_FAST); 384 } 385 testGyroscopeHardwareBufferFast()386 public void testGyroscopeHardwareBufferFast() { 387 runSensorDirectReportTest( 388 Sensor.TYPE_GYROSCOPE, 389 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 390 SensorDirectChannel.RATE_FAST); 391 } testGyroscopeHardwareBufferFastUidIdle()392 public void testGyroscopeHardwareBufferFastUidIdle() { 393 runSensorDirectReportUidIdleTest( 394 Sensor.TYPE_GYROSCOPE, 395 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 396 SensorDirectChannel.RATE_FAST); 397 } 398 testMagneticFieldHardwareBufferFast()399 public void testMagneticFieldHardwareBufferFast() { 400 runSensorDirectReportTest( 401 Sensor.TYPE_MAGNETIC_FIELD, 402 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 403 SensorDirectChannel.RATE_FAST); 404 } 405 testMagneticFieldHardwareBufferFastUidIdle()406 public void testMagneticFieldHardwareBufferFastUidIdle() { 407 runSensorDirectReportUidIdleTest( 408 Sensor.TYPE_MAGNETIC_FIELD, 409 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 410 SensorDirectChannel.RATE_FAST); 411 } 412 testAccelerometerHardwareBufferVeryFast()413 public void testAccelerometerHardwareBufferVeryFast() { 414 runSensorDirectReportTest( 415 Sensor.TYPE_ACCELEROMETER, 416 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 417 SensorDirectChannel.RATE_VERY_FAST); 418 } 419 testAccelerometerHardwareBufferVeryFastUidIdle()420 public void testAccelerometerHardwareBufferVeryFastUidIdle() { 421 runSensorDirectReportUidIdleTest( 422 Sensor.TYPE_ACCELEROMETER, 423 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 424 SensorDirectChannel.RATE_VERY_FAST); 425 } 426 testGyroscopeHardwareBufferVeryFast()427 public void testGyroscopeHardwareBufferVeryFast() { 428 runSensorDirectReportTest( 429 Sensor.TYPE_GYROSCOPE, 430 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 431 SensorDirectChannel.RATE_VERY_FAST); 432 } 433 testGyroscopeHardwareBufferVeryFastUidIdle()434 public void testGyroscopeHardwareBufferVeryFastUidIdle() { 435 runSensorDirectReportUidIdleTest( 436 Sensor.TYPE_GYROSCOPE, 437 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 438 SensorDirectChannel.RATE_VERY_FAST); 439 } 440 testMagneticFieldHardwareBufferVeryFast()441 public void testMagneticFieldHardwareBufferVeryFast() { 442 runSensorDirectReportTest( 443 Sensor.TYPE_MAGNETIC_FIELD, 444 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 445 SensorDirectChannel.RATE_VERY_FAST); 446 } 447 testMagneticFieldHardwareBufferVeryFastUidIdle()448 public void testMagneticFieldHardwareBufferVeryFastUidIdle() { 449 runSensorDirectReportUidIdleTest( 450 Sensor.TYPE_MAGNETIC_FIELD, 451 SensorDirectChannel.TYPE_HARDWARE_BUFFER, 452 SensorDirectChannel.RATE_VERY_FAST); 453 } 454 testRateIndependencyAccelGyroSingleChannel()455 public void testRateIndependencyAccelGyroSingleChannel() { 456 runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER, 457 Sensor.TYPE_GYROSCOPE); 458 } 459 testRateIndependencyAccelMagSingleChannel()460 public void testRateIndependencyAccelMagSingleChannel() { 461 runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER, 462 Sensor.TYPE_MAGNETIC_FIELD); 463 } 464 testRateIndependencyGyroMagSingleChannel()465 public void testRateIndependencyGyroMagSingleChannel() { 466 runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE, 467 Sensor.TYPE_MAGNETIC_FIELD); 468 } 469 testRateIndependencyAccelUncalAccelSingleChannel()470 public void testRateIndependencyAccelUncalAccelSingleChannel() { 471 runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER, 472 Sensor.TYPE_ACCELEROMETER_UNCALIBRATED); 473 } 474 testRateIndependencyGyroUncalGyroSingleChannel()475 public void testRateIndependencyGyroUncalGyroSingleChannel() { 476 runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE, 477 Sensor.TYPE_GYROSCOPE_UNCALIBRATED); 478 } 479 testRateIndependencyMagUncalMagSingleChannel()480 public void testRateIndependencyMagUncalMagSingleChannel() { 481 runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_MAGNETIC_FIELD, 482 Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED); 483 } 484 testRateIndependencyAccelMultiChannel()485 public void testRateIndependencyAccelMultiChannel() { 486 runMultiChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER); 487 } 488 testRateIndependencyGyroMultiChannel()489 public void testRateIndependencyGyroMultiChannel() { 490 runMultiChannelRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE); 491 } 492 testRateIndependencyMagMultiChannel()493 public void testRateIndependencyMagMultiChannel() { 494 runMultiChannelRateIndependencyTestGroup(Sensor.TYPE_MAGNETIC_FIELD); 495 } 496 testRateIndependencyAccelMultiMode()497 public void testRateIndependencyAccelMultiMode() { 498 runMultiModeRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER); 499 } 500 testRateIndependencyGyroMultiMode()501 public void testRateIndependencyGyroMultiMode() { 502 runMultiModeRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE); 503 } 504 testRateIndependencyMagMultiMode()505 public void testRateIndependencyMagMultiMode() { 506 runMultiModeRateIndependencyTestGroup(Sensor.TYPE_MAGNETIC_FIELD); 507 } 508 testTimestampAccel()509 public void testTimestampAccel() { 510 runTimestampTestGroup(Sensor.TYPE_ACCELEROMETER); 511 } 512 testTimestampGyro()513 public void testTimestampGyro() { 514 runTimestampTestGroup(Sensor.TYPE_GYROSCOPE); 515 } 516 testTimestampMag()517 public void testTimestampMag() { 518 runTimestampTestGroup(Sensor.TYPE_MAGNETIC_FIELD); 519 } 520 testAtomicCounterAccel()521 public void testAtomicCounterAccel() { 522 for (int memType : POSSIBLE_CHANNEL_TYPES) { 523 runAtomicCounterTest(Sensor.TYPE_ACCELEROMETER, memType); 524 } 525 } 526 testAtomicCounterGyro()527 public void testAtomicCounterGyro() { 528 for (int memType : POSSIBLE_CHANNEL_TYPES) { 529 runAtomicCounterTest(Sensor.TYPE_GYROSCOPE, memType); 530 } 531 } 532 testAtomicCounterMag()533 public void testAtomicCounterMag() { 534 for (int memType : POSSIBLE_CHANNEL_TYPES) { 535 runAtomicCounterTest(Sensor.TYPE_MAGNETIC_FIELD, memType); 536 } 537 } 538 testRegisterMultipleChannels()539 public void testRegisterMultipleChannels() throws AssertionError { 540 resetEvent(); 541 freeSharedMemory(); 542 543 for (int memType : POSSIBLE_CHANNEL_TYPES) { 544 if (!isMemoryTypeNeeded(memType)) { 545 continue; 546 } 547 548 for (int repeat = 0; repeat < 10; ++repeat) { 549 // allocate new memory every time 550 allocateSharedMemory(); 551 552 mChannel = prepareDirectChannel(memType, false /* secondary */); 553 assertNotNull("mChannel is null", mChannel); 554 555 mChannelSecondary = prepareDirectChannel(memType, true /* secondary */); 556 assertNotNull("mChannelSecondary is null", mChannelSecondary); 557 558 if (mChannel != null) { 559 mChannel.close(); 560 mChannel = null; 561 } 562 if (mChannelSecondary != null) { 563 mChannelSecondary.close(); 564 mChannelSecondary = null; 565 } 566 567 // free shared memory 568 freeSharedMemory(); 569 } 570 } 571 } 572 testRegisterMultipleChannelsUsingSameMemory()573 public void testRegisterMultipleChannelsUsingSameMemory() throws AssertionError { 574 // MemoryFile identification is not supported by Android yet 575 int memType = SensorDirectChannel.TYPE_HARDWARE_BUFFER; 576 if (!isMemoryTypeNeeded(memType)) { 577 return; 578 } 579 580 mChannel = prepareDirectChannel(memType, false /* secondary */); 581 assertNotNull("mChannel is null", mChannel); 582 583 // use same memory to register, should fail. 584 mChannelSecondary = prepareDirectChannel(memType, false /* secondary */); 585 assertNull("mChannelSecondary is not null", mChannelSecondary); 586 587 mChannel.close(); 588 // after mChannel.close(), memory should free up and this should return non-null 589 // channel 590 mChannelSecondary = prepareDirectChannel(memType, false /* secondary */); 591 assertNotNull("mChannelSecondary is null", mChannelSecondary); 592 mChannelSecondary.close(); 593 } 594 testReconfigure()595 public void testReconfigure() { 596 TestResultCollector c = new TestResultCollector("testReconfigure", TAG); 597 598 for (int type : POSSIBLE_SENSOR_TYPES) { 599 for (int memType : POSSIBLE_CHANNEL_TYPES) { 600 c.perform(() -> { runReconfigureTest(type, memType);}, 601 String.format("sensor type %d, mem type %d", type, memType)); 602 } 603 } 604 c.judge(); 605 } 606 testCloseWithoutConfigStop()607 public void testCloseWithoutConfigStop() { 608 for (int type : POSSIBLE_SENSOR_TYPES) { 609 for (int memType : POSSIBLE_CHANNEL_TYPES) { 610 Sensor s = mSensorManager.getDefaultSensor(type); 611 if (s == null 612 || s.getHighestDirectReportRateLevel() == SensorDirectChannel.RATE_STOP 613 || !s.isDirectChannelTypeSupported(memType)) { 614 continue; 615 } 616 617 mChannel = prepareDirectChannel(memType, false /* secondary */); 618 assertTrue("createDirectChannel failed", mChannel != null); 619 620 try { 621 waitBeforeStartSensor(); 622 mChannel.configure(s, s.getHighestDirectReportRateLevel()); 623 624 // wait for a while 625 waitBeforeStartSensor(); 626 627 // The following line is commented out intentionally. 628 // mChannel.configure(s, SensorDirectChannel.RATE_STOP); 629 } finally { 630 mChannel.close(); 631 mChannel = null; 632 } 633 waitBeforeStartSensor(); 634 } 635 } 636 } 637 runSingleChannelRateIndependencyTestGroup(int type1, int type2)638 private void runSingleChannelRateIndependencyTestGroup(int type1, int type2) { 639 if (type1 == type2) { 640 throw new IllegalArgumentException("Cannot run single channel rate independency test " 641 + "on type " + type1 + " and " + type2); 642 } 643 String stype1 = SensorCtsHelper.sensorTypeShortString(type1); 644 String stype2 = SensorCtsHelper.sensorTypeShortString(type2); 645 646 TestResultCollector c = 647 new TestResultCollector( 648 "testRateIndependency" + stype1 + stype2 + "SingleChannel", TAG); 649 650 for (int rate1 : POSSIBLE_RATE_LEVELS) { 651 for (int rate2 : POSSIBLE_RATE_LEVELS) { 652 for (int memType : POSSIBLE_CHANNEL_TYPES) { 653 c.perform( 654 () -> { 655 runSingleChannelRateIndependencyTest( 656 type1, rate1, type2, rate2, 657 SensorDirectChannel.TYPE_MEMORY_FILE); 658 }, 659 String.format("(%s rate %d, %s rate %d, mem %d)", 660 stype1, rate1, stype2, rate2, memType)); 661 } 662 } 663 } 664 c.judge(); 665 } 666 runMultiChannelRateIndependencyTestGroup(int sensorType)667 public void runMultiChannelRateIndependencyTestGroup(int sensorType) { 668 TestResultCollector c = new TestResultCollector( 669 "testRateIndependency" + SensorCtsHelper.sensorTypeShortString(sensorType) 670 + "MultiChannel", TAG); 671 672 for (int rate1 : POSSIBLE_RATE_LEVELS) { 673 for (int rate2 : POSSIBLE_RATE_LEVELS) { 674 for (int type1 : POSSIBLE_CHANNEL_TYPES) { 675 for (int type2 : POSSIBLE_CHANNEL_TYPES) { 676 // only test upper triangle 677 if (rate1 > rate2 || type1 > type2) { 678 continue; 679 } 680 c.perform(() -> { 681 runMultiChannelRateIndependencyTest( 682 sensorType, rate1, rate2, type1, type2);}, 683 String.format("rate1 %d, rate2 %d, type1 %d, type2 %d", 684 rate1, rate2, type1, type2)); 685 } 686 } 687 } 688 } 689 c.judge(); 690 } 691 runMultiModeRateIndependencyTestGroup(int sensorType)692 public void runMultiModeRateIndependencyTestGroup(int sensorType) { 693 TestResultCollector c = new TestResultCollector( 694 "testRateIndependency" + SensorCtsHelper.sensorTypeShortString(sensorType) 695 + "MultiMode", TAG); 696 697 for (int rate : POSSIBLE_RATE_LEVELS) { 698 for (int type : POSSIBLE_CHANNEL_TYPES) { 699 for (int samplingPeriodUs : POSSIBLE_SAMPLE_PERIOD_US) { 700 c.perform(() -> {runMultiModeRateIndependencyTest( 701 sensorType, rate, type, samplingPeriodUs);}, 702 String.format("rateLevel %d, memType %d, period %d", 703 rate, type, samplingPeriodUs)); 704 } 705 } 706 } 707 c.judge(); 708 } 709 runTimestampTestGroup(int sensorType)710 private void runTimestampTestGroup(int sensorType) { 711 String stype = SensorCtsHelper.sensorTypeShortString(sensorType); 712 713 TestResultCollector c = 714 new TestResultCollector("testTimestamp" + stype, TAG); 715 716 for (int rateLevel : POSSIBLE_RATE_LEVELS) { 717 for (int memType : POSSIBLE_CHANNEL_TYPES) { 718 c.perform( 719 () -> { 720 runTimestampTest(sensorType, rateLevel, memType); 721 }, 722 String.format("(%s, rate %d, memtype %d)", stype, rateLevel, memType)); 723 } 724 } 725 c.judge(); 726 } 727 runSensorDirectReportTest(int sensorType, int memType, int rateLevel)728 private void runSensorDirectReportTest(int sensorType, int memType, int rateLevel) 729 throws AssertionError { 730 Sensor s = mSensorManager.getDefaultSensor(sensorType); 731 if (s == null 732 || s.getHighestDirectReportRateLevel() < rateLevel 733 || !s.isDirectChannelTypeSupported(memType)) { 734 return; 735 } 736 resetEvent(); 737 738 mChannel = prepareDirectChannel(memType, false /* secondary */); 739 assertTrue("createDirectChannel failed", mChannel != null); 740 741 try { 742 assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType)); 743 waitBeforeStartSensor(); 744 745 int token = mChannel.configure(s, rateLevel); 746 assertTrue("configure direct mChannel failed", token > 0); 747 748 waitSensorCollection(); 749 750 //stop sensor and analyze content 751 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 752 checkSharedMemoryContent(s, memType, rateLevel, token); 753 } finally { 754 mChannel.close(); 755 mChannel = null; 756 } 757 } 758 runSensorDirectReportUidIdleTest(int sensorType, int memType, int rateLevel)759 private void runSensorDirectReportUidIdleTest(int sensorType, int memType, int rateLevel) { 760 Sensor s = mSensorManager.getDefaultSensor(sensorType); 761 if (s == null 762 || s.getHighestDirectReportRateLevel() < rateLevel 763 || !s.isDirectChannelTypeSupported(memType)) { 764 return; 765 } 766 resetEvent(); 767 768 mChannel = prepareDirectChannel(memType, false /* secondary */); 769 assertTrue("createDirectChannel failed", mChannel != null); 770 771 try { 772 assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType)); 773 waitBeforeStartSensor(); 774 775 int token = mChannel.configure(s, rateLevel); 776 assertTrue("configure direct mChannel failed", token > 0); 777 778 // Make package idle and ensure no sensor events are received 779 try { 780 SensorCtsHelper.makeMyPackageIdle(); 781 } catch (IOException e) { 782 fail("IOException while making package idle"); 783 } 784 785 int originalEventSize = mBuffer.length; 786 waitSensorCollection(); 787 788 assertEquals(mBuffer.length, originalEventSize); 789 790 try { 791 SensorCtsHelper.makeMyPackageActive(); 792 } catch (IOException e) { 793 fail("IOException while making package active"); 794 } 795 796 // Also verify sensor events can be received after becoming active. 797 resetEvent(); 798 799 waitSensorCollection(); 800 801 //stop sensor and analyze content 802 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 803 checkSharedMemoryContent(s, memType, rateLevel, token); 804 } finally { 805 mChannel.close(); 806 mChannel = null; 807 } 808 } 809 runSingleChannelRateIndependencyTest( int type1, int rateLevel1, int type2, int rateLevel2, int memType)810 private void runSingleChannelRateIndependencyTest( 811 int type1, int rateLevel1, int type2, int rateLevel2, int memType) 812 throws AssertionError { 813 Sensor s1 = mSensorManager.getDefaultSensor(type1); 814 Sensor s2 = mSensorManager.getDefaultSensor(type2); 815 if (s1 == null 816 || s1.getHighestDirectReportRateLevel() < rateLevel1 817 || !s1.isDirectChannelTypeSupported(memType)) { 818 return; 819 } 820 821 if (s2 == null 822 || s2.getHighestDirectReportRateLevel() < rateLevel2 823 || !s2.isDirectChannelTypeSupported(memType)) { 824 return; 825 } 826 resetEvent(); 827 828 mChannel = prepareDirectChannel(memType, false /* secondary */); 829 assertTrue("createDirectChannel failed", mChannel != null); 830 831 try { 832 assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType)); 833 waitBeforeStartSensor(); 834 835 int token1 = mChannel.configure(s1, rateLevel1); 836 int token2 = mChannel.configure(s2, rateLevel2); 837 assertTrue("configure direct mChannel failed, token1 = " + token1, token1 > 0); 838 assertTrue("configure direct mChannel failed, token2 = " + token2, token2 > 0); 839 840 // run half amount of time so buffer is enough for both sensors 841 try { 842 SensorCtsHelper.sleep(TEST_RUN_TIME_PERIOD_MILLISEC / 2, TimeUnit.MILLISECONDS); 843 } catch (InterruptedException e) { 844 Thread.currentThread().interrupt(); 845 } 846 847 //stop sensor and analyze content 848 mChannel.configure(s1, SensorDirectChannel.RATE_STOP); 849 mChannel.configure(s2, SensorDirectChannel.RATE_STOP); 850 851 readSharedMemory(memType, false /*secondary*/); 852 checkEventRate(TEST_RUN_TIME_PERIOD_MILLISEC / 2, 853 parseEntireBuffer(token1, mEventPool, mByteBuffer, SHARED_MEMORY_SIZE), 854 type1, rateLevel1); 855 checkEventRate(TEST_RUN_TIME_PERIOD_MILLISEC / 2, 856 parseEntireBuffer(token2, mEventPool, mByteBuffer, SHARED_MEMORY_SIZE), 857 type2, rateLevel2); 858 } finally { 859 mChannel.close(); 860 mChannel = null; 861 } 862 } 863 runMultiChannelRateIndependencyTest( int type, int rateLevel1, int rateLevel2, int memType1, int memType2)864 private void runMultiChannelRateIndependencyTest( 865 int type, int rateLevel1, int rateLevel2, int memType1, int memType2) 866 throws AssertionError { 867 Sensor s = mSensorManager.getDefaultSensor(type); 868 if (s == null 869 || s.getHighestDirectReportRateLevel() < Math.max(rateLevel1, rateLevel2) 870 || !s.isDirectChannelTypeSupported(memType1) 871 || !s.isDirectChannelTypeSupported(memType2)) { 872 return; 873 } 874 resetEvent(); 875 876 mChannel = prepareDirectChannel(memType1, false /* secondary */); 877 mChannelSecondary = prepareDirectChannel(memType2, true /* secondary */); 878 879 try { 880 assertTrue("createDirectChannel failed", mChannel != null); 881 assertTrue("Shared memory is not formatted", 882 isSharedMemoryFormatted(memType1)); 883 884 assertTrue("createDirectChannel(secondary) failed", mChannelSecondary != null); 885 assertTrue("Shared memory(secondary) is not formatted", 886 isSharedMemoryFormatted(memType2, true)); 887 888 waitBeforeStartSensor(); 889 890 int token1 = mChannel.configure(s, rateLevel1); 891 int token2 = mChannelSecondary.configure(s, rateLevel2); 892 assertTrue("configure direct mChannel failed", token1 > 0); 893 assertTrue("configure direct mChannelSecondary failed", token2 > 0); 894 895 waitSensorCollection(); 896 897 //stop sensor and analyze content 898 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 899 mChannelSecondary.configure(s, SensorDirectChannel.RATE_STOP); 900 901 // check rate 902 readSharedMemory(memType1, false /*secondary*/); 903 checkEventRate(TEST_RUN_TIME_PERIOD_MILLISEC, parseEntireBuffer(token1, mEventPool, 904 mByteBuffer, SHARED_MEMORY_SIZE), type, rateLevel1); 905 906 readSharedMemory(memType2, true /*secondary*/); 907 checkEventRate(TEST_RUN_TIME_PERIOD_MILLISEC, parseEntireBuffer(token2, mEventPool, 908 mByteBuffer, SHARED_MEMORY_SIZE), type, rateLevel2); 909 } finally { 910 if (mChannel != null) { 911 mChannel.close(); 912 mChannel = null; 913 } 914 if (mChannelSecondary != null) { 915 mChannelSecondary.close(); 916 mChannelSecondary = null; 917 } 918 } 919 } 920 runMultiModeRateIndependencyTest( int type , int rateLevel, int memType, int samplingPeriodUs)921 private void runMultiModeRateIndependencyTest( 922 int type , int rateLevel, int memType, int samplingPeriodUs) 923 throws AssertionError { 924 final Sensor s = mSensorManager.getDefaultSensor(type); 925 if (s == null 926 || s.getHighestDirectReportRateLevel() < rateLevel 927 || !s.isDirectChannelTypeSupported(memType)) { 928 return; 929 } 930 931 if (samplingPeriodUs == 0) { 932 samplingPeriodUs = s.getMinDelay(); 933 } 934 935 if (samplingPeriodUs < s.getMinDelay()) { 936 return; 937 } 938 939 if (samplingPeriodUs > s.getMaxDelay()) { 940 samplingPeriodUs = s.getMaxDelay(); 941 } 942 943 resetEvent(); 944 945 mChannel = prepareDirectChannel(memType, false /* secondary */); 946 assertTrue("createDirectChannel failed", mChannel != null); 947 SensorEventCollection listener = new SensorEventCollection(s); 948 949 try { 950 waitBeforeStartSensor(); 951 int token = mChannel.configure(s, rateLevel); 952 boolean registerRet = mSensorManager.registerListener(listener, s, samplingPeriodUs); 953 assertTrue("Register listener failed", registerRet); 954 955 waitSensorCollection(); 956 957 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 958 mSensorManager.unregisterListener(listener); 959 960 // check direct report rate 961 readSharedMemory(memType, false /*secondary*/); 962 List<DirectReportSensorEvent> events = parseEntireBuffer(token, mEventPool, mByteBuffer, 963 SHARED_MEMORY_SIZE); 964 checkEventRate(TEST_RUN_TIME_PERIOD_MILLISEC, events, type, rateLevel); 965 966 // check callback interface rate 967 checkEventRateUs(TEST_RUN_TIME_PERIOD_MILLISEC, listener.getEvents(), type, 968 samplingPeriodUs); 969 } finally { 970 mChannel.close(); 971 mChannel = null; 972 mSensorManager.unregisterListener(listener); 973 } 974 } 975 runTimestampTest(int type, int rateLevel, int memType)976 private void runTimestampTest(int type, int rateLevel, int memType) { 977 Sensor s = mSensorManager.getDefaultSensor(type); 978 if (s == null 979 || s.getHighestDirectReportRateLevel() < rateLevel 980 || !s.isDirectChannelTypeSupported(memType)) { 981 return; 982 } 983 resetEvent(); 984 985 mChannel = prepareDirectChannel(memType, false /* secondary */); 986 assertTrue("createDirectChannel failed", mChannel != null); 987 988 SensorEventCollection listener = new SensorEventCollection(s); 989 990 try { 991 float nominalFreq = getNominalFreq(rateLevel); 992 int samplingPeriodUs = Math.max((int) (1e6f / nominalFreq), s.getMinDelay()); 993 994 assertTrue("Shared memory is not formatted", 995 isSharedMemoryFormatted(memType)); 996 997 int token = mChannel.configure(s, rateLevel); 998 assertTrue("configure direct mChannel failed", token > 0); 999 1000 boolean registerRet = mSensorManager.registerListener(listener, s, samplingPeriodUs); 1001 assertTrue("Register listener failed", registerRet); 1002 1003 List<DirectReportSensorEvent> events = collectSensorEventsRealtime( 1004 memType, false /*secondary*/, TEST_RUN_TIME_PERIOD_MILLISEC); 1005 assertTrue("Realtime event collection failed", events != null); 1006 assertTrue("Realtime event collection got no data", events.size() > 0); 1007 1008 //stop sensor and analyze content 1009 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 1010 mSensorManager.unregisterListener(listener); 1011 1012 // check rate 1013 checkTimestampRelative(events, listener.getEvents()); 1014 checkTimestampAbsolute(events); 1015 } finally { 1016 mChannel.close(); 1017 mChannel = null; 1018 } 1019 } 1020 runAtomicCounterTest(int sensorType, int memType)1021 private void runAtomicCounterTest(int sensorType, int memType) throws AssertionError { 1022 Sensor s = mSensorManager.getDefaultSensor(sensorType); 1023 if (s == null 1024 || s.getHighestDirectReportRateLevel() == SensorDirectChannel.RATE_STOP 1025 || !s.isDirectChannelTypeSupported(memType)) { 1026 return; 1027 } 1028 resetEvent(); 1029 1030 mChannel = prepareDirectChannel(memType, false /* secondary */); 1031 assertTrue("createDirectChannel failed", mChannel != null); 1032 1033 try { 1034 assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType)); 1035 waitBeforeStartSensor(); 1036 1037 //int token = mChannel.configure(s, SensorDirectChannel.RATE_FAST); 1038 int token = mChannel.configure(s, s.getHighestDirectReportRateLevel()); 1039 assertTrue("configure direct mChannel failed", token > 0); 1040 1041 checkAtomicCounterUpdate(memType, 30 * 1000); // half min 1042 1043 //stop sensor and analyze content 1044 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 1045 } finally { 1046 mChannel.close(); 1047 mChannel = null; 1048 } 1049 } 1050 runReconfigureTest(int type, int memType)1051 private void runReconfigureTest(int type, int memType) { 1052 Sensor s = mSensorManager.getDefaultSensor(type); 1053 if (s == null 1054 || s.getHighestDirectReportRateLevel() == SensorDirectChannel.RATE_STOP 1055 || !s.isDirectChannelTypeSupported(memType)) { 1056 return; 1057 } 1058 resetEvent(); 1059 1060 mChannel = prepareDirectChannel(memType, false /* secondary */); 1061 assertTrue("createDirectChannel failed", mChannel != null); 1062 1063 try { 1064 assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType)); 1065 waitBeforeStartSensor(); 1066 1067 int offset = 0; 1068 long counter = 1; 1069 List<Integer> rateLevels = new ArrayList<>(); 1070 List<DirectReportSensorEvent> events; 1071 1072 rateLevels.add(s.getHighestDirectReportRateLevel()); 1073 rateLevels.add(s.getHighestDirectReportRateLevel()); 1074 if (s.getHighestDirectReportRateLevel() != SensorDirectChannel.RATE_NORMAL) { 1075 rateLevels.add(SensorDirectChannel.RATE_NORMAL); 1076 } 1077 1078 for (int rateLevel : rateLevels) { 1079 int token = mChannel.configure(s, rateLevel); 1080 assertTrue("configure direct mChannel failed", token > 0); 1081 1082 events = collectSensorEventsRealtime(memType, false /*secondary*/, 1083 TEST_RUN_TIME_PERIOD_MILLISEC, 1084 offset, counter); 1085 // stop sensor 1086 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 1087 checkEventRate(TEST_RUN_TIME_PERIOD_MILLISEC, events, type, rateLevel); 1088 1089 // collect all events after stop 1090 events = collectSensorEventsRealtime(memType, false /*secondary*/, 1091 REST_PERIOD_BEFORE_TEST_MILLISEC, 1092 offset, counter); 1093 if (events.size() > 0) { 1094 offset += (events.size() * SENSORS_EVENT_SIZE ) % SHARED_MEMORY_SIZE; 1095 counter = events.get(events.size() - 1).serial; 1096 } 1097 } 1098 1099 // finally stop the report 1100 mChannel.configure(s, SensorDirectChannel.RATE_STOP); 1101 } finally { 1102 mChannel.close(); 1103 mChannel = null; 1104 } 1105 } 1106 waitBeforeStartSensor()1107 public static void waitBeforeStartSensor() { 1108 // wait for sensor system to come to a rest after previous test to avoid flakiness. 1109 try { 1110 SensorCtsHelper.sleep(REST_PERIOD_BEFORE_TEST_MILLISEC, TimeUnit.MILLISECONDS); 1111 } catch (InterruptedException e) { 1112 Thread.currentThread().interrupt(); 1113 } 1114 } 1115 waitSensorCollection()1116 private void waitSensorCollection() { 1117 // wait for sensor collection to finish 1118 try { 1119 SensorCtsHelper.sleep(TEST_RUN_TIME_PERIOD_MILLISEC, TimeUnit.MILLISECONDS); 1120 } catch (InterruptedException e) { 1121 Thread.currentThread().interrupt(); 1122 } 1123 } 1124 collectSensorEventsRealtime( int memType, boolean secondary, int timeoutMs)1125 private List<DirectReportSensorEvent> collectSensorEventsRealtime( 1126 int memType, boolean secondary, int timeoutMs) { 1127 return collectSensorEventsRealtime(memType, secondary, timeoutMs, 1128 0 /*initialOffset*/, 1l /*initialCounter*/); 1129 } 1130 collectSensorEventsRealtime( int memType, boolean secondary, int timeoutMs, int initialOffset, long initialCounter)1131 private List<DirectReportSensorEvent> collectSensorEventsRealtime( 1132 int memType, boolean secondary, int timeoutMs, int initialOffset, long initialCounter) { 1133 List<DirectReportSensorEvent> events = new ArrayList<>(); 1134 long endTime = SystemClock.elapsedRealtime() + timeoutMs; 1135 1136 long atomicCounter = initialCounter; 1137 int offset = initialOffset; 1138 1139 long timeA = SystemClock.elapsedRealtimeNanos(); 1140 boolean synced = false; 1141 int filtered = 0; 1142 1143 while (SystemClock.elapsedRealtime() < endTime) { 1144 if (!readSharedMemory( 1145 memType, secondary, offset + ATOMIC_COUNTER_OFFSET, ATOMIC_COUNTER_SIZE)) { 1146 return null; 1147 } 1148 1149 long timeB = SystemClock.elapsedRealtimeNanos(); 1150 if (timeB - timeA > 1_000_000L ) { // > 1ms 1151 synced = false; 1152 } 1153 timeA = timeB; 1154 1155 if (readAtomicCounter(offset) == atomicCounter) { 1156 // read entire event again and parse 1157 if (!readSharedMemory(memType, secondary, offset, SENSORS_EVENT_SIZE)) { 1158 return null; 1159 } 1160 DirectReportSensorEvent e = mEventPool.get(); 1161 assertNotNull("cannot get event from reserve", e); 1162 parseSensorEvent(offset, e, mByteBuffer); 1163 1164 atomicCounter += 1; 1165 if (synced) { 1166 events.add(e); 1167 } else { 1168 ++filtered; 1169 } 1170 1171 offset += SENSORS_EVENT_SIZE; 1172 if (offset + SENSORS_EVENT_SIZE > SHARED_MEMORY_SIZE) { 1173 offset = 0; 1174 } 1175 } else { 1176 synced = true; 1177 } 1178 } 1179 Log.d(TAG, "filtered " + filtered + " events, remain " + events.size() + " events"); 1180 return events; 1181 } 1182 checkAtomicCounterUpdate(int memType, int timeoutMs)1183 private void checkAtomicCounterUpdate(int memType, int timeoutMs) { 1184 List<DirectReportSensorEvent> events = new ArrayList<>(); 1185 long endTime = SystemClock.elapsedRealtime() + timeoutMs; 1186 1187 boolean lastValid = false; 1188 long atomicCounter = 1; 1189 int lastOffset = 0; 1190 int offset = 0; 1191 1192 byte[] lastArray = new byte[SENSORS_EVENT_SIZE]; 1193 DirectReportSensorEvent e = getEvent(); 1194 1195 while (SystemClock.elapsedRealtime() < endTime) { 1196 if (!readSharedMemory(memType, false/*secondary*/, lastOffset, SENSORS_EVENT_SIZE) 1197 || !readSharedMemory(memType, false/*secondary*/, 1198 offset + ATOMIC_COUNTER_OFFSET, ATOMIC_COUNTER_SIZE)) { 1199 throw new IllegalStateException("cannot read shared memory, type " + memType); 1200 } 1201 1202 if (lastValid) { 1203 boolean failed = false; 1204 int i; 1205 for (i = 0; i < SENSORS_EVENT_SIZE; ++i) { 1206 if (lastArray[i] != mBuffer[lastOffset + i]) { 1207 failed = true; 1208 break; 1209 } 1210 } 1211 1212 if (failed) { 1213 byte[] currentArray = new byte[SENSORS_EVENT_SIZE]; 1214 System.arraycopy(mBuffer, lastOffset, currentArray, 0, SENSORS_EVENT_SIZE); 1215 1216 // wait for 100ms and read again to see if the change settle 1217 try { 1218 SensorCtsHelper.sleep(100, TimeUnit.MILLISECONDS); 1219 } catch (InterruptedException ex) { 1220 Thread.currentThread().interrupt(); 1221 } 1222 1223 byte[] delayedRead = new byte[SENSORS_EVENT_SIZE]; 1224 if (!readSharedMemory( 1225 memType, false/*secondary*/, lastOffset, SENSORS_EVENT_SIZE)) { 1226 throw new IllegalStateException( 1227 "cannot read shared memory, type " + memType); 1228 } 1229 System.arraycopy(mBuffer, lastOffset, delayedRead, 0, SENSORS_EVENT_SIZE); 1230 1231 fail(String.format( 1232 "At offset %d(0x%x), byte %d(0x%x) changed after atomicCounter" 1233 + "(expecting %d, 0x%x) update, old = [%s], new = [%s], " 1234 + "delayed = [%s]", 1235 lastOffset, lastOffset, i, i, atomicCounter, atomicCounter, 1236 SensorCtsHelper.bytesToHex(lastArray, -1, -1), 1237 SensorCtsHelper.bytesToHex(currentArray, -1, -1), 1238 SensorCtsHelper.bytesToHex(delayedRead, -1, -1))); 1239 } 1240 } 1241 1242 if (readAtomicCounter(offset) == atomicCounter) { 1243 // read entire event again and parse 1244 if (!readSharedMemory(memType, false/*secondary*/, offset, SENSORS_EVENT_SIZE)) { 1245 throw new IllegalStateException("cannot read shared memory, type " + memType); 1246 } 1247 parseSensorEvent(offset, e, mByteBuffer); 1248 1249 atomicCounter += 1; 1250 1251 lastOffset = offset; 1252 System.arraycopy(mBuffer, lastOffset, lastArray, 0, SENSORS_EVENT_SIZE); 1253 lastValid = true; 1254 1255 offset += SENSORS_EVENT_SIZE; 1256 if (offset + SENSORS_EVENT_SIZE > SHARED_MEMORY_SIZE) { 1257 offset = 0; 1258 } 1259 } 1260 } 1261 Log.d(TAG, "at finish checkAtomicCounterUpdate has atomic counter = " + atomicCounter); 1262 // atomicCounter will not wrap back in reasonable amount of time 1263 assertTrue("Realtime event collection got no data", atomicCounter != 1); 1264 } 1265 allocateMemoryFile()1266 private MemoryFile allocateMemoryFile() { 1267 MemoryFile memFile = null; 1268 try { 1269 memFile = new MemoryFile("Sensor Channel", SHARED_MEMORY_SIZE); 1270 } catch (IOException e) { 1271 Log.e(TAG, "IOException when allocating MemoryFile"); 1272 } 1273 return memFile; 1274 } 1275 allocateHardwareBuffer()1276 private HardwareBuffer allocateHardwareBuffer() { 1277 HardwareBuffer hardwareBuffer; 1278 1279 hardwareBuffer = HardwareBuffer.create( 1280 SHARED_MEMORY_SIZE, 1 /* height */, HardwareBuffer.BLOB, 1 /* layer */, 1281 HardwareBuffer.USAGE_CPU_READ_OFTEN | HardwareBuffer.USAGE_GPU_DATA_BUFFER 1282 | HardwareBuffer.USAGE_SENSOR_DIRECT_DATA); 1283 return hardwareBuffer; 1284 } 1285 prepareDirectChannel(int memType, boolean secondary)1286 private SensorDirectChannel prepareDirectChannel(int memType, boolean secondary) { 1287 SensorDirectChannel channel = null; 1288 1289 try { 1290 switch(memType) { 1291 case SensorDirectChannel.TYPE_MEMORY_FILE: { 1292 MemoryFile memoryFile = secondary ? mMemoryFileSecondary : mMemoryFile; 1293 assertTrue("MemoryFile" + (secondary ? "(secondary)" : "") + " is null", 1294 memoryFile != null); 1295 channel = mSensorManager.createDirectChannel(memoryFile); 1296 break; 1297 } 1298 case SensorDirectChannel.TYPE_HARDWARE_BUFFER: { 1299 HardwareBuffer hardwareBuffer 1300 = secondary ? mHardwareBufferSecondary : mHardwareBuffer; 1301 assertTrue("HardwareBuffer" + (secondary ? "(secondary)" : "") + " is null", 1302 hardwareBuffer != null); 1303 channel = mSensorManager.createDirectChannel(hardwareBuffer); 1304 break; 1305 } 1306 default: 1307 Log.e(TAG, "Specified illegal memory type " + memType); 1308 } 1309 } catch (IllegalStateException | UncheckedIOException e) { 1310 Log.e(TAG, "Cannot initialize channel for memory type " + memType 1311 + ", details:" + e); 1312 channel = null; 1313 } 1314 return channel; 1315 } 1316 readSharedMemory(int memType, boolean secondary, int offset, int length)1317 private boolean readSharedMemory(int memType, boolean secondary, int offset, int length) { 1318 switch(memType) { 1319 case SensorDirectChannel.TYPE_MEMORY_FILE: 1320 try { 1321 MemoryFile f = secondary ? mMemoryFileSecondary : mMemoryFile; 1322 if (f.readBytes(mBuffer, offset, offset, length) != length) { 1323 Log.e(TAG, "cannot read entire MemoryFile"); 1324 return false; 1325 } 1326 } catch (IOException e) { 1327 Log.e(TAG, "accessing MemoryFile causes IOException"); 1328 return false; 1329 } 1330 return true; 1331 case SensorDirectChannel.TYPE_HARDWARE_BUFFER: 1332 return nativeReadHardwareBuffer( 1333 secondary ? mHardwareBufferSecondary : mHardwareBuffer, 1334 mBuffer, offset, offset, length); 1335 default: 1336 return false; 1337 } 1338 } 1339 readSharedMemory(int memType, boolean secondary)1340 private boolean readSharedMemory(int memType, boolean secondary) { 1341 return readSharedMemory(memType, secondary, 0, SHARED_MEMORY_SIZE); 1342 } 1343 readSharedMemory(int memType)1344 private boolean readSharedMemory(int memType) { 1345 return readSharedMemory(memType, false /*secondary*/); 1346 } 1347 isMemoryTypeNeeded(int memType)1348 private boolean isMemoryTypeNeeded(int memType) { 1349 List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); 1350 for (Sensor s : sensorList) { 1351 if (s.isDirectChannelTypeSupported(memType)) { 1352 return true; 1353 } 1354 } 1355 return false; 1356 } 1357 isSharedMemoryFormatted(int memType)1358 private boolean isSharedMemoryFormatted(int memType) { 1359 return isSharedMemoryFormatted(memType, false /* secondary */); 1360 } 1361 isSharedMemoryFormatted(int memType, boolean secondary)1362 private boolean isSharedMemoryFormatted(int memType, boolean secondary) { 1363 readSharedMemory(memType, secondary); 1364 1365 for (byte b : mBuffer) { 1366 if (b != 0) { 1367 return false; 1368 } 1369 } 1370 return true; 1371 } 1372 checkSharedMemoryContent(Sensor s, int memType, int rateLevel, int token)1373 private void checkSharedMemoryContent(Sensor s, int memType, int rateLevel, int token) { 1374 assertTrue("read mem type " + memType + " content failed", readSharedMemory(memType)); 1375 1376 int offset = 0; 1377 int nextSerial = 1; 1378 DirectReportSensorEvent e = getEvent(); 1379 while (offset <= SHARED_MEMORY_SIZE - SENSORS_EVENT_SIZE) { 1380 parseSensorEvent(offset, e, mByteBuffer); 1381 1382 if (e.serial == 0) { 1383 // reaches end of events 1384 break; 1385 } 1386 1387 assertTrue("incorrect size " + e.size + " at offset " + offset, 1388 e.size == SENSORS_EVENT_SIZE); 1389 assertTrue("incorrect token " + e.token + " at offset " + offset, 1390 e.token == token); 1391 assertTrue("incorrect serial " + e.serial + " at offset " + offset, 1392 e.serial == nextSerial); 1393 assertTrue("incorrect type " + e.type + " offset " + offset, 1394 e.type == s.getType()); 1395 1396 switch(s.getType()) { 1397 case Sensor.TYPE_ACCELEROMETER: 1398 double accNorm = Math.sqrt(e.x * e.x + e.y * e.y + e.z * e.z); 1399 assertTrue("incorrect gravity norm " + accNorm + " at offset " + offset, 1400 accNorm < GRAVITY_MAX && accNorm > GRAVITY_MIN); 1401 break; 1402 case Sensor.TYPE_GYROSCOPE: 1403 double gyroNorm = Math.sqrt(e.x * e.x + e.y * e.y + e.z * e.z); 1404 assertTrue("gyro norm too large (" + gyroNorm + ") at offset " + offset, 1405 gyroNorm < GYRO_NORM_MAX); 1406 break; 1407 } 1408 1409 ++nextSerial; 1410 offset += SENSORS_EVENT_SIZE; 1411 } 1412 1413 int nEvents = nextSerial - 1; 1414 float nominalFreq = 0; 1415 1416 switch (rateLevel) { 1417 case SensorDirectChannel.RATE_NORMAL: 1418 nominalFreq = RATE_NORMAL_NOMINAL; 1419 break; 1420 case SensorDirectChannel.RATE_FAST: 1421 nominalFreq = RATE_FAST_NOMINAL; 1422 break; 1423 case SensorDirectChannel.RATE_VERY_FAST: 1424 nominalFreq = RATE_VERY_FAST_NOMINAL; 1425 break; 1426 } 1427 1428 if (nominalFreq != 0) { 1429 int minEvents; 1430 int maxEvents; 1431 minEvents = (int) Math.floor( 1432 nominalFreq 1433 * FREQ_LOWER_BOUND 1434 * (TEST_RUN_TIME_PERIOD_MILLISEC - ALLOWED_SENSOR_INIT_TIME_MILLISEC) 1435 * (1 - MERCY_FACTOR) 1436 / 1000); 1437 maxEvents = (int) Math.ceil( 1438 nominalFreq 1439 * FREQ_UPPER_BOUND 1440 * TEST_RUN_TIME_PERIOD_MILLISEC 1441 * (1 + MERCY_FACTOR) 1442 / 1000); 1443 1444 assertTrue("nEvent is " + nEvents + " not between " + minEvents + " and " + maxEvents, 1445 nEvents >= minEvents && nEvents <=maxEvents); 1446 } 1447 } 1448 checkEventRate(int testTimeMs, List<DirectReportSensorEvent> events, int type, int rateLevel)1449 private void checkEventRate(int testTimeMs, List<DirectReportSensorEvent> events, 1450 int type, int rateLevel) { 1451 assertTrue("insufficient events of type " + type, events.size() > 1); 1452 for (DirectReportSensorEvent e : events) { 1453 assertTrue("incorrect type " + e.type + " expecting " + type, e.type == type); 1454 } 1455 1456 // check number of events 1457 int[] minMax = calculateExpectedNEvents(testTimeMs, rateLevel); 1458 assertTrue( 1459 "Number of event of type " + type + " is " + events.size() 1460 + ", which is not in range [" + minMax[0] + ", " + minMax[1] + "].", 1461 minMax[0] <= events.size() && events.size() <= minMax[1]); 1462 1463 // intervals 1464 List<Long> intervals = new ArrayList<>(events.size() - 1); 1465 long minInterval = Long.MAX_VALUE; 1466 long maxInterval = Long.MIN_VALUE; 1467 long averageInterval = 0; 1468 for (int i = 1; i < events.size(); ++i) { 1469 long d = events.get(i).ts - events.get(i-1).ts; 1470 averageInterval += d; 1471 minInterval = Math.min(d, minInterval); 1472 maxInterval = Math.max(d, maxInterval); 1473 intervals.add(d); 1474 } 1475 averageInterval /= (events.size() - 1); 1476 1477 // average rate 1478 float averageFreq = 1e9f / averageInterval; 1479 float nominalFreq = getNominalFreq(rateLevel); 1480 Log.d(TAG, String.format( 1481 "checkEventRate type %d: averageFreq %f, nominalFreq %f, lbound %f, ubound %f", 1482 type, averageFreq, nominalFreq, 1483 nominalFreq * FREQ_LOWER_BOUND, 1484 nominalFreq * FREQ_UPPER_BOUND)); 1485 assertTrue("Average frequency of type " + type + " rateLevel " + rateLevel 1486 + " is " + averageFreq, 1487 nominalFreq * FREQ_LOWER_BOUND * (1 - MERCY_FACTOR) <= averageFreq && 1488 averageFreq <= nominalFreq * FREQ_UPPER_BOUND * (1 + MERCY_FACTOR)); 1489 1490 // jitter variance 1491 List<Long> percentileValues = 1492 SensorCtsHelper.getPercentileValue(intervals, 0.025f, (1 - 0.025f)); 1493 assertTrue("Timestamp jitter of type " + type + " rateLevel " + rateLevel + " is " 1494 + (percentileValues.get(1) - percentileValues.get(0) / 1000) + " us, " 1495 + "while average interval is " + (averageInterval / 1000) + "us, over-range", 1496 (percentileValues.get(1) - percentileValues.get(0)) / averageInterval < 0.05); 1497 Log.d(TAG, String.format( 1498 "checkEventRate type %d, timestamp interval range %f - %f ms, " + 1499 "span %f ms, %.2f%% of averageInterval", 1500 type, percentileValues.get(0)/1e6f, percentileValues.get(1)/1e6f, 1501 (percentileValues.get(1) - percentileValues.get(0))/1e6f, 1502 (percentileValues.get(1) - percentileValues.get(0)) / averageInterval * 100.f)); 1503 1504 } 1505 checkEventRateUs(int testTimeMs, List<DirectReportSensorEvent> events, int type, int samplingPeriodUs)1506 private void checkEventRateUs(int testTimeMs, List<DirectReportSensorEvent> events, 1507 int type, int samplingPeriodUs) { 1508 // samplingPeriodUs must be a valid one advertised by sensor 1509 assertTrue("insufficient events of type " + type, events.size() > 1); 1510 for (DirectReportSensorEvent e : events) { 1511 assertTrue("incorrect type " + e.type + " expecting " + type, e.type == type); 1512 } 1513 1514 // check number of events 1515 int[] minMax = calculateExpectedNEventsUs(testTimeMs, samplingPeriodUs); 1516 assertTrue( 1517 "Number of event of type " + type + " is " + events.size() 1518 + ", which is not in range [" + minMax[0] + ", " + minMax[1] + "].", 1519 minMax[0] <= events.size() && events.size() <= minMax[1]); 1520 1521 // intervals 1522 List<Long> intervals = new ArrayList<>(events.size() - 1); 1523 long minInterval = Long.MAX_VALUE; 1524 long maxInterval = Long.MIN_VALUE; 1525 long averageInterval = 0; 1526 for (int i = 1; i < events.size(); ++i) { 1527 long d = events.get(i).ts - events.get(i-1).ts; 1528 averageInterval += d; 1529 minInterval = Math.min(d, minInterval); 1530 maxInterval = Math.max(d, maxInterval); 1531 intervals.add(d); 1532 } 1533 averageInterval /= (events.size() - 1); 1534 1535 // average rate 1536 float averageFreq = 1e9f / averageInterval; 1537 float nominalFreq = 1e6f / samplingPeriodUs; 1538 Log.d(TAG, String.format( 1539 "checkEventRateUs type %d: averageFreq %f, nominalFreq %f, lbound %f, ubound %f", 1540 type, averageFreq, nominalFreq, 1541 nominalFreq * FREQ_LOWER_BOUND_POLL, 1542 nominalFreq * FREQ_UPPER_BOUND_POLL)); 1543 assertTrue("Average frequency of type " + type 1544 + " is " + averageFreq, 1545 nominalFreq * FREQ_LOWER_BOUND_POLL * (1 - MERCY_FACTOR) <= averageFreq && 1546 averageFreq <= nominalFreq * FREQ_UPPER_BOUND_POLL * (1 + MERCY_FACTOR)); 1547 1548 // jitter variance 1549 List<Long> percentileValues = 1550 SensorCtsHelper.getPercentileValue(intervals, 0.025f, (1 - 0.025f)); 1551 assertTrue("Timestamp jitter of type " + type + " is " 1552 + (percentileValues.get(1) - percentileValues.get(0) / 1000) + " us, " 1553 + "while average interval is " + (averageInterval / 1000) + "us, over-range", 1554 (percentileValues.get(1) - percentileValues.get(0)) / averageInterval < 0.05); 1555 Log.d(TAG, String.format( 1556 "checkEventRateUs type %d, timestamp interval range %f - %f ms, " + 1557 "span %f ms, %.2f%% of averageInterval", 1558 type, percentileValues.get(0)/1e6f, percentileValues.get(1)/1e6f, 1559 (percentileValues.get(1) - percentileValues.get(0)) / 1e6f, 1560 (percentileValues.get(1) - percentileValues.get(0)) / averageInterval * 100.f)); 1561 } 1562 allocateSharedMemory()1563 private void allocateSharedMemory() { 1564 if (mNeedMemoryFile) { 1565 mMemoryFile = allocateMemoryFile(); 1566 mMemoryFileSecondary = allocateMemoryFile(); 1567 } 1568 1569 if (mNeedHardwareBuffer) { 1570 mHardwareBuffer = allocateHardwareBuffer(); 1571 mHardwareBufferSecondary = allocateHardwareBuffer(); 1572 } 1573 } 1574 freeSharedMemory()1575 private void freeSharedMemory() { 1576 if (mMemoryFile != null) { 1577 mMemoryFile.close(); 1578 mMemoryFile = null; 1579 } 1580 1581 if (mMemoryFileSecondary != null) { 1582 mMemoryFileSecondary.close(); 1583 mMemoryFileSecondary = null; 1584 } 1585 1586 if (mHardwareBuffer != null) { 1587 mHardwareBuffer.close(); 1588 mHardwareBuffer = null; 1589 } 1590 1591 if (mHardwareBufferSecondary != null) { 1592 mHardwareBufferSecondary.close(); 1593 mHardwareBufferSecondary = null; 1594 } 1595 } 1596 getNominalFreq(int rateLevel)1597 private float getNominalFreq(int rateLevel) { 1598 float nominalFreq = 0; 1599 switch (rateLevel) { 1600 case SensorDirectChannel.RATE_NORMAL: 1601 nominalFreq = RATE_NORMAL_NOMINAL; 1602 break; 1603 case SensorDirectChannel.RATE_FAST: 1604 nominalFreq = RATE_FAST_NOMINAL; 1605 break; 1606 case SensorDirectChannel.RATE_VERY_FAST: 1607 nominalFreq = RATE_VERY_FAST_NOMINAL; 1608 break; 1609 } 1610 return nominalFreq; 1611 } 1612 calculateExpectedNEvents(int timeMs, int rateLevel)1613 private int[] calculateExpectedNEvents(int timeMs, int rateLevel) { 1614 int[] minMax = new int[] { -1, Integer.MAX_VALUE }; 1615 float nominalFreq = getNominalFreq(rateLevel); 1616 if (nominalFreq != 0) { 1617 // min 1618 if (timeMs > ALLOWED_SENSOR_INIT_TIME_MILLISEC) { 1619 minMax[0] = (int) Math.floor( 1620 nominalFreq 1621 * FREQ_LOWER_BOUND 1622 * (timeMs - ALLOWED_SENSOR_INIT_TIME_MILLISEC) 1623 * (1 - MERCY_FACTOR) 1624 / 1000); 1625 } 1626 // max 1627 minMax[1] = (int) Math.ceil( 1628 nominalFreq 1629 * FREQ_UPPER_BOUND 1630 * timeMs 1631 * (1 + MERCY_FACTOR) 1632 / 1000); 1633 } 1634 return minMax; 1635 } 1636 checkTimestampAbsolute(List<DirectReportSensorEvent> events)1637 private void checkTimestampAbsolute(List<DirectReportSensorEvent> events) { 1638 final int MAX_DETAIL_ITEM = 10; 1639 1640 StringBuffer buf = new StringBuffer(); 1641 int oneMsEarlyCount = 0; 1642 int fiveMsLateCount = 0; 1643 int tenMsLateCount = 0; 1644 int errorCount = 0; 1645 1646 for (int i = 0; i < events.size(); ++i) { 1647 DirectReportSensorEvent e = events.get(i); 1648 long d = e.arrivalTs - e.ts; 1649 boolean oneMsEarly = d < -1000_000; 1650 boolean fiveMsLate = d > 5000_000; 1651 boolean tenMsLate = d > 10_000_000; 1652 1653 if (oneMsEarly || fiveMsLate || tenMsLate) { 1654 oneMsEarlyCount += oneMsEarly ? 1 : 0; 1655 fiveMsLateCount += fiveMsLate ? 1 : 0; 1656 tenMsLateCount += tenMsLate ? 1 : 0; 1657 1658 if (errorCount++ < MAX_DETAIL_ITEM) { 1659 buf.append("[").append(i).append("] diff = ").append(d / 1e6f).append(" ms; "); 1660 } 1661 } 1662 } 1663 1664 Log.d(TAG, String.format("Irregular timestamp, %d, %d, %d out of %d", 1665 oneMsEarlyCount, fiveMsLateCount, tenMsLateCount, events.size())); 1666 1667 if (CHECK_ABSOLUTE_LATENCY) { 1668 assertTrue(String.format( 1669 "Timestamp error, out of %d events, %d is >1ms early, %d is >5ms late, " 1670 + "%d is >10ms late, details: %s%s", 1671 events.size(), oneMsEarlyCount, fiveMsLateCount, tenMsLateCount, 1672 buf.toString(), errorCount > MAX_DETAIL_ITEM ? "..." : ""), 1673 oneMsEarlyCount == 0 1674 && fiveMsLateCount <= events.size() / 20 1675 && tenMsLateCount <= events.size() / 100); 1676 } 1677 } 1678 checkTimestampRelative(List<DirectReportSensorEvent> directEvents, List<DirectReportSensorEvent> pollEvents)1679 private void checkTimestampRelative(List<DirectReportSensorEvent> directEvents, 1680 List<DirectReportSensorEvent> pollEvents) { 1681 if (directEvents.size() < 10 || pollEvents.size() < 10) { 1682 // cannot check with so few data points 1683 return; 1684 } 1685 1686 long directAverageLatency = 0; 1687 for (DirectReportSensorEvent e : directEvents) { 1688 directAverageLatency += e.arrivalTs - e.ts; 1689 } 1690 directAverageLatency /= directEvents.size(); 1691 1692 long pollAverageLatency = 0; 1693 for (DirectReportSensorEvent e : pollEvents) { 1694 pollAverageLatency += e.arrivalTs - e.ts; 1695 } 1696 pollAverageLatency /= pollEvents.size(); 1697 1698 Log.d(TAG, String.format("Direct, poll latency = %f, %f ms", 1699 directAverageLatency / 1e6f, pollAverageLatency / 1e6f)); 1700 assertTrue( 1701 String.format("Direct, poll latency = %f, %f ms, expect direct < poll", 1702 directAverageLatency / 1e6f, 1703 pollAverageLatency / 1e6f), 1704 directAverageLatency < pollAverageLatency + 1000_000); 1705 } 1706 1707 private int[] calculateExpectedNEventsUs(int timeMs, int samplingPeriodUs) { 1708 int[] minMax = new int[2]; 1709 minMax[0] = Math.max((int) Math.floor( 1710 (timeMs - ALLOWED_SENSOR_INIT_TIME_MILLISEC) * 1000/ samplingPeriodUs), 0); 1711 minMax[1] = (int) Math.ceil(timeMs * 1000 * 2 / samplingPeriodUs); 1712 return minMax; 1713 } 1714 1715 public static class DirectReportSensorEvent { 1716 public int size; 1717 public int token; 1718 public int type; 1719 public long serial; 1720 public long ts; 1721 public float x; 1722 public float y; 1723 public float z; 1724 public long arrivalTs; 1725 }; 1726 1727 // EventPool to avoid allocating too many event objects and hitting GC during test 1728 public static class EventPool { 1729 public EventPool(int n) { 1730 mEvents = Arrays.asList(new DirectReportSensorEvent[n]); 1731 for (int i = 0; i < n; ++i) { 1732 mEvents.set(i, new DirectReportSensorEvent()); 1733 } 1734 reset(); 1735 } 1736 1737 public synchronized void reset() { 1738 Log.d(TAG, "Reset EventPool (" + mIndex + " events used)"); 1739 mIndex = 0; 1740 } 1741 1742 public synchronized DirectReportSensorEvent get() { 1743 if (mIndex < mEvents.size()) { 1744 return mEvents.get(mIndex++); 1745 } else { 1746 throw new IllegalStateException("EventPool depleted"); 1747 } 1748 } 1749 1750 private List<DirectReportSensorEvent> mEvents; 1751 private int mIndex; 1752 }; 1753 1754 private DirectReportSensorEvent getEvent() { 1755 return mEventPool.get(); 1756 } 1757 1758 private DirectReportSensorEvent getEvent(DirectReportSensorEvent e) { 1759 DirectReportSensorEvent event = mEventPool.get(); 1760 event.size = e.size; 1761 event.token = e.token; 1762 event.type = e.type; 1763 event.serial = e.serial; 1764 event.ts = e.ts; 1765 event.x = e.x; 1766 event.y = e.y; 1767 event.z = e.z; 1768 event.arrivalTs = e.arrivalTs; 1769 return event; 1770 } 1771 1772 private void resetEvent() { 1773 mEventPool.reset(); 1774 } 1775 1776 private class SensorEventCollection implements SensorEventListener { 1777 List<DirectReportSensorEvent> mEvents = new ArrayList<>(); 1778 Sensor mSensor; 1779 1780 public SensorEventCollection(Sensor s) { 1781 mSensor = s; 1782 } 1783 1784 List<DirectReportSensorEvent> getEvents() { 1785 return mEvents; 1786 } 1787 1788 @Override 1789 public void onSensorChanged(SensorEvent event) { 1790 if (mSensor == null || event.sensor == mSensor) { 1791 DirectReportSensorEvent e = mEventPool.get(); 1792 e.size = SENSORS_EVENT_SIZE; 1793 e.token = event.sensor.getType(); 1794 e.type = e.token; 1795 e.serial = -1; 1796 e.ts = event.timestamp; 1797 e.arrivalTs = SystemClock.elapsedRealtimeNanos(); 1798 1799 e.x = event.values[0]; 1800 if (event.values.length > 1) { 1801 e.y = event.values[1]; 1802 } 1803 if (event.values.length > 2) { 1804 e.z = event.values[2]; 1805 } 1806 mEvents.add(e); 1807 } 1808 } 1809 1810 @Override 1811 public void onAccuracyChanged(Sensor s, int accuracy) { 1812 // do nothing 1813 } 1814 }; 1815 1816 public static List<DirectReportSensorEvent> parseEntireBuffer(int token, EventPool eventPool, 1817 ByteBuffer byteBuffer, int sharedMemorySize) { 1818 int offset = 0; 1819 int nextSerial = 1; 1820 List<DirectReportSensorEvent> events = new ArrayList<>(); 1821 1822 while (offset <= sharedMemorySize - SENSORS_EVENT_SIZE) { 1823 SensorDirectReportTest.DirectReportSensorEvent e = eventPool.get(); 1824 parseSensorEvent(offset, e, byteBuffer); 1825 1826 if (e.serial == 0) { 1827 // reaches end of events 1828 break; 1829 } 1830 1831 assertTrue("incorrect size " + e.size + " at offset " + offset, 1832 e.size == SENSORS_EVENT_SIZE); 1833 assertTrue("incorrect serial " + e.serial + " at offset " + offset, 1834 e.serial == nextSerial); 1835 1836 if (e.token == token) { 1837 events.add(e); 1838 } 1839 1840 ++nextSerial; 1841 offset += SENSORS_EVENT_SIZE; 1842 } 1843 1844 return events; 1845 } 1846 1847 // parse sensors_event_t from byteBuffer and fill information into DirectReportSensorEvent 1848 public static void parseSensorEvent(int offset, DirectReportSensorEvent ev, 1849 ByteBuffer byteBuffer) { 1850 byteBuffer.position(offset); 1851 1852 ev.size = byteBuffer.getInt(); 1853 ev.token = byteBuffer.getInt(); 1854 ev.type = byteBuffer.getInt(); 1855 ev.serial = ((long) byteBuffer.getInt()) & 0xFFFFFFFFl; // signed=>unsigned 1856 ev.ts = byteBuffer.getLong(); 1857 ev.arrivalTs = SystemClock.elapsedRealtimeNanos(); 1858 ev.x = byteBuffer.getFloat(); 1859 ev.y = byteBuffer.getFloat(); 1860 ev.z = byteBuffer.getFloat(); 1861 } 1862 1863 // parse sensors_event_t and fill information into DirectReportSensorEvent 1864 private static void parseSensorEvent(byte [] buf, int offset, DirectReportSensorEvent ev) { 1865 ByteBuffer b = ByteBuffer.wrap(buf, offset, SENSORS_EVENT_SIZE); 1866 b.order(NATIVE_BYTE_ORDER); 1867 1868 ev.size = b.getInt(); 1869 ev.token = b.getInt(); 1870 ev.type = b.getInt(); 1871 ev.serial = ((long) b.getInt()) & 0xFFFFFFFFl; // signed=>unsigned 1872 ev.ts = b.getLong(); 1873 ev.arrivalTs = SystemClock.elapsedRealtimeNanos(); 1874 ev.x = b.getFloat(); 1875 ev.y = b.getFloat(); 1876 ev.z = b.getFloat(); 1877 } 1878 1879 private long readAtomicCounter(int offset) { 1880 mByteBuffer.position(offset + ATOMIC_COUNTER_OFFSET); 1881 return ((long) mByteBuffer.getInt()) & 0xFFFFFFFFl; // signed => unsigned 1882 } 1883 1884 private static long readAtomicCounter(byte [] buf, int offset) { 1885 ByteBuffer b = ByteBuffer.wrap(buf, offset + ATOMIC_COUNTER_OFFSET, ATOMIC_COUNTER_SIZE); 1886 b.order(ByteOrder.nativeOrder()); 1887 1888 return ((long) b.getInt()) & 0xFFFFFFFFl; // signed => unsigned 1889 } 1890 } 1891