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