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, PendingIntent.FLAG_MUTABLE_UNAUDITED);
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 (mDeviceSuspendLock != null && mDeviceSuspendLock.isHeld()) {
115                 mDeviceSuspendLock.release();
116             }
117             if (mScreenManipulator != null) {
118                 mScreenManipulator.releaseScreenOn();
119                 mScreenManipulator.close();
120             }
121         }
122 
123         public static class AlarmReceiver extends BroadcastReceiver {
124             @Override
onReceive(Context context, Intent intent)125             public void onReceive(Context context, Intent intent) {
126                 Intent alarm_intent = new Intent(context, DeviceSuspendTestActivity.class);
127                 alarm_intent.setAction(DeviceSuspendTestActivity.ACTION_ALARM);
128                 LocalBroadcastManager.getInstance(context).sendBroadcastSync(alarm_intent);
129             }
130         }
131 
132         public BroadcastReceiver myBroadCastReceiver = new BroadcastReceiver() {
133             @Override
134             public void onReceive(Context context, Intent intent) {
135                 if (!mDeviceSuspendLock.isHeld()) {
136                     mDeviceSuspendLock.acquire();
137                 }
138             }
139         };
140 
141         public static class DeviceSuspendTestService extends Service {
142             private static final String NOTIFICATION_CHANNEL_ID =
143                     "com.android.cts.verifier.sensors.DeviceSuspendTestActivity.Notification";
144             private static final String NOTIFICATION_CHANNEL_NAME = "Device Suspend Test";
145 
146             @Override
onBind(Intent intent)147             public IBinder onBind(Intent intent) {
148                 return null;
149             }
150 
151             @Override
onStartCommand(Intent intent, int flags, int startId)152             public int onStartCommand(Intent intent, int flags, int startId) {
153                 NotificationChannel channel = new NotificationChannel(
154                         NOTIFICATION_CHANNEL_ID,
155                         NOTIFICATION_CHANNEL_NAME,
156                         NotificationManager.IMPORTANCE_DEFAULT);
157                 NotificationManager notificationManager =
158                         getSystemService(NotificationManager.class);
159                 notificationManager.createNotificationChannel(channel);
160                 Notification notification =
161                         new Notification.Builder(getApplicationContext(), NOTIFICATION_CHANNEL_ID)
162                         .setContentTitle(getString(R.string.snsr_device_suspend_service_active))
163                         .setContentText(getString(
164                                 R.string.snsr_device_suspend_service_notification))
165                         .setSmallIcon(R.drawable.icon)
166                         .setAutoCancel(true)
167                         .build();
168                 startForeground(1, notification);
169 
170                 return START_NOT_STICKY;
171             }
172         }
173 
testAPWakeUpWhenReportLatencyExpiresAccel()174         public String testAPWakeUpWhenReportLatencyExpiresAccel() throws Throwable {
175             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER, true);
176             if (wakeUpSensor == null) {
177                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, true);
178             }
179             return runAPWakeUpWhenReportLatencyExpires(wakeUpSensor);
180         }
181 
testAPWakeUpWhenReportLatencyExpiresGyro()182         public String testAPWakeUpWhenReportLatencyExpiresGyro() throws Throwable {
183             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE, true);
184             if (wakeUpSensor == null) {
185                 throw new SensorNotSupportedException(Sensor.TYPE_GYROSCOPE, true);
186             }
187             return runAPWakeUpWhenReportLatencyExpires(wakeUpSensor);
188         }
189 
testAPWakeUpWhenReportLatencyExpiresMag()190         public String testAPWakeUpWhenReportLatencyExpiresMag() throws Throwable {
191             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD,true);
192             if (wakeUpSensor == null) {
193                 throw new SensorNotSupportedException(Sensor.TYPE_MAGNETIC_FIELD, true);
194             }
195             return runAPWakeUpWhenReportLatencyExpires(wakeUpSensor);
196         }
197 
testAPWakeUpWhenFIFOFullAccel()198         public String testAPWakeUpWhenFIFOFullAccel() throws Throwable {
199             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER, true);
200             if (wakeUpSensor == null) {
201                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, true);
202             }
203             return runAPWakeUpWhenFIFOFull(wakeUpSensor);
204         }
205 
testAPWakeUpWhenFIFOFullGyro()206         public String testAPWakeUpWhenFIFOFullGyro() throws Throwable {
207             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE, true);
208             if (wakeUpSensor == null) {
209                 throw new SensorNotSupportedException(Sensor.TYPE_GYROSCOPE, true);
210             }
211             return runAPWakeUpWhenFIFOFull(wakeUpSensor);
212         }
213 
testAPWakeUpWhenFIFOFullMag()214         public String testAPWakeUpWhenFIFOFullMag() throws Throwable {
215             Sensor wakeUpSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD,true);
216             if (wakeUpSensor == null) {
217                 throw new SensorNotSupportedException(Sensor.TYPE_MAGNETIC_FIELD, true);
218             }
219             return runAPWakeUpWhenFIFOFull(wakeUpSensor);
220         }
221 
testAccelBatchingInAPSuspendLargeReportLatency()222         public String testAccelBatchingInAPSuspendLargeReportLatency() throws Throwable {
223             Sensor accel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
224             if (accel == null) {
225                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, false);
226             }
227             return runAPWakeUpByAlarmNonWakeSensor(accel, (int)TimeUnit.SECONDS.toMicros(1000));
228         }
229 
testAccelBatchingInAPSuspendZeroReportLatency()230         public String testAccelBatchingInAPSuspendZeroReportLatency() throws Throwable {
231             Sensor accel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
232            if (accel == null) {
233                 throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER, false);
234             }
235             return runAPWakeUpByAlarmNonWakeSensor(accel, 0);
236         }
237 
238         /**
239          * Verify that the device is able to suspend
240          */
verifyDeviceCanSuspend()241         public void verifyDeviceCanSuspend() throws Throwable {
242             // Make sure clocks are different (i.e. kernel has suspended at least once)
243             // so that we can determine if sensors are using correct clocksource timestamp
244             final int MAX_SLEEP_ATTEMPTS = 10;
245             final int SLEEP_DURATION_MS = 2000;
246             int sleep_attempts = 0;
247             boolean device_needs_sleep = true;
248             boolean wakelock_was_held = false;
249 
250             final long ALARM_WAKE_UP_DELAY_MS = TimeUnit.SECONDS.toMillis(20);
251             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
252                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
253                                     mPendingIntent);
254 
255             if (mDeviceSuspendLock != null && mDeviceSuspendLock.isHeld()) {
256                 wakelock_was_held = true;
257                 mDeviceSuspendLock.release();
258             }
259 
260             do {
261                 try {
262                     verifyClockDelta();
263                     device_needs_sleep = false;
264                 } catch(Throwable e) {
265                     // Delta between clocks too small, must sleep longer
266                     if (sleep_attempts++ > MAX_SLEEP_ATTEMPTS) {
267                         mAlarmManager.cancel(mPendingIntent);
268                         if (wakelock_was_held) {
269                             mDeviceSuspendLock.acquire();
270                         }
271                         throw e;
272                     }
273                     Thread.sleep(SLEEP_DURATION_MS);
274                 }
275             } while (device_needs_sleep);
276 
277             if (wakelock_was_held) {
278                 mDeviceSuspendLock.acquire();
279             }
280             mAlarmManager.cancel(mPendingIntent);
281         }
282 
283         /**
284          * Verify that each continuous sensor is using the correct
285          * clock source (CLOCK_BOOTTIME) for timestamps.
286          */
testTimestampClockSource()287         public String testTimestampClockSource() throws Throwable {
288             String string = null;
289             boolean error_occurred = false;
290             List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
291             if (sensorList == null) {
292                 throw new SensorTestStateNotSupportedException(
293                     "Sensors are not available in the system.");
294             }
295 
296             boolean needToVerifySuspend = true;
297 
298             for (Sensor sensor : sensorList) {
299                 if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
300                     Log.i(TAG, "testTimestampClockSource skipping non-continuous sensor: '" + sensor.getName());
301                     continue;
302                 }
303                 if (sensor.getType() >= Sensor.TYPE_DEVICE_PRIVATE_BASE) {
304                     Log.i(TAG, "testTimestampClockSource skipping vendor specific sensor: '" + sensor.getName());
305                     continue;
306                 }
307 
308                 if (needToVerifySuspend) {
309                     verifyDeviceCanSuspend();
310                     needToVerifySuspend = false;
311                 }
312 
313                 try {
314                     string = runVerifySensorTimestampClockbase(sensor, false);
315                     if (string != null) {
316                         return string;
317                     }
318                 } catch(Throwable e) {
319                     Log.e(TAG, e.getMessage());
320                     error_occurred = true;
321                 }
322             }
323             if (error_occurred) {
324                 throw new Error("Sensors must use CLOCK_BOOTTIME as clock source for timestamping events");
325             }
326             return null;
327         }
328 
runAPWakeUpWhenReportLatencyExpires(Sensor sensor)329         public String runAPWakeUpWhenReportLatencyExpires(Sensor sensor) throws Throwable {
330 
331             verifyBatchingSupport(sensor);
332 
333             int fifoMaxEventCount = sensor.getFifoMaxEventCount();
334             int samplingPeriodUs = sensor.getMaxDelay();
335             if (samplingPeriodUs == 0) {
336                 // If maxDelay is not defined, set the value for 5 Hz.
337                 samplingPeriodUs = 200000;
338             }
339 
340             long fifoBasedReportLatencyUs = maxBatchingPeriod(sensor, samplingPeriodUs);
341             verifyBatchingPeriod(fifoBasedReportLatencyUs);
342 
343             final long MAX_REPORT_LATENCY_US = TimeUnit.SECONDS.toMicros(15); // 15 seconds
344             TestSensorEnvironment environment = new TestSensorEnvironment(
345                     this,
346                     sensor,
347                     false,
348                     samplingPeriodUs,
349                     (int) MAX_REPORT_LATENCY_US,
350                     true /*isDeviceSuspendTest*/);
351 
352             TestSensorOperation op = TestSensorOperation.createOperation(environment,
353                                                                           mDeviceSuspendLock,
354                                                                           false);
355             final long ALARM_WAKE_UP_DELAY_MS =
356                     TimeUnit.MICROSECONDS.toMillis(MAX_REPORT_LATENCY_US) +
357                     TimeUnit.SECONDS.toMillis(10);
358 
359             op.addVerification(BatchArrivalVerification.getDefault(environment));
360             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
361                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
362                                     mPendingIntent);
363             try {
364                 Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
365                 op.execute(getCurrentTestNode());
366             } finally {
367                 mAlarmManager.cancel(mPendingIntent);
368             }
369             return null;
370         }
371 
runAPWakeUpWhenFIFOFull(Sensor sensor)372         public String runAPWakeUpWhenFIFOFull(Sensor sensor) throws Throwable {
373             verifyBatchingSupport(sensor);
374 
375             // Try to fill the FIFO at the fastest rate and check if the time is enough to run
376             // the manual test.
377             int samplingPeriodUs = sensor.getMinDelay();
378 
379             long fifoBasedReportLatencyUs = maxBatchingPeriod(sensor, samplingPeriodUs);
380 
381             final long MIN_LATENCY_US = TimeUnit.SECONDS.toMicros(20);
382             // Ensure that FIFO based report latency is at least 20 seconds, we need at least 10
383             // seconds of time to allow the device to be in suspend state.
384             if (fifoBasedReportLatencyUs < MIN_LATENCY_US) {
385                 int fifoMaxEventCount = sensor.getFifoMaxEventCount();
386                 samplingPeriodUs = (int) MIN_LATENCY_US/fifoMaxEventCount;
387                 fifoBasedReportLatencyUs = MIN_LATENCY_US;
388             }
389 
390             final int MAX_REPORT_LATENCY_US = Integer.MAX_VALUE;
391             final long ALARM_WAKE_UP_DELAY_MS =
392                     TimeUnit.MICROSECONDS.toMillis(fifoBasedReportLatencyUs) +
393                     TimeUnit.SECONDS.toMillis(10);
394 
395             TestSensorEnvironment environment = new TestSensorEnvironment(
396                     this,
397                     sensor,
398                     false,
399                     (int) samplingPeriodUs,
400                     (int) MAX_REPORT_LATENCY_US,
401                     true /*isDeviceSuspendTest*/);
402 
403             TestSensorOperation op = TestSensorOperation.createOperation(environment,
404                                                                         mDeviceSuspendLock,
405                                                                         true);
406             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
407                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
408                                     mPendingIntent);
409             op.addDefaultVerifications();
410             try {
411                 Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
412                 op.execute(getCurrentTestNode());
413             } finally {
414                 mAlarmManager.cancel(mPendingIntent);
415             }
416             return null;
417         }
418 
419         /**
420          * Verify the CLOCK_MONOTONIC and CLOCK_BOOTTIME clock sources are different
421          * by at least 2 seconds.  Since delta between these two clock sources represents
422          * time kernel has spent in suspend, device needs to have gone into suspend for
423          * for at least 2 seconds since device was initially booted.
424          */
verifyClockDelta()425         private void verifyClockDelta() throws Throwable {
426             final int MIN_DELTA_BETWEEN_CLOCKS_MS = 2000;
427             long uptimeMs = SystemClock.uptimeMillis();
428             long realtimeMs = SystemClock.elapsedRealtime();
429             long deltaMs = (realtimeMs - uptimeMs);
430             if (deltaMs < MIN_DELTA_BETWEEN_CLOCKS_MS) {
431                 throw new Error("Delta between clock sources too small ("
432                                   + deltaMs + "mS), device must sleep more than "
433                                   + MIN_DELTA_BETWEEN_CLOCKS_MS/1000 + " seconds");
434             }
435             Log.i(TAG, "Delta between CLOCK_MONOTONIC and CLOCK_BOOTTIME is " + deltaMs + " mS");
436         }
437 
438 
439         /**
440          * Verify sensor is using the correct clock source (CLOCK_BOOTTIME) for timestamps.
441          * To tell the clock sources apart, the kernel must have suspended at least once.
442          *
443          * @param sensor - sensor to verify
444          * @param verify_clock_delta
445          *          true to verify that clock sources differ before running test
446          *          false to skip verification of sufficient delta between clock sources
447          */
runVerifySensorTimestampClockbase(Sensor sensor, boolean verify_clock_delta)448         public String runVerifySensorTimestampClockbase(Sensor sensor, boolean verify_clock_delta)
449             throws Throwable {
450             Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
451             if (verify_clock_delta) {
452                 verifyClockDelta();
453             }
454             /* Enable a sensor, grab a sample, and then verify timestamp is > realtimeNs
455              * to assure the correct clock source is being used for the sensor timestamp.
456              */
457             final int MIN_TIMESTAMP_BASE_SAMPLES = 1;
458             int samplingPeriodUs = sensor.getMinDelay();
459             TestSensorEnvironment environment = new TestSensorEnvironment(
460                     this,
461                     sensor,
462                     false,
463                     (int) samplingPeriodUs,
464                     0,
465                     false /*isDeviceSuspendTest*/);
466             TestSensorOperation op = TestSensorOperation.createOperation(environment, MIN_TIMESTAMP_BASE_SAMPLES);
467             op.addVerification(TimestampClockSourceVerification.getDefault(environment));
468             try {
469                 op.execute(getCurrentTestNode());
470             } finally {
471             }
472             return null;
473         }
474 
475 
runAPWakeUpByAlarmNonWakeSensor(Sensor sensor, int maxReportLatencyUs)476         public String runAPWakeUpByAlarmNonWakeSensor(Sensor sensor, int maxReportLatencyUs)
477             throws  Throwable {
478             verifyBatchingSupport(sensor);
479 
480             int samplingPeriodUs = sensor.getMaxDelay();
481             if (samplingPeriodUs == 0 || samplingPeriodUs > 200000) {
482                 // If maxDelay is not defined, set the value for 5 Hz.
483                 samplingPeriodUs = 200000;
484             }
485 
486             long fifoBasedReportLatencyUs = maxBatchingPeriod(sensor, samplingPeriodUs);
487             verifyBatchingPeriod(fifoBasedReportLatencyUs);
488 
489             TestSensorEnvironment environment = new TestSensorEnvironment(
490                     this,
491                     sensor,
492                     false,
493                     (int) samplingPeriodUs,
494                     maxReportLatencyUs,
495                     true /*isDeviceSuspendTest*/);
496 
497             final long ALARM_WAKE_UP_DELAY_MS = 20000;
498             TestSensorOperation op = TestSensorOperation.createOperation(environment,
499                                                                          mDeviceSuspendLock,
500                                                                          true);
501             mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
502                                     SystemClock.elapsedRealtime() + ALARM_WAKE_UP_DELAY_MS,
503                                     mPendingIntent);
504             try {
505                 Log.i(TAG, "Running .. " + getCurrentTestNode().getName() + " " + sensor.getName());
506                 op.execute(getCurrentTestNode());
507             } finally {
508                 mAlarmManager.cancel(mPendingIntent);
509             }
510             return null;
511         }
512 
verifyBatchingSupport(Sensor sensor)513         private void verifyBatchingSupport(Sensor sensor)
514                 throws SensorTestStateNotSupportedException {
515             int fifoMaxEventCount = sensor.getFifoMaxEventCount();
516             if (fifoMaxEventCount == 0) {
517                 throw new SensorTestStateNotSupportedException("Batching not supported.");
518             }
519         }
520 
verifyBatchingPeriod(long periodUs)521         private void verifyBatchingPeriod(long periodUs)
522                 throws SensorTestStateNotSupportedException {
523             // Ensure that FIFO based report latency is at least 20 seconds, we need at least 10
524             // seconds of time to allow the device to be in suspend state.
525             if (periodUs < TimeUnit.SECONDS.toMicros(20)) {
526                 throw new SensorTestStateNotSupportedException("FIFO too small to test reliably");
527             }
528         }
529 
maxBatchingPeriod(Sensor sensor, long samplePeriod)530         private long maxBatchingPeriod (Sensor sensor, long samplePeriod) {
531             long fifoMaxEventCount = sensor.getFifoMaxEventCount();
532             return fifoMaxEventCount * samplePeriod;
533         }
534 
535 }
536