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 package com.android.cts.verifier.sensors; 17 18 import android.app.AlarmManager; 19 import android.app.PendingIntent; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.hardware.Sensor; 25 import android.hardware.SensorEvent; 26 import android.hardware.SensorEventListener; 27 import android.hardware.SensorManager; 28 import android.hardware.cts.helpers.SensorNotSupportedException; 29 import android.hardware.cts.helpers.SuspendStateMonitor; 30 import android.os.PowerManager; 31 import android.os.SystemClock; 32 import androidx.localbroadcastmanager.content.LocalBroadcastManager; 33 import android.util.Log; 34 35 import com.android.cts.verifier.R; 36 import com.android.cts.verifier.sensors.helpers.SensorTestScreenManipulator; 37 import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity; 38 39 import java.util.concurrent.CountDownLatch; 40 import java.util.concurrent.TimeUnit; 41 42 import junit.framework.Assert; 43 import static junit.framework.Assert.fail; 44 45 46 /** 47 * Manual test for testing the low-latency offbody detect sensor. This test consists of 3 48 * sub-tests designed to verify the sensor event data, verify event trigger response times 49 * are within spec for the sensor type, and to verify that the sensor can wake the device. 50 */ 51 public class OffBodySensorTestActivity 52 extends SensorCtsVerifierTestActivity { 53 private static final String TAG="OffbodySensorTest"; 54 private static String ACTION_ALARM = "OffBodySensorTestActivity.ACTION_ALARM"; 55 private static final int MAX_OFF_BODY_EVENT_LATENCY_MS = 1000; 56 private static final int MAX_ON_BODY_EVENT_LATENCY_MS = 5000; 57 private static final int COUNTDOWN_INTERVAL_MS = 1000; 58 private static final int LLOB_EVENT_MAX_DELAY_SEC = 20; 59 private static final long MAX_ALLOWED_DELAY_MS = TimeUnit.SECONDS.toMillis(1); 60 private static final long RESULT_REPORT_SHOW_TIME_MS = TimeUnit.SECONDS.toMillis(5); 61 private static final int OFFBODY_EVENT_VALUES_LENGTH = 1; 62 private static final int COUNTDOWN_NUM_INTERVALS = 3; 63 64 private static final float OFF_BODY_EVENT_VALUE = 0; 65 private static final float ON_BODY_EVENT_VALUE = 1; 66 private static final float BAD_VALUE_SEEN_INIT = 0; 67 private static float mBadValueSeen = BAD_VALUE_SEEN_INIT; 68 69 private enum State { 70 OFF_BODY, ON_BODY, UNKNOWN 71 } 72 73 // time to wait for offbody event after the device has gone into suspend. Even after 74 // 45 secs if LLOB sensor does not trigger, the test will fail. 75 private static final long ALARM_WAKE_UP_AP_DELAY_MS = TimeUnit.SECONDS.toMillis(45); 76 77 // acceptable time difference between event time and AP wake up time. 78 private static final long MAX_ACCEPTABLE_DELAY_EVENT_AP_WAKE_UP_NS = 79 TimeUnit.MILLISECONDS.toNanos(1200); 80 81 private static final int NANOSECONDS_PER_MILLISECOND = 1000000; 82 private AlarmManager mAlarmManager; 83 private SensorManager mSensorManager; 84 private Sensor mOffBodySensor; 85 private boolean mOffBodySensorRegistered; 86 private long mTestStartTimestampMs; 87 private State mPreviousSensorState; 88 private PendingIntent mPendingIntent; 89 private PowerManager.WakeLock mDeviceSuspendLock; 90 private SensorEventVerifier mVerifier; 91 private SensorTestScreenManipulator mScreenManipulator; 92 93 public class SensorEventRegistry { 94 public final SensorEvent event; 95 public final long receiveTimestampNanos; 96 SensorEventRegistry(SensorEvent event, long realtimeTimestampNanos)97 public SensorEventRegistry(SensorEvent event, long realtimeTimestampNanos) { 98 this.event = event; 99 this.receiveTimestampNanos = realtimeTimestampNanos; 100 } 101 } 102 103 private class SensorEventVerifier implements SensorEventListener { 104 private volatile CountDownLatch mCountDownLatch; 105 private volatile SensorEventRegistry mEventRegistry; 106 private volatile long mTimestampForLastSensorEvent = 0; 107 108 @Override onAccuracyChanged(Sensor sensor, int accuracy)109 public void onAccuracyChanged(Sensor sensor, int accuracy) {} 110 111 @Override onSensorChanged(SensorEvent event)112 public void onSensorChanged(SensorEvent event) { 113 long elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos(); 114 int type = event.sensor.getType(); 115 116 if (type == Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT) { 117 switch((int) event.values[0]) { 118 case (int) OFF_BODY_EVENT_VALUE: 119 Log.i(TAG, "onSensorChanged(): OFF_BODY ts="+event.timestamp+ 120 ", now="+elapsedRealtimeNanos+", delta="+ 121 (elapsedRealtimeNanos-event.timestamp)/1000000+"mS"); 122 mPreviousSensorState = State.OFF_BODY; 123 break; 124 case (int) ON_BODY_EVENT_VALUE: 125 Log.i(TAG, "onSensorChanged(): ON_BODY ts = "+event.timestamp+ 126 ", now="+elapsedRealtimeNanos+", delta="+ 127 (elapsedRealtimeNanos-event.timestamp)/1000000+"mS"); 128 mPreviousSensorState = State.ON_BODY; 129 break; 130 default: 131 Log.e(TAG, "onSensorChanged(): invalid value "+event.values[0]+ 132 " received"); 133 mBadValueSeen = event.values[0]; 134 break; 135 } 136 mEventRegistry = new SensorEventRegistry(event, elapsedRealtimeNanos); 137 getTestLogger().logMessage( 138 R.string.snsr_offbody_state_change, 139 (int) event.values[0], 140 elapsedRealtimeNanos); 141 releaseLatch(); 142 } 143 } 144 releaseLatch()145 public void releaseLatch() { 146 if (mCountDownLatch != null) { 147 mCountDownLatch.countDown(); 148 } 149 } 150 getTimeStampForSensorEvent()151 public long getTimeStampForSensorEvent() { 152 return mTimestampForLastSensorEvent; 153 } 154 awaitAndVerifyEvent(float expectedResponseValue)155 public String awaitAndVerifyEvent(float expectedResponseValue) throws Throwable { 156 return awaitAndVerifyEvent(expectedResponseValue, 0); 157 } 158 awaitAndVerifyEvent(float expectedResponseValue, int maxEventLatencyMs)159 public String awaitAndVerifyEvent(float expectedResponseValue, int maxEventLatencyMs) 160 throws Throwable { 161 SensorEventRegistry registry = waitForEvent(); 162 String eventArrivalMessage; 163 if ((registry == null) || (registry.event == null)) { 164 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, false); 165 Assert.fail(eventArrivalMessage); 166 } 167 168 // verify an event arrived, and it is indeed a Low Latency Offbody Detect event 169 SensorEvent event = registry.event; 170 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, event != null); 171 Assert.assertNotNull(eventArrivalMessage, event); 172 173 String result = verifyEvent(registry, expectedResponseValue, maxEventLatencyMs); 174 return result; 175 } 176 verifyEvent(SensorEventRegistry registry, float expectedResponseValue, int maxEventLatencyMs)177 public String verifyEvent(SensorEventRegistry registry, float expectedResponseValue, 178 int maxEventLatencyMs) throws Throwable { 179 int eventType = registry.event.sensor.getType(); 180 String eventTypeMessage = getString( 181 R.string.snsr_offbody_event_type, 182 Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, 183 eventType); 184 Assert.assertEquals(eventTypeMessage, 185 Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, 186 eventType); 187 188 float value = registry.event.values[0]; 189 String sensorName = registry.event.sensor.getName(); 190 String eventName = (value == ON_BODY_EVENT_VALUE) ? "ON-BODY" : "OFF-BODY"; 191 192 long eventLatencyMs = (registry.receiveTimestampNanos/NANOSECONDS_PER_MILLISECOND) 193 - mTestStartTimestampMs; 194 195 int valuesLength = registry.event.values.length; 196 String valuesLengthMessage = getString( 197 R.string.snsr_event_length, 198 OFFBODY_EVENT_VALUES_LENGTH, 199 valuesLength, 200 sensorName); 201 Assert.assertEquals(valuesLengthMessage, OFFBODY_EVENT_VALUES_LENGTH, valuesLength); 202 203 String valuesMessage = getString( 204 R.string.snsr_event_value, 205 expectedResponseValue, 206 value, 207 sensorName); 208 Assert.assertEquals(valuesMessage, expectedResponseValue, value); 209 210 if (maxEventLatencyMs != 0) { 211 Log.i(TAG, "event latency was "+eventLatencyMs+" ms for "+ 212 eventName+" event"); 213 String responseViolationMessage = getString( 214 R.string.snsr_offbody_response_timing_violation, 215 eventName, 216 maxEventLatencyMs, 217 eventLatencyMs); 218 boolean violation = (eventLatencyMs > maxEventLatencyMs); 219 Assert.assertFalse(responseViolationMessage, violation); 220 } 221 return null; 222 } 223 verifyOffbodyEventNotInvalid()224 private void verifyOffbodyEventNotInvalid() throws InterruptedException { 225 if (mBadValueSeen != BAD_VALUE_SEEN_INIT) { 226 Assert.fail( 227 String.format(getString(R.string.snsr_offbody_event_invalid_value), 228 OFF_BODY_EVENT_VALUE, 229 ON_BODY_EVENT_VALUE, 230 mBadValueSeen)); 231 } 232 } 233 waitForEvent()234 private SensorEventRegistry waitForEvent() throws InterruptedException { 235 return waitForEvent(null); 236 } 237 waitForEvent(PowerManager.WakeLock suspendLock)238 private SensorEventRegistry waitForEvent(PowerManager.WakeLock suspendLock) 239 throws InterruptedException { 240 mCountDownLatch = new CountDownLatch(1); 241 242 if ((suspendLock != null) && suspendLock.isHeld()) { 243 suspendLock.release(); 244 } 245 246 mCountDownLatch.await(LLOB_EVENT_MAX_DELAY_SEC, TimeUnit.SECONDS); 247 248 if ((suspendLock != null) && !suspendLock.isHeld()) { 249 suspendLock.acquire(); 250 } 251 252 SensorEventRegistry registry = mEventRegistry; 253 254 // Save the last timestamp when the event triggered. 255 if (mEventRegistry != null && mEventRegistry.event != null) { 256 mTimestampForLastSensorEvent = mEventRegistry.event.timestamp; 257 } 258 259 mEventRegistry = null; 260 verifyOffbodyEventNotInvalid(); 261 return registry != null ? registry : new SensorEventRegistry(null, 0); 262 } 263 waitForSensorEvent()264 public SensorEvent waitForSensorEvent() throws InterruptedException { 265 SensorEvent event = null; 266 mCountDownLatch = new CountDownLatch(1); 267 mCountDownLatch.await(LLOB_EVENT_MAX_DELAY_SEC, TimeUnit.SECONDS); 268 269 if (mEventRegistry != null && mEventRegistry.event != null) { 270 event = mEventRegistry.event; 271 } 272 273 mEventRegistry = null; 274 verifyOffbodyEventNotInvalid(); 275 return event; 276 } 277 } 278 OffBodySensorTestActivity()279 public OffBodySensorTestActivity() { 280 super(OffBodySensorTestActivity.class); 281 } 282 283 284 @Override activitySetUp()285 protected void activitySetUp() throws InterruptedException { 286 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 287 mDeviceSuspendLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 288 "OffBodySensorTestActivity"); 289 mDeviceSuspendLock.acquire(); 290 mOffBodySensorRegistered = false; 291 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 292 mOffBodySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, 293 true); 294 if (mOffBodySensor == null) { 295 setTestResultAndFinish(true); 296 return; 297 } 298 LocalBroadcastManager.getInstance(this).registerReceiver(myBroadCastReceiver, 299 new IntentFilter(ACTION_ALARM)); 300 Intent intent = new Intent(this, AlarmReceiver.class); 301 mPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); 302 mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 303 mScreenManipulator = new SensorTestScreenManipulator(this); 304 try { 305 mScreenManipulator.initialize(this); 306 } catch (InterruptedException e) { 307 } 308 } 309 startTimeoutTimer(long delayMs)310 private void startTimeoutTimer(long delayMs) { 311 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 312 SystemClock.elapsedRealtime() + delayMs, 313 mPendingIntent); 314 } 315 stopTimeoutTimer()316 private void stopTimeoutTimer() { 317 mAlarmManager.cancel(mPendingIntent); 318 } 319 stopOffbodySensorListener(SensorEventVerifier verifier)320 private void stopOffbodySensorListener(SensorEventVerifier verifier) { 321 if (mOffBodySensorRegistered) { 322 mSensorManager.unregisterListener(verifier); 323 mOffBodySensorRegistered = false; 324 } 325 } 326 startOffbodySensorListener(SensorEventVerifier verifier)327 private boolean startOffbodySensorListener(SensorEventVerifier verifier) { 328 if (!mOffBodySensorRegistered) { 329 if (!mSensorManager.registerListener(verifier, mOffBodySensor, 330 SensorManager.SENSOR_DELAY_FASTEST)) { 331 Log.e(TAG, "error registering listener for LLOB"); 332 setTestResultAndFinish(true); 333 return false; 334 } 335 mOffBodySensorRegistered = true; 336 } 337 return true; 338 } 339 340 public static class AlarmReceiver extends BroadcastReceiver { 341 @Override onReceive(Context context, Intent intent)342 public void onReceive(Context context, Intent intent) { 343 Intent alarm_intent = new Intent(context, OffBodySensorTestActivity.class); 344 alarm_intent.setAction(OffBodySensorTestActivity.ACTION_ALARM); 345 LocalBroadcastManager.getInstance(context).sendBroadcastSync(alarm_intent); 346 } 347 } 348 349 public BroadcastReceiver myBroadCastReceiver = new BroadcastReceiver() { 350 @Override 351 public void onReceive(Context context, Intent intent) { 352 mVerifier.releaseLatch(); 353 mScreenManipulator.turnScreenOn(); 354 if (!mDeviceSuspendLock.isHeld()) { 355 mDeviceSuspendLock.acquire(); 356 } 357 } 358 }; 359 testOffbodyDetectResponseTime()360 public String testOffbodyDetectResponseTime() throws Throwable { 361 Sensor wakeUpSensor = mSensorManager.getDefaultSensor( 362 Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true); 363 if (wakeUpSensor == null) { 364 throw new SensorNotSupportedException(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true); 365 } 366 return runOffbodyDetectResponseTimeTest(wakeUpSensor); 367 } 368 testOnbodyDetectResponseTime()369 public String testOnbodyDetectResponseTime() throws Throwable { 370 Sensor wakeUpSensor = mSensorManager.getDefaultSensor( 371 Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true); 372 if (wakeUpSensor == null) { 373 throw new SensorNotSupportedException(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true); 374 } 375 return runOnbodyDetectResponseTimeTest(wakeUpSensor); 376 } 377 testWakeAPOffbodyDetect()378 public String testWakeAPOffbodyDetect() throws Throwable { 379 Sensor wakeUpSensor = mSensorManager.getDefaultSensor( 380 Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true); 381 if (wakeUpSensor == null) { 382 throw new SensorNotSupportedException(Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT, true); 383 } 384 return runWakeAPOffbodyDetectTest(wakeUpSensor); 385 } 386 runOffbodyDetectResponseTimeTest(Sensor sensor)387 public String runOffbodyDetectResponseTimeTest(Sensor sensor) throws Throwable { 388 boolean success; 389 String eventArrivalMessage; 390 mOffBodySensor = sensor; 391 mBadValueSeen = BAD_VALUE_SEEN_INIT; 392 393 try { 394 // If device not currently on-body, instruct user to put it on wrist 395 mTestStartTimestampMs = 0; 396 mVerifier = new SensorEventVerifier(); 397 success = startOffbodySensorListener(mVerifier); 398 Assert.assertTrue( 399 getString(R.string.snsr_offbody_sensor_registration, success), 400 success); 401 SensorEvent event = mVerifier.waitForSensorEvent(); 402 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, event != null); 403 Assert.assertNotNull(eventArrivalMessage, event); 404 405 SensorTestLogger logger = getTestLogger(); 406 if (event.values[0] != ON_BODY_EVENT_VALUE) { 407 // Instruct user on how to perform offbody detect test 408 logger.logInstructions(R.string.snsr_start_offbody_sensor_test_instr); 409 waitForUserToBegin(); 410 if (mPreviousSensorState != State.ON_BODY) { 411 event = mVerifier.waitForSensorEvent(); 412 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, 413 event != null); 414 Assert.assertNotNull(eventArrivalMessage, event); 415 if (event.values[0] != ON_BODY_EVENT_VALUE) { 416 Assert.fail( 417 String.format(getString(R.string.snsr_offbody_event_wrong_value), 418 ON_BODY_EVENT_VALUE, 419 event.values[0])); 420 } 421 } 422 } 423 424 // Instruct user on how to perform offbody detect test 425 logger.logInstructions(R.string.snsr_offbody_detect_test_instr); 426 waitForUserToBegin(); 427 428 // Count down before actually starting, leaving time to react after pressing the Next 429 // button. 430 for (int i = 0; i < COUNTDOWN_NUM_INTERVALS; i++) { 431 try { 432 Thread.sleep(COUNTDOWN_INTERVAL_MS); 433 } catch (InterruptedException e) { 434 // Ignore the interrupt and continue counting down. 435 } 436 logger.logInstructions(R.string.snsr_offbody_detect_test_countdown, 437 COUNTDOWN_NUM_INTERVALS - i - 1); 438 } 439 mTestStartTimestampMs = SystemClock.elapsedRealtime(); 440 441 // Verify off-body event latency is within spec 442 mVerifier.awaitAndVerifyEvent(OFF_BODY_EVENT_VALUE, MAX_OFF_BODY_EVENT_LATENCY_MS); 443 } finally { 444 stopOffbodySensorListener(mVerifier); 445 } 446 return null; 447 } 448 runOnbodyDetectResponseTimeTest(Sensor sensor)449 public String runOnbodyDetectResponseTimeTest(Sensor sensor) throws Throwable { 450 mOffBodySensor = sensor; 451 SensorTestLogger logger = getTestLogger(); 452 mBadValueSeen = BAD_VALUE_SEEN_INIT; 453 454 try { 455 // If device not currently off-body, instruct user to remove it from wrist 456 mTestStartTimestampMs = 0; 457 mVerifier = new SensorEventVerifier(); 458 boolean success = startOffbodySensorListener(mVerifier); 459 Assert.assertTrue( 460 getString(R.string.snsr_offbody_sensor_registration, success), 461 success); 462 SensorEvent event = mVerifier.waitForSensorEvent(); 463 String eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, 464 event != null); 465 Assert.assertNotNull(eventArrivalMessage, event); 466 if (event.values[0] != OFF_BODY_EVENT_VALUE) { 467 // Instruct user on how to perform offbody detect test 468 logger.logInstructions(R.string.snsr_start_onbody_sensor_test_instr); 469 waitForUserToBegin(); 470 if (mPreviousSensorState != State.OFF_BODY) { 471 event = mVerifier.waitForSensorEvent(); 472 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, 473 event != null); 474 Assert.assertNotNull(eventArrivalMessage, event); 475 if (event.values[0] != OFF_BODY_EVENT_VALUE) { 476 Assert.fail( 477 String.format(getString(R.string.snsr_offbody_event_wrong_value), 478 OFF_BODY_EVENT_VALUE, 479 event.values[0])); 480 } 481 } 482 } 483 484 // Display on-body latency test instructions 485 logger.logInstructions(R.string.snsr_onbody_detect_test_instr); 486 waitForUserToBegin(); 487 mTestStartTimestampMs = SystemClock.elapsedRealtime(); 488 mVerifier.awaitAndVerifyEvent(ON_BODY_EVENT_VALUE, MAX_ON_BODY_EVENT_LATENCY_MS); 489 } finally { 490 stopOffbodySensorListener(mVerifier); 491 } 492 return null; 493 } 494 runWakeAPOffbodyDetectTest(Sensor sensor)495 public String runWakeAPOffbodyDetectTest(Sensor sensor) throws Throwable { 496 final long ALARM_WAKE_UP_DELAY_MS = 40000; 497 String eventArrivalMessage; 498 SensorEventRegistry registry; 499 SensorTestLogger logger = getTestLogger(); 500 mBadValueSeen = BAD_VALUE_SEEN_INIT; 501 mVerifier = new SensorEventVerifier(); 502 mOffBodySensor = sensor; 503 mTestStartTimestampMs = 0; 504 505 mTestStartTimestampMs = SystemClock.elapsedRealtime(); 506 SuspendStateMonitor suspendStateMonitor = new SuspendStateMonitor(); 507 try { 508 boolean success = startOffbodySensorListener(mVerifier); 509 Assert.assertTrue( 510 getString(R.string.snsr_offbody_sensor_registration, success), 511 success); 512 513 // grab the current off-body state, which should be ON-BODY 514 if (mPreviousSensorState != State.ON_BODY) { 515 registry = mVerifier.waitForEvent(); 516 if ((registry == null) || (registry.event == null) || 517 (registry.event.values[0] != ON_BODY_EVENT_VALUE)) { 518 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, false); 519 Assert.fail(eventArrivalMessage); 520 521 // Tell user to put watch on wrist 522 logger.logInstructions(R.string.snsr_start_offbody_sensor_test_instr); 523 waitForUserToBegin(); 524 if (mPreviousSensorState != State.ON_BODY) { 525 registry = mVerifier.waitForEvent(); 526 if ((registry == null) || (registry.event == null)) { 527 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, false); 528 Assert.fail(eventArrivalMessage); 529 } else { 530 Assert.assertTrue( 531 String.format(getString(R.string.snsr_offbody_event_wrong_value), 532 ON_BODY_EVENT_VALUE, 533 registry.event.values[0]), 534 ON_BODY_EVENT_VALUE == registry.event.values[0]); 535 } 536 } 537 } 538 } 539 540 // Instruct user on how to perform offbody detect sleep test 541 logger.logInstructions(R.string.snsr_ap_wake_offbody_detect_test_instr); 542 waitForUserToBegin(); 543 544 long testStartTimeNs = SystemClock.elapsedRealtimeNanos(); 545 startTimeoutTimer(ALARM_WAKE_UP_AP_DELAY_MS); 546 547 // Wait for the first event to trigger. Device is expected to go into suspend here. 548 registry = mVerifier.waitForEvent(mDeviceSuspendLock); 549 if ((registry == null) || (registry.event == null)) { 550 eventArrivalMessage = getString(R.string.snsr_offbody_event_arrival, false); 551 Assert.fail(eventArrivalMessage); 552 } 553 554 mVerifier.verifyEvent(registry, OFF_BODY_EVENT_VALUE, 0); 555 556 long eventTimeStampNs = registry.event.timestamp; 557 long endTimeNs = SystemClock.elapsedRealtimeNanos(); 558 long lastWakeupTimeNs = TimeUnit.MILLISECONDS.toNanos( 559 suspendStateMonitor.getLastWakeUpTime()); 560 Assert.assertTrue(getString(R.string.snsr_device_did_not_go_into_suspend), 561 testStartTimeNs < lastWakeupTimeNs && lastWakeupTimeNs < endTimeNs); 562 long timestampDelta = Math.abs(lastWakeupTimeNs - eventTimeStampNs); 563 Assert.assertTrue( 564 String.format(getString(R.string.snsr_device_did_not_wake_up_at_trigger), 565 TimeUnit.NANOSECONDS.toMillis(lastWakeupTimeNs), 566 TimeUnit.NANOSECONDS.toMillis(eventTimeStampNs)), 567 timestampDelta < MAX_ACCEPTABLE_DELAY_EVENT_AP_WAKE_UP_NS); 568 } finally { 569 stopTimeoutTimer(); 570 suspendStateMonitor.cancel(); 571 mScreenManipulator.turnScreenOn(); 572 playSound(); 573 } 574 return null; 575 } 576 577 @Override 578 protected void activityCleanUp() { 579 if (mOffBodySensorRegistered) { 580 stopOffbodySensorListener(mVerifier); 581 } 582 stopTimeoutTimer(); 583 LocalBroadcastManager.getInstance(this).unregisterReceiver(myBroadCastReceiver); 584 if (mOffBodySensor != null) { 585 mOffBodySensor = null; 586 } 587 if (mScreenManipulator != null){ 588 mScreenManipulator.close(); 589 } 590 if ((mDeviceSuspendLock != null) && mDeviceSuspendLock.isHeld()) { 591 mDeviceSuspendLock.release(); 592 } 593 } 594 } 595