Merge "resolved conflicts for merge of 6d814d9f to lmp-dev" into lmp-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index b67bdf8..3373ef1 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -34,6 +34,7 @@
<uses-permission android:name="android.permission.FULLSCREEN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
+ <uses-permission android:name="android.permission.VIBRATE" />
<uses-feature android:name="android.hardware.camera.front"
android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus"
@@ -43,7 +44,6 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
-
<uses-feature android:name="android.hardware.usb.accessory" />
<!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
@@ -927,6 +927,32 @@
<meta-data android:name="test_category" android:value="@string/test_category_deskclock" />
</activity>
+ <activity
+ android:name="com.android.cts.verifier.sensors.StepCounterTestActivity"
+ android:label="@string/snsr_step_counter_test"
+ android:screenOrientation="nosensor" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+ </activity>
+
+ <activity
+ android:name="com.android.cts.verifier.sensors.SignificantMotionTestActivity"
+ android:label="@string/snsr_significant_motion_test"
+ android:screenOrientation="nosensor" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+
+ <meta-data
+ android:name="test_category"
+ android:value="@string/test_category_sensors" />
+ </activity>
+
<receiver android:name=".widget.WidgetCtsProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 1fb7ecb..d7e6d33 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -442,6 +442,12 @@
<!-- Magnetic Field -->
<string name="snsr_mag_m_test">Magnetic Field Measurement Tests</string>
+ <!-- Step Counter and Detector -->
+ <string name="snsr_step_counter_test">Step Counter and Detector Tests</string>
+
+ <!-- Significant Motion -->
+ <string name="snsr_significant_motion_test">Significant Motion Tests</string>
+
<!-- Strings for Sample Test Activities -->
<string name="share_button_text">Share</string>
<string name="sample_framework_test">Sample Framework Test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
new file mode 100644
index 0000000..9258ba6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.sensors;
+
+import junit.framework.Assert;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
+import android.media.AudioManager;
+import android.media.ToneGenerator;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Vibrator;
+
+@TargetApi(Build.VERSION_CODES.KITKAT)
+class TriggerListener extends TriggerEventListener {
+ // how much difference between system time and event time considered to be
+ // acceptable [msec]
+ private final long MAX_ACCEPTABLE_EVENT_TIME_DELAY_MILLIS = 500;
+
+ // state used for internal recording of the event detection
+ private boolean mEventDetected = false;
+
+ public void onTrigger(TriggerEvent event) {
+ final long NANOS_PER_MS = 1000000L;
+
+ Assert.assertEquals("values should be of length 1 for significant motion event", 1,
+ event.values.length);
+ Assert.assertEquals("values[0] should be 1.0 for significant motion event", 1.0f,
+ event.values[0]);
+
+ // Check that timestamp is within MAX_ACCEPTABLE_EVENT_TIME_DELAY_MILLIS
+ // It might take time to determine Significant Motion, but then that
+ // event should be reported to the host in a timely fashion.
+ long timeReportedMillis = event.timestamp / NANOS_PER_MS;
+ long timeActualMillis = System.currentTimeMillis();
+ Assert.assertEquals("Incorrect time reported in the event",
+ timeReportedMillis, timeActualMillis, MAX_ACCEPTABLE_EVENT_TIME_DELAY_MILLIS);
+
+ // Verify event type is truly Significant Motion
+ Assert.assertEquals("Triggered event type is not Significant Motion",
+ event.sensor.getType(), Sensor.TYPE_SIGNIFICANT_MOTION);
+
+ // Event detected flag should be false if indeed only one event per
+ // request
+ Assert.assertFalse("Significant Motion sensor did not automatically "
+ + "disable itself from subsequent detection", mEventDetected);
+
+ // audible cue to indicate Significant Motion occurred
+ beep();
+ mEventDetected = true;
+ }
+
+ public boolean wasEventTriggered() {
+ return mEventDetected;
+ }
+
+ public void reset() {
+ mEventDetected = false;
+ }
+
+ private void beep() {
+ final ToneGenerator tg = new ToneGenerator(
+ AudioManager.STREAM_NOTIFICATION, 100);
+ tg.startTone(ToneGenerator.TONE_PROP_BEEP);
+ }
+}
+
+@TargetApi(Build.VERSION_CODES.KITKAT)
+public class SignificantMotionTestActivity extends BaseSensorSemiAutomatedTestActivity {
+ // minimum time for test to consider valid [msec]
+ private final int MIN_TEST_TIME_MILLIS = 20000;
+ private final int VIBRATE_DURATION_MILLIS = 10000;
+
+ private SensorManager mSensorManager;
+ private Sensor mSensorSignificantMotion;
+ private final TriggerListener mTriggeredListener = new TriggerListener();
+ private long mTestStartTimestamp;
+ private static int sNumPassedTests = 0;
+
+ @Override
+ protected void onRun() throws Throwable {
+ switch (sNumPassedTests) {
+ // avoid re-running passed tests, so purposely want fallthroughs here
+ case 0:
+ // use walking to change location and trigger significant motion
+ runTest("walk 15 steps for significant motion to be detected", true, false, false);
+ case 1:
+ runTest("walk another 15 steps to ensure significant motion "
+ + "is not reported after trigger cancelled", false, true, false);
+ case 2:
+ // use vibrator to ensure significant motion is not triggered
+ runTest("leave the device on a level surface", false, false, true);
+ case 3:
+ // use natural motion that does not change location to ensure
+ // significant motion is not triggered
+ runTest("hold the device in hand while performing natural "
+ + "hand movements", false, false, false);
+ case 4:
+ runTest("keep the device in pocket and move naturally while "
+ + "sitting in a chair", false, false, false);
+ default:
+ break;
+ }
+ }
+
+ private void vibrateDevice(int timeInMs) {
+ Vibrator vibrator = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);
+ vibrator.vibrate(timeInMs);
+ }
+
+ /**
+ * @param instructions Instruction to be shown to testers
+ * @param isMotionExpected Should the device detect significant motion event
+ * for this test?
+ * @param cancelEventNotification If TRUE, motion notifications will be
+ * requested first and request will be cancelled
+ * @param vibrate If TRUE, vibration will be concurrent with the test
+ * @throws Throwable
+ */
+ private void runTest(String instructions, final boolean isMotionExpected,
+ final boolean cancelEventNotification, final boolean vibrate) throws Throwable {
+
+ appendText("Click 'Next' and " + instructions);
+ waitForUser();
+
+ if (vibrate) {
+ vibrateDevice(VIBRATE_DURATION_MILLIS);
+ }
+
+ mTestStartTimestamp = System.currentTimeMillis();
+ startMeasurements(cancelEventNotification);
+
+ long testTime = System.currentTimeMillis() - mTestStartTimestamp;
+
+ while (!mTriggeredListener.wasEventTriggered()
+ && testTime < MIN_TEST_TIME_MILLIS) {
+ int timeWaitSec = Math
+ .round((MIN_TEST_TIME_MILLIS - testTime) / 1000);
+ clearText();
+ appendText("Current test: " + instructions);
+ appendText(
+ String.format("%d seconds for the test to complete", timeWaitSec),
+ Color.GRAY);
+
+ Thread.sleep(1000);
+ testTime = System.currentTimeMillis() - mTestStartTimestamp;
+ }
+ clearText();
+ appendText("Current test: " + instructions);
+ playSound();
+ verifyMeasurements(isMotionExpected);
+ sNumPassedTests++;
+ }
+
+ private void startMeasurements(boolean isCancelTriggerRequested) throws Throwable {
+ mTriggeredListener.reset();
+
+ mSensorManager.requestTriggerSensor(mTriggeredListener, mSensorSignificantMotion);
+
+ if (isCancelTriggerRequested) {
+ mSensorManager.cancelTriggerSensor(mTriggeredListener, mSensorSignificantMotion);
+ }
+ }
+
+ private void verifyMeasurements(boolean isMotionExpected) throws Throwable {
+ Assert.assertEquals("Significant motion event expected/detected mismatch: "
+ + isMotionExpected + " / " + mTriggeredListener.wasEventTriggered(),
+ isMotionExpected, mTriggeredListener.wasEventTriggered());
+ appendText("Significant motion event " + isMotionExpected + " as expected", Color.GRAY);
+ logSuccess();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mSensorManager = (SensorManager) getApplicationContext()
+ .getSystemService(Context.SENSOR_SERVICE);
+
+ mSensorSignificantMotion = mSensorManager
+ .getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
+
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (mSensorManager != null && mSensorSignificantMotion != null) {
+ mSensorManager.requestTriggerSensor(mTriggeredListener,
+ mSensorSignificantMotion);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ if (mSensorManager != null && mSensorSignificantMotion != null) {
+ mSensorManager.cancelTriggerSensor(mTriggeredListener,
+ mSensorSignificantMotion);
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
new file mode 100644
index 0000000..0dfe341
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.sensors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Color;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.media.AudioManager;
+import android.media.ToneGenerator;
+import android.os.Build;
+import android.os.SystemClock;
+import android.os.Vibrator;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import com.android.cts.verifier.R;
+
+@TargetApi(Build.VERSION_CODES.KITKAT)
+public class StepCounterTestActivity extends BaseSensorSemiAutomatedTestActivity
+ implements SensorEventListener {
+
+ private SensorManager mSensorManager;
+ private Sensor mSensorStepCounter;
+ private Sensor mSensorStepDetector;
+
+ private int mStepsReported = 0; // number of steps as reported by user
+ private int mInitialStepCount = 0; // step counter at the start of test
+ private int mStepsDetected = 0; // number of steps during the test
+
+ private List<Long> mTimestampsUserReported = new ArrayList<Long>();
+ private List<Long> mTimestampsStepCounter = new ArrayList<Long>();
+ private List<Long> mTimestampsStepDetector = new ArrayList<Long>();
+
+ private final int MIN_TEST_TIME_MILLIS = 20000; // 20 sec
+ private final double NANOSECONDS_IN_SEC = 1e9;
+ private final int MIN_NUM_STEPS_PER_TEST = 10;
+ private final int MAX_STEP_DISCREPANCY = 4;
+ private final int MAX_TOLERANCE_STEP_TIME_LATENCY_SECONDS = 8;
+
+ private boolean mCheckForMotion = false;
+
+ private Sensor mSensorAcceleration;
+ private boolean mMoveDetected = false;
+ private static int sNumPassedTests = 0;
+
+ @Override
+ protected void onRun() throws Throwable {
+ View screen = (View) findViewById(R.id.log_text).getParent();
+ Assert.assertNotNull(screen);
+ screen.setOnClickListener(mClickListener);
+
+ switch (sNumPassedTests) {
+ // avoid re-running passed tests, so purposely want fallthroughs here
+ case 0:
+ runTest("walk at least " + MIN_NUM_STEPS_PER_TEST
+ + " steps and tap on the screen with each step",
+ MIN_NUM_STEPS_PER_TEST, MAX_STEP_DISCREPANCY, false, false);
+ case 1:
+ runTest("hold device still in hand", 0, MAX_STEP_DISCREPANCY, true, true);
+ case 2:
+ runTest("wave device in hand throughout test", 0, MAX_STEP_DISCREPANCY, false,
+ true);
+ default:
+ break;
+ }
+ }
+
+ private OnClickListener mClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (!mCheckForMotion) {
+ SensorCtsHelper.beep(ToneGenerator.TONE_PROP_BEEP);
+ mTimestampsUserReported.add(SystemClock.elapsedRealtimeNanos());
+ mStepsReported = mTimestampsUserReported.size();
+ }
+ }
+ };
+
+ /**
+ * @param instructions Instruction to be shown to testers
+ * @param expectedSteps Number of steps expected in this test
+ * @param tolerance Number of steps the count can be off by and still pass
+ * @param vibrate If TRUE, vibration will be concurrent with the test
+ * @param onlyWarn If TRUE, only warn the user if the test fails. This
+ * option will be removed on a future release of CTS. TODO:
+ * remove this option
+ * @throws Throwable
+ */
+ static long[] sVibratePattern = {
+ 1000L, 500L, 1000L, 750L, 1000L, 500L, 1000L, 750L, 1000L, 1000L, 500L, 1000L,
+ 750L, 1000L, 500L, 1000L
+ };
+ private void runTest(String instructions, int expectedSteps, int tolerance, boolean vibrate,
+ boolean onlyWarn)
+ throws Throwable {
+
+ mTimestampsUserReported.clear();
+ mTimestampsStepCounter.clear();
+ mTimestampsStepDetector.clear();
+
+ mMoveDetected = false;
+ mCheckForMotion = true;
+
+ appendText("Click 'Next' and " + instructions);
+ waitForUser();
+
+ mInitialStepCount = 0;
+ mStepsDetected = 0;
+ mStepsReported = 0;
+ if (vibrate) {
+ vibrate(sVibratePattern);
+ }
+
+ mCheckForMotion = (expectedSteps == 0);
+ startMeasurements();
+
+ long testStartTime = System.currentTimeMillis();
+ long testTime = 0;
+
+ while (testTime < MIN_TEST_TIME_MILLIS) {
+ int timeWaitSec = Math.round((MIN_TEST_TIME_MILLIS - testTime) / 1000);
+ clearText();
+ appendText("Current test: " + instructions);
+ appendText(String.format("%d seconds left, %d steps detected, %d reported",
+ timeWaitSec, mStepsDetected, mStepsReported), Color.GRAY);
+ Thread.sleep(1000);
+ testTime = System.currentTimeMillis() - testStartTime;
+ }
+ clearText();
+ appendText("Current test: " + instructions);
+ verifyMeasurements(expectedSteps, tolerance, onlyWarn);
+ appendText(mERNWarning + "\n" + mSCWarning, Color.YELLOW);
+ mCheckForMotion = false;
+ sNumPassedTests++;
+ mERNWarning = "";
+ mSCWarning = "";
+ }
+
+ private void startMeasurements() throws Throwable {
+ mSensorStepCounter = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
+ if (mSensorStepCounter != null) {
+ mSensorManager.registerListener(this, mSensorStepCounter,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ } else {
+ appendText("Failed test, step counter sensor was not found", Color.RED);
+ Assert.fail("Step counter sensor was not found");
+ }
+
+ mSensorStepDetector = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
+ if (mSensorStepDetector != null) {
+ mSensorManager.registerListener(this, mSensorStepDetector,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ } else {
+ appendText("Failed test, step detector sensor was not found", Color.RED);
+ Assert.fail("Step detector sensor was not found");
+ }
+
+ mSensorAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ if (mSensorAcceleration != null && mCheckForMotion) {
+ mSensorManager.registerListener(this, mSensorAcceleration,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ }
+
+ private void verifyMeasurements(int stepsExpected, int tolerance, boolean onlyWarn)
+ throws Throwable {
+ if (mSensorManager != null) {
+ mSensorManager.unregisterListener(this);
+ }
+
+ Assert.assertFalse(String.format("You need to report at least %d steps", stepsExpected),
+ mStepsReported < stepsExpected);
+ double maxStepReportTime = compareTimestamps();
+ Assert.assertTrue(String.format("Step report time %f longer than %d seconds",
+ maxStepReportTime, MAX_TOLERANCE_STEP_TIME_LATENCY_SECONDS),
+ maxStepReportTime < MAX_TOLERANCE_STEP_TIME_LATENCY_SECONDS);
+
+ if (mCheckForMotion && !mMoveDetected) {
+ String message = "Movement is needed during this test";
+
+ warnOrAssert(onlyWarn, message);
+ }
+
+ if (Math.abs(mStepsDetected - mStepsReported) > tolerance) {
+ String message = String.format("Step count test: "
+ + "detected %d steps but %d were expected (to within %d steps)",
+ mStepsDetected, mStepsReported, tolerance);
+ warnOrAssert(onlyWarn, message);
+ }
+
+ appendText("PASS step count test", Color.GREEN);
+
+ if (Math.abs(mTimestampsStepDetector.size() - mStepsReported) > tolerance) {
+ String message = String.format("Step detector test: "
+ + "detected %d steps but %d were expected (to within %d steps)",
+ mTimestampsStepDetector.size(), mStepsReported, tolerance);
+ warnOrAssert(onlyWarn, message);
+ }
+
+ appendText("PASS step detection test", Color.GREEN);
+
+ logSuccess();
+ }
+
+ public final void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ private void warnOrAssert(boolean onlyWarn, String message) throws Throwable {
+ if (onlyWarn) {
+ appendText("WARNING: " + message, Color.YELLOW);
+ } else {
+ Assert.fail("FAILED " + message);
+ }
+ }
+
+ String mERNWarning = "";
+ String mSCWarning = "";
+
+ public long checkTimestamp(long eventTimestamp) {
+ long timestamp = SystemClock.elapsedRealtimeNanos();
+ if (Math.abs(timestamp - eventTimestamp) > MIN_TEST_TIME_MILLIS * 1e6) {
+ // elapsedRealtimeNanos will lead to test failure, warn for now
+ mERNWarning = "WARNING: elapsedRealtimeNanos is significantly different than "
+ + " sensor event timestamps. This should be rectified.";
+ } else {
+ timestamp = eventTimestamp;
+ }
+ return timestamp;
+ }
+
+ public void onStepCounterChanged(SensorEvent event) throws Throwable {
+ int steps = (int) event.values[0] - mInitialStepCount;
+
+ if (mInitialStepCount == 0) { // set the initial number of steps
+ mInitialStepCount = steps;
+ } else if (steps > 0) {
+ mTimestampsStepCounter.add(checkTimestamp(event.timestamp));
+ Assert.assertTrue(String.format("Step counter did not increase monotonically: "
+ + "%d changed to %d", mStepsDetected, steps), steps >= mStepsDetected);
+ mStepsDetected = steps;
+ } else {
+ Assert.fail("Step Counter change called when no steps reported");
+ }
+ }
+
+ public void onStepDetectorChanged(SensorEvent event) throws Throwable {
+ Assert.assertEquals("Incorrect value[0] in step detector event", event.values[0], 1.0f);
+ mTimestampsStepDetector.add(checkTimestamp(event.timestamp));
+ }
+
+ public final void onSensorChanged(SensorEvent event) {
+ int type = event.sensor.getType();
+ try {
+ if (type == Sensor.TYPE_STEP_COUNTER) {
+ onStepCounterChanged(event);
+ } else if (type == Sensor.TYPE_STEP_DETECTOR) {
+ onStepDetectorChanged(event);
+ } else if (type == Sensor.TYPE_ACCELEROMETER) {
+ mMoveDetected = SensorCtsHelper.checkMovementDetection(event);
+ } else {
+ Assert.fail("Sensor type " + type + " called when not registered for by this test");
+ }
+ } catch (Throwable ae) {
+ mSCWarning = ae.getMessage();
+ }
+ }
+
+ protected double compareTimestamps() {
+ double timeDeltaInSec;
+ double maxTimeDeltaInSec = 0;
+ StringBuilder reportLine = new StringBuilder();
+ reportLine.append("Reported Step: Step Detector / Counter Latency (sec)\n");
+ for (int eventCounter = 0; eventCounter < mStepsReported; eventCounter++) {
+ reportLine.append((eventCounter + 1) + ": ");
+
+ if (eventCounter < mTimestampsStepDetector.size()) {
+ timeDeltaInSec = (mTimestampsStepDetector.get(eventCounter)
+ - mTimestampsUserReported.get(eventCounter)) / NANOSECONDS_IN_SEC;
+ maxTimeDeltaInSec = Math.max(maxTimeDeltaInSec, Math.abs(timeDeltaInSec));
+ reportLine.append(String.format("%.2f", timeDeltaInSec));
+ } else {
+ reportLine.append("--");
+ }
+
+ reportLine.append(" / ");
+ if (eventCounter < mTimestampsStepCounter.size()) {
+ timeDeltaInSec = (mTimestampsStepCounter.get(eventCounter)
+ - mTimestampsUserReported.get(eventCounter)) / NANOSECONDS_IN_SEC;
+ maxTimeDeltaInSec = Math.max(maxTimeDeltaInSec, Math.abs(timeDeltaInSec));
+ reportLine.append(String.format("%.2f", timeDeltaInSec));
+ } else {
+ reportLine.append("--");
+ }
+ reportLine.append("\n");
+ }
+ appendText(reportLine.toString(), Color.GRAY);
+
+ return maxTimeDeltaInSec;
+ }
+
+ protected void vibrate(long[] pattern) {
+ Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+ if(v==null) {
+ appendText("Cannot access vibrator for this test...continuing anyway", Color.YELLOW);
+ } else {
+ v.vibrate(pattern, -1);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mSensorManager == null) {
+ mSensorManager = (SensorManager) getApplicationContext()
+ .getSystemService(Context.SENSOR_SERVICE);
+ }
+
+ if (mSensorStepCounter != null) {
+ mSensorManager.registerListener(this, mSensorStepCounter,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ if (mSensorStepDetector != null) {
+ mSensorManager.registerListener(this, mSensorStepDetector,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ if (mSensorAcceleration != null && mCheckForMotion) {
+ mSensorManager.registerListener(this, mSensorAcceleration,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mSensorManager != null) {
+ mSensorManager.unregisterListener(this);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
index ed55b01..ed6560f 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -17,7 +17,10 @@
import android.content.Context;
import android.hardware.Sensor;
+import android.hardware.SensorEvent;
import android.hardware.SensorManager;
+import android.media.AudioManager;
+import android.media.ToneGenerator;
import java.util.ArrayList;
import java.util.Collection;
@@ -248,4 +251,45 @@
}
return sensorManager;
}
+
+ public static void beep(int tone) {
+ ToneGenerator mToneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
+ mToneGenerator.startTone(tone);
+ }
+
+ private final static float mAccelerationThresholdForMoveDetection = 4.0f;
+ private static float[] mGravity = {0.0f, 0.0f, 0.0f};
+ public static boolean checkMovementDetection(SensorEvent event) {
+ // Alpha is calculated as t / (t + dT),
+ // where t is the low-pass filter's time-constant and
+ // dT is the event delivery rate.
+ boolean mMoveDetected = false;
+ final float alpha = 0.8f;
+ float[] linear_acceleration = {0.0f, 0.0f, 0.0f};
+
+ if (mGravity[0] == 0f && mGravity[2] == 0f) {
+ mGravity[0] = event.values[0];
+ mGravity[1] = event.values[1];
+ mGravity[2] = event.values[2];
+ } else {
+ // Isolate the force of gravity with the low-pass filter.
+ mGravity[0] = alpha * mGravity[0] + (1 - alpha) * event.values[0];
+ mGravity[1] = alpha * mGravity[1] + (1 - alpha) * event.values[1];
+ mGravity[2] = alpha * mGravity[2] + (1 - alpha) * event.values[2];
+ }
+
+ // Remove the gravity contribution with the high-pass filter.
+ linear_acceleration[0] = event.values[0] - mGravity[0];
+ linear_acceleration[1] = event.values[1] - mGravity[1];
+ linear_acceleration[2] = event.values[2] - mGravity[2];
+
+ float totalAcceleration = Math.abs(linear_acceleration[0])
+ + Math.abs(linear_acceleration[1])
+ + Math.abs(linear_acceleration[2]);
+
+ if (totalAcceleration > mAccelerationThresholdForMoveDetection) {
+ mMoveDetected = true;
+ }
+ return mMoveDetected;
+ }
}
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index 66f4ac0..fb84509 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -21,8 +21,8 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.READ_EPG_DATA" />
- <uses-permission android:name="android.permission.WRITE_EPG_DATA" />
+ <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
+ <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<application>
<uses-library android:name="android.test.runner" />