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 
nativeReadHardwareBuffer(HardwareBuffer hardwareBuffer, byte[] buffer, int srcOffset, int destOffset, int count)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
setUp()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
tearDown()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 
testSharedMemoryAllocation()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 
testAccelerometerAshmemNormal()207     public void testAccelerometerAshmemNormal() {
208         runSensorDirectReportTest(
209                 Sensor.TYPE_ACCELEROMETER,
210                 SensorDirectChannel.TYPE_MEMORY_FILE,
211                 SensorDirectChannel.RATE_NORMAL);
212     }
213 
testGyroscopeAshmemNormal()214     public void testGyroscopeAshmemNormal() {
215         runSensorDirectReportTest(
216                 Sensor.TYPE_GYROSCOPE,
217                 SensorDirectChannel.TYPE_MEMORY_FILE,
218                 SensorDirectChannel.RATE_NORMAL);
219     }
220 
testMagneticFieldAshmemNormal()221     public void testMagneticFieldAshmemNormal() {
222         runSensorDirectReportTest(
223                 Sensor.TYPE_MAGNETIC_FIELD,
224                 SensorDirectChannel.TYPE_MEMORY_FILE,
225                 SensorDirectChannel.RATE_NORMAL);
226     }
227 
testAccelerometerAshmemFast()228     public void testAccelerometerAshmemFast() {
229         runSensorDirectReportTest(
230                 Sensor.TYPE_ACCELEROMETER,
231                 SensorDirectChannel.TYPE_MEMORY_FILE,
232                 SensorDirectChannel.RATE_FAST);
233 
234     }
235 
testGyroscopeAshmemFast()236     public void testGyroscopeAshmemFast() {
237         runSensorDirectReportTest(
238                 Sensor.TYPE_GYROSCOPE,
239                 SensorDirectChannel.TYPE_MEMORY_FILE,
240                 SensorDirectChannel.RATE_FAST);
241     }
242 
testMagneticFieldAshmemFast()243     public void testMagneticFieldAshmemFast() {
244         runSensorDirectReportTest(
245                 Sensor.TYPE_MAGNETIC_FIELD,
246                 SensorDirectChannel.TYPE_MEMORY_FILE,
247                 SensorDirectChannel.RATE_FAST);
248     }
249 
testAccelerometerAshmemVeryFast()250     public void testAccelerometerAshmemVeryFast() {
251         runSensorDirectReportTest(
252                 Sensor.TYPE_ACCELEROMETER,
253                 SensorDirectChannel.TYPE_MEMORY_FILE,
254                 SensorDirectChannel.RATE_VERY_FAST);
255 
256     }
257 
testGyroscopeAshmemVeryFast()258     public void testGyroscopeAshmemVeryFast() {
259         runSensorDirectReportTest(
260                 Sensor.TYPE_GYROSCOPE,
261                 SensorDirectChannel.TYPE_MEMORY_FILE,
262                 SensorDirectChannel.RATE_VERY_FAST);
263     }
264 
testMagneticFieldAshmemVeryFast()265     public void testMagneticFieldAshmemVeryFast() {
266         runSensorDirectReportTest(
267                 Sensor.TYPE_MAGNETIC_FIELD,
268                 SensorDirectChannel.TYPE_MEMORY_FILE,
269                 SensorDirectChannel.RATE_VERY_FAST);
270     }
271 
testAccelerometerHardwareBufferNormal()272     public void testAccelerometerHardwareBufferNormal() {
273         runSensorDirectReportTest(
274                 Sensor.TYPE_ACCELEROMETER,
275                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
276                 SensorDirectChannel.RATE_NORMAL);
277     }
278 
testGyroscopeHardwareBufferNormal()279     public void testGyroscopeHardwareBufferNormal() {
280         runSensorDirectReportTest(
281                 Sensor.TYPE_GYROSCOPE,
282                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
283                 SensorDirectChannel.RATE_NORMAL);
284     }
285 
testMagneticFieldHardwareBufferNormal()286     public void testMagneticFieldHardwareBufferNormal() {
287         runSensorDirectReportTest(
288                 Sensor.TYPE_MAGNETIC_FIELD,
289                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
290                 SensorDirectChannel.RATE_NORMAL);
291     }
292 
testAccelerometerHardwareBufferFast()293     public void testAccelerometerHardwareBufferFast() {
294         runSensorDirectReportTest(
295                 Sensor.TYPE_ACCELEROMETER,
296                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
297                 SensorDirectChannel.RATE_FAST);
298     }
299 
testGyroscopeHardwareBufferFast()300     public void testGyroscopeHardwareBufferFast() {
301         runSensorDirectReportTest(
302                 Sensor.TYPE_GYROSCOPE,
303                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
304                 SensorDirectChannel.RATE_FAST);
305     }
306 
testMagneticFieldHardwareBufferFast()307     public void testMagneticFieldHardwareBufferFast() {
308         runSensorDirectReportTest(
309                 Sensor.TYPE_MAGNETIC_FIELD,
310                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
311                 SensorDirectChannel.RATE_FAST);
312     }
313 
testAccelerometerHardwareBufferVeryFast()314     public void testAccelerometerHardwareBufferVeryFast() {
315         runSensorDirectReportTest(
316                 Sensor.TYPE_ACCELEROMETER,
317                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
318                 SensorDirectChannel.RATE_VERY_FAST);
319     }
320 
testGyroscopeHardwareBufferVeryFast()321     public void testGyroscopeHardwareBufferVeryFast() {
322         runSensorDirectReportTest(
323                 Sensor.TYPE_GYROSCOPE,
324                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
325                 SensorDirectChannel.RATE_VERY_FAST);
326     }
327 
testMagneticFieldHardwareBufferVeryFast()328     public void testMagneticFieldHardwareBufferVeryFast() {
329         runSensorDirectReportTest(
330                 Sensor.TYPE_MAGNETIC_FIELD,
331                 SensorDirectChannel.TYPE_HARDWARE_BUFFER,
332                 SensorDirectChannel.RATE_VERY_FAST);
333     }
334 
testRateIndependencyAccelGyroSingleChannel()335     public void testRateIndependencyAccelGyroSingleChannel() {
336         runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER,
337                                                   Sensor.TYPE_GYROSCOPE);
338     }
339 
testRateIndependencyAccelMagSingleChannel()340     public void testRateIndependencyAccelMagSingleChannel() {
341         runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER,
342                                                   Sensor.TYPE_MAGNETIC_FIELD);
343     }
344 
testRateIndependencyGyroMagSingleChannel()345     public void testRateIndependencyGyroMagSingleChannel() {
346         runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE,
347                                                   Sensor.TYPE_MAGNETIC_FIELD);
348     }
349 
testRateIndependencyAccelUncalAccelSingleChannel()350     public void testRateIndependencyAccelUncalAccelSingleChannel() {
351         runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER,
352                                              Sensor.TYPE_ACCELEROMETER_UNCALIBRATED);
353     }
354 
testRateIndependencyGyroUncalGyroSingleChannel()355     public void testRateIndependencyGyroUncalGyroSingleChannel() {
356         runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE,
357                                              Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
358     }
359 
testRateIndependencyMagUncalMagSingleChannel()360     public void testRateIndependencyMagUncalMagSingleChannel() {
361         runSingleChannelRateIndependencyTestGroup(Sensor.TYPE_MAGNETIC_FIELD,
362                                              Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
363     }
364 
testRateIndependencyAccelMultiChannel()365     public void testRateIndependencyAccelMultiChannel() {
366         runMultiChannelRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER);
367     }
368 
testRateIndependencyGyroMultiChannel()369     public void testRateIndependencyGyroMultiChannel() {
370         runMultiChannelRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE);
371     }
372 
testRateIndependencyMagMultiChannel()373     public void testRateIndependencyMagMultiChannel() {
374         runMultiChannelRateIndependencyTestGroup(Sensor.TYPE_MAGNETIC_FIELD);
375     }
376 
testRateIndependencyAccelMultiMode()377     public void testRateIndependencyAccelMultiMode() {
378         runMultiModeRateIndependencyTestGroup(Sensor.TYPE_ACCELEROMETER);
379     }
380 
testRateIndependencyGyroMultiMode()381     public void testRateIndependencyGyroMultiMode() {
382         runMultiModeRateIndependencyTestGroup(Sensor.TYPE_GYROSCOPE);
383     }
384 
testRateIndependencyMagMultiMode()385     public void testRateIndependencyMagMultiMode() {
386         runMultiModeRateIndependencyTestGroup(Sensor.TYPE_MAGNETIC_FIELD);
387     }
388 
testTimestampAccel()389     public void testTimestampAccel() {
390         runTimestampTestGroup(Sensor.TYPE_ACCELEROMETER);
391     }
392 
testTimestampGyro()393     public void testTimestampGyro() {
394         runTimestampTestGroup(Sensor.TYPE_GYROSCOPE);
395     }
396 
testTimestampMag()397     public void testTimestampMag() {
398         runTimestampTestGroup(Sensor.TYPE_MAGNETIC_FIELD);
399     }
400 
testAtomicCounterAccel()401     public void testAtomicCounterAccel() {
402         for (int memType : POSSIBLE_CHANNEL_TYPES) {
403             runAtomicCounterTest(Sensor.TYPE_ACCELEROMETER, memType);
404         }
405     }
406 
testAtomicCounterGyro()407     public void testAtomicCounterGyro() {
408         for (int memType : POSSIBLE_CHANNEL_TYPES) {
409             runAtomicCounterTest(Sensor.TYPE_GYROSCOPE, memType);
410         }
411     }
412 
testAtomicCounterMag()413     public void testAtomicCounterMag() {
414         for (int memType : POSSIBLE_CHANNEL_TYPES) {
415             runAtomicCounterTest(Sensor.TYPE_MAGNETIC_FIELD, memType);
416         }
417     }
418 
testRegisterMultipleChannels()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 
testRegisterMultipleChannelsUsingSameMemory()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 
testReconfigure()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 
testCloseWithoutConfigStop()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 
runSingleChannelRateIndependencyTestGroup(int type1, int type2)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 
runMultiChannelRateIndependencyTestGroup(int sensorType)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 
runMultiModeRateIndependencyTestGroup(int sensorType)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 
runTimestampTestGroup(int sensorType)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 
runSensorDirectReportTest(int sensorType, int memType, int rateLevel)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 
runSingleChannelRateIndependencyTest( int type1, int rateLevel1, int type2, int rateLevel2, int memType)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 
runMultiChannelRateIndependencyTest( int type, int rateLevel1, int rateLevel2, int memType1, int memType2)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 
runMultiModeRateIndependencyTest( int type , int rateLevel, int memType, int samplingPeriodUs)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 
runTimestampTest(int type, int rateLevel, int memType)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 
runAtomicCounterTest(int sensorType, int memType)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 
runReconfigureTest(int type, int memType)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 
waitBeforeStartSensor()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 
waitSensorCollection()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 
collectSensorEventsRealtime( int memType, boolean secondary, int timeoutMs)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 
collectSensorEventsRealtime( int memType, boolean secondary, int timeoutMs, int initialOffset, long initialCounter)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 
checkAtomicCounterUpdate(int memType, int timeoutMs)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 
allocateMemoryFile()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 
allocateHardwareBuffer()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 
prepareDirectChannel(int memType, boolean secondary)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 
readSharedMemory(int memType, boolean secondary, int offset, int length)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 
readSharedMemory(int memType, boolean secondary)1161     private boolean readSharedMemory(int memType, boolean secondary) {
1162         return readSharedMemory(memType, secondary, 0, SHARED_MEMORY_SIZE);
1163     }
1164 
readSharedMemory(int memType)1165     private boolean readSharedMemory(int memType) {
1166         return readSharedMemory(memType, false /*secondary*/);
1167     }
1168 
isMemoryTypeNeeded(int memType)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 
isSharedMemoryFormatted(int memType)1179     private boolean isSharedMemoryFormatted(int memType) {
1180         return isSharedMemoryFormatted(memType, false /* secondary */);
1181     }
1182 
isSharedMemoryFormatted(int memType, boolean secondary)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 
checkSharedMemoryContent(Sensor s, int memType, int rateLevel, int token)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 
checkEventRate(int testTimeMs, List<DirectReportSensorEvent> events, int type, int rateLevel)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 
checkEventRateUs(int testTimeMs, List<DirectReportSensorEvent> events, int type, int samplingPeriodUs)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 
allocateSharedMemory()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 
freeSharedMemory()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 
getNominalFreq(int rateLevel)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 
calculateExpectedNEvents(int timeMs, int rateLevel)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 
checkTimestampAbsolute(List<DirectReportSensorEvent> events)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 
checkTimestampRelative(List<DirectReportSensorEvent> directEvents, List<DirectReportSensorEvent> pollEvents)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