blob: 2dfc7c8e24e5ad1ec0e3e2bd2931dd27a68e8b00 [file] [log] [blame]
Jim Steelec57c8432014-05-24 09:53:32 -07001/*
2 * Copyright (C) 2014 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
17package com.android.cts.verifier.sensors;
18
Aravind Akelladbc95c52015-06-09 10:22:16 -070019import java.util.Timer;
20import java.util.TimerTask;
21import java.util.concurrent.CountDownLatch;
22import java.util.concurrent.TimeUnit;
23
destradaaa07a7a22014-08-21 17:09:03 -070024import com.android.cts.verifier.R;
destradaaa0b3bbc2014-09-03 14:08:00 -070025import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
Aravind Akelladbc95c52015-06-09 10:22:16 -070026import com.android.cts.verifier.sensors.helpers.SensorTestScreenManipulator;
destradaaa07a7a22014-08-21 17:09:03 -070027
Aravind Akelladbc95c52015-06-09 10:22:16 -070028import android.app.AlarmManager;
29import android.app.PendingIntent;
30import android.content.BroadcastReceiver;
Jim Steelec57c8432014-05-24 09:53:32 -070031import android.content.Context;
Aravind Akelladbc95c52015-06-09 10:22:16 -070032import android.content.Intent;
33import android.content.IntentFilter;
Jim Steelec57c8432014-05-24 09:53:32 -070034import android.hardware.Sensor;
35import android.hardware.SensorManager;
36import android.hardware.TriggerEvent;
37import android.hardware.TriggerEventListener;
destradaa91553992014-09-19 17:50:15 -070038import android.hardware.cts.helpers.SensorNotSupportedException;
destradaa7bed8102014-09-24 13:18:16 -070039import android.hardware.cts.helpers.TestSensorEnvironment;
Aravind Akelladbc95c52015-06-09 10:22:16 -070040import android.hardware.cts.helpers.SuspendStateMonitor;
41import android.os.Handler;
42import android.os.Looper;
43import android.os.PowerManager;
destradaaa07a7a22014-08-21 17:09:03 -070044import android.os.SystemClock;
Aravind Akelladbc95c52015-06-09 10:22:16 -070045import android.support.v4.content.LocalBroadcastManager;
46import android.util.Log;
Jim Steelec57c8432014-05-24 09:53:32 -070047
Aravind Akelladbc95c52015-06-09 10:22:16 -070048import junit.framework.Assert;
Jim Steelec57c8432014-05-24 09:53:32 -070049
destradaaa07a7a22014-08-21 17:09:03 -070050/**
51 * Test cases for Significant Motion sensor.
52 * They use walking motion to change the location and trigger Significant Motion.
53 */
destradaaa0b3bbc2014-09-03 14:08:00 -070054public class SignificantMotionTestActivity extends SensorCtsVerifierTestActivity {
destradaaa07a7a22014-08-21 17:09:03 -070055 public SignificantMotionTestActivity() {
56 super(SignificantMotionTestActivity.class);
Jim Steelec57c8432014-05-24 09:53:32 -070057 }
58
destradaaa07a7a22014-08-21 17:09:03 -070059 // acceptable time difference between event time and system time
destradaa139500e2014-08-22 16:01:52 -070060 private static final long MAX_ACCEPTABLE_EVENT_TIME_DELAY_NANOS =
61 TimeUnit.MILLISECONDS.toNanos(500);
Jim Steelec57c8432014-05-24 09:53:32 -070062
Aravind Akelladbc95c52015-06-09 10:22:16 -070063 // acceptable time difference between event time and AP wake up time.
64 private static final long MAX_ACCEPTABLE_DELAY_EVENT_AP_WAKE_UP_NS =
65 TimeUnit.MILLISECONDS.toNanos(2000);
66
67 // time to wait for SMD after the device has gone into suspend. Even after
68 // 45 secs if SMD does not trigger, the test will fail.
69 private static final long ALARM_WAKE_TIME_DELAY_MS = TimeUnit.SECONDS.toMillis(45);
70
destradaaa07a7a22014-08-21 17:09:03 -070071 // time for the test to wait for a trigger
72 private static final int TRIGGER_MAX_DELAY_SECONDS = 30;
73 private static final int VIBRATE_DURATION_MILLIS = 10000;
Jim Steelec57c8432014-05-24 09:53:32 -070074
destradaaa07a7a22014-08-21 17:09:03 -070075 private static final int EVENT_VALUES_LENGTH = 1;
76 private static final float EXPECTED_EVENT_VALUE = 1.0f;
Aravind Akelladbc95c52015-06-09 10:22:16 -070077 private static String ACTION_ALARM = "SignificantMotionTestActivity.ACTION_ALARM";
Jim Steelec57c8432014-05-24 09:53:32 -070078
79 private SensorManager mSensorManager;
80 private Sensor mSensorSignificantMotion;
Aravind Akelladbc95c52015-06-09 10:22:16 -070081 private TriggerVerifier mVerifier;
82 private SensorTestScreenManipulator mScreenManipulator;
Jim Steelec57c8432014-05-24 09:53:32 -070083
destradaaa07a7a22014-08-21 17:09:03 -070084 /**
85 * Test cases.
86 */
destradaafd031b92014-10-10 10:45:51 -070087 @SuppressWarnings("unused")
destradaaa07a7a22014-08-21 17:09:03 -070088 public String testTrigger() throws Throwable {
89 return runTest(
90 R.string.snsr_significant_motion_test_trigger,
91 true /* isMotionExpected */,
92 false /* cancelEventNotification */,
93 false /* vibrate */);
Jim Steelec57c8432014-05-24 09:53:32 -070094 }
95
destradaafd031b92014-10-10 10:45:51 -070096 @SuppressWarnings("unused")
destradaa16203b42014-09-29 13:26:51 -070097 public String testNotTriggerAfterCancel() throws Throwable {
destradaaa07a7a22014-08-21 17:09:03 -070098 return runTest(
99 R.string.snsr_significant_motion_test_cancel,
100 false /* isMotionExpected */,
101 true /* cancelEventNotification */,
102 false /* vibrate */);
Jim Steelec57c8432014-05-24 09:53:32 -0700103 }
104
105 /**
destradaaa07a7a22014-08-21 17:09:03 -0700106 * Verifies that Significant Motion is not trigger by the vibrator motion.
107 */
destradaafd031b92014-10-10 10:45:51 -0700108 @SuppressWarnings("unused")
destradaaa07a7a22014-08-21 17:09:03 -0700109 public String testVibratorDoesNotTrigger() throws Throwable {
110 return runTest(
111 R.string.snsr_significant_motion_test_vibration,
112 false /* isMotionExpected */,
113 false /* cancelEventNotification */,
114 true /* vibrate */);
115 }
116
117 /**
118 * Verifies that the natural motion of keeping the device in hand does not change the location.
119 * It ensures that Significant Motion will not trigger in that scenario.
120 */
destradaafd031b92014-10-10 10:45:51 -0700121 @SuppressWarnings("unused")
destradaaa07a7a22014-08-21 17:09:03 -0700122 public String testInHandDoesNotTrigger() throws Throwable {
123 return runTest(
124 R.string.snsr_significant_motion_test_in_hand,
125 false /* isMotionExpected */,
126 false /* cancelEventNotification */,
127 false /* vibrate */);
128 }
129
destradaafd031b92014-10-10 10:45:51 -0700130 @SuppressWarnings("unused")
destradaaa07a7a22014-08-21 17:09:03 -0700131 public String testSittingDoesNotTrigger() throws Throwable {
132 return runTest(
133 R.string.snsr_significant_motion_test_sitting,
134 false /* isMotionExpected */,
135 false /* cancelEventNotification */,
136 false /* vibrate */);
137 }
138
destradaafd031b92014-10-10 10:45:51 -0700139 @SuppressWarnings("unused")
destradaaa07a7a22014-08-21 17:09:03 -0700140 public String testTriggerDeactivation() throws Throwable {
destradaa16203b42014-09-29 13:26:51 -0700141 SensorTestLogger logger = getTestLogger();
142 logger.logInstructions(R.string.snsr_significant_motion_test_deactivation);
143 waitForUserToBegin();
destradaaa07a7a22014-08-21 17:09:03 -0700144
145 TriggerVerifier verifier = new TriggerVerifier();
146 mSensorManager.requestTriggerSensor(verifier, mSensorSignificantMotion);
destradaa16203b42014-09-29 13:26:51 -0700147 logger.logWaitForSound();
destradaaa07a7a22014-08-21 17:09:03 -0700148
149 // wait for the first event to trigger
150 verifier.verifyEventTriggered();
151
152 // wait for a second event not to trigger
153 String result = verifier.verifyEventNotTriggered();
154 playSound();
155 return result;
156 }
157
Aravind Akelladbc95c52015-06-09 10:22:16 -0700158 public static class AlarmReceiver extends BroadcastReceiver {
159 @Override
160 public void onReceive(Context context, Intent intent) {
161 Intent alarm_intent = new Intent(context, SignificantMotionTestActivity.class);
162 alarm_intent.setAction(SignificantMotionTestActivity.ACTION_ALARM);
163 LocalBroadcastManager.getInstance(context).sendBroadcastSync(alarm_intent);
164 }
165 }
166
167 public BroadcastReceiver myBroadCastReceiver = new BroadcastReceiver() {
168 @Override
169 public void onReceive(Context context, Intent intent) {
170 mVerifier.releaseLatch();
171 mScreenManipulator.turnScreenOn();
172 try {
173 playSound();
174 } catch (InterruptedException e) {
175 // Ignore ...
176 }
177 }
178 };
179
180 @SuppressWarnings("unused")
181 public String testAPWakeUpOnSMDTrigger() throws Throwable {
182 SensorTestLogger logger = getTestLogger();
183 logger.logInstructions(R.string.snsr_significant_motion_ap_suspend);
184 waitForUserToBegin();
185 mVerifier = new TriggerVerifier();
186 mSensorManager.requestTriggerSensor(mVerifier, mSensorSignificantMotion);
187 long testStartTimeNs = SystemClock.elapsedRealtimeNanos();
188 Handler handler = new Handler(Looper.getMainLooper());
189 SuspendStateMonitor suspendStateMonitor = new SuspendStateMonitor();
190
191 Intent intent = new Intent(this, AlarmReceiver.class);
192 PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
193
194 AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
195 am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
196 SystemClock.elapsedRealtime() + ALARM_WAKE_TIME_DELAY_MS, pendingIntent);
197 try {
198 // Wait for the first event to trigger. Device is expected to go into suspend here.
199 mVerifier.verifyEventTriggered();
200 long eventTimeStampNs = mVerifier.getTimeStampForTriggerEvent();
201 long endTimeNs = SystemClock.elapsedRealtimeNanos();
202 long lastWakeupTimeNs = TimeUnit.MILLISECONDS.toNanos(
203 suspendStateMonitor.getLastWakeUpTime());
204 Assert.assertTrue(getString(R.string.snsr_device_did_not_go_into_suspend),
205 testStartTimeNs < lastWakeupTimeNs && lastWakeupTimeNs < endTimeNs);
206 long timestampDelta = Math.abs(lastWakeupTimeNs - eventTimeStampNs);
207 Assert.assertTrue(
208 String.format(getString(R.string.snsr_device_did_not_wake_up_at_trigger),
209 TimeUnit.NANOSECONDS.toMillis(lastWakeupTimeNs),
210 TimeUnit.NANOSECONDS.toMillis(eventTimeStampNs)),
211 timestampDelta < MAX_ACCEPTABLE_DELAY_EVENT_AP_WAKE_UP_NS);
212 } finally {
213 am.cancel(pendingIntent);
214 suspendStateMonitor.cancel();
215 mScreenManipulator.turnScreenOn();
216 playSound();
217 }
218 return null;
219 }
220
destradaaa07a7a22014-08-21 17:09:03 -0700221 /**
222 * @param instructionsResId Instruction to be shown to testers
Jim Steelec57c8432014-05-24 09:53:32 -0700223 * @param isMotionExpected Should the device detect significant motion event
224 * for this test?
225 * @param cancelEventNotification If TRUE, motion notifications will be
226 * requested first and request will be cancelled
227 * @param vibrate If TRUE, vibration will be concurrent with the test
228 * @throws Throwable
229 */
destradaaa07a7a22014-08-21 17:09:03 -0700230 private String runTest(
231 int instructionsResId,
232 boolean isMotionExpected,
233 boolean cancelEventNotification,
234 boolean vibrate) throws Throwable {
destradaa16203b42014-09-29 13:26:51 -0700235 SensorTestLogger logger = getTestLogger();
236 logger.logInstructions(instructionsResId);
237 waitForUserToBegin();
Jim Steelec57c8432014-05-24 09:53:32 -0700238
239 if (vibrate) {
destradaaa07a7a22014-08-21 17:09:03 -0700240 vibrate(VIBRATE_DURATION_MILLIS);
Jim Steelec57c8432014-05-24 09:53:32 -0700241 }
242
destradaaa07a7a22014-08-21 17:09:03 -0700243 TriggerVerifier verifier = new TriggerVerifier();
destradaa91553992014-09-19 17:50:15 -0700244 boolean success = mSensorManager.requestTriggerSensor(verifier, mSensorSignificantMotion);
destradaaa07a7a22014-08-21 17:09:03 -0700245 Assert.assertTrue(
destradaa91553992014-09-19 17:50:15 -0700246 getString(R.string.snsr_significant_motion_registration, success),
247 success);
destradaaa07a7a22014-08-21 17:09:03 -0700248 if (cancelEventNotification) {
249 Assert.assertTrue(
250 getString(R.string.snsr_significant_motion_cancelation),
251 mSensorManager.cancelTriggerSensor(verifier, mSensorSignificantMotion));
Jim Steelec57c8432014-05-24 09:53:32 -0700252 }
destradaa16203b42014-09-29 13:26:51 -0700253 logger.logWaitForSound();
Jim Steelec57c8432014-05-24 09:53:32 -0700254
destradaaa07a7a22014-08-21 17:09:03 -0700255 String result;
256 try {
257 if (isMotionExpected) {
258 result = verifier.verifyEventTriggered();
259 } else {
260 result = verifier.verifyEventNotTriggered();
261 }
262 } finally {
263 mSensorManager.cancelTriggerSensor(verifier, mSensorSignificantMotion);
destradaafd031b92014-10-10 10:45:51 -0700264 playSound();
Jim Steelec57c8432014-05-24 09:53:32 -0700265 }
destradaaa07a7a22014-08-21 17:09:03 -0700266 return result;
Jim Steelec57c8432014-05-24 09:53:32 -0700267 }
268
269 @Override
destradaa91553992014-09-19 17:50:15 -0700270 protected void activitySetUp() {
Jim Steelec57c8432014-05-24 09:53:32 -0700271 mSensorManager = (SensorManager) getApplicationContext()
272 .getSystemService(Context.SENSOR_SERVICE);
destradaa91553992014-09-19 17:50:15 -0700273 mSensorSignificantMotion = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
274 if (mSensorSignificantMotion == null) {
275 throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
276 }
Aravind Akelladbc95c52015-06-09 10:22:16 -0700277
278 mScreenManipulator = new SensorTestScreenManipulator(this);
279 try {
280 mScreenManipulator.initialize(this);
281 } catch (InterruptedException e) {
282 }
283 PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
284 LocalBroadcastManager.getInstance(this).registerReceiver(myBroadCastReceiver,
285 new IntentFilter(ACTION_ALARM));
286 }
287
288 @Override
289 protected void activityCleanUp() {
Aravind Akella80ae6ff2015-09-14 16:07:42 -0700290 if (mScreenManipulator != null) {
291 mScreenManipulator.turnScreenOff();
292 }
Aravind Akelladbc95c52015-06-09 10:22:16 -0700293 LocalBroadcastManager.getInstance(this).unregisterReceiver(myBroadCastReceiver);
294 }
295
296 @Override
297 protected void onDestroy() {
298 super.onDestroy();
299 mScreenManipulator.close();
Jim Steelec57c8432014-05-24 09:53:32 -0700300 }
301
destradaaa07a7a22014-08-21 17:09:03 -0700302 /**
303 * Helper Trigger listener for testing.
304 * It cannot be reused.
305 */
306 private class TriggerVerifier extends TriggerEventListener {
Aravind Akella8f2596c2015-08-27 12:07:52 -0700307 private volatile CountDownLatch mCountDownLatch;
destradaaa07a7a22014-08-21 17:09:03 -0700308 private volatile TriggerEventRegistry mEventRegistry;
Aravind Akella8f2596c2015-08-27 12:07:52 -0700309 private volatile long mTimestampForTriggeredEvent = 0;
Jim Steelec57c8432014-05-24 09:53:32 -0700310
destradaa139500e2014-08-22 16:01:52 -0700311 // TODO: refactor out if needed
destradaaa07a7a22014-08-21 17:09:03 -0700312 private class TriggerEventRegistry {
313 public final TriggerEvent triggerEvent;
314 public final long realtimeTimestampNanos;
315
316 public TriggerEventRegistry(TriggerEvent event, long realtimeTimestampNanos) {
317 this.triggerEvent = event;
318 this.realtimeTimestampNanos = realtimeTimestampNanos;
319 }
Jim Steelec57c8432014-05-24 09:53:32 -0700320 }
Jim Steelec57c8432014-05-24 09:53:32 -0700321
destradaaa07a7a22014-08-21 17:09:03 -0700322 public void onTrigger(TriggerEvent event) {
323 long elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
324 mEventRegistry = new TriggerEventRegistry(event, elapsedRealtimeNanos);
325 mCountDownLatch.countDown();
326 }
Jim Steelec57c8432014-05-24 09:53:32 -0700327
Aravind Akelladbc95c52015-06-09 10:22:16 -0700328 public void releaseLatch() {
329 if (mCountDownLatch != null) {
330 mCountDownLatch.countDown();
331 }
332 }
333
334 public long getTimeStampForTriggerEvent() {
Aravind Akella8f2596c2015-08-27 12:07:52 -0700335 return mTimestampForTriggeredEvent;
Aravind Akelladbc95c52015-06-09 10:22:16 -0700336 }
337
destradaaa07a7a22014-08-21 17:09:03 -0700338 public String verifyEventTriggered() throws Throwable {
339 TriggerEventRegistry registry = awaitForEvent();
340
341 // verify an event arrived, and it is indeed a Significant Motion event
342 TriggerEvent event = registry.triggerEvent;
343 String eventArrivalMessage =
destradaaa7714542014-09-04 16:23:03 -0700344 getString(R.string.snsr_significant_motion_event_arrival, event != null);
destradaaa07a7a22014-08-21 17:09:03 -0700345 Assert.assertNotNull(eventArrivalMessage, event);
346
347 int eventType = event.sensor.getType();
348 String eventTypeMessage = getString(
349 R.string.snsr_significant_motion_event_type,
350 Sensor.TYPE_SIGNIFICANT_MOTION,
351 eventType);
352 Assert.assertEquals(eventTypeMessage, Sensor.TYPE_SIGNIFICANT_MOTION, eventType);
353
destradaa139500e2014-08-22 16:01:52 -0700354 String sensorName = event.sensor.getName();
destradaaa07a7a22014-08-21 17:09:03 -0700355 int valuesLength = event.values.length;
356 String valuesLengthMessage = getString(
destradaa139500e2014-08-22 16:01:52 -0700357 R.string.snsr_event_length,
destradaaa07a7a22014-08-21 17:09:03 -0700358 EVENT_VALUES_LENGTH,
destradaa139500e2014-08-22 16:01:52 -0700359 valuesLength,
360 sensorName);
destradaaa07a7a22014-08-21 17:09:03 -0700361 Assert.assertEquals(valuesLengthMessage, EVENT_VALUES_LENGTH, valuesLength);
362
363 float value = event.values[0];
364 String valuesMessage = getString(
destradaa139500e2014-08-22 16:01:52 -0700365 R.string.snsr_event_value,
destradaaa07a7a22014-08-21 17:09:03 -0700366 EXPECTED_EVENT_VALUE,
destradaa139500e2014-08-22 16:01:52 -0700367 value,
368 sensorName);
destradaaa07a7a22014-08-21 17:09:03 -0700369 Assert.assertEquals(valuesMessage, EXPECTED_EVENT_VALUE, value);
370
destradaa7bed8102014-09-24 13:18:16 -0700371 long deltaThreshold = MAX_ACCEPTABLE_EVENT_TIME_DELAY_NANOS
372 + TestSensorEnvironment.getSensorMaxDetectionLatencyNs(event.sensor);
destradaa139500e2014-08-22 16:01:52 -0700373 return assertTimestampSynchronization(
374 event.timestamp,
375 registry.realtimeTimestampNanos,
destradaa7bed8102014-09-24 13:18:16 -0700376 deltaThreshold,
destradaa139500e2014-08-22 16:01:52 -0700377 sensorName);
destradaaa07a7a22014-08-21 17:09:03 -0700378 }
379
380 public String verifyEventNotTriggered() throws Throwable {
381 TriggerEventRegistry registry = awaitForEvent();
382
383 TriggerEvent event = registry.triggerEvent;
384 String eventMessage =
destradaaa7714542014-09-04 16:23:03 -0700385 getString(R.string.snsr_significant_motion_event_unexpected, event != null);
destradaaa07a7a22014-08-21 17:09:03 -0700386 Assert.assertNull(eventMessage, event);
387 return eventMessage;
388 }
389
390 private TriggerEventRegistry awaitForEvent() throws InterruptedException {
Aravind Akella8f2596c2015-08-27 12:07:52 -0700391 mCountDownLatch = new CountDownLatch(1);
destradaaa07a7a22014-08-21 17:09:03 -0700392 mCountDownLatch.await(TRIGGER_MAX_DELAY_SECONDS, TimeUnit.SECONDS);
destradaaa07a7a22014-08-21 17:09:03 -0700393 TriggerEventRegistry registry = mEventRegistry;
destradaaa07a7a22014-08-21 17:09:03 -0700394
Aravind Akella8f2596c2015-08-27 12:07:52 -0700395 // Save the last timestamp when the event triggered.
396 if (mEventRegistry != null && mEventRegistry.triggerEvent != null) {
397 mTimestampForTriggeredEvent = mEventRegistry.triggerEvent.timestamp;
398 }
399
400 mEventRegistry = null;
destradaaa07a7a22014-08-21 17:09:03 -0700401 playSound();
402 return registry != null ? registry : new TriggerEventRegistry(null, 0);
Jim Steelec57c8432014-05-24 09:53:32 -0700403 }
404 }
405}