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