1 package com.android.cts.verifier.sensors;
2 
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Timer;
6 import java.util.TimerTask;
7 import java.util.concurrent.CountDownLatch;
8 import java.util.concurrent.TimeUnit;
9 
10 import com.android.cts.verifier.R;
11 import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
12 import com.android.cts.verifier.sensors.helpers.SensorTestScreenManipulator;
13 
14 import android.app.AlarmManager;
15 import android.app.IntentService;
16 import android.app.Notification;
17 import android.app.NotificationChannel;
18 import android.app.NotificationManager;
19 import android.app.PendingIntent;
20 import android.app.Service;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.hardware.Sensor;
26 import android.hardware.SensorEvent;
27 import android.hardware.SensorEventListener;
28 import android.hardware.SensorManager;
29 import android.hardware.TriggerEvent;
30 import android.hardware.TriggerEventListener;
31 import android.hardware.cts.helpers.MovementDetectorHelper;
32 import android.hardware.cts.helpers.SensorStats;
33 import android.hardware.cts.helpers.SensorStats;
34 import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
35 import android.hardware.cts.helpers.TestSensorEnvironment;
36 import android.hardware.cts.helpers.TestSensorEvent;
37 import android.hardware.cts.helpers.TestSensorEventListener;
38 import android.hardware.cts.helpers.TestSensorManager;
39 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
40 import android.hardware.cts.helpers.SensorNotSupportedException;
41 import android.hardware.cts.helpers.sensorverification.BatchArrivalVerification;
42 import android.hardware.cts.helpers.sensorverification.TimestampClockSourceVerification;
43 import android.os.IBinder;
44 import android.os.PowerManager;
45 import android.os.PowerManager.WakeLock;
46 import android.os.SystemClock;
47 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
48 import android.util.Log;
49 import android.view.MotionEvent;
50 import android.view.View;
51 
52 import junit.framework.Assert;
53 
54 public class DeviceSuspendTestActivity
55             extends SensorCtsVerifierTestActivity {
DeviceSuspendTestActivity()56         public DeviceSuspendTestActivity() {
57             super(DeviceSuspendTestActivity.class);
58         }
59 
60         private SensorTestScreenManipulator mScreenManipulator;
61         private PowerManager.WakeLock mDeviceSuspendLock;
62         private PendingIntent mPendingIntent;
63         private AlarmManager mAlarmManager;
64         private static String ACTION_ALARM = "DeviceSuspendTestActivity.ACTION_ALARM";
65         private static String TAG = "DeviceSuspendSensorTest";
66         private SensorManager mSensorManager;
67 
68         @Override
activitySetUp()69         protected void activitySetUp() throws InterruptedException {
70             mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
71             mScreenManipulator = new SensorTestScreenManipulator(this);
72             mScreenManipulator.initialize(this);
73             LocalBroadcastManager.getInstance(this).registerReceiver(myBroadCastReceiver,
74                                             new IntentFilter(ACTION_ALARM));
75 
76             Intent intent = new Intent(this, AlarmReceiver.class);
77             mPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
78 
79             mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
80 
81             PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
82             mDeviceSuspendLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
83                                                 "DeviceSuspendTestActivity");
84 
85             // Launch a foreground service to ensure that the test remains in the foreground and is
86             // able to be woken-up when sensor data is delivered.
87             startForegroundService(new Intent(this, DeviceSuspendTestService.class));
88 
89             mDeviceSuspendLock.acquire();
90             SensorTestLogger logger = getTestLogger();
91             logger.logInstructions(R.string.snsr_device_suspend_test_instr);
92             waitForUserToBegin();
93         }
94 
95         @Override
activityCleanUp()96         protected void activityCleanUp() {
97             mScreenManipulator.turnScreenOn();
98             try {
99                 playSound();
100             } catch(InterruptedException e) {
101               // Ignore.
102             }
103             LocalBroadcastManager.getInstance(this).unregisterReceiver(myBroadCastReceiver);
104             if (mDeviceSuspendLock != null && mDeviceSuspendLock.isHeld()) {
105                 mDeviceSuspendLock.release();
106             }
107 
108             stopService(new Intent(this, DeviceSuspendTestService.class));
109         }
110 
111         @Override
onDestroy()112         protected void onDestroy() {
113             super.onDestroy();
114             if (mScreenManipulator != null) {
115                 mScreenManipulator.releaseScreenOn();
116                 mScreenManipulator.close();
117             }
118         }
119 
120         public static class AlarmReceiver extends BroadcastReceiver {
121             @Override
onReceive(Context context, Intent intent)122             public void onReceive(Context context, Intent intent) {
123                 Intent alarm_intent = new Intent(context, DeviceSuspendTestActivity.class);
124                 alarm_intent.setAction(DeviceSuspendTestActivity.ACTION_ALARM);
125                 LocalBroadcastManager.getInstance(context).sendBroadcastSync(alarm_intent);
126             }
127         }
128 
129         public BroadcastReceiver myBroadCastReceiver = new BroadcastReceiver() {
130             @Override
131             public void onReceive(Context context, Intent intent) {
132                 if (!mDeviceSuspendLock.isHeld()) {
133                     mDeviceSuspendLock.acquire();
134                 }
135             }
136         };
137 
138         public static class DeviceSuspendTestService extends Service {
139             private static final String NOTIFICATION_CHANNEL_ID =
140                     "com.android.cts.verifier.sensors.DeviceSuspendTestActivity.Notification";
141             private static final String NOTIFICATION_CHANNEL_NAME = "Device Suspend Test";
142 
143             @Override
onBind(Intent intent)144             public IBinder onBind(Intent intent) {
145                 return null;
146             }
147 
148             @Override
onStartCommand(Intent intent, int flags, int startId)149             public int onStartCommand(Intent intent, int flags, int startId) {
150                 NotificationChannel channel = new NotificationChannel(
151                         NOTIFICATION_CHANNEL_ID,
152                         NOTIFICATION_CHANNEL_NAME,
153                         NotificationManager.IMPORTANCE_DEFAULT);
154                 NotificationManager notificationManager =
155                         getSystemService(NotificationManager.class);
156                 notificationManager.createNotificationChannel(channel);
157                 Notification notification =
158                         new Notification.Builder(getApplicationContext(), NOTIFICATION_CHANNEL_ID)
159                         .setContentTitle(getString(R.string.snsr_device_suspend_service_active))
160                         .setContentText(getString(
161                                 R.string.snsr_device_suspend_service_notification))
162                         .setSmallIcon(R.drawable.icon)
163                         .setAutoCancel(true)
164                         .build();
165                 startForeground(1, notification);
166 
167                 return START_NOT_STICKY;
168             }
169         }
170 
testAPWakeUpWhenReportLatencyExpiresAccel()171         public String testAPWakeUpWhenReportLatencyExpiresAccel() throws Throwable {
172             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER, true);
173             if (wakeUpSensor == null) {
174                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, true);
175             }
176             return runAPWakeUpWhenReportLatencyExpires(wakeUpSensor);
177         }
178 
testAPWakeUpWhenReportLatencyExpiresGyro()179         public String testAPWakeUpWhenReportLatencyExpiresGyro() throws Throwable {
180             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE, true);
181             if (wakeUpSensor == null) {
182                 throw new SensorNotSupportedException(Sensor.TYPE_GYROSCOPE, true);
183             }
184             return runAPWakeUpWhenReportLatencyExpires(wakeUpSensor);
185         }
186 
testAPWakeUpWhenReportLatencyExpiresMag()187         public String testAPWakeUpWhenReportLatencyExpiresMag() throws Throwable {
188             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD,true);
189             if (wakeUpSensor == null) {
190                 throw new SensorNotSupportedException(Sensor.TYPE_MAGNETIC_FIELD, true);
191             }
192             return runAPWakeUpWhenReportLatencyExpires(wakeUpSensor);
193         }
194 
testAPWakeUpWhenFIFOFullAccel()195         public String testAPWakeUpWhenFIFOFullAccel() throws Throwable {
196             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER, true);
197             if (wakeUpSensor == null) {
198                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, true);
199             }
200             return runAPWakeUpWhenFIFOFull(wakeUpSensor);
201         }
202 
testAPWakeUpWhenFIFOFullGyro()203         public String testAPWakeUpWhenFIFOFullGyro() throws Throwable {
204             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE, true);
205             if (wakeUpSensor == null) {
206                 throw new SensorNotSupportedException(Sensor.TYPE_GYROSCOPE, true);
207             }
208             return runAPWakeUpWhenFIFOFull(wakeUpSensor);
209         }
210 
testAPWakeUpWhenFIFOFullMag()211         public String testAPWakeUpWhenFIFOFullMag() throws Throwable {
212             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD,true);
213             if (wakeUpSensor == null) {
214                 throw new SensorNotSupportedException(Sensor.TYPE_MAGNETIC_FIELD, true);
215             }
216             return runAPWakeUpWhenFIFOFull(wakeUpSensor);
217         }
218 
testAccelBatchingInAPSuspendLargeReportLatency()219         public String testAccelBatchingInAPSuspendLargeReportLatency() throws Throwable {
220             Sensor accel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
221             if (accel == null) {
222                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, false);
223             }
224             return runAPWakeUpByAlarmNonWakeSensor(accel, (int)TimeUnit.SECONDS.toMicros(1000));
225         }
226 
testAccelBatchingInAPSuspendZeroReportLatency()227         public String testAccelBatchingInAPSuspendZeroReportLatency() throws Throwable {
228             Sensor accel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
229            if (accel == null) {
230                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, false);
231             }
232             return runAPWakeUpByAlarmNonWakeSensor(accel, 0);
233         }
234 
235         /**
236          * Verify that the device is able to suspend
237          */
verifyDeviceCanSuspend()238         public void verifyDeviceCanSuspend() throws Throwable {
239             // Make sure clocks are different (i.e. kernel has suspended at least once)
240             // so that we can determine if sensors are using correct clocksource timestamp
241             final int MAX_SLEEP_ATTEMPTS = 10;
242             final int SLEEP_DURATION_MS = 2000;
243             int sleep_attempts = 0;
244             boolean device_needs_sleep = true;
245             boolean wakelock_was_held = false;
246 
247             final long ALARM_WAKE_UP_DELAY_MS = TimeUnit.SECONDS.toMillis(20);
248             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
249                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
250                                     mPendingIntent);
251 
252             if (mDeviceSuspendLock != null && mDeviceSuspendLock.isHeld()) {
253                 wakelock_was_held = true;
254                 mDeviceSuspendLock.release();
255             }
256 
257             do {
258                 try {
259                     verifyClockDelta();
260                     device_needs_sleep = false;
261                 } catch(Throwable e) {
262                     // Delta between clocks too small, must sleep longer
263                     if (sleep_attempts++ > MAX_SLEEP_ATTEMPTS) {
264                         mAlarmManager.cancel(mPendingIntent);
265                         if (wakelock_was_held) {
266                             mDeviceSuspendLock.acquire();
267                         }
268                         throw e;
269                     }
270                     Thread.sleep(SLEEP_DURATION_MS);
271                 }
272             } while (device_needs_sleep);
273 
274             if (wakelock_was_held) {
275                 mDeviceSuspendLock.acquire();
276             }
277             mAlarmManager.cancel(mPendingIntent);
278         }
279 
280         /**
281          * Verify that each continuous sensor is using the correct
282          * clock source (CLOCK_BOOTTIME) for timestamps.
283          */
testTimestampClockSource()284         public String testTimestampClockSource() throws Throwable {
285             String string = null;
286             boolean error_occurred = false;
287             List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
288             if (sensorList == null) {
289                 throw new SensorTestStateNotSupportedException(
290                     "Sensors are not available in the system.");
291             }
292 
293             boolean needToVerifySuspend = true;
294 
295             for (Sensor sensor : sensorList) {
296                 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
297                     Log.i(TAG, "testTimestampClockSource skipping non-continuous sensor: '" + sensor.getName());
298                     continue;
299                 }
300                 if (sensor.getType() >= Sensor.TYPE_DEVICE_PRIVATE_BASE) {
301                     Log.i(TAG, "testTimestampClockSource skipping vendor specific sensor: '" + sensor.getName());
302                     continue;
303                 }
304 
305                 if (needToVerifySuspend) {
306                     verifyDeviceCanSuspend();
307                     needToVerifySuspend = false;
308                 }
309 
310                 try {
311                     string = runVerifySensorTimestampClockbase(sensor, false);
312                     if (string != null) {
313                         return string;
314                     }
315                 } catch(Throwable e) {
316                     Log.e(TAG, e.getMessage());
317                     error_occurred = true;
318                 }
319             }
320             if (error_occurred) {
321                 throw new Error("Sensors must use CLOCK_BOOTTIME as clock source for timestamping events");
322             }
323             return null;
324         }
325 
runAPWakeUpWhenReportLatencyExpires(Sensor sensor)326         public String runAPWakeUpWhenReportLatencyExpires(Sensor sensor) throws Throwable {
327 
328             verifyBatchingSupport(sensor);
329 
330             int fifoMaxEventCount = sensor.getFifoMaxEventCount();
331             int samplingPeriodUs = sensor.getMaxDelay();
332             if (samplingPeriodUs == 0) {
333                 // If maxDelay is not defined, set the value for 5 Hz.
334                 samplingPeriodUs = 200000;
335             }
336 
337             long fifoBasedReportLatencyUs = maxBatchingPeriod(sensor, samplingPeriodUs);
338             verifyBatchingPeriod(fifoBasedReportLatencyUs);
339 
340             final long MAX_REPORT_LATENCY_US = TimeUnit.SECONDS.toMicros(15); // 15 seconds
341             TestSensorEnvironment environment = new TestSensorEnvironment(
342                     this,
343                     sensor,
344                     false,
345                     samplingPeriodUs,
346                     (int) MAX_REPORT_LATENCY_US,
347                     true /*isDeviceSuspendTest*/);
348 
349             TestSensorOperation op = TestSensorOperation.createOperation(environment,
350                                                                           mDeviceSuspendLock,
351                                                                           false);
352             final long ALARM_WAKE_UP_DELAY_MS =
353                     TimeUnit.MICROSECONDS.toMillis(MAX_REPORT_LATENCY_US) +
354                     TimeUnit.SECONDS.toMillis(10);
355 
356             op.addVerification(BatchArrivalVerification.getDefault(environment));
357             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
358                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
359                                     mPendingIntent);
360             try {
361                 Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
362                 op.execute(getCurrentTestNode());
363             } finally {
364                 mAlarmManager.cancel(mPendingIntent);
365             }
366             return null;
367         }
368 
runAPWakeUpWhenFIFOFull(Sensor sensor)369         public String runAPWakeUpWhenFIFOFull(Sensor sensor) throws Throwable {
370             verifyBatchingSupport(sensor);
371 
372             // Try to fill the FIFO at the fastest rate and check if the time is enough to run
373             // the manual test.
374             int samplingPeriodUs = sensor.getMinDelay();
375 
376             long fifoBasedReportLatencyUs = maxBatchingPeriod(sensor, samplingPeriodUs);
377 
378             final long MIN_LATENCY_US = TimeUnit.SECONDS.toMicros(20);
379             // Ensure that FIFO based report latency is at least 20 seconds, we need at least 10
380             // seconds of time to allow the device to be in suspend state.
381             if (fifoBasedReportLatencyUs < MIN_LATENCY_US) {
382                 int fifoMaxEventCount = sensor.getFifoMaxEventCount();
383                 samplingPeriodUs = (int) MIN_LATENCY_US/fifoMaxEventCount;
384                 fifoBasedReportLatencyUs = MIN_LATENCY_US;
385             }
386 
387             final int MAX_REPORT_LATENCY_US = Integer.MAX_VALUE;
388             final long ALARM_WAKE_UP_DELAY_MS =
389                     TimeUnit.MICROSECONDS.toMillis(fifoBasedReportLatencyUs) +
390                     TimeUnit.SECONDS.toMillis(10);
391 
392             TestSensorEnvironment environment = new TestSensorEnvironment(
393                     this,
394                     sensor,
395                     false,
396                     (int) samplingPeriodUs,
397                     (int) MAX_REPORT_LATENCY_US,
398                     true /*isDeviceSuspendTest*/);
399 
400             TestSensorOperation op = TestSensorOperation.createOperation(environment,
401                                                                         mDeviceSuspendLock,
402                                                                         true);
403             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
404                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
405                                     mPendingIntent);
406             op.addDefaultVerifications();
407             try {
408                 Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
409                 op.execute(getCurrentTestNode());
410             } finally {
411                 mAlarmManager.cancel(mPendingIntent);
412             }
413             return null;
414         }
415 
416         /**
417          * Verify the CLOCK_MONOTONIC and CLOCK_BOOTTIME clock sources are different
418          * by at least 2 seconds.  Since delta between these two clock sources represents
419          * time kernel has spent in suspend, device needs to have gone into suspend for
420          * for at least 2 seconds since device was initially booted.
421          */
verifyClockDelta()422         private void verifyClockDelta() throws Throwable {
423             final int MIN_DELTA_BETWEEN_CLOCKS_MS = 2000;
424             long uptimeMs = SystemClock.uptimeMillis();
425             long realtimeMs = SystemClock.elapsedRealtime();
426             long deltaMs = (realtimeMs - uptimeMs);
427             if (deltaMs < MIN_DELTA_BETWEEN_CLOCKS_MS) {
428                 throw new Error("Delta between clock sources too small ("
429                                   + deltaMs + "mS), device must sleep more than "
430                                   + MIN_DELTA_BETWEEN_CLOCKS_MS/1000 + " seconds");
431             }
432             Log.i(TAG, "Delta between CLOCK_MONOTONIC and CLOCK_BOOTTIME is " + deltaMs + " mS");
433         }
434 
435 
436         /**
437          * Verify sensor is using the correct clock source (CLOCK_BOOTTIME) for timestamps.
438          * To tell the clock sources apart, the kernel must have suspended at least once.
439          *
440          * @param sensor - sensor to verify
441          * @param verify_clock_delta
442          *          true to verify that clock sources differ before running test
443          *          false to skip verification of sufficient delta between clock sources
444          */
runVerifySensorTimestampClockbase(Sensor sensor, boolean verify_clock_delta)445         public String runVerifySensorTimestampClockbase(Sensor sensor, boolean verify_clock_delta)
446             throws Throwable {
447             Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
448             if (verify_clock_delta) {
449                 verifyClockDelta();
450             }
451             /* Enable a sensor, grab a sample, and then verify timestamp is > realtimeNs
452              * to assure the correct clock source is being used for the sensor timestamp.
453              */
454             final int MIN_TIMESTAMP_BASE_SAMPLES = 1;
455             int samplingPeriodUs = sensor.getMinDelay();
456             TestSensorEnvironment environment = new TestSensorEnvironment(
457                     this,
458                     sensor,
459                     false,
460                     (int) samplingPeriodUs,
461                     0,
462                     false /*isDeviceSuspendTest*/);
463             TestSensorOperation op = TestSensorOperation.createOperation(environment, MIN_TIMESTAMP_BASE_SAMPLES);
464             op.addVerification(TimestampClockSourceVerification.getDefault(environment));
465             try {
466                 op.execute(getCurrentTestNode());
467             } finally {
468             }
469             return null;
470         }
471 
472 
runAPWakeUpByAlarmNonWakeSensor(Sensor sensor, int maxReportLatencyUs)473         public String runAPWakeUpByAlarmNonWakeSensor(Sensor sensor, int maxReportLatencyUs)
474             throws  Throwable {
475             verifyBatchingSupport(sensor);
476 
477             int samplingPeriodUs = sensor.getMaxDelay();
478             if (samplingPeriodUs == 0 || samplingPeriodUs > 200000) {
479                 // If maxDelay is not defined, set the value for 5 Hz.
480                 samplingPeriodUs = 200000;
481             }
482 
483             long fifoBasedReportLatencyUs = maxBatchingPeriod(sensor, samplingPeriodUs);
484             verifyBatchingPeriod(fifoBasedReportLatencyUs);
485 
486             TestSensorEnvironment environment = new TestSensorEnvironment(
487                     this,
488                     sensor,
489                     false,
490                     (int) samplingPeriodUs,
491                     maxReportLatencyUs,
492                     true /*isDeviceSuspendTest*/);
493 
494             final long ALARM_WAKE_UP_DELAY_MS = 20000;
495             TestSensorOperation op = TestSensorOperation.createOperation(environment,
496                                                                          mDeviceSuspendLock,
497                                                                          true);
498             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
499                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
500                                     mPendingIntent);
501             try {
502                 Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
503                 op.execute(getCurrentTestNode());
504             } finally {
505                 mAlarmManager.cancel(mPendingIntent);
506             }
507             return null;
508         }
509 
verifyBatchingSupport(Sensor sensor)510         private void verifyBatchingSupport(Sensor sensor)
511                 throws SensorTestStateNotSupportedException {
512             int fifoMaxEventCount = sensor.getFifoMaxEventCount();
513             if (fifoMaxEventCount == 0) {
514                 throw new SensorTestStateNotSupportedException("Batching not supported.");
515             }
516         }
517 
verifyBatchingPeriod(long periodUs)518         private void verifyBatchingPeriod(long periodUs)
519                 throws SensorTestStateNotSupportedException {
520             // Ensure that FIFO based report latency is at least 20 seconds, we need at least 10
521             // seconds of time to allow the device to be in suspend state.
522             if (periodUs < TimeUnit.SECONDS.toMicros(20)) {
523                 throw new SensorTestStateNotSupportedException("FIFO too small to test reliably");
524             }
525         }
526 
maxBatchingPeriod(Sensor sensor, long samplePeriod)527         private long maxBatchingPeriod (Sensor sensor, long samplePeriod) {
528             long fifoMaxEventCount = sensor.getFifoMaxEventCount();
529             return fifoMaxEventCount * samplePeriod;
530         }
531 
532 }
533