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