summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java51
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java585
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java112
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java206
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java45
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java289
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java48
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java172
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java81
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java (renamed from tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java)185
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java31
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java40
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java152
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java118
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java41
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java54
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java39
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java51
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java61
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java93
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java96
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyNormOperation.java80
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java81
23 files changed, 1800 insertions, 911 deletions
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java
deleted file mode 100644
index 2e33a5d292d..00000000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.hardware.cts;
-
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-
-public class SensorAccelerometerTest extends SensorCommonTests {
- private final int AXIS_COUNT = 3;
-
- @Override
- protected int getMaxFrequencySupportedInuS() {
- return 10000; // 100Hz
- }
-
- @Override
- protected int getSensorType() {
- return Sensor.TYPE_ACCELEROMETER;
- }
-
- /**
- * Regress:
- * - b/9503957
- * - b/9611609
- */
- @Override
- public void testEventValidity() {
- final float THRESHOLD = 0.5f; // m / s^2
- validateNormForSensorEvent(SensorManager.STANDARD_GRAVITY, THRESHOLD, AXIS_COUNT);
- }
-
- @Override
- public void testStandardDeviationWhileStatic() {
- final float STANDARD_DEVIATION = 1f; // m / s^2
- validateStandardDeviationWhileStatic(STANDARD_DEVIATION, AXIS_COUNT);
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java
deleted file mode 100644
index b535c717e1d..00000000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.hardware.cts;
-
-import android.content.Context;
-
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-import android.hardware.TriggerEvent;
-import android.hardware.TriggerEventListener;
-
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.TestSensorManager;
-
-import android.os.PowerManager;
-
-import android.os.SystemClock;
-import android.test.AndroidTestCase;
-
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.TimeUnit;
-
-import junit.framework.Assert;
-
-/**
- * Class is not marked public to avoid TestRunner to pick the tests in it
- */
-abstract class SensorCommonTests extends AndroidTestCase {
- protected final String LOG_TAG = "TestRunner";
- protected TestSensorManager mTestSensorManager;
- private PowerManager.WakeLock mWakeLock;
-
- protected SensorCommonTests() {}
-
- /**
- * Abstract methods needed by concrete sensor classes to provide
- */
- protected abstract int getSensorType();
- protected abstract int getMaxFrequencySupportedInuS();
-
- /**
- * Abstract test methods that sensors need to verify
- */
- public abstract void testEventValidity();
- public abstract void testStandardDeviationWhileStatic();
-
- /**
- * Methods to control the behavior of the tests by concrete sensor tests
- */
- protected int getHighNumberOfIterationsToExecute() {
- return 100;
- }
-
- protected int getLowNumberOfIterationsToExecute() {
- return 10;
- }
-
- protected int getNumberOfThreadsToUse() {
- return 5;
- }
-
- /**
- * Test execution methods
- */
- @Override
- protected void setUp() throws Exception {
- PowerManager powerManager = (PowerManager) this.getContext().getSystemService(
- Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getLogTag());
- mWakeLock.acquire();
- }
-
- @Override
- protected void tearDown() throws Exception {
- if(mTestSensorManager != null) {
- mTestSensorManager.close();
- mTestSensorManager = null;
- }
-
- releaseWakeLock();
- }
-
- @Override
- public void runBare() throws Throwable {
- SensorManager sensorManager = (SensorManager) this.getContext().getSystemService(Context.SENSOR_SERVICE);
- assertNotNull("getSystemService#Sensor_Service", sensorManager);
-
- List<Sensor> availableSensors = sensorManager.getSensorList(this.getSensorType());
- // it is OK if there are no sensors available
- for(Sensor sensor : availableSensors) {
- mTestSensorManager = new TestSensorManager(this, sensorManager, sensor);
- super.runBare();
- }
- }
-
- /**
- * Test cases continuous mode.
- */
- public void testCanRegisterListener() {
- mTestSensorManager.registerListener(SensorManager.SENSOR_DELAY_NORMAL);
- }
-
- public void testNotTriggerSensor() {
- TestTriggerListener listener = new TestTriggerListener();
- boolean result = mTestSensorManager.getUnderlyingSensorManager().requestTriggerSensor(
- listener,
- mTestSensorManager.getSensorUnderTest());
- assertFalse("requestTriggerSensor", result);
- }
-
- public void testCanReceiveEvents() {
- mTestSensorManager.collectEvents(SensorManager.SENSOR_DELAY_NORMAL, 5);
- }
-
- public void testMaxFrequency() {
- // TODO: verify that events do arrive at the proper rate
- mTestSensorManager.registerListener(this.getMaxFrequencySupportedInuS());
- }
-
- public void testEventsArriveInOrder() {
- // TODO: test for other sensor frequencies, rely on helper test classes for sensors
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectEvents(
- SensorManager.SENSOR_DELAY_FASTEST,
- 100);
- for(int i = 1; i < events.length; ++i) {
- long previousTimestamp = events[i-1].timestamp;
- long timestamp = events[i].timestamp;
- assertTrue(
- String.format("[timestamp:%d] %d >= %d", i, previousTimestamp, timestamp),
- previousTimestamp < timestamp);
- }
- }
-
- public void testStartStopRepeatedly() {
- validateRegisterUnregisterRepeteadly(mTestSensorManager);
- }
-
- public void testUpdateRate() {
- // the seed is constant for now, use a random seed when we can log the seed properly
- final long seed = 0xABCDE012;
- Random generator = new Random(seed);
- for(int i = 0; i < this.getHighNumberOfIterationsToExecute(); ++i) {
- int rate;
- switch(generator.nextInt(5)) {
- case 0:
- rate = SensorManager.SENSOR_DELAY_FASTEST;
- break;
- case 1:
- rate = SensorManager.SENSOR_DELAY_GAME;
- break;
- case 2:
- rate = SensorManager.SENSOR_DELAY_NORMAL;
- break;
- case 3:
- rate = SensorManager.SENSOR_DELAY_UI;
- break;
- case 4:
- default:
- rate = this.getMaxFrequencySupportedInuS() * generator.nextInt(10);
- }
-
- // TODO: check that the rate has indeed changed
- mTestSensorManager.collectEvents(
- rate,
- generator.nextInt(5) + 1,
- String.format("iteration:%d, rate:%d", i, rate));
- }
- }
-
- public void testOneClientSeveralThreads() throws InterruptedException {
- Runnable operation = new Runnable() {
- @Override
- public void run() {
- validateRegisterUnregisterRepeteadly(mTestSensorManager);
- }
- };
- SensorCtsHelper.performOperationInThreads(this.getNumberOfThreadsToUse(), operation);
- }
-
- public void testSeveralClients() throws InterruptedException {
- final Assert assertionObject = this;
- Runnable operation = new Runnable() {
- @Override
- public void run() {
- TestSensorManager testSensorManager = new TestSensorManager(
- assertionObject,
- mTestSensorManager.getUnderlyingSensorManager(),
- mTestSensorManager.getSensorUnderTest());
- validateRegisterUnregisterRepeteadly(testSensorManager);
- }
- };
- SensorCtsHelper.performOperationInThreads(this.getNumberOfThreadsToUse(), operation);
- }
-
- public void testStoppingOtherClients() {
- // TODO: use a higher test abstraction and move these to integration tests
- final int EVENT_COUNT = 1;
- final int SECOND_EVENT_COUNT = 5;
- TestSensorManager sensorManager2 = new TestSensorManager(
- this,
- mTestSensorManager.getUnderlyingSensorManager(),
- mTestSensorManager.getSensorUnderTest());
-
- mTestSensorManager.registerListener(SensorManager.SENSOR_DELAY_NORMAL);
-
- // is receiving events
- mTestSensorManager.getEvents(EVENT_COUNT);
-
- // operate in a different client
- sensorManager2.collectEvents(SensorManager.SENSOR_DELAY_FASTEST, SECOND_EVENT_COUNT);
-
- // verify first client is still operating
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.getEvents(EVENT_COUNT);
- assertTrue(
- String.format("Events| expected:%d, actual:%d", EVENT_COUNT, events.length),
- events.length >= EVENT_COUNT);
- }
-
- public void testStoppingOtherClientsBatching() {
- final int EVENT_COUNT = 1;
- final int SECOND_EVENT_COUNT = 5;
- TestSensorManager sensorManager2 = new TestSensorManager(
- this,
- mTestSensorManager.getUnderlyingSensorManager(),
- mTestSensorManager.getSensorUnderTest());
-
- mTestSensorManager.registerListener(SensorManager.SENSOR_DELAY_NORMAL);
-
- // is receiving events
- mTestSensorManager.getEvents(EVENT_COUNT);
-
- // operate in a different client
- sensorManager2.collectBatchEvents(
- SensorManager.SENSOR_DELAY_FASTEST,
- SensorCtsHelper.getSecondsAsMicroSeconds(1),
- SECOND_EVENT_COUNT);
-
- // verify first client is still operating
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.getEvents(EVENT_COUNT);
- assertTrue(
- String.format("Events| expected:%d, actual:%d", EVENT_COUNT, events.length),
- events.length >= EVENT_COUNT);
- }
-
- /**
- * Test cases batching mode.
- */
- public void testRegisterForBatchingZeroReport() {
- releaseWakeLock();
- // TODO: use test wrappers to verify for reportLatency ==0 !=0
- mTestSensorManager.collectBatchEvents(SensorManager.SENSOR_DELAY_NORMAL, 0, 10);
- }
-
- public void testCanReceiveBatchEvents() {
- releaseWakeLock();
- mTestSensorManager.collectBatchEvents(
- SensorManager.SENSOR_DELAY_NORMAL,
- SensorCtsHelper.getSecondsAsMicroSeconds(5),
- 10 /*eventCount*/);
- }
-
- /**
- * Regress:
- * -b/10790905
- */
- public void ignore_testBatchingReportLatency() {
- long startTime = SystemClock.elapsedRealtimeNanos();
- // TODO: define the sensor frequency per sensor
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectBatchEvents(
- SensorCtsHelper.getSecondsAsMicroSeconds(1),
- SensorCtsHelper.getSecondsAsMicroSeconds(5),
- 1 /*eventCount*/);
- long elapsedTime = SystemClock.elapsedRealtimeNanos() - startTime;
- long expectedTime =
- TimeUnit.NANOSECONDS.convert(5, TimeUnit.SECONDS) +
- TimeUnit.NANOSECONDS.convert(500, TimeUnit.MILLISECONDS);
-
- // TODO: ensure the proper batching time considers the size of the FIFO (fifoMaxEventCount),
- // and make sure that no other application is registered
- assertTrue(
- String.format("WaitTime| expected:%d, actual:%d", expectedTime, elapsedTime),
- elapsedTime <= expectedTime);
- }
-
- public void testBatchEventsArriveInOrder() {
- releaseWakeLock();
-
- // TODO: identify if we can reuse code from the non-batching case, same for other batch tests
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectBatchEvents(
- SensorManager.SENSOR_DELAY_NORMAL,
- SensorCtsHelper.getSecondsAsMicroSeconds(5),
- 100);
- for(int i = 1; i < events.length; ++i) {
- long previousTimestamp = events[i-1].timestamp;
- long timestamp = events[i].timestamp;
- assertTrue(
- String.format("[timestamp:%d] %d >= %d", i, previousTimestamp, timestamp),
- previousTimestamp < timestamp);
- }
- }
-
- public void testStartStopBatchingRepeatedly() {
- releaseWakeLock();
- validateRegisterUnregisterRepeteadlyBatching(mTestSensorManager);
- }
-
- public void testUpdateBatchRate() {
- releaseWakeLock();
-
- // use a constant seed until it can be logged properly
- final long seed = 0xFEDCBA98;
- Random generator = new Random(seed);
- for(int i = 0; i < this.getHighNumberOfIterationsToExecute(); ++i) {
- int rate;
- switch(generator.nextInt(5)) {
- case 0:
- rate = SensorManager.SENSOR_DELAY_FASTEST;
- break;
- case 1:
- rate = SensorManager.SENSOR_DELAY_GAME;
- break;
- case 2:
- rate = SensorManager.SENSOR_DELAY_NORMAL;
- break;
- case 3:
- rate = SensorManager.SENSOR_DELAY_UI;
- break;
- case 4:
- default:
- rate = this.getMaxFrequencySupportedInuS() * generator.nextInt(10);
- }
-
- String iterationInfo = String.format("iteration:%d, rate:%d", i, rate);
- mTestSensorManager.collectBatchEvents(
- rate,
- generator.nextInt(SensorCtsHelper.getSecondsAsMicroSeconds(5)),
- generator.nextInt(5) + 1,
- iterationInfo);
- }
- }
-
- public void testOneClientSeveralThreadsBatching() throws InterruptedException {
- Runnable operation = new Runnable() {
- @Override
- public void run() {
- validateRegisterUnregisterRepeteadlyBatching(mTestSensorManager);
- }
- };
- SensorCtsHelper.performOperationInThreads(this.getNumberOfThreadsToUse(), operation);
- }
-
- public void testSeveralClientsBatching() throws InterruptedException {
- final Assert assertionObject = this;
- Runnable operation = new Runnable() {
- @Override
- public void run() {
- TestSensorManager testSensorManager = new TestSensorManager(
- assertionObject,
- mTestSensorManager.getUnderlyingSensorManager(),
- mTestSensorManager.getSensorUnderTest());
- validateRegisterUnregisterRepeteadlyBatching(testSensorManager);
- }
- };
- SensorCtsHelper.performOperationInThreads(this.getNumberOfThreadsToUse(), operation);
- }
-
- public void testBatchingStoppingOtherClients() {
- final int EVENT_COUNT = 1;
- final int SECOND_EVENT_COUNT = 5;
- TestSensorManager sensorManager2 = new TestSensorManager(
- this,
- mTestSensorManager.getUnderlyingSensorManager(),
- mTestSensorManager.getSensorUnderTest());
-
- mTestSensorManager.registerBatchListener(
- SensorManager.SENSOR_DELAY_NORMAL,
- SensorCtsHelper.getSecondsAsMicroSeconds(5));
-
- // is receiving events
- mTestSensorManager.getEvents(EVENT_COUNT);
-
- // operate in a different client
- sensorManager2.collectEvents(SensorManager.SENSOR_DELAY_FASTEST, SECOND_EVENT_COUNT);
-
- // verify first client is still operating
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.getEvents(EVENT_COUNT);
- assertTrue(
- String.format("Events| expected:%d, actual:%d", EVENT_COUNT, events.length),
- events.length >= EVENT_COUNT);
- }
-
- public void testBatchingStoppingOtherClientsBatching() {
- final int EVENT_COUNT = 1;
- final int SECOND_EVENT_COUNT = 5;
- TestSensorManager sensorManager2 = new TestSensorManager(
- this,
- mTestSensorManager.getUnderlyingSensorManager(),
- mTestSensorManager.getSensorUnderTest());
-
- mTestSensorManager.registerBatchListener(
- SensorManager.SENSOR_DELAY_NORMAL,
- SensorCtsHelper.getSecondsAsMicroSeconds(5));
-
- // is receiving events
- mTestSensorManager.getEvents(EVENT_COUNT);
-
- // operate in a different client
- sensorManager2.collectBatchEvents(
- SensorManager.SENSOR_DELAY_FASTEST,
- SensorCtsHelper.getSecondsAsMicroSeconds(1),
- SECOND_EVENT_COUNT);
-
- // verify first client is still operating
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.getEvents(EVENT_COUNT);
- assertTrue(
- String.format("Events| expected:%d, actual:%d", EVENT_COUNT, events.length),
- events.length >= EVENT_COUNT);
- }
-
- /**
- * Tests for sensor characteristics.
- */
- public void ignore_testEventJittering() {
- final long EXPECTED_TIMESTAMP_NS = this.getMaxFrequencySupportedInuS() * 1000;
- final long THRESHOLD_IN_NS = EXPECTED_TIMESTAMP_NS / 10; // 10%
-
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectEvents(
- this.getMaxFrequencySupportedInuS(),
- 100);
- ArrayList<Double> jitterValues = new ArrayList<Double>();
- double jitterMean = SensorCtsHelper.getJitterMean(events, jitterValues);
- double percentile95InNs = SensorCtsHelper.get95PercentileValue(jitterValues);
-
- if(percentile95InNs > THRESHOLD_IN_NS) {
- for(double jitter : jitterValues) {
- Log.e(LOG_TAG, "Jitter: " + jitter);
- }
- double actualPercentValue = (percentile95InNs * 100) / jitterMean;
- String message = String.format(
- "95%% Jitter| 10%%:%dns, actual:%fns(%.2f%%)",
- THRESHOLD_IN_NS,
- percentile95InNs,
- actualPercentValue);
- fail(message);
- }
- }
-
- public void ignore_testFrequencyAccuracy() {
- final long EXPECTED_TIMESTAMP_NS = this.getMaxFrequencySupportedInuS() * 1000;
- final long THRESHOLD_IN_NS = EXPECTED_TIMESTAMP_NS / 10; // 10%
-
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectEvents(
- this.getMaxFrequencySupportedInuS(),
- 100);
- ArrayList<Long> timestampDelayValues = new ArrayList<Long>();
- Double frequencyMean = SensorCtsHelper.getAverageTimestampDelayWithValues(
- events,
- timestampDelayValues);
- if(Math.abs(EXPECTED_TIMESTAMP_NS - frequencyMean) > THRESHOLD_IN_NS) {
- for(long value : timestampDelayValues) {
- Log.e(LOG_TAG, "TimestampDelay: " + value);
- }
- String message = String.format(
- "Frequency| expected:%d, actual:%f",
- EXPECTED_TIMESTAMP_NS,
- frequencyMean);
- fail(message);
- }
- }
-
- /**
- * Private helpers.
- */
- private String getLogTag() {
- return this.getClass().getSimpleName();
- }
-
- private void releaseWakeLock() {
- PowerManager.WakeLock wakeLock = mWakeLock;
- mWakeLock = null;
-
- if(wakeLock != null) {
- wakeLock.release();
- }
- }
-
- /**
- * Test method helper implementations
- */
- protected void validateNormForSensorEvent(float reference, float threshold, int axisCount) {
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectEvents(
- SensorManager.SENSOR_DELAY_FASTEST,
- 1);
- TestSensorManager.SensorEventForTest event = events[0];
-
- StringBuilder valuesBuilder = new StringBuilder();
- double norm = 0.0;
- for(int i = 0; i < axisCount; ++i) {
- float value = event.values[i];
- norm += Math.pow(value, 2);
-
- valuesBuilder.append(value);
- valuesBuilder.append(", ");
- }
- norm = Math.sqrt(norm);
-
- String message = String.format(
- "Norm| expected:%f, threshold:%f, actual:%f (%s)",
- reference,
- threshold,
- norm,
- valuesBuilder.toString());
- assertTrue(message, Math.abs(reference - norm) <= threshold);
- }
-
- protected void validateRegisterUnregisterRepeteadly(TestSensorManager testSensorManager) {
- for(int i = 0; i < this.getLowNumberOfIterationsToExecute(); ++i) {
- String iterationInfo = String.format("iteration:%d", i);
- testSensorManager.collectEvents(SensorManager.SENSOR_DELAY_FASTEST, 1, iterationInfo);
- }
- }
-
- protected void validateRegisterUnregisterRepeteadlyBatching(
- TestSensorManager testSensorManager) {
- // TODO: refactor if allowed with test wrapper abstractions
- for(int i = 0; i < this.getLowNumberOfIterationsToExecute(); ++i) {
- testSensorManager.collectBatchEvents(
- SensorManager.SENSOR_DELAY_FASTEST,
- SensorCtsHelper.getSecondsAsMicroSeconds(5),
- 5 /*eventCont*/,
- String.format("iteration:%d", i));
- }
- }
-
- protected void validateStandardDeviationWhileStatic(
- float expectedStandardDeviation,
- int axisCount) {
- // TODO: refactor the report parameter with test wrappers if available
- TestSensorManager.SensorEventForTest[] events = mTestSensorManager.collectEvents(
- this.getMaxFrequencySupportedInuS(),
- 100);
-
- for(int i = 0; i < axisCount; ++i) {
- ArrayList<Float> values = new ArrayList<Float>();
- for(TestSensorManager.SensorEventForTest event : events) {
- values.add(event.values[i]);
- }
-
- double standardDeviation = SensorCtsHelper.getStandardDeviation(values);
- String message = String.format(
- "StandardDeviation| axis:%d, expected:%f, actual:%f",
- i,
- expectedStandardDeviation,
- standardDeviation);
- assertTrue(message, standardDeviation <= expectedStandardDeviation);
- }
- }
-
- /**
- * Private class definitions to support test of event handlers.
- */
- private class TestTriggerListener extends TriggerEventListener {
- @Override
- public void onTrigger(TriggerEvent event) {
- }
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java
new file mode 100644
index 00000000000..9efa71dfd35
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+
+import android.hardware.cts.helpers.SensorTestCase;
+
+import android.hardware.cts.helpers.sensorTestOperations.VerifyEventOrderingOperation;
+
+/**
+ * Verifies the proper ordering in time of sensor events.
+ */
+public class SensorEventOrderingTests extends SensorTestCase {
+ /**
+ * Builder for the test suite.
+ * This is the method that will build dynamically the set of test cases to execute.
+ * Each 'base' test case is composed by three parts:
+ * - the matrix definition
+ * - the test method that will execute the test case
+ * - a static method that will combine both and add test case instances to the test suite
+ */
+ public static Test suite() {
+ TestSuite testSuite = new TestSuite();
+
+ // add test generation routines
+ createEventOrderingTestCases(testSuite);
+
+ return testSuite;
+ }
+
+ /**
+ * Event ordering test cases.
+ */
+ private int mSensorType;
+ private int mSamplingRateInUs;
+ private int mReportLatencyInUs;
+
+ private static void createEventOrderingTestCases(TestSuite testSuite) {
+ int testDefinitionMatrix[][] = {
+ // { SensorType, SamplingRateInUs, ReportLatencyInUs },
+ { Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_LIGHT, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_PROXIMITY, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_LINEAR_ACCELERATION, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_RELATIVE_HUMIDITY, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_AMBIENT_TEMPERATURE, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_GAME_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_GYROSCOPE_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST, 0 },
+ { Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,0 },
+ };
+
+ for(int definition[] : testDefinitionMatrix) {
+ SensorEventOrderingTests test = new SensorEventOrderingTests();
+ test.mSensorType = definition[0];
+ test.mSamplingRateInUs = definition[1];
+ test.mReportLatencyInUs = definition[2];
+ test.setName("testEventOrdering");
+ testSuite.addTest(test);
+ }
+ }
+
+ /**
+ * This test verifies the ordering of the sampled data reported by the Sensor under test.
+ * This test is used to guarantee that sensor data is reported in the order it occurs, and that
+ * events are always reported in order.
+ *
+ * The test takes a set of samples from the Sensor under test, and then it verifies that each
+ * event's timestamp is in the future compared with the previous event. At the end of the
+ * validation, the full set of events is verified to be ordered by timestamp as they are
+ * generated.
+ *
+ * The test can be susceptible to errors if the sensor sampled data is not timestamped at the
+ * Hardware level. Or events sampled at high rates are added to the FIFO without controlling the
+ * appropriate ordering of the events.
+ *
+ * The assertion associated with the test provides the information of the two consecutive events
+ * that cause the test to fail.
+ */
+ public void testEventOrdering() throws Throwable {
+ VerifyEventOrderingOperation operation = new VerifyEventOrderingOperation(
+ this,
+ mSensorType,
+ mSamplingRateInUs,
+ mReportLatencyInUs);
+ operation.execute();
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java
new file mode 100644
index 00000000000..c829c36e203
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import android.hardware.Sensor;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorTestCase;
+
+import android.hardware.cts.helpers.sensorTestOperations.VerifyJitteringOperation;
+import android.hardware.cts.helpers.sensorTestOperations.VerifyMaximumFrequencyOperation;
+
+/**
+ * Verifies several properties of the sampling rate of the different sensors in the platform.
+ */
+public class SensorFrequencyTests extends SensorTestCase {
+ private int mSensorType;
+ private int mReportLatencyInUs;
+ private int mThresholdPercentageOfNs;
+
+ /**
+ * Builder for the test suite.
+ * This is the method that will build dynamically the set of test cases to execute.
+ * Each 'base' test case is composed by three parts:
+ * - the matrix definition
+ * - the test method that will execute the test case
+ * - a static method that will combine both and add test case instances to the test suite
+ */
+ public static Test suite() {
+ TestSuite testSuite = new TestSuite();
+
+ // add test generation routines
+ createMaxFrequencyExpectedTestCases(testSuite);
+ // TODO: tests are a unreliable in the lab
+ //createMaxFrequencyTestCases(testSuite);
+ //createJitteringTestCases(testSuite);
+
+ return testSuite;
+ }
+
+ /**
+ * Max frequency test cases.
+ */
+ private static void createMaxFrequencyTestCases(TestSuite testSuite) {
+ int testDefinitionMatrix[][] = {
+ // { SensorType, ReportLatencyInUs, ThresholdPercentageOfNs },
+ { Sensor.TYPE_ACCELEROMETER, 0, 10 },
+ { Sensor.TYPE_GYROSCOPE, 0, 10 },
+ { Sensor.TYPE_MAGNETIC_FIELD, 0, 10 },
+ };
+
+ for(int definition[] : testDefinitionMatrix) {
+ SensorFrequencyTests test = new SensorFrequencyTests();
+ test.mSensorType = definition[0];
+ test.mReportLatencyInUs = definition[1];
+ test.mThresholdPercentageOfNs = definition[2];
+ test.setName("testMaxFrequency");
+ testSuite.addTest(test);
+ }
+ }
+
+ /**
+ * This test verifies that the Sensor under test can sample and report data at the Maximum
+ * frequency (sampling rate) it advertises.
+ *
+ * The test takes a set of samples from the sensor under test, and calculates the mean of the
+ * frequency at which the events are reported. The frequency between events is calculated by
+ * looking at the delta between the timestamps associated with each event.
+ *
+ * The test is susceptible to errors if the Sensor is not capable to sample data at the maximum
+ * rate it supports, or the sensor events are not timestamped at the Hardware level.
+ *
+ * The assertion associated with the test provides the required data to identify:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the expected frequency
+ * - the observed frequency
+ * In addition to that, the device's debug output (adb logcat) dumps the set of timestamp deltas
+ * associated with the set of data gathered from the Sensor under test.
+ */
+ public void testMaxFrequency() throws Throwable {
+ VerifyMaximumFrequencyOperation operation = new VerifyMaximumFrequencyOperation(
+ this,
+ mSensorType,
+ mReportLatencyInUs,
+ mThresholdPercentageOfNs);
+ operation.execute();
+ }
+
+ /**
+ * Jittering test cases.
+ */
+ private static void createJitteringTestCases(TestSuite testSuite) {
+ int testDefinitionMatrix[][] = {
+ // { SensorType, ReportLatencyInUs, ThresholdPercentageOfNs },
+ { Sensor.TYPE_ACCELEROMETER, 0, 10 },
+ { Sensor.TYPE_GYROSCOPE, 0, 10 },
+ { Sensor.TYPE_MAGNETIC_FIELD, 0, 10 },
+ };
+
+ for(int definition[] : testDefinitionMatrix) {
+ SensorFrequencyTests test = new SensorFrequencyTests();
+ test.mSensorType = definition[0];
+ test.mReportLatencyInUs = definition[1];
+ test.mThresholdPercentageOfNs = definition[2];
+ test.setName("testJittering");
+ testSuite.addTest(test);
+ }
+ }
+
+ /**
+ * This test verifies that the event jittering associated with the sampled data reported by the
+ * Sensor under test, aligns with the requirements imposed in the CDD.
+ * This test characterizes how the sensor behaves while sampling data at a specific rate.
+ *
+ * The test takes a set of samples from the sensor under test, using the maximum sampling rate
+ * advertised by the Sensor under test. It then compares the 95%ile associated with the
+ * jittering of the timestamps, with an expected value.
+ *
+ * The test is susceptible to errors if the sensor events are not timestamped at the Hardware
+ * level.
+ *
+ * The assertion associated with the failure provides the following information:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the expectation of the test with respect of the 95%ile
+ * - the calculated 95%ile jittering
+ * Additionally, the device's debug output (adb logcat) dumps the set of jitter values
+ * calculated.
+ */
+ public void testJittering() throws Throwable {
+ VerifyJitteringOperation operation = new VerifyJitteringOperation(
+ this,
+ mSensorType,
+ mReportLatencyInUs,
+ mThresholdPercentageOfNs);
+ operation.execute();
+ }
+
+ /**
+ * Max Frequency expected Test Cases.
+ */
+ private int mExpectedSamplingRateInUs;
+
+ private static void createMaxFrequencyExpectedTestCases(TestSuite testSuite) {
+ int testDefinitionMatrix[][] = {
+ // { SensorType, ExpectedSamplingRateInUs },
+ { Sensor.TYPE_ACCELEROMETER, 10000 /* 100 Hz */ },
+ { Sensor.TYPE_GYROSCOPE, 10000 /* 100 Hz */ },
+ { Sensor.TYPE_MAGNETIC_FIELD, 100000 /* 10 Hz */ },
+ };
+
+ for(int definition[] : testDefinitionMatrix) {
+ SensorFrequencyTests test = new SensorFrequencyTests();
+ test.mSensorType = definition[0];
+ test.mExpectedSamplingRateInUs = definition[1];
+ test.setName("testMaxFrequencyExpected");
+ testSuite.addTest(test);
+ }
+ }
+
+ /**
+ * This test verifies that the sensor's maximum advertised frequency (sampling rate) complies
+ * with the required frequency set in the CDD.
+ * This characterizes that the sensor is able to provide data at the rate the platform requires
+ * it.
+ *
+ * The test simply compares the sampling rate specified in the CDD with the maximum sampling
+ * rate advertised by the Sensor under test.
+ *
+ * The test can fail if the Sensor Hardware does not support the sampling rate required by the
+ * platform.
+ *
+ * The assertion associated with the test failure contains:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the expected maximum sampling rate
+ * - the observed maximum sampling rate
+ */
+ public void testMaxFrequencyExpected() {
+ Sensor sensor = SensorCtsHelper.getSensor(this, mSensorType);
+ int samplingRateInUs = sensor.getMinDelay();
+ String message = String.format(
+ "samplingRateInUs| expected:%d, actual:%d",
+ mExpectedSamplingRateInUs,
+ samplingRateInUs);
+ assertTrue(message, mExpectedSamplingRateInUs >= samplingRateInUs);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java
deleted file mode 100644
index b7c082e219e..00000000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.hardware.cts;
-
-import android.hardware.Sensor;
-
-public class SensorGyroscopeTest extends SensorCommonTests {
- private final int AXIS_COUNT = 3;
-
- @Override
- protected int getMaxFrequencySupportedInuS() {
- return 10000; // 100Hz
- }
-
- @Override
- protected int getSensorType() {
- return Sensor.TYPE_GYROSCOPE;
- }
-
- @Override
- public void testEventValidity() {
- final float THRESHOLD = 0.1f; // dps
- validateNormForSensorEvent(0 /*reference*/, THRESHOLD, AXIS_COUNT);
- }
-
- @Override
- public void testStandardDeviationWhileStatic() {
- final float STANDARD_DEVIATION = 0.5f; // dps
- validateStandardDeviationWhileStatic(STANDARD_DEVIATION, AXIS_COUNT);
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index 7272d7231a8..0612c03d10a 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -15,114 +15,257 @@
*/
package android.hardware.cts;
-import android.content.Context;
+import junit.framework.Test;
+import junit.framework.TestSuite;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.TestSensorManager;
+import android.hardware.cts.helpers.SensorTestCase;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestOperation;
-import android.os.PowerManager;
+import android.hardware.cts.helpers.sensorTestOperations.ParallelCompositeSensorTestOperation;
+import android.hardware.cts.helpers.sensorTestOperations.RepeatingSensorTestOperation;
+import android.hardware.cts.helpers.sensorTestOperations.SequentialCompositeSensorTestOperation;
+import android.hardware.cts.helpers.sensorTestOperations.VerifyEventOrderingOperation;
-import android.test.AndroidTestCase;
+import java.util.Random;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
+/**
+ * Set of tests that verifies proper interaction of the sensors in the platform.
+ *
+ * To execute these test cases, the following command can be used:
+ * $ adb shell am instrument -e class android.hardware.cts.SensorIntegrationTests \
+ * -w com.android.cts.hardware/android.test.InstrumentationCtsTestRunner
+ */
+public class SensorIntegrationTests extends SensorTestCase {
+ /**
+ * Builder for the test suite.
+ * This is the method that will build dynamically the set of test cases to execute.
+ * Each 'base' test case is composed by three parts:
+ * - the matrix definition
+ * - the test method that will execute the test case
+ * - a static method that will combine both and add test case instances to the test suite
+ */
+ public static Test suite() {
+ TestSuite testSuite = new TestSuite();
-public class SensorIntegrationTests extends AndroidTestCase {
- protected final String LOG_TAG = "SensorIntegrationTests";
- private PowerManager.WakeLock mWakeLock;
- private SensorManager mSensorManager;
+ // add test generation routines
+ addTestToSuite(testSuite, "testSensorsWithSeveralClients");
+ addTestToSuite(testSuite, "testSensorsMovingRates");
+ createStoppingTestCases(testSuite);
+
+ return testSuite;
+ }
/**
- * Test execution methods
+ * This test focuses in the interaction of continuous and batching clients for the same Sensor
+ * under test. The verification ensures that sensor clients can interact with the System and
+ * not affect other clients in the way.
+ *
+ * The test verifies for each client that the a set of sampled data arrives in order. However
+ * each client in the test has different set of parameters that represent different types of
+ * clients in the real world.
+ *
+ * A test failure might indicate that the HAL implementation does not respect the assumption
+ * that the sensors must be independent. Activating one sensor should not cause another sensor
+ * to deactivate or to change behavior.
+ * It is however, acceptable that when a client is activated at a higher sampling rate, it would
+ * cause other clients to receive data at a faster sampling rate. A client causing other clients
+ * to receive data at a lower sampling rate is, however, not acceptable.
+ *
+ * The assertion associated with the test failure provides:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the event that caused the issue
+ * It is important to look at the internals of the Sensor HAL to identify how the interaction
+ * of several clients can lead to the failing state.
*/
- @Override
- protected void setUp() throws Exception {
- PowerManager powerManager = (PowerManager) this.getContext().getSystemService(
- Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
- mWakeLock.acquire();
-
- mSensorManager = (SensorManager) this.getContext().getSystemService(
- Context.SENSOR_SERVICE);
- }
+ public void testSensorsWithSeveralClients() throws Throwable {
+ final int ITERATIONS = 50;
+ final int BATCHING_RATE_IN_SECONDS = 5;
- @Override
- protected void tearDown() throws Exception {
- mSensorManager = null;
+ int sensorTypes[] = {
+ Sensor.TYPE_ACCELEROMETER,
+ Sensor.TYPE_MAGNETIC_FIELD,
+ Sensor.TYPE_GYROSCOPE };
- mWakeLock.release();
- mWakeLock = null;
+ ParallelCompositeSensorTestOperation operation = new ParallelCompositeSensorTestOperation();
+ for(int sensorType : sensorTypes) {
+ SensorTestOperation continuousOperation = new VerifyEventOrderingOperation(
+ this,
+ sensorType,
+ SensorManager.SENSOR_DELAY_NORMAL,
+ 0 /* reportLatencyInUs */);
+ operation.add(new RepeatingSensorTestOperation(continuousOperation, ITERATIONS));
+
+ SensorTestOperation batchingOperation = new VerifyEventOrderingOperation(
+ this,
+ sensorType,
+ SensorTestInformation.getMaxSamplingRateInUs(this, sensorType),
+ SensorCtsHelper.getSecondsAsMicroSeconds(BATCHING_RATE_IN_SECONDS));
+ operation.add(new RepeatingSensorTestOperation(batchingOperation, ITERATIONS));
+ }
+ operation.execute();
}
/**
- * Test cases.
+ * This test focuses in the interaction of several sensor Clients. The test characterizes by
+ * using clients for different Sensors under Test that vary the sampling rates and report
+ * latencies for the requests.
+ * The verification ensures that the sensor clients can vary the parameters of their requests
+ * without affecting other clients.
+ *
+ * The test verifies for each client that a set of sampled data arrives in order. However each
+ * client in the test has different set of parameters that represent different types of clients
+ * in the real world.
+ *
+ * The test can be susceptible to issues when several clients interacting with the system
+ * actually affect the operation of other clients.
+ *
+ * The assertion associated with the test failure provides:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the event that caused the issue
+ * It is important to look at the internals of the Sensor HAL to identify how the interaction
+ * of several clients can lead to the failing state.
*/
+ public void testSensorsMovingRates() throws Throwable {
+ // use at least two instances to ensure more than one client of any given sensor is in play
+ final int INSTANCES_TO_USE = 5;
+ final int ITERATIONS_TO_EXECUTE = 100;
+
+ ParallelCompositeSensorTestOperation operation = new ParallelCompositeSensorTestOperation();
+ int sensorTypes[] = {
+ Sensor.TYPE_ACCELEROMETER,
+ Sensor.TYPE_MAGNETIC_FIELD,
+ Sensor.TYPE_GYROSCOPE };
+
+ for(int sensorType : sensorTypes) {
+ for(int instance = 0; instance < INSTANCES_TO_USE; ++instance) {
+ SequentialCompositeSensorTestOperation sequentialOperation =
+ new SequentialCompositeSensorTestOperation();
+ for(int iteration = 0; iteration < ITERATIONS_TO_EXECUTE; ++iteration) {
+ VerifyEventOrderingOperation sensorOperation = new VerifyEventOrderingOperation(
+ this,
+ sensorType,
+ this.generateSamplingRateInUs(sensorType),
+ this.generateReportLatencyInUs());
+ sequentialOperation.add(sensorOperation);
+ }
+ operation.add(sequentialOperation);
+ }
+ }
+
+ operation.execute();
+ }
/**
* Regress:
* - b/10641388
*/
- public void testAccelerometerDoesNotStopGyroscope() {
- validateSensorCanBeStoppedIndependently(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GYROSCOPE);
- }
+ private int mSensorTypeTester;
+ private int mSensorTypeTestee;
- public void testAccelerometerDoesNotStopMagnetometer() {
- validateSensorCanBeStoppedIndependently(
+ private static void createStoppingTestCases(TestSuite testSuite) {
+ int sensorTypes[] = {
Sensor.TYPE_ACCELEROMETER,
- Sensor.TYPE_MAGNETIC_FIELD);
- }
+ Sensor.TYPE_GYROSCOPE,
+ Sensor.TYPE_MAGNETIC_FIELD};
- public void testGyroscopeDoesNotStopAccelerometer() {
- validateSensorCanBeStoppedIndependently(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_ACCELEROMETER);
+ for(int sensorTypeTester : sensorTypes) {
+ for(int sensorTypeTestee : sensorTypes) {
+ SensorIntegrationTests test = new SensorIntegrationTests();
+ test.mSensorTypeTester = sensorTypeTester;
+ test.mSensorTypeTestee = sensorTypeTestee;
+ test.setName("testSensorStoppingInteraction");
+ testSuite.addTest(test);
+ }
+ }
}
- public void testGyroscopeDoesNotStopMagnetometer() {
- validateSensorCanBeStoppedIndependently(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_MAGNETIC_FIELD);
- }
+ /**
+ * This test verifies that starting/stopping a particular Sensor client in the System does not
+ * affect other sensor clients.
+ * the test is used to validate that starting/stopping operations are independent on several
+ * sensor clients.
+ *
+ * The test verifies for each client that the a set of sampled data arrives in order. However
+ * each client in the test has different set of parameters that represent different types of
+ * clients in the real world.
+ *
+ * The test can be susceptible to issues when several clients interacting with the system
+ * actually affect the operation of other clients.
+ *
+ * The assertion associated with the test failure provides:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the event that caused the issue
+ * It is important to look at the internals of the Sensor HAL to identify how the interaction
+ * of several clients can lead to the failing state.
+ */
+ public void testSensorStoppingInteraction() throws Throwable {
+ SensorTestOperation tester = new VerifyEventOrderingOperation(
+ this,
+ mSensorTypeTester,
+ SensorManager.SENSOR_DELAY_NORMAL,
+ 0 /*reportLatencyInUs*/);
+ tester.start();
- public void testMagnetometerDoesNotStopAccelerometer() {
- validateSensorCanBeStoppedIndependently(
- Sensor.TYPE_MAGNETIC_FIELD,
- Sensor.TYPE_ACCELEROMETER);
- }
+ SensorTestOperation testee = new VerifyEventOrderingOperation(
+ this,
+ mSensorTypeTestee,
+ SensorManager.SENSOR_DELAY_UI,
+ 0 /*reportLatencyInUs*/);
+ testee.start();
- public void testMagnetometerDoesNotStopGyroscope() {
- validateSensorCanBeStoppedIndependently(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_GYROSCOPE);
+ testee.waitForCompletion();
+ tester.waitForCompletion();
+
+ testee.execute();
}
/**
- * Private methods for sensor validation.
+ * Private helpers.
*/
- public void validateSensorCanBeStoppedIndependently(int sensorTypeTester, int sensorTypeTestee) {
- // if any of the required sensors is not supported, skip the test
- Sensor sensorTester = mSensorManager.getDefaultSensor(sensorTypeTester);
- if(sensorTester == null) {
- return;
- }
- Sensor sensorTestee = mSensorManager.getDefaultSensor(sensorTypeTestee);
- if(sensorTestee == null) {
- return;
- }
-
- TestSensorManager tester = new TestSensorManager(this, mSensorManager, sensorTester);
- tester.registerListener(SensorManager.SENSOR_DELAY_NORMAL);
+ private final Random mGenerator = new Random();
- TestSensorManager testee = new TestSensorManager(this, mSensorManager, sensorTestee);
- testee.registerBatchListener(
- (int) TimeUnit.MICROSECONDS.convert(200, TimeUnit.MILLISECONDS),
- SensorCtsHelper.getSecondsAsMicroSeconds(10));
-
- testee.getEvents(10);
- tester.getEvents(5);
+ private int generateSamplingRateInUs(int sensorType) {
+ int rate;
+ switch(mGenerator.nextInt(5)) {
+ case 0:
+ rate = SensorManager.SENSOR_DELAY_FASTEST;
+ break;
+ case 1:
+ rate = SensorManager.SENSOR_DELAY_GAME;
+ break;
+ case 2:
+ rate = SensorManager.SENSOR_DELAY_NORMAL;
+ break;
+ case 3:
+ rate = SensorManager.SENSOR_DELAY_UI;
+ break;
+ case 4:
+ default:
+ int maxSamplingRate = SensorTestInformation.getMaxSamplingRateInUs(
+ this,
+ sensorType);
+ rate = maxSamplingRate * mGenerator.nextInt(10);
+ }
+ return rate;
+ }
- tester.unregisterListener();
- testee.getEvents(5);
+ private int generateReportLatencyInUs() {
+ int reportLatency = SensorCtsHelper.getSecondsAsMicroSeconds(
+ mGenerator.nextInt(5) + 1);
+ return reportLatency;
+ }
- // clean up
- tester.close();
- testee.close();
+ private static void addTestToSuite(TestSuite testSuite, String testName) {
+ SensorIntegrationTests test = new SensorIntegrationTests();
+ test.setName(testName);
+ testSuite.addTest(test);
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java
deleted file mode 100644
index e4041d6a5f2..00000000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.hardware.cts;
-
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-
-public class SensorMagneticFieldTest extends SensorCommonTests {
- private final int AXIS_COUNT = 3;
-
- @Override
- protected int getMaxFrequencySupportedInuS() {
- return 100000; // 10Hz
- }
-
- @Override
- protected int getSensorType() {
- return Sensor.TYPE_MAGNETIC_FIELD;
- }
-
- @Override
- public void testEventValidity() {
- validateNormForSensorEvent(
- SensorManager.MAGNETIC_FIELD_EARTH_MAX,
- SensorManager.MAGNETIC_FIELD_EARTH_MIN,
- AXIS_COUNT);
- }
-
- @Override
- public void testStandardDeviationWhileStatic() {
- final float STANDARD_DEVIATION = 2f; // uT
- validateStandardDeviationWhileStatic(STANDARD_DEVIATION, AXIS_COUNT);
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java
new file mode 100644
index 00000000000..7251fba1d41
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+
+import android.hardware.cts.helpers.SensorTestCase;
+
+import android.hardware.cts.helpers.sensorTestOperations.VerifyNormOperation;
+import android.hardware.cts.helpers.sensorTestOperations.VerifyStandardDeviationOperation;
+
+/**
+ * Verifies several properties of the sensor measurements.
+ */
+public class SensorMeasurementTests extends SensorTestCase {
+ private int mSensorType;
+ private int mSamplingRateInUs;
+
+ /**
+ * Builder for the test suite.
+ * This is the method that will build dynamically the set of test cases to execute.
+ * Each 'base' test case is composed by three parts:
+ * - the matrix definition
+ * - the test method that will execute the test case
+ * - a static method that will combine both and add test case instances to the test suite
+ */
+ public static Test suite() {
+ TestSuite testSuite = new TestSuite();
+
+ // add test generation routines
+ createEventNormTestCases(testSuite);
+ createStandardDeviationTestCases(testSuite);
+
+ return testSuite;
+ }
+
+ /**
+ * SensorEvent Norm test cases.
+ *
+ * Regress:
+ * - b/9503957
+ * - b/9611609
+ */
+ private float mReferenceValue;
+ private float mThreshold;
+
+ private static void createEventNormTestCases(TestSuite testSuite) {
+ Object testDefinitionMatrix[][] = {
+ // { SensorType, SamplingRateInUs, ReferenceValue, Threshold },
+ { Sensor.TYPE_ACCELEROMETER,
+ SensorManager.SENSOR_DELAY_FASTEST,
+ SensorManager.STANDARD_GRAVITY,
+ 1.5f /* m / s^2 */},
+ { Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, 0.0f, 2.5f /* dps */ },
+ };
+
+ for(Object definition[] : testDefinitionMatrix) {
+ SensorMeasurementTests test = new SensorMeasurementTests();
+ test.mSensorType = (Integer)definition[0];
+ test.mSamplingRateInUs = (Integer)definition[1];
+ test.mReferenceValue = (Float)definition[2];
+ test.mThreshold = (Float)definition[3];
+ test.setName("testEventNorm");
+ testSuite.addTest(test);
+ }
+ }
+
+ /**
+ * This test verifies that the Norm of the sensor data is close to the expected reference value.
+ * The units of the reference value are dependent on the type of sensor.
+ * This test is used to verify that the data reported by the sensor is close to the expected
+ * range and scale.
+ *
+ * The test takes a sample from the sensor under test and calculates the Euclidean Norm of the
+ * vector represented by the sampled data. It then compares it against the test expectations
+ * that are represented by a reference value and a threshold.
+ *
+ * The test is susceptible to errors when the Sensor under test is uncalibrated, or the units in
+ * which the data are reported and the expectations are set are different.
+ *
+ * The assertion associated with the test provides the required data needed to identify any
+ * possible issue. It provides:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the values representing the expectation of the test
+ * - the values sampled from the sensor
+ */
+ public void testEventNorm() throws Throwable {
+ VerifyNormOperation operation = new VerifyNormOperation(
+ this,
+ mSensorType,
+ mSamplingRateInUs,
+ mReferenceValue,
+ mThreshold);
+ operation.execute();
+ }
+
+ /**
+ * SensorEvent Standard Deviation test cases.
+ */
+ private int mReportLatencyInUs;
+ private float mExpectedStandardDeviation;
+
+ private static void createStandardDeviationTestCases(TestSuite testSuite) {
+ Object testDefinitionMatrix[][] = {
+ // { SensorType, SamplingRateInUs, ReportLatencyInUs, ExpectedStandardDeviation },
+ { Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST, 0, 1f /* m/s^2 */ },
+ { Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, 0, 0.5f /* dps */ },
+ };
+
+ for(Object definition[] : testDefinitionMatrix) {
+ SensorMeasurementTests test = new SensorMeasurementTests();
+ test.mSensorType = (Integer)definition[0];
+ test.mSamplingRateInUs = (Integer)definition[1];
+ test.mReportLatencyInUs = (Integer)definition[2];
+ test.mExpectedStandardDeviation = (Float)definition[3];
+ test.setName("testStandardDeviation");
+ testSuite.addTest(test);
+ }
+ }
+
+ /**
+ * This test verifies that the standard deviation of a set of sampled data from a particular
+ * sensor falls into the expectations defined in the CDD. The verification applies to each axis
+ * of the sampled data reported by the Sensor under test.
+ * This test is used to validate the requirement imposed by the CDD to Sensors in Android. And
+ * characterizes how the Sensor behaves while static.
+ *
+ * The test takes a set of samples from the sensor under test, and calculates the Standard
+ * Deviation for each of the axes the Sensor reports data for. The StdDev is compared against
+ * the expected value documented in the CDD.
+ *
+ * The test is susceptible to errors if the device is moving while the test is running, or if
+ * the Sensor's sampled data indeed falls into a large StdDev.
+ *
+ * The assertion associated with the test provides the required data to identify any possible
+ * issue. It provides:
+ * - the thread id on which the failure occurred
+ * - the sensor type and sensor handle that caused the failure
+ * - the expectation of the test
+ * - the std dev calculated and the axis it applies to
+ * Additionally, the device's debug output (adb logcat) dumps the set of values associated with
+ * the failure to help track down the issue.
+ */
+ public void testStandardDeviation() throws Throwable {
+ VerifyStandardDeviationOperation operation = new VerifyStandardDeviationOperation(
+ this,
+ mSensorType,
+ mSamplingRateInUs,
+ mReportLatencyInUs,
+ mExpectedStandardDeviation);
+ operation.execute();
+ }
+}
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 5abdd064606..47b3973c4c8 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -15,7 +15,15 @@
*/
package android.hardware.cts.helpers;
+import android.content.Context;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+
import android.os.Environment;
+
+import android.test.AndroidTestCase;
+
import android.util.Log;
import java.io.DataOutputStream;
@@ -94,9 +102,7 @@ public class SensorCtsHelper {
* @param jitterValues The Collection that will contain the computed jitter values.
* @return The mean of the jitter Values.
*/
- public static double getJitterMean(
- TestSensorManager.SensorEventForTest events[],
- Collection<Double> jitterValues) {
+ public static double getJitterMean(TestSensorEvent events[], Collection<Double> jitterValues) {
ArrayList<Long> timestampDelayValues = new ArrayList<Long>();
double averageTimestampDelay = SensorCtsHelper.getAverageTimestampDelayWithValues(events,
timestampDelayValues);
@@ -116,7 +122,7 @@ public class SensorCtsHelper {
* @return The mean of the frequency values.
*/
public static double getAverageTimestampDelayWithValues(
- TestSensorManager.SensorEventForTest events[],
+ TestSensorEvent events[],
Collection<Long> timestampDelayValues) {
for(int i = 1; i < events.length; ++i) {
long previousTimestamp = events[i-1].timestamp;
@@ -133,7 +139,12 @@ public class SensorCtsHelper {
}
/**
- * NOTE: The bug report is usually written to /sdcard/Downloads
+ * NOTE:
+ * - The bug report is usually written to /sdcard/Downloads
+ * - In order for the test Instrumentation to gather useful data the following permissions are
+ * required:
+ * . android.permission.READ_LOGS
+ * . android.permission.DUMP
*/
public static void collectBugreport(String collectorId)
throws IOException, InterruptedException {
@@ -173,17 +184,55 @@ public class SensorCtsHelper {
}
}
- public static void performOperationInThreads(int numberOfThreadsToUse, Runnable operation)
- throws InterruptedException {
- ArrayList<Thread> threads = new ArrayList<Thread>();
- for(int i = 0; i < numberOfThreadsToUse; ++i) {
- threads.add(new Thread(operation));
+ public static Sensor getSensor(AndroidTestCase testCase, int sensorType) {
+ SensorManager sensorManager = (SensorManager)testCase.getContext().getSystemService(
+ Context.SENSOR_SERVICE);
+ testCase.assertNotNull(sensorManager);
+ Sensor sensor = sensorManager.getDefaultSensor(sensorType);
+ if(sensor == null) {
+ throw new SensorNotSupportedException(sensorType);
}
+ return sensor;
+ }
+
+ public static <TReference extends Number> double getFrequencyInHz(TReference samplingRateInUs) {
+ return 1000000000 / samplingRateInUs.doubleValue();
+ }
- while(!threads.isEmpty()) {
- Thread thread = threads.remove(0);
- thread.join();
+ public static String formatAssertionMessage(
+ String verificationName,
+ Sensor sensor,
+ String format,
+ Object ... params) {
+ return formatAssertionMessage(verificationName, null, sensor, format, params);
+ }
+
+ public static String formatAssertionMessage(
+ String verificationName,
+ SensorTestOperation test,
+ Sensor sensor,
+ String format,
+ Object ... params) {
+ StringBuilder builder = new StringBuilder();
+
+ // identify the verification
+ builder.append(verificationName);
+ builder.append("| ");
+ // add test context information
+ if(test != null) {
+ builder.append(test.toString());
+ builder.append("| ");
}
+ // add context information
+ builder.append(
+ SensorTestInformation.getSensorName(sensor.getType()));
+ builder.append(", handle:");
+ builder.append(sensor.getHandle());
+ builder.append("| ");
+ // add the custom formatting
+ builder.append(String.format(format, params));
+
+ return builder.toString();
}
/**
@@ -195,7 +244,3 @@ public class SensorCtsHelper {
}
}
}
-
-
-
-
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java
index 98a0af06168..f7f55c9e5d2 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -16,12 +16,15 @@
package android.hardware.cts.helpers;
+import android.content.Context;
+
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener2;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
+import android.test.AndroidTestCase;
import java.io.Closeable;
@@ -35,150 +38,146 @@ import junit.framework.Assert;
* Test class to wrap SensorManager with verifications and test checks.
* This class allows to perform operations in the Sensor Manager and performs all the expected test
* verification on behalf of th owner.
- * An object can be used to quickly writing tests that focus on the scenario that needs to be verified,
- * and not in the implicit verifications that need to take place at any step.
+ * An object can be used to quickly writing tests that focus on the scenario that needs to be
+ * verified, and not in the implicit verifications that need to take place at any step.
*/
-public class TestSensorManager implements Closeable {
+public class SensorManagerTestVerifier implements Closeable {
private final int WAIT_TIMEOUT_IN_SECONDS = 30;
- private Assert mAssert;
- private SensorManager mSensorManager;
- private Sensor mSensorUnderTest;
+ private final Assert mAssert;
+ private final SensorManager mSensorManager;
+ private final Sensor mSensorUnderTest;
+ private final int mSamplingRateInUs;
+ private final int mReportLatencyInUs;
+
private TestSensorListener mEventListener;
- public TestSensorManager(Assert assertionObject, SensorManager sensorManager, Sensor sensor) {
- mAssert = assertionObject;
- mSensorManager = sensorManager;
- mSensorUnderTest = sensor;
+ /**
+ * Construction methods.
+ */
+ public SensorManagerTestVerifier(
+ AndroidTestCase testCase,
+ int sensorType,
+ int samplingRateInUs,
+ int reportLatencyInUs) {
+ mAssert = testCase;
+
+ mSensorManager = (SensorManager)testCase.getContext().getSystemService(
+ Context.SENSOR_SERVICE);
+ mSensorUnderTest = SensorCtsHelper.getSensor(testCase, sensorType);
+ mSamplingRateInUs = samplingRateInUs;
+ mReportLatencyInUs = reportLatencyInUs;
- mEventListener = new TestSensorListener();
+ mEventListener = new TestSensorListener(mSensorUnderTest);
}
+ /**
+ * Members
+ */
public void close() {
this.unregisterListener();
mEventListener = null;
- mSensorUnderTest = null;
- }
-
- public SensorManager getUnderlyingSensorManager() {
- return mSensorManager;
}
- public Sensor getSensorUnderTest() {
+ public Sensor getUnderlyingSensor() {
return mSensorUnderTest;
}
- public void registerListener(int delay, String debugInfo) {
- mAssert.assertTrue(
- "registerListener| " + debugInfo,
- mSensorManager.registerListener(mEventListener, mSensorUnderTest, delay));
- }
-
- public void registerListener(int delay) {
- registerListener(delay, "");
- }
-
- public void registerBatchListener(int delay, int reportLatency, String debugInfo) {
+ public void registerListener(String debugInfo) {
boolean result = mSensorManager.registerListener(
mEventListener,
mSensorUnderTest,
- delay,
- reportLatency);
- mAssert.assertTrue("registerBatchListener| " + debugInfo, result);
+ mSamplingRateInUs,
+ mReportLatencyInUs);
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "registerListener",
+ mSensorUnderTest,
+ debugInfo);
+ mAssert.assertTrue(message, result);
}
- public void registerBatchListener(int delay, int reportLatency) {
- registerBatchListener(delay, reportLatency, "");
+ public void registerListener() {
+ this.registerListener("");
}
public void unregisterListener() {
mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
}
- public SensorEventForTest[] getEvents(int count, String debugInfo) {
+ public TestSensorEvent[] getEvents(int count, String debugInfo) {
mEventListener.waitForEvents(count, debugInfo);
- SensorEventForTest[] events = mEventListener.getAllEvents();
+ TestSensorEvent[] events = mEventListener.getAllEvents();
mEventListener.clearEvents();
return events;
}
- public SensorEventForTest[] getEvents(int count) {
+ public TestSensorEvent[] getEvents(int count) {
return this.getEvents(count, "");
}
- public SensorEventForTest[] collectEvents(
- int collectionDelay,
- int eventCount,
- String debugInfo) {
- this.registerListener(collectionDelay, debugInfo);
- SensorEventForTest[] events = this.getEvents(eventCount, debugInfo);
+ public TestSensorEvent[] collectEvents(int eventCount, String debugInfo) {
+ this.registerListener(debugInfo);
+ TestSensorEvent[] events = this.getEvents(eventCount, debugInfo);
this.unregisterListener();
return events;
}
- public SensorEventForTest[] collectEvents(int collectionDelay, int eventCount) {
- return this.collectEvents(collectionDelay, eventCount, "");
+ public TestSensorEvent[] collectEvents(int eventCount) {
+ return this.collectEvents(eventCount, "");
}
- public SensorEventForTest[] collectBatchEvents(
- int collectionDelay,
- int batchReportLatency,
- int eventCount,
- String debugInfo) {
- this.registerBatchListener(collectionDelay, batchReportLatency, debugInfo);
- SensorEventForTest[] events = this.getEvents(eventCount, debugInfo);
- this.unregisterListener();
-
- return events;
- }
-
- public SensorEventForTest[] collectBatchEvents(
- int collectionDelay,
- int batchReportLatency,
- int eventCount) {
- return this.collectBatchEvents(collectionDelay, batchReportLatency, eventCount, "");
+ public void startFlush() {
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "Flush",
+ mSensorUnderTest,
+ "" /* format */);
+ mAssert.assertTrue(message, mSensorManager.flush(mEventListener));
}
public void waitForFlush() throws InterruptedException {
- mAssert.assertTrue(
- String.format("flush| sensorType:%d", mSensorUnderTest.getType()),
- mSensorManager.flush(mEventListener));
mEventListener.waitForFlushComplete();
}
+ public void flush() throws InterruptedException {
+ this.startFlush();
+ this.waitForFlush();
+ }
+
/**
- * Definition of support test classes.
+ * Support methods for clients of this class.
*/
- public class SensorEventForTest {
- public final Sensor sensor;
- public final long timestamp;
- public final int accuracy;
- public final float values[];
-
- public SensorEventForTest(SensorEvent event) {
- values = new float[event.values.length];
- System.arraycopy(event.values, 0, values, 0, event.values.length);
-
- sensor = event.sensor;
- timestamp = event.timestamp;
- accuracy = event.accuracy;
- }
+ public Assert verifier() {
+ return mAssert;
+ }
+
+ public int getUnderlyingType() {
+ return mSensorUnderTest.getType();
}
+ /**
+ * Definition of support test classes.
+ */
private class TestSensorListener implements SensorEventListener2 {
- private final ConcurrentLinkedDeque<SensorEventForTest> mSensorEventsList =
- new ConcurrentLinkedDeque<SensorEventForTest>();
+ private final Sensor mSensorUnderTest;
+
+ private final ConcurrentLinkedDeque<TestSensorEvent> mSensorEventsList =
+ new ConcurrentLinkedDeque<TestSensorEvent>();
+
private volatile CountDownLatch mEventLatch;
private volatile CountDownLatch mFlushLatch = new CountDownLatch(1);
+ public TestSensorListener(Sensor sensor) {
+ mSensorUnderTest = sensor;
+ }
+
@Override
public void onSensorChanged(SensorEvent event) {
CountDownLatch latch = mEventLatch;
if(latch != null) {
// copy the event because there is no better way to do this in the platform
- mSensorEventsList.addLast(new SensorEventForTest(event));
+ mSensorEventsList.addLast(new TestSensorEvent(event));
latch.countDown();
}
}
@@ -200,9 +199,11 @@ public class TestSensorManager implements Closeable {
public void waitForFlushComplete() throws InterruptedException {
CountDownLatch latch = mFlushLatch;
if(latch != null) {
- mAssert.assertTrue(
+ String message = SensorCtsHelper.formatAssertionMessage(
"WaitForFlush",
- latch.await(WAIT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS));
+ mSensorUnderTest,
+ "" /* format */);
+ mAssert.assertTrue(message, latch.await(WAIT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS));
}
}
@@ -216,24 +217,26 @@ public class TestSensorManager implements Closeable {
boolean awaitCompleted = mEventLatch.await(WAIT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
// TODO: can we collect bug reports on error based only if needed? env var?
- String assertMessage = String.format(
- "WaitForEvents| count:%d, available:%d, %s",
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "WaitForEvents",
+ mSensorUnderTest,
+ "count:%d, available:%d, %s",
eventCount,
mSensorEventsList.size(),
timeoutInfo);
- mAssert.assertTrue(assertMessage, awaitCompleted);
+ mAssert.assertTrue(message, awaitCompleted);
} catch(InterruptedException e) {
} finally {
mEventLatch = null;
}
}
- public SensorEventForTest getLastEvent() {
+ public TestSensorEvent getLastEvent() {
return mSensorEventsList.getLast();
}
- public SensorEventForTest[] getAllEvents() {
- return mSensorEventsList.toArray(new SensorEventForTest[0]);
+ public TestSensorEvent[] getAllEvents() {
+ return mSensorEventsList.toArray(new TestSensorEvent[0]);
}
public void clearEvents() {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java
new file mode 100644
index 00000000000..4c413d7346d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers;
+
+/**
+ * Exception that indicates that a given sensor is not supported in the device.
+ * This exception can be caught in tests to safely ignore test cases that are not necessary in a
+ * given environment.
+ */
+public class SensorNotSupportedException extends RuntimeException {
+ public SensorNotSupportedException(int sensorType) {
+ super(String.format(
+ "Sensor '%s' of type %d is not supported.",
+ SensorTestInformation.getSensorName(sensorType),
+ sensorType));
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java
new file mode 100644
index 00000000000..4bd0eed2e6a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers;
+
+import android.test.AndroidTestCase;
+
+import android.util.Log;
+
+/**
+ * Test Case class that handles gracefully sensors that are not available in the device.
+ */
+public abstract class SensorTestCase extends AndroidTestCase {
+ protected final String LOG_TAG = "TestRunner";
+
+ protected SensorTestCase() {}
+
+ @Override
+ public void runTest() throws Throwable {
+ try {
+ super.runTest();
+ } catch (SensorNotSupportedException e) {
+ // the sensor is not supported/available in the device, log a warning and skip the test
+ Log.w(LOG_TAG, e.getMessage());
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java
new file mode 100644
index 00000000000..f7bdbb70d09
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers;
+
+import android.hardware.Sensor;
+
+import android.test.AndroidTestCase;
+
+import java.security.InvalidParameterException;
+
+/**
+ * A 'property' bag of sensor information used for testing purposes.
+ */
+public class SensorTestInformation {
+ private SensorTestInformation() {}
+
+ public static int getAxisCount(int sensorType) {
+ switch(sensorType) {
+ case Sensor.TYPE_ACCELEROMETER:
+ return 3;
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ return 3;
+// case Sensor.TYPE_ORIENTATION:
+// return "Orientation";
+ case Sensor.TYPE_GYROSCOPE:
+ return 3;
+// case Sensor.TYPE_LIGHT:
+// return "Light";
+// case Sensor.TYPE_PRESSURE:
+// return "Pressure";
+// case Sensor.TYPE_TEMPERATURE:
+// return "Temperature";
+// case Sensor.TYPE_PROXIMITY:
+// return "Proximity";
+// case Sensor.TYPE_GRAVITY:
+// return "Gravity";
+// case Sensor.TYPE_LINEAR_ACCELERATION:
+// return "Linear Acceleration";
+// case Sensor.TYPE_ROTATION_VECTOR:
+// return "Rotation Vector";
+// case Sensor.TYPE_RELATIVE_HUMIDITY:
+// return "Relative Humidity";
+// case Sensor.TYPE_AMBIENT_TEMPERATURE:
+// return "Ambient Temperature";
+// case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+// return "Magnetic Field Uncalibrated";
+// case Sensor.TYPE_GAME_ROTATION_VECTOR:
+// return "Game Rotation Vector";
+// case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+// return "Gyroscope Uncalibrated";
+// case Sensor.TYPE_SIGNIFICANT_MOTION:
+// return "Significant Motion";
+// case Sensor.TYPE_STEP_DETECTOR:
+// return "Step Detector";
+// case Sensor.TYPE_STEP_COUNTER:
+// return "Step Counter";
+// case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+// return "Geomagnetic Rotation Vector";
+ default:
+ throw new InvalidParameterException(
+ String.format("Invalid sensorType:%d", sensorType));
+ }
+ }
+
+ public static String getSensorName(int sensorType) {
+ String name;
+ switch(sensorType) {
+ case Sensor.TYPE_ACCELEROMETER:
+ name = "Accelerometer";
+ break;
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ name = "Magnetic Field";
+ break;
+ case Sensor.TYPE_ORIENTATION:
+ name = "Orientation";
+ break;
+ case Sensor.TYPE_GYROSCOPE:
+ name = "Gyroscope";
+ break;
+ case Sensor.TYPE_LIGHT:
+ name = "Light";
+ break;
+ case Sensor.TYPE_PRESSURE:
+ name = "Pressure";
+ break;
+ case Sensor.TYPE_TEMPERATURE:
+ name = "Temperature";
+ break;
+ case Sensor.TYPE_PROXIMITY:
+ name = "Proximity";
+ break;
+ case Sensor.TYPE_GRAVITY:
+ name = "Gravity";
+ break;
+ case Sensor.TYPE_LINEAR_ACCELERATION:
+ name = "Linear Acceleration";
+ break;
+ case Sensor.TYPE_ROTATION_VECTOR:
+ name = "Rotation Vector";
+ break;
+ case Sensor.TYPE_RELATIVE_HUMIDITY:
+ name = "Relative Humidity";
+ break;
+ case Sensor.TYPE_AMBIENT_TEMPERATURE:
+ name = "Ambient Temperature";
+ break;
+ case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ name = "Magnetic Field Uncalibrated";
+ break;
+ case Sensor.TYPE_GAME_ROTATION_VECTOR:
+ name = "Game Rotation Vector";
+ break;
+ case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+ name = "Gyroscope Uncalibrated";
+ break;
+ case Sensor.TYPE_SIGNIFICANT_MOTION:
+ name = "Significant Motion";
+ break;
+ case Sensor.TYPE_STEP_DETECTOR:
+ name = "Step Detector";
+ break;
+ case Sensor.TYPE_STEP_COUNTER:
+ name = "Step Counter";
+ break;
+ case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ name = "Geomagnetic Rotation Vector";
+ break;
+ default:
+ name = "<Unknown>";
+ }
+ return String.format("%s (%d)", name, sensorType);
+ }
+
+ public static int getMaxSamplingRateInUs(AndroidTestCase testCase, int sensorType) {
+ Sensor sensor = SensorCtsHelper.getSensor(testCase, sensorType);
+ return sensor.getMinDelay();
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java
new file mode 100644
index 00000000000..11b113fab21
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers;
+
+/**
+ * Base test class that supports a basic test operation performed in a sensor.
+ * The class follows a command patter as a base for its work.
+ *
+ * Remarks:
+ * - The class wraps verifications and test checks that are needed to verify the operation.
+ * - The operation runs in a background thread where it performs the bulk of its work.
+ */
+public abstract class SensorTestOperation {
+ private final SensorTestExceptionHandler mExceptionHandler = new SensorTestExceptionHandler();
+
+ protected final String LOG_TAG = "TestRunner";
+ protected final int WAIT_TIMEOUT_IN_MILLISECONDS = 30 * 1000;
+
+ private Thread mThread;
+
+ protected int mIterationCount;
+
+ /**
+ * Public API definition.
+ */
+ public synchronized void start() throws Throwable {
+ if(mThread != null) {
+ throw new IllegalStateException("The operation has already been started.");
+ }
+
+ mThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ doWork();
+ } catch (Throwable e) {
+ // log the exception so it can be sent back to the appropriate test thread
+ this.getUncaughtExceptionHandler().uncaughtException(this, e);
+ }
+ }
+ };
+
+ ++mIterationCount;
+ mThread.setUncaughtExceptionHandler(mExceptionHandler);
+ mThread.start();
+ }
+
+ public synchronized void waitForCompletion() throws Throwable {
+ if(mThread == null) {
+ // let a wait on a stopped operation to be no-op
+ return;
+ }
+ mThread.join(WAIT_TIMEOUT_IN_MILLISECONDS);
+ mThread = null;
+ mExceptionHandler.rethrow();
+ }
+
+ public void execute() throws Throwable {
+ this.start();
+ this.waitForCompletion();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ThreadId:%d, Iteration:%d", mThread.getId(), mIterationCount);
+ }
+
+ /**
+ * Subclasses implement this method to perform the work associated with the operation they
+ * represent.
+ */
+ protected abstract void doWork() throws Throwable;
+
+ /**
+ * Private helpers.
+ */
+ private class SensorTestExceptionHandler implements Thread.UncaughtExceptionHandler {
+ private final Object mLock = new Object();
+
+ private Throwable mThrowable;
+
+ @Override
+ public void uncaughtException(Thread thread, Throwable throwable) {
+ synchronized(mLock) {
+ // the fist exception is in general the one that is more interesting
+ if(mThrowable != null) {
+ return;
+ }
+ mThrowable = throwable;
+ }
+ }
+
+ public void rethrow() throws Throwable {
+ Throwable throwable;
+ synchronized(mLock) {
+ throwable = mThrowable;
+ mThrowable = null;
+ }
+ if(throwable != null) {
+ throw throwable;
+ }
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
new file mode 100644
index 00000000000..1a2cdfe7f60
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+
+/**
+ * Test class to wrap SensorEvent.
+ * It currently only provides a way to clone SensorEvent data, but in the future it can contain
+ * verifications and test checks.
+ */
+public class TestSensorEvent {
+ public final Sensor sensor;
+ public final long timestamp;
+ public final int accuracy;
+ public final float values[];
+
+ public TestSensorEvent(SensorEvent event) {
+ values = new float[event.values.length];
+ System.arraycopy(event.values, 0, values, 0, event.values.length);
+
+ sensor = event.sensor;
+ timestamp = event.timestamp;
+ accuracy = event.accuracy;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java
new file mode 100644
index 00000000000..3730f4be715
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorTestOperation;
+
+import java.util.ArrayList;
+
+/**
+ * A test operation that groups a set of SensorTestOperations and allows to execute them all in
+ * parallel.
+ * This class can be combined to compose other primitive SensorTestOperations.
+ */
+public class ParallelCompositeSensorTestOperation extends SensorTestOperation {
+ private final ArrayList<SensorTestOperation> mOperations = new ArrayList<SensorTestOperation>();
+
+ /**
+ * There is no synchronization
+ * @param operations
+ */
+ public void add(SensorTestOperation ... operations) {
+ synchronized (mOperations) {
+ for(SensorTestOperation operation : operations) {
+ mOperations.add(operation);
+ }
+ }
+ }
+
+ @Override
+ protected void doWork() throws Throwable {
+ synchronized (mOperations) {
+ for(SensorTestOperation operation : mOperations) {
+ operation.start();
+ }
+ for(SensorTestOperation operation : mOperations) {
+ operation.waitForCompletion();
+ }
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java
new file mode 100644
index 00000000000..7a3c45018b4
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorTestOperation;
+
+/**
+ * High level SensorTestOperation that executes the inner operation in a loop.
+ */
+public class RepeatingSensorTestOperation extends SensorTestOperation {
+ private final SensorTestOperation mSensorTestOperation;
+ private final int mRepetitionCount;
+
+ public RepeatingSensorTestOperation(SensorTestOperation operation, int repetitionCount) {
+ mSensorTestOperation = operation;
+ mRepetitionCount = repetitionCount;
+ }
+
+ @Override
+ protected void doWork() throws Throwable {
+ for(int i = 0; i < mRepetitionCount; ++i) {
+ mSensorTestOperation.execute();
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java
new file mode 100644
index 00000000000..4b921680eae
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorTestOperation;
+
+import java.util.ArrayList;
+
+/**
+ * A test operation that groups a set of SensorTestOperations and allows to execute them in a
+ * sequence, each operation executes in the order they are added to the composite container.
+ * This class can be combined to compose other primitive SensorTestOperations.
+ */
+public class SequentialCompositeSensorTestOperation extends SensorTestOperation {
+ private final ArrayList<SensorTestOperation> mOperations = new ArrayList<SensorTestOperation>();
+
+ /**
+ * There is no synchronization
+ * @param operations
+ */
+ public void add(SensorTestOperation ... operations) {
+ synchronized (mOperations) {
+ for(SensorTestOperation operation : operations) {
+ mOperations.add(operation);
+ }
+ }
+ }
+
+ @Override
+ protected void doWork() throws Throwable {
+ synchronized (mOperations) {
+ for(SensorTestOperation operation : mOperations) {
+ operation.execute();
+ }
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java
new file mode 100644
index 00000000000..a4e5642c8d8
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorManagerTestVerifier;
+import android.hardware.cts.helpers.SensorTestOperation;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import android.test.AndroidTestCase;
+
+/**
+ * Test Operation class that validates the ordering of sensor events.
+ */
+public class VerifyEventOrderingOperation extends SensorTestOperation {
+ private SensorManagerTestVerifier mSensor;
+
+ public VerifyEventOrderingOperation(
+ AndroidTestCase testCase,
+ int sensorType,
+ int samplingRateInUs,
+ int reportLatencyInUs) {
+ mSensor = new SensorManagerTestVerifier(
+ testCase,
+ sensorType,
+ samplingRateInUs,
+ reportLatencyInUs);
+ }
+
+ @Override
+ public void doWork() {
+ TestSensorEvent events[] = mSensor.collectEvents(100);
+ for(int i = 1; i < events.length; ++i) {
+ long previousTimestamp = events[i-1].timestamp;
+ long timestamp = events[i].timestamp;
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "Ordering",
+ this,
+ mSensor.getUnderlyingSensor(),
+ "position:%d, previous:%d, timestamp:%d",
+ i,
+ previousTimestamp,
+ timestamp);
+ mSensor.verifier().assertTrue(message, previousTimestamp < timestamp);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java
new file mode 100644
index 00000000000..79b835caa70
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorManagerTestVerifier;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestOperation;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import android.test.AndroidTestCase;
+
+import android.util.Log;
+
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test Operation class that validates the sampling rate jittering of a given sensor.
+ *
+ * Remarks:
+ * - In order to guarantee proper results in any environment, the maximum sampling rate supported by
+ * the Sensor is used, this guarantees the frequency reference for the test.
+ */
+public class VerifyJitteringOperation extends SensorTestOperation {
+ protected SensorManagerTestVerifier mSensor;
+ protected long mExpectedtimestampInNs;
+ protected long mThresholdPercentage;
+ protected long mThresholdInNs;
+
+ public VerifyJitteringOperation(
+ AndroidTestCase testCase,
+ int sensorType,
+ int reportLatencyInUs,
+ int thresholdPercentageOfNs) throws InvalidParameterException {
+ if(thresholdPercentageOfNs < 0) {
+ throw new InvalidParameterException("thresholdPercentageOfNs needs to be >= 0");
+ }
+ // use the max sampling frequency the sensor reports to guarantee the results
+ int maxSamplingRateInUs = SensorTestInformation.getMaxSamplingRateInUs(testCase, sensorType);
+ mSensor = new SensorManagerTestVerifier(
+ testCase,
+ sensorType,
+ maxSamplingRateInUs,
+ reportLatencyInUs);
+ // set expectations
+ mExpectedtimestampInNs = TimeUnit.NANOSECONDS.convert(
+ maxSamplingRateInUs,
+ TimeUnit.MICROSECONDS);
+ mThresholdPercentage = thresholdPercentageOfNs;
+ mThresholdInNs = mExpectedtimestampInNs / mThresholdPercentage;
+ }
+
+ @Override
+ public void doWork() {
+ TestSensorEvent events[] = mSensor.collectEvents(100);
+ ArrayList<Double> jitterValues = new ArrayList<Double>();
+ double jitterMean = SensorCtsHelper.getJitterMean(events, jitterValues);
+ double percentile95InNs = SensorCtsHelper.get95PercentileValue(jitterValues);
+
+ if(percentile95InNs > mThresholdInNs) {
+ for(double jitter : jitterValues) {
+ Log.e(LOG_TAG, "Jitter: " + jitter);
+ }
+ double actualPercentValue = (percentile95InNs * 100) / jitterMean;
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "Jitter(95%%ile)",
+ this,
+ mSensor.getUnderlyingSensor(),
+ "expected:%dns(%d%%), actual:%fns(%.2f%%)",
+ mThresholdInNs,
+ mThresholdPercentage,
+ percentile95InNs,
+ actualPercentValue);
+ mSensor.verifier().fail(message);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java
new file mode 100644
index 00000000000..1ff8cde531a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorManagerTestVerifier;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestOperation;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import android.test.AndroidTestCase;
+
+import android.util.Log;
+
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test Operation class that validates the max sampling rate of a given sensor.
+ *
+ * Remarks:
+ * - In order to guarantee proper results in any environment, the maximum sampling rate supported by
+ * the Sensor is used, this guarantees the frequency reference for the test.
+ */
+public class VerifyMaximumFrequencyOperation extends SensorTestOperation {
+ protected SensorManagerTestVerifier mSensor;
+ protected long mExpectedTimestampInNs;
+ protected long mThresholdPercentage;
+ protected long mThresholdInNs;
+
+ public VerifyMaximumFrequencyOperation(
+ AndroidTestCase testCase,
+ int sensorType,
+ int reportLatencyInUs,
+ int thresholdPercentageOfNs) throws InvalidParameterException {
+ if(thresholdPercentageOfNs < 0) {
+ throw new InvalidParameterException("thresholdPercentageOfNs needs to be >= 0");
+ }
+ // use the max sampling frequency the sensor reports to guarantee the results
+ int maxSamplingRateInUs = SensorTestInformation.getMaxSamplingRateInUs(testCase, sensorType);
+ mSensor = new SensorManagerTestVerifier(
+ testCase,
+ sensorType,
+ maxSamplingRateInUs,
+ reportLatencyInUs);
+ // set expectations
+ mExpectedTimestampInNs = TimeUnit.NANOSECONDS.convert(
+ maxSamplingRateInUs,
+ TimeUnit.MICROSECONDS);
+ mThresholdPercentage = thresholdPercentageOfNs;
+ mThresholdInNs = mExpectedTimestampInNs / mThresholdPercentage;
+ }
+
+ @Override
+ public void doWork() {
+ TestSensorEvent events[] = mSensor.collectEvents(100);
+ ArrayList<Long> timestampDelayValues = new ArrayList<Long>();
+ Double frequencyMeanInUs = SensorCtsHelper.getAverageTimestampDelayWithValues(
+ events,
+ timestampDelayValues);
+
+ if(Math.abs(mExpectedTimestampInNs - frequencyMeanInUs) > mThresholdInNs) {
+ for(long value : timestampDelayValues) {
+ Log.e(LOG_TAG, "TimestampDelay: " + value);
+ }
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "Frequency",
+ this,
+ mSensor.getUnderlyingSensor(),
+ "expected:%dns(%.2fHz), actual:%fns(%.2fHz), threshold:%dns(%d%%)",
+ mExpectedTimestampInNs,
+ SensorCtsHelper.getFrequencyInHz(mExpectedTimestampInNs),
+ frequencyMeanInUs,
+ SensorCtsHelper.getFrequencyInHz(frequencyMeanInUs),
+ mThresholdInNs,
+ mThresholdPercentage);
+ mSensor.verifier().fail(message);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyNormOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyNormOperation.java
new file mode 100644
index 00000000000..75998db2c4f
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyNormOperation.java
@@ -0,0 +1,80 @@
+/*
+ * Copyri 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorManagerTestVerifier;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestOperation;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import android.test.AndroidTestCase;
+
+/**
+ * Test Operation class that validates the norm of a given sensor.
+ * The operation relies in the number of axes each sensor type reports.
+ */
+public class VerifyNormOperation extends SensorTestOperation {
+ private SensorManagerTestVerifier mSensor;
+ private int mAxisCount;
+ private double mReferenceValue;
+ private double mThreshold;
+
+ public VerifyNormOperation(
+ AndroidTestCase testCase,
+ int sensorType,
+ int samplingRateInUs,
+ float referenceValue,
+ float threshold) {
+ mSensor = new SensorManagerTestVerifier(
+ testCase,
+ sensorType,
+ samplingRateInUs,
+ 0 /*reportLatencyInUs*/);
+ // set expectations
+ mAxisCount = SensorTestInformation.getAxisCount(mSensor.getUnderlyingType());
+ mReferenceValue = referenceValue;
+ mThreshold = threshold;
+ }
+
+ @Override
+ public void doWork() {
+ TestSensorEvent event = mSensor.collectEvents(1)[0];
+ StringBuilder valuesBuilder = new StringBuilder();
+ double norm = 0.0;
+
+ for(int i = 0; i < mAxisCount; ++i) {
+ float value = event.values[i];
+ norm += Math.pow(value, 2);
+
+ valuesBuilder.append(value);
+ valuesBuilder.append(", ");
+ }
+ norm = Math.sqrt(norm);
+
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "Norm",
+ this,
+ mSensor.getUnderlyingSensor(),
+ "expected:%f, threshold:%f, actual:%f ( %s)",
+ mReferenceValue,
+ mThreshold,
+ norm,
+ valuesBuilder.toString());
+ mSensor.verifier().assertTrue(message, Math.abs(mReferenceValue - norm) <= mThreshold);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java
new file mode 100644
index 00000000000..dd4df7242be
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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 android.hardware.cts.helpers.sensorTestOperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorManagerTestVerifier;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestOperation;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import android.test.AndroidTestCase;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Test Operation class that validates the standard deviation of a given sensor.
+ */
+public class VerifyStandardDeviationOperation extends SensorTestOperation {
+ private SensorManagerTestVerifier mSensor;
+ private int mAxisCount;
+ private double mExpectedStandardDeviation;
+
+ public VerifyStandardDeviationOperation(
+ AndroidTestCase testCase,
+ int sensorType,
+ int samplingRateInUs,
+ int reportLatencyInUs,
+ float expectedStandardDeviation) {
+ mSensor = new SensorManagerTestVerifier(
+ testCase,
+ sensorType,
+ samplingRateInUs,
+ reportLatencyInUs);
+ // set expectations
+ mAxisCount = SensorTestInformation.getAxisCount(mSensor.getUnderlyingType());
+ mExpectedStandardDeviation = expectedStandardDeviation;
+ }
+
+ @Override
+ public void doWork() {
+ TestSensorEvent events[] = mSensor.collectEvents(100);
+ for(int i = 0; i < mAxisCount; ++i) {
+ ArrayList<Float> values = new ArrayList<Float>();
+ for(TestSensorEvent event : events) {
+ values.add(event.values[i]);
+ }
+
+ double standardDeviation = SensorCtsHelper.getStandardDeviation(values);
+ if(standardDeviation > mExpectedStandardDeviation) {
+ for(float value : values) {
+ Log.e(LOG_TAG, String.format("SensorValue:%f", value));
+ }
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "StandardDeviation",
+ this,
+ mSensor.getUnderlyingSensor(),
+ "axis:%d, expected:%f, actual:%f",
+ i,
+ mExpectedStandardDeviation,
+ standardDeviation);
+ mSensor.verifier().fail(message);
+ }
+ }
+ }
+}