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