Merge "CTS:Start a GL activity with a unreachable stopping criteria"
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
index bcd00ed..5a0af28 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
@@ -18,7 +18,8 @@
import android.hardware.Sensor;
import android.hardware.SensorManager;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyMeasurementsOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.MeanVerification;
import java.util.concurrent.TimeUnit;
@@ -72,22 +73,24 @@
* - the values representing the expectation of the test
* - the mean of values sampled from the sensor
*/
- private void verifyMeasurements(double ... expectations) throws Throwable {
+ private void verifyMeasurements(float ... expectations) throws Throwable {
Thread.sleep(500 /*ms*/);
- VerifyMeasurementsOperation verifyMeasurements = new VerifyMeasurementsOperation(
+ TestSensorOperation verifyMeasurements = new TestSensorOperation(
getApplicationContext(),
Sensor.TYPE_ACCELEROMETER,
SensorManager.SENSOR_DELAY_FASTEST,
0 /*reportLatencyInUs*/,
+ 100 /* event count */);
+ verifyMeasurements.addVerification(new MeanVerification(
expectations,
- 1.95f /* m / s^2 */);
+ new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */));
verifyMeasurements.execute();
logSuccess();
}
private void delayedVerifyMeasurements(
String message,
- double ... expectations) throws Throwable {
+ float ... expectations) throws Throwable {
appendText(String.format("\n%s.", message));
appendText("A sound will be played once the verification is complete...");
waitForUser();
@@ -100,7 +103,7 @@
}
}
- private void verifyMeasurements(String message, double ... expectations) throws Throwable {
+ private void verifyMeasurements(String message, float ... expectations) throws Throwable {
appendText(String.format("\n%s.", message));
appendText("Press 'Next' when ready and keep the device steady.");
waitForUser();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
index df15b66..066bda4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
@@ -18,7 +18,8 @@
import android.hardware.Sensor;
import android.hardware.SensorManager;
-import android.hardware.cts.helpers.sensorTestOperations.VerifySignumOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.SigNumVerification;
/**
* Semi-automated test that focuses on characteristics associated with Accelerometer measurements.
@@ -89,19 +90,22 @@
private void verifyMeasurements(
String scenarioInstructions,
boolean usePortraitOrientation,
- double ... expectations) throws Throwable {
+ int ... expectations) throws Throwable {
final String orientation = usePortraitOrientation ? "Portrait": "Landscape";
appendText(String.format("\n[Device orientation]: %s", orientation));
appendText(String.format("Press 'Next' and %s.", scenarioInstructions));
waitForUser();
Thread.sleep(500 /*ms*/);
- VerifySignumOperation verifySignum = new VerifySignumOperation(
+ TestSensorOperation verifySignum = new TestSensorOperation(
getApplicationContext(),
Sensor.TYPE_GYROSCOPE,
SensorManager.SENSOR_DELAY_FASTEST,
+ 0 /*reportLatencyInUs*/,
+ 100 /* event count */);
+ verifySignum.addVerification(new SigNumVerification(
expectations,
- 0.2 /*noiseThreshold*/);
+ new float[]{0.2f, 0.2f, 0.2f} /*noiseThreshold*/));
verifySignum.execute();
logSuccess();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
index 713710d..a131b2b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
@@ -19,10 +19,13 @@
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
import android.hardware.SensorManager;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyNormOperation;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyStandardDeviationOperation;
+import android.hardware.cts.helpers.TestSensorEventListener;
+import android.hardware.cts.helpers.TestSensorManager;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.MagnitudeVerification;
+import android.hardware.cts.helpers.sensorverification.StandardDeviationVerification;
/**
* Semi-automated test that focuses characteristics associated with Accelerometer measurements.
@@ -43,27 +46,34 @@
}
private void calibrateMagnetometer() {
- SensorManagerTestVerifier magnetometer = new SensorManagerTestVerifier(
- this.getApplicationContext(),
- Sensor.TYPE_MAGNETIC_FIELD,
- SensorManager.SENSOR_DELAY_NORMAL,
- 0 /*reportLatencyInUs*/) {
+ SensorEventListener2 listener = new SensorEventListener2() {
@Override
public void onSensorChanged(SensorEvent event) {
float values[] = event.values;
clearText();
- appendText(
- "Please calibrate the Magnetometer by moving it in 8 shapes in different " +
- "orientations.");
- appendText(
- String.format("-> (%.2f, %.2f, %.2f) uT", values[0], values[1], values[2]),
- Color.GRAY);
+ appendText("Please calibrate the Magnetometer by moving it in 8 shapes in "
+ + "different orientations.");
+ appendText(String.format("-> (%.2f, %.2f, %.2f) uT", values[0], values[1],
+ values[2]), Color.GRAY);
appendText("Then leave the device in a flat surface and press Next...\n");
}
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+ @Override
+ public void onFlushCompleted(Sensor sensor) {}
};
- magnetometer.registerListener();
- waitForUser();
- magnetometer.unregisterListener();
+
+ TestSensorManager magnetometer = new TestSensorManager(
+ this.getApplicationContext(), Sensor.TYPE_MAGNETIC_FIELD,
+ SensorManager.SENSOR_DELAY_NORMAL, 0);
+ try {
+ magnetometer.registerListener(new TestSensorEventListener(listener));
+ waitForUser();
+ } finally {
+ magnetometer.unregisterListener();
+ }
}
/**
@@ -91,12 +101,15 @@
(SensorManager.MAGNETIC_FIELD_EARTH_MAX + SensorManager.MAGNETIC_FIELD_EARTH_MIN) / 2;
float magneticFieldEarthThreshold =
expectedMagneticFieldEarth - SensorManager.MAGNETIC_FIELD_EARTH_MIN;
- VerifyNormOperation verifyNorm = new VerifyNormOperation(
+ TestSensorOperation verifyNorm = new TestSensorOperation(
this.getApplicationContext(),
Sensor.TYPE_MAGNETIC_FIELD,
SensorManager.SENSOR_DELAY_FASTEST,
+ 0 /*reportLatencyInUs*/,
+ 100 /* event count */);
+ verifyNorm.addVerification(new MagnitudeVerification(
expectedMagneticFieldEarth,
- magneticFieldEarthThreshold);
+ magneticFieldEarthThreshold));
verifyNorm.execute();
logSuccess();
}
@@ -125,12 +138,14 @@
* the failure to help track down the issue.
*/
private void verifyStandardDeviation() throws Throwable {
- VerifyStandardDeviationOperation verifyStdDev = new VerifyStandardDeviationOperation(
+ TestSensorOperation verifyStdDev = new TestSensorOperation(
this.getApplicationContext(),
Sensor.TYPE_MAGNETIC_FIELD,
SensorManager.SENSOR_DELAY_FASTEST,
0 /*reportLatencyInUs*/,
- 2f /* uT */);
+ 100 /* event count */);
+ verifyStdDev.addVerification(new StandardDeviationVerification(
+ new float[]{2f, 2f, 2f} /* uT */));
verifyStdDev.execute();
logSuccess();
}
diff --git a/apps/cts-usb-accessory/Android.mk b/apps/cts-usb-accessory/Android.mk
index 76022a1..8d18da3 100644
--- a/apps/cts-usb-accessory/Android.mk
+++ b/apps/cts-usb-accessory/Android.mk
@@ -28,7 +28,7 @@
LOCAL_C_INCLUDES += \
bionic/libc/kernel/uapi \
- bionic/libc/kernel/uapi/asm-$(HOST_ARCH) \
+ bionic/libc/kernel/uapi/asm-x86 \
LOCAL_STATIC_LIBRARIES := libusbhost libcutils
LOCAL_LDLIBS += -lpthread
diff --git a/libs/deviceutil/src/android/cts/util/DeviceReportLog.java b/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
index b707fc8..a3ceecf 100644
--- a/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
+++ b/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
@@ -16,19 +16,24 @@
package android.cts.util;
-import com.android.cts.util.ReportLog;
-
import android.app.Instrumentation;
import android.os.Bundle;
import android.util.Log;
+import com.android.cts.util.ReportLog;
+
public class DeviceReportLog extends ReportLog {
private static final String TAG = "DeviceCtsReport";
private static final String CTS_RESULT = "CTS_RESULT";
private static final int INST_STATUS_IN_PROGRESS = 2;
+ private static final int BASE_DEPTH = 4;
- DeviceReportLog() {
- mDepth = 4;
+ public DeviceReportLog() {
+ mDepth = BASE_DEPTH;
+ }
+
+ public DeviceReportLog(int depth) {
+ mDepth = BASE_DEPTH + depth;
}
@Override
diff --git a/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp b/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp
index fe91cb3..06c92d6 100644
--- a/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp
+++ b/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp
@@ -42,12 +42,12 @@
: mHwId(hwId),
mPcmHandle(NULL)
{
- LOGV("AudioPlaybackLocal %x", (unsigned int)this);
+ LOGV("AudioPlaybackLocal %x", (unsigned long)this);
}
AudioPlaybackLocal::~AudioPlaybackLocal()
{
- LOGV("~AudioPlaybackLocal %x", (unsigned int)this);
+ LOGV("~AudioPlaybackLocal %x", (unsigned long)this);
releaseHw();
}
@@ -108,7 +108,7 @@
void AudioPlaybackLocal::releaseHw()
{
if (mPcmHandle != NULL) {
- LOGV("releaseHw %x", (unsigned int)this);
+ LOGV("releaseHw %x", (unsigned long)this);
doStop();
pcm_close(mPcmHandle);
mPcmHandle = NULL;
diff --git a/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp b/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp
index 1325949..eda705d 100644
--- a/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp
+++ b/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp
@@ -29,12 +29,12 @@
: mHwId(hwId),
mPcmHandle(NULL)
{
- LOGV("AudioRecordingLocal %x", (unsigned int)this);
+ LOGV("AudioRecordingLocal %x", (unsigned long)this);
}
AudioRecordingLocal::~AudioRecordingLocal()
{
- LOGV("~AudioRecordingLocal %x", (unsigned int)this);
+ LOGV("~AudioRecordingLocal %x", (unsigned long)this);
releaseHw();
}
@@ -97,7 +97,7 @@
void AudioRecordingLocal::releaseHw()
{
if (mPcmHandle != NULL) {
- LOGV("releaseHw %x", (unsigned int)this);
+ LOGV("releaseHw %x", (unsigned long)this);
doStop();
pcm_close(mPcmHandle);
mPcmHandle = NULL;
diff --git a/suite/audio_quality/lib/src/task/TaskProcess.cpp b/suite/audio_quality/lib/src/task/TaskProcess.cpp
index f1e47af..061dda5 100644
--- a/suite/audio_quality/lib/src/task/TaskProcess.cpp
+++ b/suite/audio_quality/lib/src/task/TaskProcess.cpp
@@ -271,7 +271,7 @@
list.push_back(param);
LOGD(" val %s", param.getParamString().string());
} else if (isInput && (StringUtil::compare(item[0], "consti") == 0)) {
- long long value = atoll(item[1].string());
+ int64_t value = atoll(item[1].string());
TaskCase::Value v(value);
Param param(v);
list.push_back(param);
diff --git a/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java b/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
index d992839..83c339b 100644
--- a/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
+++ b/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
@@ -201,14 +201,16 @@
// http://code.google.com/p/vogar/source/browse/trunk/src/vogar/target/TestEnvironment.java
static class TestEnvironment {
- private Locale mDefaultLocale;
- private String mUserHome;
- private String mJavaIoTmpDir;
- private HostnameVerifier mHostnameVerifier;
- private SSLSocketFactory mSslSocketFactory;
+ private final Locale mDefaultLocale;
+ private final TimeZone mDefaultTimeZone;
+ private final String mUserHome;
+ private final String mJavaIoTmpDir;
+ private final HostnameVerifier mHostnameVerifier;
+ private final SSLSocketFactory mSslSocketFactory;
TestEnvironment() {
mDefaultLocale = Locale.getDefault();
+ mDefaultTimeZone = TimeZone.getDefault();
mUserHome = System.getProperty("user.home");
mJavaIoTmpDir = System.getProperty("java.io.tmpdir");
mHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
@@ -217,6 +219,7 @@
void reset() {
Locale.setDefault(mDefaultLocale);
+ TimeZone.setDefault(mDefaultTimeZone);
System.setProperty("user.home", mUserHome);
System.setProperty("java.io.tmpdir", mJavaIoTmpDir);
Authenticator.setDefault(null);
diff --git a/tests/jni/Android.mk b/tests/jni/Android.mk
index 28aa15a..139118d 100644
--- a/tests/jni/Android.mk
+++ b/tests/jni/Android.mk
@@ -30,7 +30,7 @@
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libdl
LOCAL_SRC_FILES += android_os_cts_CpuFeatures.cpp
LOCAL_C_INCLUDES += ndk/sources/cpufeatures
diff --git a/tests/src/android/renderscript/cts/intrinsic_3dlut.rs b/tests/src/android/renderscript/cts/intrinsic_3dlut.rs
new file mode 100644
index 0000000..d577b63
--- /dev/null
+++ b/tests/src/android/renderscript/cts/intrinsic_3dlut.rs
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "shared.rsh"
+
+static rs_allocation gCube;
+static int4 gDims;
+static float4 gCoordMul;
+
+void setCube(rs_allocation c) {
+ gCube = c;
+ gDims.x = rsAllocationGetDimX(gCube);
+ gDims.y = rsAllocationGetDimY(gCube);
+ gDims.z = rsAllocationGetDimZ(gCube);
+ gDims.w = 0;
+ gCoordMul = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+ float4 baseCoord = convert_float4(in) * gCoordMul;
+ int4 coord1 = convert_int4(floor(baseCoord));
+ int4 coord2 = min(coord1 + 1, gDims - 1);
+ float4 f = baseCoord - convert_float4(coord1);
+
+ float4 v000 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord1.z));
+ float4 v100 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord1.z));
+ float4 v010 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord1.z));
+ float4 v110 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord1.z));
+ float4 v001 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord2.z));
+ float4 v101 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord2.z));
+ float4 v011 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord2.z));
+ float4 v111 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord2.z));
+
+ float4 yz00 = mix(v000, v100, f.x);
+ float4 yz10 = mix(v010, v110, f.x);
+ float4 yz01 = mix(v001, v101, f.x);
+ float4 yz11 = mix(v011, v111, f.x);
+
+ float4 z0 = mix(yz00, yz10, f.y);
+ float4 z1 = mix(yz01, yz11, f.y);
+
+ float4 v = mix(z0, z1, f.z);
+
+ v = clamp(v, 0.f, 255.f);
+ uchar4 o = convert_uchar4(v + 0.5f);
+ o.w = in.w;
+ return o;
+}
+
diff --git a/tests/src/android/renderscript/cts/intrinsic_blur.rs b/tests/src/android/renderscript/cts/intrinsic_blur.rs
new file mode 100644
index 0000000..88f9ca5
--- /dev/null
+++ b/tests/src/android/renderscript/cts/intrinsic_blur.rs
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "shared.rsh"
+
+int height;
+int width;
+static int radius;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+float4 __attribute__((kernel)) convert1_uToF(uchar v) {
+ float4 r = rsUnpackColor8888(v);
+ return r.r;
+}
+
+float4 __attribute__((kernel)) convert4_uToF(uchar4 v) {
+ return rsUnpackColor8888(v);
+}
+
+uchar __attribute__((kernel)) convert1_fToU(float4 v) {
+ uchar4 r = rsPackColorTo8888(v);
+ return r.r;
+}
+
+uchar4 __attribute__((kernel)) convert4_fToU(float4 v) {
+ return rsPackColorTo8888(v);
+}
+
+void setRadius(int rad) {
+ // This function is a duplicate of:
+ // RsdCpuScriptIntrinsicBlur::ComputeGaussianWeights()
+ // Which is the reference C implementation
+ radius = rad;
+ const float e = M_E;
+ const float pi = M_PI;
+ float sigma = 0.4f * (float)radius + 0.6f;
+ float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+ float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+ float normalizeFactor = 0.0f;
+ float floatR = 0.0f;
+ for (int r = -radius; r <= radius; r ++) {
+ floatR = (float)r;
+ gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+ normalizeFactor += gaussian[r + radius];
+ }
+
+ normalizeFactor = 1.0f / normalizeFactor;
+ for (int r = -radius; r <= radius; r ++) {
+ floatR = (float)r;
+ gaussian[r + radius] *= normalizeFactor;
+ }
+}
+
+float4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+ float4 blurredPixel = 0;
+ int gi = 0;
+ for (int r = -radius; r <= radius; r ++) {
+ int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+ float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+ blurredPixel += i * gaussian[gi++];
+ }
+ return blurredPixel;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+ float4 blurredPixel = 0;
+ int gi = 0;
+ for (int r = -radius; r <= radius; r ++) {
+ // Stepping left and right away from the pixel
+ int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+ float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+ blurredPixel += i * gaussian[gi++];
+ }
+ return blurredPixel;
+}
+
+
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index e0ad6e5..2ad58ba 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -34,7 +34,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target android-ex-camera2
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner mockito-target android-ex-camera2
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java
deleted file mode 100644
index 116ac80..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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_PRESSURE, 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.getContext(),
- 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
deleted file mode 100644
index b35f515..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.getContext(),
- 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.getContext(),
- 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.getContext(), 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/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index a1aa760..d5d7972 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -15,23 +15,19 @@
*/
package android.hardware.cts;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
import android.content.Context;
-
import android.hardware.Sensor;
import android.hardware.SensorManager;
-
import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorTestCase;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.RepeatingSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.SequentialSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
-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 junit.framework.Test;
+import junit.framework.TestSuite;
import java.util.Random;
@@ -43,6 +39,8 @@
* -w com.android.cts.hardware/android.test.InstrumentationCtsTestRunner
*/
public class SensorIntegrationTests extends SensorTestCase {
+ private static final String TAG = "SensorIntegrationTests";
+
/**
* Builder for the test suite.
* This is the method that will build dynamically the set of test cases to execute.
@@ -87,7 +85,7 @@
*/
public void testSensorsWithSeveralClients() throws Throwable {
final int ITERATIONS = 50;
- final int BATCHING_RATE_IN_SECONDS = 5;
+ final int MAX_REPORTING_LATENCY_IN_SECONDS = 5;
final Context context = this.getContext();
int sensorTypes[] = {
@@ -95,23 +93,28 @@
Sensor.TYPE_MAGNETIC_FIELD,
Sensor.TYPE_GYROSCOPE };
- ParallelCompositeSensorTestOperation operation = new ParallelCompositeSensorTestOperation();
+ ParallelSensorOperation operation = new ParallelSensorOperation();
for(int sensorType : sensorTypes) {
- SensorTestOperation continuousOperation = new VerifyEventOrderingOperation(
+ TestSensorOperation continuousOperation = new TestSensorOperation(
context,
sensorType,
SensorManager.SENSOR_DELAY_NORMAL,
- 0 /* reportLatencyInUs */);
- operation.add(new RepeatingSensorTestOperation(continuousOperation, ITERATIONS));
+ 0 /* reportLatencyInUs */,
+ 100 /* event count */);
+ continuousOperation.addVerification(new EventOrderingVerification());
+ operation.add(new RepeatingSensorOperation(continuousOperation, ITERATIONS));
- SensorTestOperation batchingOperation = new VerifyEventOrderingOperation(
+ TestSensorOperation batchingOperation = new TestSensorOperation(
context,
sensorType,
- SensorTestInformation.getMaxSamplingRateInUs(context, sensorType),
- SensorCtsHelper.getSecondsAsMicroSeconds(BATCHING_RATE_IN_SECONDS));
- operation.add(new RepeatingSensorTestOperation(batchingOperation, ITERATIONS));
+ SensorCtsHelper.getSensor(getContext(), sensorType).getMinDelay(),
+ SensorCtsHelper.getSecondsAsMicroSeconds(MAX_REPORTING_LATENCY_IN_SECONDS),
+ 100);
+ batchingOperation.addVerification(new EventOrderingVerification());
+ operation.add(new RepeatingSensorOperation(batchingOperation, ITERATIONS));
}
operation.execute();
+ SensorStats.logStats(TAG, operation.getStats());
}
/**
@@ -140,7 +143,7 @@
final int INSTANCES_TO_USE = 5;
final int ITERATIONS_TO_EXECUTE = 100;
- ParallelCompositeSensorTestOperation operation = new ParallelCompositeSensorTestOperation();
+ ParallelSensorOperation operation = new ParallelSensorOperation();
int sensorTypes[] = {
Sensor.TYPE_ACCELEROMETER,
Sensor.TYPE_MAGNETIC_FIELD,
@@ -148,14 +151,15 @@
for(int sensorType : sensorTypes) {
for(int instance = 0; instance < INSTANCES_TO_USE; ++instance) {
- SequentialCompositeSensorTestOperation sequentialOperation =
- new SequentialCompositeSensorTestOperation();
+ SequentialSensorOperation sequentialOperation = new SequentialSensorOperation();
for(int iteration = 0; iteration < ITERATIONS_TO_EXECUTE; ++iteration) {
- VerifyEventOrderingOperation sensorOperation = new VerifyEventOrderingOperation(
+ TestSensorOperation sensorOperation = new TestSensorOperation(
this.getContext(),
sensorType,
this.generateSamplingRateInUs(sensorType),
- this.generateReportLatencyInUs());
+ this.generateReportLatencyInUs(),
+ 100);
+ sensorOperation.addVerification(new EventOrderingVerification());
sequentialOperation.add(sensorOperation);
}
operation.add(sequentialOperation);
@@ -163,6 +167,7 @@
}
operation.execute();
+ SensorStats.logStats(TAG, operation.getStats());
}
/**
@@ -212,24 +217,30 @@
public void testSensorStoppingInteraction() throws Throwable {
Context context = this.getContext();
- SensorTestOperation tester = new VerifyEventOrderingOperation(
+ TestSensorOperation tester = new TestSensorOperation(
context,
mSensorTypeTester,
SensorManager.SENSOR_DELAY_NORMAL,
- 0 /*reportLatencyInUs*/);
- tester.start();
+ 0 /*reportLatencyInUs*/,
+ 100 /* event count */);
+ tester.addVerification(new EventOrderingVerification());
- SensorTestOperation testee = new VerifyEventOrderingOperation(
+ TestSensorOperation testee = new TestSensorOperation(
context,
mSensorTypeTestee,
SensorManager.SENSOR_DELAY_UI,
- 0 /*reportLatencyInUs*/);
- testee.start();
+ 0 /*reportLatencyInUs*/,
+ 100 /* event count */);
+ testee.addVerification(new EventOrderingVerification());
- testee.waitForCompletion();
- tester.waitForCompletion();
+ ParallelSensorOperation operation = new ParallelSensorOperation();
+ operation.add(tester, testee);
+ operation.execute();
+ SensorStats.logStats(TAG, operation.getStats());
+ testee = testee.clone();
testee.execute();
+ SensorStats.logStats(TAG, testee.getStats());
}
/**
@@ -254,9 +265,8 @@
break;
case 4:
default:
- int maxSamplingRate = SensorTestInformation.getMaxSamplingRateInUs(
- this.getContext(),
- sensorType);
+ int maxSamplingRate = SensorCtsHelper.getSensor(getContext(), sensorType)
+ .getMinDelay();
rate = maxSamplingRate * mGenerator.nextInt(10);
}
return rate;
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java
deleted file mode 100644
index ea025ba..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.getContext(),
- 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.getContext(),
- mSensorType,
- mSamplingRateInUs,
- mReportLatencyInUs,
- mExpectedStandardDeviation);
- operation.execute();
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTestCase.java b/tests/tests/hardware/src/android/hardware/cts/SensorTestCase.java
new file mode 100644
index 0000000..222da56
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTestCase.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.app.Instrumentation;
+import android.cts.util.CtsAndroidTestCase;
+import android.cts.util.DeviceReportLog;
+import android.hardware.cts.helpers.SensorNotSupportedException;
+import android.hardware.cts.helpers.SensorStats;
+import android.util.Log;
+
+import com.android.cts.util.ReportLog;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+
+/**
+ * Test Case class that handles gracefully sensors that are not available in the device.
+ */
+public abstract class SensorTestCase extends CtsAndroidTestCase {
+ 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());
+ }
+ }
+
+ /**
+ * Utility method to log selected stats to a {@link ReportLog} object. The stats must be
+ * a number or an array of numbers.
+ */
+ public static void logSelectedStatsToReportLog(Instrumentation instrumentation, int depth,
+ String[] keys, SensorStats stats) {
+ DeviceReportLog reportLog = new DeviceReportLog(depth);
+
+ for (String key : keys) {
+ Object value = stats.getValue(key);
+ if (value instanceof Integer) {
+ reportLog.printValue(key, (Integer) value, ResultType.NEUTRAL, ResultUnit.NONE);
+ } else if (value instanceof Double) {
+ reportLog.printValue(key, (Double) value, ResultType.NEUTRAL, ResultUnit.NONE);
+ } else if (value instanceof Float) {
+ reportLog.printValue(key, (Float) value, ResultType.NEUTRAL, ResultUnit.NONE);
+ } else if (value instanceof double[]) {
+ reportLog.printArray(key, (double[]) value, ResultType.NEUTRAL, ResultUnit.NONE);
+ } else if (value instanceof float[]) {
+ float[] tmpFloat = (float[]) value;
+ double[] tmpDouble = new double[tmpFloat.length];
+ for (int i = 0; i < tmpDouble.length; i++) tmpDouble[i] = tmpFloat[i];
+ reportLog.printArray(key, tmpDouble, ResultType.NEUTRAL, ResultUnit.NONE);
+ }
+ }
+
+ reportLog.printSummary("summary", 0, ResultType.NEUTRAL, ResultUnit.NONE);
+ reportLog.deliverReportToHost(instrumentation);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
new file mode 100644
index 0000000..cd6adb1
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Set of tests to verify that sensors operate correctly when operating alone.
+ * <p>
+ * To execute these test cases, the following command can be used:
+ * </p><pre>
+ * adb shell am instrument -e class android.hardware.cts.SingleSensorTests \
+ * -w com.android.cts.hardware/android.test.InstrumentationCtsTestRunner
+ * </pre><p>
+ * For each sensor that reports continuously, it takes a set of samples. The test suite verifies
+ * that the event ordering, frequency, and jitter pass for the collected sensor events. It
+ * additionally tests that the mean, standard deviation, and magnitude are correct for the sensor
+ * event values, where applicable for a device in a static environment.
+ * </p><p>
+ * The event ordering 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. 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.
+ * </p><p>
+ * The frequency test verifies that the sensor under test can sample and report data at the maximum
+ * frequency (sampling rate) it advertises. The frequency between events is calculated by looking at
+ * the delta between the timestamps associated with each event to get the period. 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.
+ * </p><p>
+ * The jitter 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. It compares the 95th percentile of
+ * the jittering with a certain percentage of the minimum period. The test is susceptible to errors
+ * if the sensor events are not timestamped at the hardware level.
+ * </p><p>
+ * The mean test verifies that the mean 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 is
+ * susceptible to errors if the device is moving while the test is running, or if the sensor's
+ * sampled data indeed varies from the expected mean.
+ * </p><p>
+ * The magnitude test verifies that the magnitude 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 calculates the Euclidean norm of the vector represented by the sampled
+ * data and compares it against the test expectations. The test is susceptible to errors when the
+ * sensor under test is uncalibrated, or the units between the data and expectations are different.
+ * </p><p>
+ * The standard deviation 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 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 standard deviation.
+ * </p>
+ */
+public class SingleSensorTests extends SensorTestCase {
+ private static final String TAG = "SingleSensorTests";
+
+ private static final int BATCHING_OFF = 0;
+ private static final int BATCHING_5S = 5000000;
+
+ private static final int RATE_100HZ = 10000;
+ private static final int RATE_50HZ = 20000;
+ private static final int RATE_25HZ = 40000;
+ private static final int RATE_15HZ = 66667;
+ private static final int RATE_10HZ = 100000;
+ private static final int RATE_5HZ = 200000;
+ private static final int RATE_1HZ = 1000000;
+
+ private static final String[] STAT_KEYS = {
+ SensorStats.FREQUENCY_KEY,
+ SensorStats.JITTER_95_PERCENTILE_KEY,
+ SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY,
+ SensorStats.MAGNITUDE_KEY,
+ SensorStats.MEAN_KEY,
+ SensorStats.STANDARD_DEVIATION_KEY,
+ };
+
+ /**
+ * This test verifies that the sensor's properties complies with the required properites set in
+ * the CDD.
+ * <p>
+ * It checks that the sampling rate advertised by the sensor under test matches that which is
+ * required by the CDD.
+ * </p>
+ */
+ public void testSensorProperties() {
+ // sensor type: [getMinDelay()]
+ Map<Integer, Object[]> expectedProperties = new HashMap<Integer, Object[]>(3);
+ expectedProperties.put(Sensor.TYPE_ACCELEROMETER, new Object[]{10000});
+ expectedProperties.put(Sensor.TYPE_GYROSCOPE, new Object[]{10000});
+ expectedProperties.put(Sensor.TYPE_MAGNETIC_FIELD, new Object[]{100000});
+
+ for (Entry<Integer, Object[]> entry : expectedProperties.entrySet()) {
+ Sensor sensor = SensorCtsHelper.getSensor(getContext(), entry.getKey());
+ String sensorName = SensorTestInformation.getSensorName(entry.getKey());
+ if (entry.getValue()[0] != null) {
+ int expected = (Integer) entry.getValue()[0];
+ String msg = String.format(
+ "%s: min delay %dus expected to be less than or equal to %dus",
+ sensorName, sensor.getMinDelay(), expected);
+ assertTrue(msg, sensor.getMinDelay() <= expected);
+ }
+ }
+ }
+
+ // TODO: Figure out if a better way to enumerate test cases programmatically exists that works
+ // with CTS framework.
+ public void testAccelerometer_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testAccelerometer_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ public void testAccelerometer_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testMagneticField_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
+ }
+
+ public void testMagneticField_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticField_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ public void testMagneticField_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_50HZ, BATCHING_5S);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_100HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_50HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_25HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_15HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_10HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_5HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_1HZ, BATCHING_OFF);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testOrientation_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_ORIENTATION, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testGyroscope_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
+ }
+
+ public void testGyroscope_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscope_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ public void testGyroscope_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testPressure_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
+ }
+
+ public void testPressure_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testPressure_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ public void testPressure_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_PRESSURE, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testGravity_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
+ }
+
+ public void testGravity_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testGravity_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ public void testGravity_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GRAVITY, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testRotationVector_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_OFF);
+ }
+ public void testRotationVector_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testRotationVector_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_5S);
+ }
+
+ public void testRotationVector_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testMagneticFieldUncalibrated_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testMagneticFieldUncalibrated_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_5S);
+ }
+
+ public void testMagneticFieldUncalibrated_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testGameRotationVector_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testGameRotationVector_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_5S);
+ }
+
+ public void testGameRotationVector_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testGyroscopeUncalibrated_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testGyroscopeUncalibrated_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_5S);
+ }
+
+ public void testGyroscopeUncalibrated_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_50HZ, BATCHING_5S);
+ }
+
+ public void testGeomagneticRotationVector_fastest() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_100hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_100HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_50hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_50HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_25hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_25HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_15hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_15HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_10hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_10HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_5hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_5HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_1hz() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_1HZ, BATCHING_OFF);
+ }
+
+ public void testGeomagneticRotationVector_fastest_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
+ BATCHING_5S);
+ }
+
+ public void testGeomagneticRotationVector_50hz_batching() throws Throwable {
+ runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_50HZ, BATCHING_5S);
+ }
+
+ private void runSensorTest(int sensorType, int rateUs, int maxBatchReportLatencyUs)
+ throws Throwable {
+ TestSensorOperation op = new TestSensorOperation(this.getContext(), sensorType,
+ rateUs, maxBatchReportLatencyUs, 5, TimeUnit.SECONDS);
+ op.setDefaultVerifications();
+ op.setLogEvents(true);
+ try {
+ op.execute();
+
+ // Only report stats if it passes.
+ logSelectedStatsToReportLog(getInstrumentation(), 2, STAT_KEYS,
+ op.getStats());
+ } finally {
+ SensorStats.logStats(TAG, op.getStats());
+
+ String sensorName = SensorTestInformation.getSanitizedSensorName(sensorType);
+ String sensorRate;
+ if (rateUs == SensorManager.SENSOR_DELAY_FASTEST) {
+ sensorRate = "fastest";
+ } else {
+ sensorRate = String.format("%.0fhz",
+ SensorCtsHelper.getFrequency(rateUs, TimeUnit.MICROSECONDS));
+ }
+ String batching = maxBatchReportLatencyUs > 0 ? "_batching" : "";
+ String fileName = String.format("single_sensor_%s_%s%s.txt",
+ sensorName, sensorRate, batching);
+ SensorStats.logStatsToFile(fileName, op.getStats());
+
+
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
new file mode 100644
index 0000000..981d74c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+import android.os.SystemClock;
+
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link TestSensorEventListener} which collects events to be processed after the test is run.
+ * This should only be used for short tests.
+ */
+public class CollectingSensorEventListener extends TestSensorEventListener {
+ private final ConcurrentLinkedDeque<TestSensorEvent> mSensorEventsList =
+ new ConcurrentLinkedDeque<TestSensorEvent>();
+
+ /**
+ * Constructs a {@link CollectingSensorEventListener} with an additional
+ * {@link SensorEventListener2}.
+ */
+ public CollectingSensorEventListener(SensorEventListener2 listener) {
+ super(listener);
+ }
+
+ /**
+ * Constructs a {@link CollectingSensorEventListener}.
+ */
+ public CollectingSensorEventListener() {
+ this(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ super.onSensorChanged(event);
+ mSensorEventsList.addLast(new TestSensorEvent(event, SystemClock.elapsedRealtimeNanos()));
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Clears the event queue before starting.
+ * </p>
+ */
+ @Override
+ public void waitForEvents(int eventCount) {
+ clearEvents();
+ super.waitForEvents(eventCount);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Clears the event queue before starting.
+ * </p>
+ */
+ @Override
+ public void waitForEvents(long duration, TimeUnit timeUnit) {
+ clearEvents();
+ super.waitForEvents(duration, timeUnit);
+ }
+
+ /**
+ * Get the {@link TestSensorEvent} array from the event queue.
+ */
+ public TestSensorEvent[] getEvents() {
+ return mSensorEventsList.toArray(new TestSensorEvent[0]);
+ }
+
+ /**
+ * Clear the event queue.
+ */
+ public void clearEvents() {
+ mSensorEventsList.clear();
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/FrameworkUnitTests.java b/tests/tests/hardware/src/android/hardware/cts/helpers/FrameworkUnitTests.java
new file mode 100644
index 0000000..6075add
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/FrameworkUnitTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import android.hardware.cts.helpers.sensoroperations.SensorOperationTest;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerificationTest;
+import android.hardware.cts.helpers.sensorverification.FrequencyVerificationTest;
+import android.hardware.cts.helpers.sensorverification.JitterVerificationTest;
+import android.hardware.cts.helpers.sensorverification.MagnitudeVerificationTest;
+import android.hardware.cts.helpers.sensorverification.MeanVerificationTest;
+import android.hardware.cts.helpers.sensorverification.EventGapVerificationTest;
+import android.hardware.cts.helpers.sensorverification.SigNumVerificationTest;
+import android.hardware.cts.helpers.sensorverification.StandardDeviationVerificationTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test suite for the CTS sensor framework.
+ */
+public class FrameworkUnitTests extends TestSuite {
+
+ public FrameworkUnitTests() {
+ super();
+
+ // helpers
+ addTestSuite(SensorCtsHelperTest.class);
+ addTestSuite(SensorStatsTest.class);
+
+ // sensorverification
+ addTestSuite(EventOrderingVerificationTest.class);
+ addTestSuite(FrequencyVerificationTest.class);
+ addTestSuite(JitterVerificationTest.class);
+ addTestSuite(MagnitudeVerificationTest.class);
+ addTestSuite(MeanVerificationTest.class);
+ addTestSuite(EventGapVerificationTest.class);
+ addTestSuite(SigNumVerificationTest.class);
+ addTestSuite(StandardDeviationVerificationTest.class);
+
+ // sensorOperations
+ addTestSuite(SensorOperationTest.class);
+ }
+
+ public static Test suite() {
+ return new FrameworkUnitTests();
+ }
+}
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 c8733ba..ed55b01 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -16,65 +16,51 @@
package android.hardware.cts.helpers;
import android.content.Context;
-
import android.hardware.Sensor;
import android.hardware.SensorManager;
-import android.os.Environment;
-
-import android.util.Log;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-import java.text.SimpleDateFormat;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Date;
-
+import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Set of static helper methods for CTS tests.
*/
+//TODO: Refactor this class and SensorTestInformation into several more well defined helper classes
public class SensorCtsHelper {
+
+ private static long NANOS_PER_MILLI = 1000000;
+
/**
- * This is an static class.
+ * Private constructor for static class.
*/
private SensorCtsHelper() {}
- public static <TValue extends Comparable> TValue get95PercentileValue(
+ /**
+ * Get the value of the 95th percentile using nearest rank algorithm.
+ *
+ * @throws IllegalArgumentException if the collection is null or empty
+ */
+ public static <TValue extends Comparable<? super TValue>> TValue get95PercentileValue(
Collection<TValue> collection) {
validateCollection(collection);
- ArrayList<TValue> arrayCopy = new ArrayList<TValue>(collection);
+ List<TValue> arrayCopy = new ArrayList<TValue>(collection);
Collections.sort(arrayCopy);
// zero-based array index
- int arrayIndex = (int)(arrayCopy.size() * 0.95) - 1;
- if(arrayIndex < 0) {
- arrayIndex = 0;
- }
+ int arrayIndex = (int) Math.round(arrayCopy.size() * 0.95 + .5) - 1;
return arrayCopy.get(arrayIndex);
}
/**
- * Calculates the mean for each of the values in the set of TestSensorEvents.
+ * Calculate the mean of a collection.
+ *
+ * @throws IllegalArgumentException if the collection is null or empty
*/
- public static void getMeans(TestSensorEvent events[], double means[]) {
- for(TestSensorEvent event : events) {
- for(int i = 0; i < means.length; ++i) {
- means[i] += event.values[i];
- }
- }
- for(int i = 0; i < means.length; ++i) {
- means[i] /= events.length;
- }
- }
-
public static <TValue extends Number> double getMean(Collection<TValue> collection) {
validateCollection(collection);
@@ -85,124 +71,43 @@
return sum / collection.size();
}
+ /**
+ * Calculate the bias-corrected sample variance of a collection.
+ *
+ * @throws IllegalArgumentException if the collection is null or empty
+ */
public static <TValue extends Number> double getVariance(Collection<TValue> collection) {
validateCollection(collection);
double mean = getMean(collection);
- ArrayList<Double> squaredDifferences = new ArrayList<Double>();
+ ArrayList<Double> squaredDiffs = new ArrayList<Double>();
for(TValue value : collection) {
double difference = mean - value.doubleValue();
- squaredDifferences.add(Math.pow(difference, 2));
+ squaredDiffs.add(Math.pow(difference, 2));
}
- double variance = getMean(squaredDifferences);
- return variance;
- }
-
- public static <TValue extends Number> double getStandardDeviation(Collection<TValue> collection) {
- validateCollection(collection);
-
- double variance = getVariance(collection);
- return Math.sqrt(variance);
+ double sum = 0.0;
+ for (Double value : squaredDiffs) {
+ sum += value;
+ }
+ return sum / (squaredDiffs.size() - 1);
}
/**
- * Gets the jitter values associated with a set of sensor events.
+ * Calculate the bias-corrected standard deviation of a collection.
*
- * @param events The events to use to obtain the jittering information.
- * @param jitterValues The Collection that will contain the computed jitter values.
- * @return The mean of the jitter Values.
+ * @throws IllegalArgumentException if the collection is null or empty
*/
- public static double getJitterMean(TestSensorEvent events[], Collection<Double> jitterValues) {
- ArrayList<Long> timestampDelayValues = new ArrayList<Long>();
- double averageTimestampDelay = SensorCtsHelper.getAverageTimestampDelayWithValues(events,
- timestampDelayValues);
- for(long frequency : timestampDelayValues) {
- jitterValues.add(Math.abs(averageTimestampDelay - frequency));
- }
-
- double jitterMean = SensorCtsHelper.getMean(timestampDelayValues);
- return jitterMean;
+ public static <TValue extends Number> double getStandardDeviation(
+ Collection<TValue> collection) {
+ return Math.sqrt(getVariance(collection));
}
/**
- * Gets the frequency values associated with a set of sensor events.
- *
- * @param events The events to use to obtain the frequency information.
- * @param timestampDelayValues The Collection that will contain the computed frequency values.
- * @return The mean of the frequency values.
+ * Get the default sensor for a given type.
*/
- public static double getAverageTimestampDelayWithValues(
- TestSensorEvent events[],
- Collection<Long> timestampDelayValues) {
- for(int i = 1; i < events.length; ++i) {
- long previousTimestamp = events[i-1].timestamp;
- long timestamp = events[i].timestamp;
- timestampDelayValues.add(timestamp - previousTimestamp);
- }
-
- double timestampDelayMean = SensorCtsHelper.getMean(timestampDelayValues);
- return timestampDelayMean;
- }
-
- public static int getSecondsAsMicroSeconds(int seconds) {
- return (int) TimeUnit.MICROSECONDS.convert(seconds, TimeUnit.SECONDS);
- }
-
- /**
- * 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 String collectBugreport(String collectorId)
- throws IOException, InterruptedException {
- String commands[] = new String[] {
- "dumpstate",
- "dumpsys",
- "logcat -d -v threadtime",
- "exit"
- };
-
- SimpleDateFormat dateFormat = new SimpleDateFormat("M-d-y_H:m:s.S");
- String outputFile = String.format(
- "%s/%s_%s",
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
- collectorId,
- dateFormat.format(new Date()));
-
- DataOutputStream processOutput = null;
- try {
- Process process = Runtime.getRuntime().exec("/system/bin/sh -");
- processOutput = new DataOutputStream(process.getOutputStream());
-
- for(String command : commands) {
- processOutput.writeBytes(String.format("%s >> %s\n", command, outputFile));
- }
-
- processOutput.flush();
- process.waitFor();
-
- Log.d(collectorId, String.format("Bug-Report collected at: %s", outputFile));
- } finally {
- if(processOutput != null) {
- try {
- processOutput.close();
- } catch(IOException e) {}
- }
- }
-
- return outputFile;
- }
-
public static Sensor getSensor(Context context, int sensorType) {
- SensorManager sensorManager = (SensorManager)context.getSystemService(
- Context.SENSOR_SERVICE);
- if(sensorManager == null) {
- throw new IllegalStateException("SensorService is not present in the system.");
- }
+ SensorManager sensorManager = getSensorManager(context);
Sensor sensor = sensorManager.getDefaultSensor(sensorType);
if(sensor == null) {
throw new SensorNotSupportedException(sensorType);
@@ -210,52 +115,137 @@
return sensor;
}
- public static <TReference extends Number> double getFrequencyInHz(TReference samplingRateInUs) {
- return 1000000000 / samplingRateInUs.doubleValue();
- }
-
- 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("| ");
+ /**
+ * Get all the sensors for a given type.
+ */
+ public static List<Sensor> getSensors(Context context, int sensorType) {
+ SensorManager sensorManager = getSensorManager(context);
+ List<Sensor> sensors = sensorManager.getSensorList(sensorType);
+ if (sensors.size() == 0) {
+ throw new SensorNotSupportedException(sensorType);
}
- // 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();
+ return sensors;
}
/**
- * Private helpers
+ * Convert a period to frequency in Hz.
*/
- private static void validateCollection(Collection collection) {
+ public static <TValue extends Number> double getFrequency(TValue period, TimeUnit unit) {
+ return 1000000000 / (TimeUnit.NANOSECONDS.convert(1, unit) * period.doubleValue());
+ }
+
+ /**
+ * Convert a frequency in Hz into a period.
+ */
+ public static <TValue extends Number> double getPeriod(TValue frequency, TimeUnit unit) {
+ return 1000000000 / (TimeUnit.NANOSECONDS.convert(1, unit) * frequency.doubleValue());
+ }
+
+ /**
+ * Convert number of seconds to number of microseconds.
+ */
+ public static int getSecondsAsMicroSeconds(int seconds) {
+ return (int) TimeUnit.MICROSECONDS.convert(seconds, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Convert the sensor delay or rate in microseconds into delay in microseconds.
+ * <p>
+ * The flags SensorManager.SENSOR_DELAY_[GAME|UI|NORMAL] are not supported since the CDD does
+ * not specify values for these flags. The rate is set to the max of
+ * {@link Sensor#getMinDelay()} and the rate given.
+ * </p>
+ */
+ public static int getDelay(Sensor sensor, int rateUs) {
+ if (!isDelayRateTestable(rateUs)) {
+ throw new IllegalArgumentException("rateUs cannot be SENSOR_DELAY_[GAME|UI|NORMAL]");
+ }
+ int delay;
+ if (rateUs == SensorManager.SENSOR_DELAY_FASTEST) {
+ delay = 0;
+ } else {
+ delay = rateUs;
+ }
+ return Math.max(delay, sensor.getMinDelay());
+ }
+
+ /**
+ * Return true if the operation rate is not one of {@link SensorManager#SENSOR_DELAY_GAME},
+ * {@link SensorManager#SENSOR_DELAY_UI}, or {@link SensorManager#SENSOR_DELAY_NORMAL}.
+ */
+ public static boolean isDelayRateTestable(int rateUs) {
+ return (rateUs != SensorManager.SENSOR_DELAY_GAME
+ && rateUs != SensorManager.SENSOR_DELAY_UI
+ && rateUs != SensorManager.SENSOR_DELAY_NORMAL);
+ }
+
+ /**
+ * Helper method to sleep for a given duration.
+ */
+ public static void sleep(long duration, TimeUnit timeUnit) {
+ long durationNs = TimeUnit.NANOSECONDS.convert(duration, timeUnit);
+ try {
+ Thread.sleep(durationNs / NANOS_PER_MILLI, (int) (durationNs % NANOS_PER_MILLI));
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Format an assertion message.
+ *
+ * @param sensor the {@link Sensor}
+ * @param label the verification name
+ * @param rateUs the rate of the sensor
+ * @param maxBatchReportLatencyUs the max batch report latency of the sensor
+ * @return The formatted string
+ */
+ public static String formatAssertionMessage(Sensor sensor, String label, int rateUs,
+ int maxBatchReportLatencyUs) {
+ return String.format("%s | %s, handle: %d", label,
+ SensorTestInformation.getSensorName(sensor.getType()), sensor.getHandle());
+ }
+
+ /**
+ * Format an assertion message with a custom message.
+ *
+ * @param sensor the {@link Sensor}
+ * @param label the verification name
+ * @param rateUs the rate of the sensor
+ * @param maxBatchReportLatencyUs the max batch report latency of the sensor
+ * @param format the additional format string
+ * @param params the additional format params
+ * @return The formatted string
+ */
+ public static String formatAssertionMessage(Sensor sensor, String label, int rateUs,
+ int maxBatchReportLatencyUs, String format, Object ... params) {
+ return String.format("%s | %s, handle: %d, rateUs: %d, maxBatchReportLatencyUs: %d | %s",
+ label, SensorTestInformation.getSensorName(sensor.getType()), sensor.getHandle(),
+ rateUs, maxBatchReportLatencyUs, String.format(format, params));
+ }
+
+ /**
+ * Validate that a collection is not null or empty.
+ *
+ * @throws IllegalStateException if collection is null or empty.
+ */
+ private static <T> void validateCollection(Collection<T> collection) {
if(collection == null || collection.size() == 0) {
throw new IllegalStateException("Collection cannot be null or empty");
}
}
+
+ /**
+ * Get the SensorManager.
+ *
+ * @throws IllegalStateException if the SensorManager is not present in the system.
+ */
+ private static SensorManager getSensorManager(Context context) {
+ SensorManager sensorManager = (SensorManager) context.getSystemService(
+ Context.SENSOR_SERVICE);
+ if(sensorManager == null) {
+ throw new IllegalStateException("SensorService is not present in the system.");
+ }
+ return sensorManager;
+ }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java
new file mode 100644
index 0000000..6f99692
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit tests for the {@link SensorCtsHelper} class.
+ */
+public class SensorCtsHelperTest extends TestCase {
+
+ /**
+ * Test {@link SensorCtsHelper#get95PercentileValue(Collection)}.
+ */
+ public void testGet95PercentileValue() {
+ Collection<Integer> values = new HashSet<Integer>();
+ for (int i = 0; i < 100; i++) {
+ values.add(i);
+ }
+ assertEquals(95, (int) SensorCtsHelper.get95PercentileValue(values));
+
+ values = new HashSet<Integer>();
+ for (int i = 0; i < 1000; i++) {
+ values.add(i);
+ }
+ assertEquals(950, (int) SensorCtsHelper.get95PercentileValue(values));
+
+ values = new HashSet<Integer>();
+ for (int i = 0; i < 100; i++) {
+ values.add(i * i);
+ }
+ assertEquals(95 * 95, (int) SensorCtsHelper.get95PercentileValue(values));
+ }
+
+ /**
+ * Test {@link SensorCtsHelper#getMean(Collection)}.
+ */
+ public void testGetMean() {
+ List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
+ double mean = SensorCtsHelper.getMean(values);
+ assertEquals(2.0, mean, 0.00001);
+
+ values = Arrays.asList(1, 2, 3, 4, 5);
+ mean = SensorCtsHelper.getMean(values);
+ assertEquals(3.0, mean, 0.00001);
+
+ values = Arrays.asList(0, 1, 4, 9, 16);
+ mean = SensorCtsHelper.getMean(values);
+ assertEquals(6.0, mean, 0.00001);
+ }
+
+ /**
+ * Test {@link SensorCtsHelper#getVariance(Collection)}.
+ */
+ public void testGetVariance() {
+ List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
+ double variance = SensorCtsHelper.getVariance(values);
+ assertEquals(2.5, variance, 0.00001);
+
+ values = Arrays.asList(1, 2, 3, 4, 5);
+ variance = SensorCtsHelper.getVariance(values);
+ assertEquals(2.5, variance, 0.00001);
+
+ values = Arrays.asList(0, 2, 4, 6, 8);
+ variance = SensorCtsHelper.getVariance(values);
+ assertEquals(10.0, variance, 0.00001);
+ }
+
+ /**
+ * Test {@link SensorCtsHelper#getStandardDeviation(Collection)}.
+ */
+ public void testGetStandardDeviation() {
+ List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
+ double stddev = SensorCtsHelper.getStandardDeviation(values);
+ assertEquals(Math.sqrt(2.5), stddev, 0.00001);
+
+ values = Arrays.asList(1, 2, 3, 4, 5);
+ stddev = SensorCtsHelper.getStandardDeviation(values);
+ assertEquals(Math.sqrt(2.5), stddev, 0.00001);
+
+ values = Arrays.asList(0, 2, 4, 6, 8);
+ stddev = SensorCtsHelper.getStandardDeviation(values);
+ assertEquals(Math.sqrt(10.0), stddev, 0.00001);
+ }
+
+ /**
+ * Test {@link SensorCtsHelper#getFrequency(Number, TimeUnit)}.
+ */
+ public void testGetFrequency() {
+ assertEquals(1.0, SensorCtsHelper.getFrequency(1, TimeUnit.SECONDS), 0.001);
+ assertEquals(10.0, SensorCtsHelper.getFrequency(0.1, TimeUnit.SECONDS), 0.001);
+ assertEquals(10.0, SensorCtsHelper.getFrequency(100, TimeUnit.MILLISECONDS), 0.001);
+ assertEquals(1000.0, SensorCtsHelper.getFrequency(1, TimeUnit.MILLISECONDS), 0.001);
+ assertEquals(10000.0, SensorCtsHelper.getFrequency(0.1, TimeUnit.MILLISECONDS), 0.001);
+ assertEquals(10000.0, SensorCtsHelper.getFrequency(100, TimeUnit.MICROSECONDS), 0.001);
+ assertEquals(1000000.0, SensorCtsHelper.getFrequency(1, TimeUnit.MICROSECONDS), 0.001);
+ assertEquals(10000000.0, SensorCtsHelper.getFrequency(0.1, TimeUnit.MICROSECONDS), 0.001);
+ assertEquals(10000000.0, SensorCtsHelper.getFrequency(100, TimeUnit.NANOSECONDS), 0.001);
+ assertEquals(1000000000.0, SensorCtsHelper.getFrequency(1, TimeUnit.NANOSECONDS), 0.001);
+ }
+
+ /**
+ * Test {@link SensorCtsHelper#getPeriod(Number, TimeUnit)}.
+ */
+ public void testGetPeriod() {
+ assertEquals(1.0, SensorCtsHelper.getPeriod(1, TimeUnit.SECONDS), 0.001);
+ assertEquals(0.1, SensorCtsHelper.getPeriod(10, TimeUnit.SECONDS), 0.001);
+ assertEquals(100, SensorCtsHelper.getPeriod(10, TimeUnit.MILLISECONDS), 0.001);
+ assertEquals(1, SensorCtsHelper.getPeriod(1000, TimeUnit.MILLISECONDS), 0.001);
+ assertEquals(0.1, SensorCtsHelper.getPeriod(10000, TimeUnit.MILLISECONDS), 0.001);
+ assertEquals(100, SensorCtsHelper.getPeriod(10000, TimeUnit.MICROSECONDS), 0.001);
+ assertEquals(1, SensorCtsHelper.getPeriod(1000000, TimeUnit.MICROSECONDS), 0.001);
+ assertEquals(0.1, SensorCtsHelper.getPeriod(10000000, TimeUnit.MICROSECONDS), 0.001);
+ assertEquals(100, SensorCtsHelper.getPeriod(10000000, TimeUnit.NANOSECONDS), 0.001);
+ assertEquals(1, SensorCtsHelper.getPeriod(1000000000, TimeUnit.NANOSECONDS), 0.001);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java
deleted file mode 100644
index 6e8b758..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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.content.Context;
-
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener2;
-import android.hardware.SensorManager;
-
-import java.io.Closeable;
-
-import java.security.InvalidParameterException;
-import java.util.concurrent.ConcurrentLinkedDeque;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-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.
- */
-public class SensorManagerTestVerifier implements Closeable, SensorEventListener2 {
- private final int WAIT_TIMEOUT_IN_SECONDS = 30;
-
- private final SensorManager mSensorManager;
- private final Sensor mSensorUnderTest;
- private final int mSamplingRateInUs;
- private final int mReportLatencyInUs;
-
- private TestSensorListener mEventListener;
-
- /**
- * Construction methods.
- */
- public SensorManagerTestVerifier(
- Context context,
- int sensorType,
- int samplingRateInUs,
- int reportLatencyInUs) {
- mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
- mSensorUnderTest = SensorCtsHelper.getSensor(context, sensorType);
- mSamplingRateInUs = samplingRateInUs;
- mReportLatencyInUs = reportLatencyInUs;
-
- mEventListener = new TestSensorListener(mSensorUnderTest, this);
- }
-
- /**
- * Public listeners for Sensor events, these are available for subclasses to implement if they
- * need access to the raw eventing model.
- */
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {}
-
- @Override
- public void onSensorChanged(SensorEvent event) {}
-
- @Override
- public void onFlushCompleted(Sensor sensor) {}
-
- /**
- * Members
- */
- public void close() {
- this.unregisterListener();
- mEventListener = null;
- }
-
- public Sensor getUnderlyingSensor() {
- return mSensorUnderTest;
- }
-
- public void registerListener(String debugInfo) {
- boolean result = mSensorManager.registerListener(
- mEventListener,
- mSensorUnderTest,
- mSamplingRateInUs,
- mReportLatencyInUs);
- String message = SensorCtsHelper.formatAssertionMessage(
- "registerListener",
- mSensorUnderTest,
- debugInfo);
- Assert.assertTrue(message, result);
- }
-
- public void registerListener() {
- this.registerListener("");
- }
-
- public void unregisterListener() {
- mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
- }
-
- public TestSensorEvent[] getEvents(int count, String debugInfo) {
- mEventListener.waitForEvents(count, debugInfo);
- TestSensorEvent[] events = mEventListener.getAllEvents();
- mEventListener.clearEvents();
-
- return events;
- }
-
- public TestSensorEvent[] getEvents(int count) {
- return this.getEvents(count, "");
- }
-
- public TestSensorEvent[] getQueuedEvents() {
- return mEventListener.getAllEvents();
- }
-
- public TestSensorEvent[] collectEvents(int eventCount, String debugInfo) {
- this.registerListener(debugInfo);
- TestSensorEvent[] events = this.getEvents(eventCount, debugInfo);
- this.unregisterListener();
-
- return events;
- }
-
- public TestSensorEvent[] collectEvents(int eventCount) {
- return this.collectEvents(eventCount, "");
- }
-
- public void startFlush() {
- String message = SensorCtsHelper.formatAssertionMessage(
- "Flush",
- mSensorUnderTest,
- "" /* format */);
- Assert.assertTrue(message, mSensorManager.flush(mEventListener));
- }
-
- public void waitForFlush() throws InterruptedException {
- mEventListener.waitForFlushComplete();
- }
-
- public void flush() throws InterruptedException {
- this.startFlush();
- this.waitForFlush();
- }
-
- /**
- * Definition of support test classes.
- */
- private class TestSensorListener implements SensorEventListener2 {
- private final Sensor mSensorUnderTest;
- private final SensorEventListener2 mListener;
-
- private final ConcurrentLinkedDeque<TestSensorEvent> mSensorEventsList =
- new ConcurrentLinkedDeque<TestSensorEvent>();
-
- private volatile CountDownLatch mEventLatch;
- private volatile CountDownLatch mFlushLatch = new CountDownLatch(1);
-
- public TestSensorListener(Sensor sensor, SensorEventListener2 listener) {
- if(sensor == null) {
- throw new InvalidParameterException("sensor cannot be null");
- }
- if(listener == null) {
- throw new InvalidParameterException("listener cannot be null");
- }
- mSensorUnderTest = sensor;
- mListener = listener;
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- // copy the event because there is no better way to do this in the platform
- mSensorEventsList.addLast(new TestSensorEvent(event));
- if(mEventLatch != null) {
- mEventLatch.countDown();
- }
- mListener.onSensorChanged(event);
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- mListener.onAccuracyChanged(sensor, accuracy);
- }
-
- @Override
- public void onFlushCompleted(Sensor sensor) {
- CountDownLatch latch = mFlushLatch;
- mFlushLatch = new CountDownLatch(1);
- if(latch != null) {
- latch.countDown();
- }
- mListener.onFlushCompleted(sensor);
- }
-
- public void waitForFlushComplete() throws InterruptedException {
- CountDownLatch latch = mFlushLatch;
- if(latch != null) {
- String message = SensorCtsHelper.formatAssertionMessage(
- "WaitForFlush",
- mSensorUnderTest,
- "" /* format */);
- Assert.assertTrue(message, latch.await(WAIT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS));
- }
- }
-
- public void waitForEvents(int eventCount, String timeoutInfo) {
- mEventLatch = new CountDownLatch(eventCount);
- this.clearEvents();
- try {
- 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 message = SensorCtsHelper.formatAssertionMessage(
- "WaitForEvents",
- mSensorUnderTest,
- "count:%d, available:%d, %s",
- eventCount,
- mSensorEventsList.size(),
- timeoutInfo);
- Assert.assertTrue(message, awaitCompleted);
- } catch(InterruptedException e) {
- } finally {
- mEventLatch = null;
- }
- }
-
- public TestSensorEvent[] getAllEvents() {
- return mSensorEventsList.toArray(new TestSensorEvent[0]);
- }
-
- public void clearEvents() {
- mSensorEventsList.clear();
- }
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
new file mode 100644
index 0000000..1a500d4
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import android.hardware.cts.helpers.sensoroperations.ISensorOperation;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Class used to store stats related to {@link ISensorOperation}s. Sensor stats may be linked
+ * together so that they form a tree.
+ */
+public class SensorStats {
+ public static final String DELIMITER = "__";
+
+ public static final String FIRST_TIMESTAMP_KEY = "first_timestamp";
+ public static final String LAST_TIMESTAMP_KEY = "last_timestamp";
+ public static final String ERROR = "error";
+ public static final String EVENT_COUNT_KEY = "event_count";
+ public static final String EVENT_GAP_COUNT_KEY = "event_gap_count";
+ public static final String EVENT_GAP_POSITIONS_KEY = "event_gap_positions";
+ public static final String EVENT_OUT_OF_ORDER_COUNT_KEY = "event_out_of_order_count";
+ public static final String EVENT_OUT_OF_ORDER_POSITIONS_KEY = "event_out_of_order_positions";
+ public static final String FREQUENCY_KEY = "frequency";
+ public static final String JITTER_95_PERCENTILE_KEY = "jitter_95_percentile";
+ public static final String MEAN_KEY = "mean";
+ public static final String STANDARD_DEVIATION_KEY = "standard_deviation";
+ public static final String MAGNITUDE_KEY = "magnitude";
+
+ private final Map<String, Object> mValues = new HashMap<String, Object>();
+ private final Map<String, SensorStats> mSensorStats = new HashMap<String, SensorStats>();
+
+ /**
+ * Add a value.
+ *
+ * @param key the key.
+ * @param value the value as an {@link Object}.
+ */
+ public synchronized void addValue(String key, Object value) {
+ if (value == null) {
+ return;
+ }
+ mValues.put(key, value);
+ }
+
+ /**
+ * Add a nested {@link SensorStats}. This is useful for keeping track of stats in a
+ * {@link ISensorOperation} tree.
+ *
+ * @param key the key
+ * @param stats the sub {@link SensorStats} object.
+ */
+ public synchronized void addSensorStats(String key, SensorStats stats) {
+ if (stats == null) {
+ return;
+ }
+ mSensorStats.put(key, stats);
+ }
+
+ /**
+ * Get the keys from the values table. Will not get the keys from the nested
+ * {@link SensorStats}.
+ */
+ public synchronized Set<String> getKeys() {
+ return mValues.keySet();
+ }
+
+ /**
+ * Get a value from the values table. Will not attempt to get values from nested
+ * {@link SensorStats}.
+ */
+ public synchronized Object getValue(String key) {
+ return mValues.get(key);
+ }
+
+ /**
+ * Flattens the map and all sub {@link SensorStats} objects. Keys will be flattened using
+ * {@value #DELIMITER}. For example, if a sub {@link SensorStats} is added with key
+ * {@code "key1"} containing the key value pair {@code ("key2", "value")}, the flattened map
+ * will contain the entry {@code ("key1__key2", "value")}.
+ *
+ * @return a {@link Map} containing all stats from the value and sub {@link SensorStats}.
+ */
+ public synchronized Map<String, Object> flatten() {
+ final Map<String, Object> flattenedMap = new HashMap<String, Object>(mValues);
+ for (Entry<String, SensorStats> statsEntry : mSensorStats.entrySet()) {
+ for (Entry<String, Object> valueEntry : statsEntry.getValue().flatten().entrySet()) {
+ String key = statsEntry.getKey() + DELIMITER + valueEntry.getKey();
+ flattenedMap.put(key, valueEntry.getValue());
+ }
+ }
+ return flattenedMap;
+ }
+
+ /**
+ * Utility method to log the stats to the logcat.
+ */
+ public static void logStats(String tag, SensorStats stats) {
+ final Map<String, Object> flattened = stats.flatten();
+ for (String key : getSortedKeys(flattened)) {
+ Object value = flattened.get(key);
+ Log.v(tag, String.format("%s: %s", key, getValueString(value)));
+ }
+ }
+
+ /**
+ * Utility method to log the stats to a file. Will overwrite the file if it already exists.
+ */
+ public static void logStatsToFile(String fileName, SensorStats stats) throws IOException {
+ final BufferedWriter writer = new BufferedWriter(new FileWriter(
+ new File(Environment.getExternalStorageDirectory(), fileName), false));
+ final Map<String, Object> flattened = stats.flatten();
+ try {
+ for (String key : getSortedKeys(flattened)) {
+ Object value = flattened.get(key);
+ writer.write(String.format("%s: %s\n", key, getValueString(value)));
+ }
+ } finally {
+ writer.flush();
+ writer.close();
+ }
+ }
+
+ private static List<String> getSortedKeys(Map<String, Object> flattenedStats) {
+ List<String> keys = new ArrayList<String>(flattenedStats.keySet());
+ Collections.sort(keys);
+ return keys;
+ }
+
+ private static String getValueString(Object value) {
+ if (value == null) {
+ return "";
+ } else if (value instanceof boolean[]) {
+ return Arrays.toString((boolean[]) value);
+ } else if (value instanceof byte[]) {
+ return Arrays.toString((byte[]) value);
+ } else if (value instanceof char[]) {
+ return Arrays.toString((char[]) value);
+ } else if (value instanceof double[]) {
+ return Arrays.toString((double[]) value);
+ } else if (value instanceof float[]) {
+ return Arrays.toString((float[]) value);
+ } else if (value instanceof int[]) {
+ return Arrays.toString((int[]) value);
+ } else if (value instanceof long[]) {
+ return Arrays.toString((long[]) value);
+ } else if (value instanceof short[]) {
+ return Arrays.toString((short[]) value);
+ } else if (value instanceof Object[]) {
+ return Arrays.toString((Object[]) value);
+ } else {
+ return value.toString();
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStatsTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStatsTest.java
new file mode 100644
index 0000000..8ba0f41
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStatsTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+
+/**
+ * Unit tests for the {@link SensorStats} class.
+ */
+public class SensorStatsTest extends TestCase {
+
+ /**
+ * Test that {@link SensorStats#flatten()} works correctly.
+ */
+ public void testFlatten() {
+ SensorStats stats = new SensorStats();
+ stats.addValue("value0", 0);
+ stats.addValue("value1", 1);
+
+ SensorStats subStats = new SensorStats();
+ subStats.addValue("value2", 2);
+ subStats.addValue("value3", 3);
+
+ SensorStats subSubStats = new SensorStats();
+ subSubStats.addValue("value4", 4);
+ subSubStats.addValue("value5", 5);
+
+ subStats.addSensorStats("stats1", subSubStats);
+ stats.addSensorStats("stats0", subStats);
+
+ // Add empty stats, expect no value in flattened map
+ stats.addSensorStats("stats2", new SensorStats());
+
+ // Add null values, expect no value in flattened map
+ stats.addSensorStats("stats3", null);
+ stats.addValue("value6", null);
+
+ Map<String, Object> flattened = stats.flatten();
+
+ assertEquals(6, flattened.size());
+ assertEquals(0, (int) (Integer) flattened.get("value0"));
+ assertEquals(1, (int) (Integer) flattened.get("value1"));
+ assertEquals(2, (int) (Integer) flattened.get("stats0__value2"));
+ assertEquals(3, (int) (Integer) flattened.get("stats0__value3"));
+ assertEquals(4, (int) (Integer) flattened.get("stats0__stats1__value4"));
+ assertEquals(5, (int) (Integer) flattened.get("stats0__stats1__value5"));
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java
deleted file mode 100644
index 4bd0eed..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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
index 90e0706..b220b00 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java
@@ -16,137 +16,149 @@
package android.hardware.cts.helpers;
-import android.content.Context;
-
import android.hardware.Sensor;
-import java.security.InvalidParameterException;
-
/**
* A 'property' bag of sensor information used for testing purposes.
*/
+// TODO: Refactor this class and SensorCtsHelper into several more well defined helper classes
public class SensorTestInformation {
private SensorTestInformation() {}
- public static int getAxisCount(int sensorType) {
+ public enum SensorReportingMode {
+ CONTINUOUS,
+ ON_CHANGE,
+ ONE_SHOT,
+ }
+
+ @SuppressWarnings("deprecation")
+ public static SensorReportingMode getReportingMode(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_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_PRESSURE:
case Sensor.TYPE_GRAVITY:
- return 3;
case Sensor.TYPE_LINEAR_ACCELERATION:
- return 3;
-// 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";
+ case Sensor.TYPE_ROTATION_VECTOR:
+ case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ case Sensor.TYPE_GAME_ROTATION_VECTOR:
+ case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+ case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ return SensorReportingMode.CONTINUOUS;
+ case Sensor.TYPE_LIGHT:
+ case Sensor.TYPE_TEMPERATURE:
+ case Sensor.TYPE_PROXIMITY:
+ case Sensor.TYPE_RELATIVE_HUMIDITY:
+ case Sensor.TYPE_AMBIENT_TEMPERATURE:
+ case Sensor.TYPE_STEP_DETECTOR:
+ case Sensor.TYPE_STEP_COUNTER:
+ return SensorReportingMode.ON_CHANGE;
+ case Sensor.TYPE_SIGNIFICANT_MOTION:
+ return SensorReportingMode.ONE_SHOT;
default:
- throw new InvalidParameterException(
- String.format("Invalid sensorType:%d. Unable to find axis count.", sensorType));
+ return null;
}
}
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);
+ return String.format("%s (%d)", getSimpleSensorName(sensorType), sensorType);
}
- public static int getMaxSamplingRateInUs(Context context, int sensorType) {
- Sensor sensor = SensorCtsHelper.getSensor(context, sensorType);
- return sensor.getMinDelay();
+ @SuppressWarnings("deprecation")
+ public static String getSimpleSensorName(int sensorType) {
+ switch(sensorType) {
+ case Sensor.TYPE_ACCELEROMETER:
+ return "Accelerometer";
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ return "Magnetic Field";
+ case Sensor.TYPE_ORIENTATION:
+ return "Orientation";
+ case Sensor.TYPE_GYROSCOPE:
+ return "Gyroscope";
+ 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:
+ return "<Unknown>";
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public static String getSanitizedSensorName(int sensorType) {
+ switch(sensorType) {
+ case Sensor.TYPE_ACCELEROMETER:
+ return "Accelerometer";
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ return "MagneticField";
+ case Sensor.TYPE_ORIENTATION:
+ return "Orientation";
+ case Sensor.TYPE_GYROSCOPE:
+ return "Gyroscope";
+ 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 "LinearAcceleration";
+ case Sensor.TYPE_ROTATION_VECTOR:
+ return "RotationVector";
+ case Sensor.TYPE_RELATIVE_HUMIDITY:
+ return "RelativeHumidity";
+ case Sensor.TYPE_AMBIENT_TEMPERATURE:
+ return "AmbientTemperature";
+ case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ return "MagneticFieldUncalibrated";
+ case Sensor.TYPE_GAME_ROTATION_VECTOR:
+ return "GameRotationVector";
+ case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+ return "GyroscopeUncalibrated";
+ case Sensor.TYPE_SIGNIFICANT_MOTION:
+ return "SignificantMotion";
+ case Sensor.TYPE_STEP_DETECTOR:
+ return "StepDetector";
+ case Sensor.TYPE_STEP_COUNTER:
+ return "StepCounter";
+ case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ return "GeomagneticRotationVector";
+ default:
+ return String.format("UnknownSensorType%d", sensorType);
+ }
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java
deleted file mode 100644
index 902c802..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 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 long WAIT_TIMEOUT_IN_MILLISECONDS =
- TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES);
-
- 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);
- if(mThread.isAlive()) {
- // the test is hung so collect the state of the system and fail
- String operationName = this.getClass().getSimpleName();
- String message = String.format(
- "%s hung. %s. BugReport collected at: %s",
- operationName,
- this.toString(),
- SensorCtsHelper.collectBugreport(operationName));
- Assert.fail(message);
- }
- 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
index 1a2cdfe..b349e1b 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
@@ -18,24 +18,52 @@
import android.hardware.Sensor;
import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
/**
- * 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.
+ * Class for holding information about individual {@link SensorEvent}s.
*/
public class TestSensorEvent {
public final Sensor sensor;
public final long timestamp;
+ public final long receivedTimestamp;
public final int accuracy;
public final float values[];
- public TestSensorEvent(SensorEvent event) {
+ /**
+ * Construct a TestSensorEvent from {@link SensorEvent} data and a received timestamp.
+ *
+ * @param event the {@link SensorEvent} to be cloned
+ * @param receivedTimestamp the timestamp when
+ * {@link SensorEventListener2#onSensorChanged(SensorEvent)} was called, in nanoseconds.
+ */
+ public TestSensorEvent(SensorEvent event, long receivedTimestamp) {
values = new float[event.values.length];
- System.arraycopy(event.values, 0, values, 0, event.values.length);
+ System.arraycopy(event.values, 0, values, 0, values.length);
sensor = event.sensor;
timestamp = event.timestamp;
accuracy = event.accuracy;
+
+ this.receivedTimestamp = receivedTimestamp;
+ }
+
+ /**
+ * Constructor for TestSensorEvent. Exposed for unit testing.
+ */
+ public TestSensorEvent(Sensor sensor, long timestamp, int accuracy, float[] values) {
+ this(sensor, timestamp, timestamp, accuracy, values);
+ }
+
+ /**
+ * Constructor for TestSensorEvent. Exposed for unit testing.
+ */
+ public TestSensorEvent(Sensor sensor, long timestamp, long receivedTimestamp, int accuracy,
+ float[] values) {
+ this.sensor = sensor;
+ this.timestamp = timestamp;
+ this.receivedTimestamp = receivedTimestamp;
+ this.accuracy = accuracy;
+ this.values = values;
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
new file mode 100644
index 0000000..ddbc8c2
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link SensorEventListener2} which performs operations such as waiting for a specific number of
+ * events or for a specific time, or waiting for a flush to complete. This class performs
+ * verifications and will throw {@link AssertionError}s if there are any errors. It may also wrap
+ * another {@link SensorEventListener2}.
+ */
+public class TestSensorEventListener implements SensorEventListener2 {
+ public static final String LOG_TAG = "TestSensorEventListener";
+ private static final long EVENT_TIMEOUT_US = TimeUnit.MICROSECONDS.convert(5, TimeUnit.SECONDS);
+ private static final long FLUSH_TIMEOUT_US = TimeUnit.MICROSECONDS.convert(5, TimeUnit.SECONDS);
+
+ private final SensorEventListener2 mListener;
+
+ private volatile CountDownLatch mEventLatch = null;
+ private volatile CountDownLatch mFlushLatch = new CountDownLatch(1);
+
+ private Sensor mSensor = null;
+ private int mRateUs = 0;
+ private int mMaxBatchReportLatencyUs = 0;
+ private boolean mLogEvents = false;
+
+ /**
+ * Construct a {@link TestSensorEventListener}.
+ */
+ public TestSensorEventListener() {
+ this(null);
+ }
+
+ /**
+ * Construct a {@link TestSensorEventListener} that wraps a {@link SensorEventListener2}.
+ */
+ public TestSensorEventListener(SensorEventListener2 listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Set the sensor, rate, and batch report latency used for the assertions.
+ */
+ public void setSensorInfo(Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
+ mSensor = sensor;
+ mRateUs = rateUs;
+ mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+ }
+
+ /**
+ * Set whether or not to log events
+ */
+ public void setLogEvents(boolean log) {
+ mLogEvents = log;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if(mEventLatch != null) {
+ mEventLatch.countDown();
+ }
+ if (mListener != null) {
+ mListener.onSensorChanged(event);
+ }
+ if (mLogEvents) {
+ StringBuilder valuesSb = new StringBuilder();
+ if (event.values.length == 1) {
+ valuesSb.append(String.format("%.2f", event.values[0]));
+ } else {
+ valuesSb.append("[").append(String.format("%.2f", event.values[0]));
+ for (int i = 1; i < event.values.length; i++) {
+ valuesSb.append(String.format(", %.2f", event.values[i]));
+ }
+ valuesSb.append("]");
+ }
+
+ Log.v(LOG_TAG, String.format(
+ "Sensor %d: sensor_timestamp=%d, received_timestamp=%d, values=%s",
+ mSensor.getType(), event.timestamp, System.nanoTime(),
+ Arrays.toString(event.values)));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ if (mListener != null) {
+ mListener.onAccuracyChanged(sensor, accuracy);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onFlushCompleted(Sensor sensor) {
+ CountDownLatch latch = mFlushLatch;
+ mFlushLatch = new CountDownLatch(1);
+ if(latch != null) {
+ latch.countDown();
+ }
+ if (mListener != null) {
+ mListener.onFlushCompleted(sensor);
+ }
+ }
+
+ /**
+ * Wait for {@link #onFlushCompleted(Sensor)} to be called.
+ *
+ * @throws AssertionError if there was a timeout after {@value #FLUSH_TIMEOUT_US} µs
+ */
+ public void waitForFlushComplete() {
+ CountDownLatch latch = mFlushLatch;
+ try {
+ if(latch != null) {
+ String message = SensorCtsHelper.formatAssertionMessage(mSensor, "WaitForFlush",
+ mRateUs, mMaxBatchReportLatencyUs);
+ Assert.assertTrue(message, latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
+ }
+ } catch(InterruptedException e) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Collect a specific number of {@link TestSensorEvent}s.
+ *
+ * @throws AssertionError if there was a timeout after {@value #FLUSH_TIMEOUT_US} µs
+ */
+ public void waitForEvents(int eventCount) {
+ mEventLatch = new CountDownLatch(eventCount);
+ try {
+ int rateUs = SensorCtsHelper.getDelay(mSensor, mRateUs);
+ // Timeout is 2 * event count * expected period + batch timeout + default wait
+ long timeoutUs = ((2 * eventCount * rateUs)
+ + mMaxBatchReportLatencyUs + EVENT_TIMEOUT_US);
+
+ String message = SensorCtsHelper.formatAssertionMessage(mSensor, "WaitForEvents",
+ mRateUs, mMaxBatchReportLatencyUs, "count:%d, available:%d", eventCount,
+ mEventLatch.getCount());
+ Assert.assertTrue(message, mEventLatch.await(timeoutUs, TimeUnit.MICROSECONDS));
+ } catch(InterruptedException e) {
+ // Ignore
+ } finally {
+ mEventLatch = null;
+ }
+ }
+
+ /**
+ * Collect {@link TestSensorEvent} for a specific duration.
+ */
+ public void waitForEvents(long duration, TimeUnit timeUnit) {
+ SensorCtsHelper.sleep(duration, timeUnit);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
new file mode 100644
index 0000000..a45ad70
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorEventListener2;
+import android.hardware.SensorManager;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A test class that performs the actions of {@link SensorManager} on a single sensor. This
+ * class allows for a single sensor to be registered and unregistered as well as performing
+ * operations such as flushing the sensor events and gathering events. This class also manages
+ * performing the test verifications for the sensor manager.
+ * <p>
+ * This class requires that operations are performed in the following order:
+ * <p><ul>
+ * <li>{@link #registerListener(TestSensorEventListener)}</li>
+ * <li>{@link #startFlush()}, {@link #waitForFlushCompleted()}, or {@link #flush()}.
+ * <li>{@link #unregisterListener()}</li>
+ * </ul><p>Or:</p><ul>
+ * <li>{@link #runSensor(TestSensorEventListener, int)}</li>
+ * </ul><p>Or:</p><ul>
+ * <li>{@link #runSensor(TestSensorEventListener, long, TimeUnit)}</li>
+ * </ul><p>
+ * If methods are called outside of this order, they will print a warning to the log and then
+ * return. Both {@link #runSensor(TestSensorEventListener, int)}} and
+ * {@link #runSensor(TestSensorEventListener, long, TimeUnit)} will perform the appropriate
+ * set up and tear down.
+ * <p>
+ */
+public class TestSensorManager {
+ private static final String LOG_TAG = "TestSensorManager";
+
+ private final SensorManager mSensorManager;
+ private final Sensor mSensor;
+ private final int mRateUs;
+ private final int mMaxBatchReportLatencyUs;
+
+ private TestSensorEventListener mTestSensorEventListener = null;
+
+ /**
+ * Construct a {@link TestSensorManager}.
+ */
+ public TestSensorManager(Context context, int sensorType, int rateUs,
+ int maxBatchReportLatencyUs) {
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ mSensor = SensorCtsHelper.getSensor(context, sensorType);
+ mRateUs = rateUs;
+ mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+ }
+
+ /**
+ * Register the listener. This method will perform a no-op if the sensor is already registered.
+ *
+ * @throws AssertionError if there was an error registering the listener with the
+ * {@link SensorManager}
+ */
+ public void registerListener(TestSensorEventListener listener) {
+ if (mTestSensorEventListener != null) {
+ Log.w(LOG_TAG, "Listener already registered, returning.");
+ return;
+ }
+
+ mTestSensorEventListener = listener != null ? listener : new TestSensorEventListener();
+ mTestSensorEventListener.setSensorInfo(mSensor, mRateUs, mMaxBatchReportLatencyUs);
+
+ String message = SensorCtsHelper.formatAssertionMessage(mSensor, "registerListener",
+ mRateUs, mMaxBatchReportLatencyUs);
+ boolean result = mSensorManager.registerListener(mTestSensorEventListener, mSensor, mRateUs,
+ mMaxBatchReportLatencyUs);
+ Assert.assertTrue(message, result);
+ }
+
+ /**
+ * Unregister the listener. This method will perform a no-op if the sensor is not registered.
+ */
+ public void unregisterListener() {
+ if (mTestSensorEventListener == null) {
+ Log.w(LOG_TAG, "No listener registered, returning.");
+ return;
+ }
+
+ mSensorManager.unregisterListener(mTestSensorEventListener, mSensor);
+ mTestSensorEventListener = null;
+ }
+
+ /**
+ * Wait for a specific number of events.
+ */
+ public void waitForEvents(int eventCount) {
+ if (mTestSensorEventListener == null) {
+ Log.w(LOG_TAG, "No listener registered, returning.");
+ return;
+ }
+
+ mTestSensorEventListener.waitForEvents(eventCount);
+ }
+
+ /**
+ * Wait for a specific duration.
+ */
+ public void waitForEvents(long duration, TimeUnit timeUnit) {
+ if (mTestSensorEventListener == null) {
+ Log.w(LOG_TAG, "No listener registered, returning.");
+ return;
+ }
+
+ mTestSensorEventListener.waitForEvents(duration, timeUnit);
+ }
+
+ /**
+ * Call {@link SensorManager#flush(SensorEventListener)}. This method will perform a no-op if
+ * the sensor is not registered.
+ *
+ * @throws AssertionError if {@link SensorManager#flush(SensorEventListener)} returns false
+ */
+ public void startFlush() {
+ if (mTestSensorEventListener == null) {
+ return;
+ }
+
+ String message = SensorCtsHelper.formatAssertionMessage(mSensor, "Flush", mRateUs,
+ mMaxBatchReportLatencyUs);
+ Assert.assertTrue(message, mSensorManager.flush(mTestSensorEventListener));
+ }
+
+ /**
+ * Wait for {@link SensorEventListener2#onFlushCompleted(Sensor)} to be called. This method will
+ * perform a no-op if the sensor is not registered.
+ *
+ * @throws AssertionError if there is a time out
+ * @throws InterruptedException if the thread was interrupted
+ */
+ public void waitForFlushCompleted() throws InterruptedException {
+ if (mTestSensorEventListener == null) {
+ return;
+ }
+
+ mTestSensorEventListener.waitForFlushComplete();
+ }
+
+ /**
+ * Call {@link SensorManager#flush(SensorEventListener)} and wait for
+ * {@link SensorEventListener2#onFlushCompleted(Sensor)} to be called. This method will perform
+ * a no-op if the sensor is not registered.
+ *
+ * @throws AssertionError if {@link SensorManager#flush(SensorEventListener)} returns false or
+ * if there is a time out
+ * @throws InterruptedException if the thread was interrupted
+ */
+ public void flush() throws InterruptedException {
+ if (mTestSensorEventListener == null) {
+ return;
+ }
+
+ startFlush();
+ waitForFlushCompleted();
+ }
+
+ /**
+ * Register a listener, wait for a specific number of events, and then unregister the listener.
+ */
+ public void runSensor(TestSensorEventListener listener, int eventCount) {
+ if (mTestSensorEventListener != null) {
+ Log.w(LOG_TAG, "Listener already registered, returning.");
+ return;
+ }
+
+ try {
+ registerListener(listener);
+ waitForEvents(eventCount);
+ } finally {
+ unregisterListener();
+ }
+ }
+
+ /**
+ * Register a listener, wait for a specific duration, and then unregister the listener.
+ */
+ public void runSensor(TestSensorEventListener listener, long duration, TimeUnit timeUnit) {
+ if (mTestSensorEventListener != null) {
+ Log.w(LOG_TAG, "Listener already registered, returning.");
+ return;
+ }
+
+ try {
+ registerListener(listener);
+ waitForEvents(duration, timeUnit);
+ } finally {
+ unregisterListener();
+ }
+ }
+
+ /**
+ * Get the sensor under test.
+ */
+ public Sensor getSensor() {
+ return mSensor;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
new file mode 100644
index 0000000..ae7ea04
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers;
+
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+import android.os.SystemClock;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * A {@link TestSensorEventListener} which performs validations on the received events on the fly.
+ * This class is useful for long running tests where it is not practical to store all the events to
+ * be processed after.
+ */
+public class ValidatingSensorEventListener extends TestSensorEventListener {
+
+ private final Collection<ISensorVerification> mVerifications =
+ new LinkedList<ISensorVerification>();
+
+ /**
+ * Construct a {@link ValidatingSensorEventListener} with an additional
+ * {@link SensorEventListener2}.
+ */
+ public ValidatingSensorEventListener(SensorEventListener2 listener,
+ ISensorVerification ... verifications) {
+ super(listener);
+ for (ISensorVerification verification : verifications) {
+ mVerifications.add(verification);
+ }
+ }
+
+ /**
+ * Construct a {@link ValidatingSensorEventListener} with an additional
+ * {@link SensorEventListener2}.
+ */
+ public ValidatingSensorEventListener(SensorEventListener2 listener,
+ Collection<ISensorVerification> verifications) {
+ this(listener, verifications.toArray(new ISensorVerification[0]));
+ }
+
+ /**
+ * Construct a {@link ValidatingSensorEventListener}.
+ */
+ public ValidatingSensorEventListener(ISensorVerification ... verifications) {
+ this(null, verifications);
+ }
+
+ /**
+ * Construct a {@link ValidatingSensorEventListener}.
+ */
+ public ValidatingSensorEventListener(Collection<ISensorVerification> verifications) {
+ this(null, verifications);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ TestSensorEvent testEvent = new TestSensorEvent(event, SystemClock.elapsedRealtimeNanos());
+ for (ISensorVerification verification : mVerifications) {
+ verification.addSensorEvent(testEvent);
+ }
+ super.onSensorChanged(event);
+ }
+}
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
deleted file mode 100644
index 3730f4b..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 7a3c450..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 4b92168..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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
deleted file mode 100644
index bb43b01..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import android.content.Context;
-
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-/**
- * Test Operation class that validates the ordering of sensor events.
- */
-public class VerifyEventOrderingOperation extends SensorTestOperation {
- private SensorManagerTestVerifier mSensor;
-
- public VerifyEventOrderingOperation(
- Context context,
- int sensorType,
- int samplingRateInUs,
- int reportLatencyInUs) {
- mSensor = new SensorManagerTestVerifier(
- context,
- 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;
- // allow two identical timestamps to be considered in order, in case the resolution of
- // the timestamp is not granular enough
- if(previousTimestamp > timestamp) {
- String message = SensorCtsHelper.formatAssertionMessage(
- "Ordering",
- this,
- mSensor.getUnderlyingSensor(),
- "position:%d, previous:%d, timestamp:%d",
- i,
- previousTimestamp,
- timestamp);
- Assert.fail(message);
- }
- }
- }
-}
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
deleted file mode 100644
index 6f1c03a..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import android.content.Context;
-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.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(
- Context context,
- 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(context, sensorType);
- mSensor = new SensorManagerTestVerifier(
- context,
- 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);
- Assert.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
deleted file mode 100644
index 3cdffe0..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import android.content.Context;
-
-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.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(
- Context context,
- 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(context, sensorType);
- mSensor = new SensorManagerTestVerifier(
- context,
- 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);
- Assert.fail(message);
- }
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMeasurementsOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMeasurementsOperation.java
deleted file mode 100644
index d0c991b3..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMeasurementsOperation.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 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 junit.framework.Assert;
-
-import android.content.Context;
-
-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 java.security.InvalidParameterException;
-
-/**
- * Test Operation class that validates the measurements of a a given sensor.
- * The operation relies on the number of axes each sensor type reports.
- * The verification calculates the mean for each axis on the measurements, and verifies that they
- * fall into the expected intervals.
- */
-public class VerifyMeasurementsOperation extends SensorTestOperation {
- private final SensorManagerTestVerifier mSensor;
- private final int mAxisCount;
- private final double mReferenceValues[];
- private final double mThreshold;
-
- public VerifyMeasurementsOperation(
- Context context,
- int sensorType,
- int samplingRateInUs,
- int reportLatencyInUs,
- double referenceValues[],
- float threshold) {
- mAxisCount = SensorTestInformation.getAxisCount(sensorType);
- if(mAxisCount != referenceValues.length) {
- throw new InvalidParameterException(
- String.format("%d reference values are expected.", mAxisCount));
- }
- mSensor = new SensorManagerTestVerifier(
- context,
- sensorType,
- samplingRateInUs,
- reportLatencyInUs);
- // set expectations
- mReferenceValues = referenceValues;
- mThreshold = threshold;
- }
-
- @Override
- public void doWork() {
- final String VALUE_SEPARATOR = ", ";
- TestSensorEvent events[] = mSensor.collectEvents(100);
- double measuredValues[] = new double[mReferenceValues.length];
- SensorCtsHelper.getMeans(events, measuredValues);
-
- boolean success = true;
- StringBuilder referenceValuesBuilder = new StringBuilder();
- StringBuilder measuredValuesBuilder = new StringBuilder();
- for(int i = 0; i < mReferenceValues.length; i++) {
- double reference = mReferenceValues[i];
- double measurement = measuredValues[i];
- double delta = Math.abs(reference - measurement);
- success &= (delta <= mThreshold);
- referenceValuesBuilder.append(reference);
- referenceValuesBuilder.append(VALUE_SEPARATOR);
- measuredValuesBuilder.append(measurement);
- measuredValuesBuilder.append(VALUE_SEPARATOR);
- }
- if(!success) {
- String message = SensorCtsHelper.formatAssertionMessage(
- "Measurement",
- this,
- mSensor.getUnderlyingSensor(),
- "expected:( %s), threshold:%f, actual: ( %s)",
- referenceValuesBuilder.toString(),
- mThreshold,
- measuredValuesBuilder.toString());
- Assert.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
deleted file mode 100644
index cce3412..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyNormOperation.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import android.content.Context;
-
-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;
-
-/**
- * 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(
- Context context,
- int sensorType,
- int samplingRateInUs,
- float referenceValue,
- float threshold) {
- mSensor = new SensorManagerTestVerifier(
- context,
- sensorType,
- samplingRateInUs,
- 0 /*reportLatencyInUs*/);
- // set expectations
- mAxisCount = SensorTestInformation.getAxisCount(mSensor.getUnderlyingSensor().getType());
- 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());
- Assert.assertTrue(message, Math.abs(mReferenceValue - norm) <= mThreshold);
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifySignumOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifySignumOperation.java
deleted file mode 100644
index 0ccf92a..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifySignumOperation.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 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 junit.framework.Assert;
-
-import android.content.Context;
-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 java.security.InvalidParameterException;
-
-/**
- * Test Operation class that validates the sign of measurements of a a given sensor.
- * The operation relies in the number of axes each sensor type reports.
- */
-public class VerifySignumOperation extends SensorTestOperation {
- private final SensorManagerTestVerifier mSensor;
- private final int mAxisCount;
- private final double mReferenceValues[];
- private final double mNoiseThreshold;
-
- /**
- * @param noiseThreshold Defines the threshold that needs to be crossed to consider a
- * measurement different from zero
- */
- public VerifySignumOperation(
- Context context,
- int sensorType,
- int samplingRateInUs,
- double referenceValues[],
- double noiseThreshold) {
- mAxisCount = SensorTestInformation.getAxisCount(sensorType);
- if(mAxisCount != referenceValues.length) {
- throw new InvalidParameterException(
- String.format("%d reference values are expected.", mAxisCount));
- }
- for(int i = 0; i < referenceValues.length; ++i) {
- double value = referenceValues[i];
- if(value != 0 && value != -1 && value != +1) {
- throw new InvalidParameterException(
- "A ReferenceValue can only be one of the following: -1, 0, +1");
- }
- }
- mSensor = new SensorManagerTestVerifier(
- context,
- sensorType,
- samplingRateInUs,
- 0 /*reportLatencyInUs*/);
- // set expectations
- mReferenceValues = referenceValues;
- mNoiseThreshold = noiseThreshold;
- }
-
- @Override
- public void doWork() {
- final String VALUE_SEPARATOR = ", ";
- TestSensorEvent events[] = mSensor.collectEvents(100);
- double measuredValues[] = new double[mReferenceValues.length];
- SensorCtsHelper.getMeans(events, measuredValues);
-
- boolean success = true;
- StringBuilder referenceValuesBuilder = new StringBuilder();
- StringBuilder measuredValuesBuilder = new StringBuilder();
- for(int i = 0; i < mReferenceValues.length; i++) {
- double reference = mReferenceValues[i];
- double measurement = measuredValues[i];
- if(reference == 0) {
- success &= Math.abs(measurement) < mNoiseThreshold;
- } else {
- double combinedValue = reference * measurement;
- if(combinedValue < mNoiseThreshold) {
- combinedValue = 0;
- }
- success &= combinedValue > 0;
- }
- referenceValuesBuilder.append(reference);
- referenceValuesBuilder.append(VALUE_SEPARATOR);
- measuredValuesBuilder.append(measurement);
- measuredValuesBuilder.append(VALUE_SEPARATOR);
- }
- if(!success) {
- String message = SensorCtsHelper.formatAssertionMessage(
- "Measurement",
- this,
- mSensor.getUnderlyingSensor(),
- "expected:( %s), actual:( %s), noiseThreshold:%f",
- referenceValuesBuilder.toString(),
- measuredValuesBuilder.toString(),
- mNoiseThreshold);
- Assert.fail(message);
- }
- }
-}
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
deleted file mode 100644
index 89cff94..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import android.content.Context;
-
-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.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(
- Context context,
- int sensorType,
- int samplingRateInUs,
- int reportLatencyInUs,
- float expectedStandardDeviation) {
- mSensor = new SensorManagerTestVerifier(
- context,
- sensorType,
- samplingRateInUs,
- reportLatencyInUs);
- // set expectations
- mAxisCount = SensorTestInformation.getAxisCount(mSensor.getUnderlyingSensor().getType());
- 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);
- Assert.fail(message);
- }
- }
- }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AbstractSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AbstractSensorOperation.java
new file mode 100644
index 0000000..5b969f2
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AbstractSensorOperation.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+/**
+ * A {@link ISensorOperation} which contains a common implementation for gathering
+ * {@link SensorStats}.
+ */
+public abstract class AbstractSensorOperation implements ISensorOperation {
+
+ private final SensorStats mStats = new SensorStats();
+
+ /**
+ * Wrapper around {@link SensorStats#addSensorStats(String, SensorStats)}
+ */
+ protected void addSensorStats(String key, SensorStats stats) {
+ mStats.addSensorStats(key, stats);
+ }
+
+ /**
+ * Wrapper around {@link SensorStats#addSensorStats(String, SensorStats)} that allows an index
+ * to be added. This is useful for {@link ISensorOperation}s that have many iterations or child
+ * operations. The key added is in the form {@code key + "_" + index} where index may be zero
+ * padded.
+ */
+ protected void addSensorStats(String key, int index, SensorStats stats) {
+ addSensorStats(String.format("%s_%03d", key, index), stats);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SensorStats getStats() {
+ return mStats;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract ISensorOperation clone();
+
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
new file mode 100644
index 0000000..95f1248
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.cts.helpers.SensorStats;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An {@link ISensorOperation} which performs another {@link ISensorOperation} and then wakes up
+ * after a specified period of time and waits for the child operation to complete.
+ * <p>
+ * This operation can be used to allow the device to go to sleep and wake it up after a specified
+ * period of time. After the device wakes up, this operation will hold a wake lock until the child
+ * operation finishes. This operation will not force the device into suspend, so if another
+ * operation is holding a wake lock, the device will stay awake. Also, if the child operation
+ * finishes before the specified period, this operation return when the child operation finishes
+ * but wake the device one time at the specified period.
+ * </p>
+ */
+public class AlarmOperation extends AbstractSensorOperation {
+ private static final String ACTION = "AlarmOperationAction";
+ private static final String WAKE_LOCK_TAG = "AlarmOperationWakeLock";
+
+ private final ISensorOperation mOperation;
+ private final Context mContext;
+ private final long mSleepDuration;
+ private final TimeUnit mTimeUnit;
+
+ private boolean mCompleted = false;
+ private WakeLock mWakeLock = null;
+
+ /**
+ * Constructor for {@link DelaySensorOperation}
+ *
+ * @param operation the child {@link ISensorOperation} to perform after the delay
+ * @param context the context used to access the alarm manager
+ * @param sleepDuration the amount of time to sleep
+ * @param timeUnit the unit of the duration
+ */
+ public AlarmOperation(ISensorOperation operation, Context context, long sleepDuration,
+ TimeUnit timeUnit) {
+ mOperation = operation;
+ mContext = context;
+ mSleepDuration = sleepDuration;
+ mTimeUnit = timeUnit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() {
+ // Start alarm
+ IntentFilter intentFilter = new IntentFilter(ACTION);
+ BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ acquireWakeLock();
+ }
+ };
+ mContext.registerReceiver(receiver, intentFilter);
+
+ AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ long wakeupTimeMs = (System.currentTimeMillis()
+ + TimeUnit.MILLISECONDS.convert(mSleepDuration, mTimeUnit));
+ Intent intent = new Intent(ACTION);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ am.setExact(AlarmManager.RTC_WAKEUP, wakeupTimeMs, pendingIntent);
+
+ // Execute operation
+ try {
+ mOperation.execute();
+ } finally {
+ releaseWakeLock();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SensorStats getStats() {
+ return mOperation.getStats();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AlarmOperation clone() {
+ return new AlarmOperation(mOperation, mContext, mSleepDuration, mTimeUnit);
+ }
+
+ /**
+ * Method that acquires a wake lock if a wake lock has not already been acquired and if the
+ * operation has not yet completed.
+ */
+ private synchronized void acquireWakeLock() {
+ // Don't acquire wake lock if the operation has already completed.
+ if (mCompleted == true || mWakeLock != null) {
+ return;
+ }
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
+ }
+
+ /**
+ * Method that releases the wake lock if it has been acquired.
+ */
+ private synchronized void releaseWakeLock() {
+ mCompleted = true;
+ if (mWakeLock != null) {
+ mWakeLock.release();
+ }
+ mWakeLock = null;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
new file mode 100644
index 0000000..bf43189
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An {@link ISensorOperation} which delays for a specified period of time before performing another
+ * {@link ISensorOperation}.
+ */
+public class DelaySensorOperation implements ISensorOperation {
+ private final ISensorOperation mOperation;
+ private final long mDelay;
+ private final TimeUnit mTimeUnit;
+
+ /**
+ * Constructor for {@link DelaySensorOperation}
+ *
+ * @param operation the child {@link ISensorOperation} to perform after the delay
+ * @param delay the amount of time to delay
+ * @param timeUnit the unit of the delay
+ */
+ public DelaySensorOperation(ISensorOperation operation, long delay, TimeUnit timeUnit) {
+ if (operation == null || timeUnit == null) {
+ throw new IllegalArgumentException("Arguments cannot be null");
+ }
+ mOperation = operation;
+ mDelay = delay;
+ mTimeUnit = timeUnit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() {
+ sleep(mDelay, mTimeUnit);
+ mOperation.execute();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SensorStats getStats() {
+ return mOperation.getStats();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public DelaySensorOperation clone() {
+ return new DelaySensorOperation(mOperation.clone(), mDelay, mTimeUnit);
+ }
+
+ /**
+ * Helper method to sleep for a given number of ns. Exposed for unit testing.
+ */
+ void sleep(long delay, TimeUnit timeUnit) {
+ SensorCtsHelper.sleep(delay, timeUnit);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/FakeSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/FakeSensorOperation.java
new file mode 100644
index 0000000..bb64dfa
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/FakeSensorOperation.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import junit.framework.Assert;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A fake {@ISensorOperation} that will run for a specified time and then pass or fail. Useful when
+ * debugging the framework.
+ */
+public class FakeSensorOperation extends AbstractSensorOperation {
+ private static final int NANOS_PER_MILLI = 1000000;
+
+ private final boolean mFail;
+ private final long mDelay;
+ private final TimeUnit mTimeUnit;
+
+ /**
+ * Constructor for {@link FakeSensorOperation} that passes
+ */
+ public FakeSensorOperation(long delay, TimeUnit timeUnit) {
+ this(false, delay, timeUnit);
+ }
+
+ /**
+ * Constructor for {@link FakeSensorOperation}
+ */
+ public FakeSensorOperation(boolean fail, long delay, TimeUnit timeUnit) {
+ if (timeUnit == null) {
+ throw new IllegalArgumentException("Arguments cannot be null");
+ }
+ mFail = fail;
+ mDelay = delay;
+ mTimeUnit = timeUnit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() {
+ long delayNs = TimeUnit.NANOSECONDS.convert(mDelay, mTimeUnit);
+ try {
+ Thread.sleep(delayNs / NANOS_PER_MILLI, (int) (delayNs % NANOS_PER_MILLI));
+ getStats().addValue("executed", true);
+ if (mFail) {
+ doFail();
+ }
+ }catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public FakeSensorOperation clone() {
+ return new FakeSensorOperation(mFail, mDelay, mTimeUnit);
+ }
+
+ /**
+ * Fails the operation.
+ */
+ protected void doFail() {
+ String msg = "FakeSensorOperation failed";
+ getStats().addValue(SensorStats.ERROR, msg);
+ Assert.fail(msg);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
new file mode 100644
index 0000000..4ae56ea
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+/**
+ * Interface used by all sensor operations. This allows for complex operations such as chaining
+ * operations together or running operations in parallel.
+ * <p>
+ * Certain restrictions exist for {@link ISensorOperation}s:
+ * <p><ul>
+ * <li>{@link #execute()} should only be called once and behavior is undefined for subsequent calls.
+ * Once {@link #execute()} is called, the class should not be modified. Generally, there is no
+ * synchronization for operations.</li>
+ * <li>{@link #getStats()} should only be called after {@link #execute()}. If it is called before,
+ * the returned value is undefined.</li>
+ * <li>{@link #clone()} may be called any time and should return an operation with the same
+ * parameters as the original.</li>
+ * </ul>
+ */
+public interface ISensorOperation {
+
+ /**
+ * Executes the sensor operation. This may throw {@link RuntimeException}s such as
+ * {@link AssertionError}s.
+ */
+ public void execute();
+
+ /**
+ * Get the stats for the operation.
+ *
+ * @return The {@link SensorStats} for the operation.
+ */
+ public SensorStats getStats();
+
+ /**
+ * Clones the {@link ISensorOperation}. The implementation should also clone all child
+ * operations, so that a cloned operation will run with the exact same parameters as the
+ * original. The stats should not be cloned.
+ *
+ * @return The cloned {@link ISensorOperation}
+ */
+ public ISensorOperation clone();
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
new file mode 100644
index 0000000..4cca428
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
@@ -0,0 +1,257 @@
+/*
+ * 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.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorOperation} that executes a set of children {@link ISensorOperation}s in parallel.
+ * The children are run in parallel but are given an index label in the order they are added. This
+ * class can be combined to compose complex {@link ISensorOperation}s.
+ */
+public class ParallelSensorOperation extends AbstractSensorOperation {
+ public static final String STATS_TAG = "parallel";
+
+ private static final String TAG = "ParallelSensorOperation";
+ private static final int NANOS_PER_MILLI = 1000000;
+
+ private final List<ISensorOperation> mOperations = new LinkedList<ISensorOperation>();
+ private final Long mTimeout;
+ private final TimeUnit mTimeUnit;
+
+ /**
+ * Constructor for the {@link ParallelSensorOperation} without a timeout.
+ */
+ public ParallelSensorOperation() {
+ mTimeout = null;
+ mTimeUnit = null;
+ }
+
+ /**
+ * Constructor for the {@link ParallelSensorOperation} with a timeout.
+ */
+ public ParallelSensorOperation(long timeout, TimeUnit timeUnit) {
+ if (timeUnit == null) {
+ throw new IllegalArgumentException("Arguments cannot be null");
+ }
+ mTimeout = timeout;
+ mTimeUnit = timeUnit;
+ }
+
+ /**
+ * Add a set of {@link ISensorOperation}s.
+ */
+ public void add(ISensorOperation ... operations) {
+ for (ISensorOperation operation : operations) {
+ if (operation == null) {
+ throw new IllegalArgumentException("Arguments cannot be null");
+ }
+ mOperations.add(operation);
+ }
+ }
+
+ /**
+ * Executes the {@link ISensorOperation}s in parallel. If an exception occurs one or more
+ * operations, the first exception will be thrown once all operations are completed.
+ */
+ @Override
+ public void execute() {
+ Long timeoutTimeNs = null;
+ if (mTimeout != null && mTimeUnit != null) {
+ timeoutTimeNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
+ }
+
+ List<OperationThread> threadPool = new ArrayList<OperationThread>(mOperations.size());
+ for (final ISensorOperation operation : mOperations) {
+ OperationThread thread = new OperationThread(operation);
+ thread.start();
+ threadPool.add(thread);
+ }
+
+ List<Integer> timeoutIndices = new ArrayList<Integer>();
+ List<OperationExceptionInfo> exceptions = new ArrayList<OperationExceptionInfo>();
+ Throwable earliestException = null;
+ Long earliestExceptionTime = null;
+
+ for (int i = 0; i < threadPool.size(); i++) {
+ OperationThread thread = threadPool.get(i);
+ join(thread, timeoutTimeNs);
+ if (thread.isAlive()) {
+ timeoutIndices.add(i);
+ thread.interrupt();
+ }
+
+ Throwable exception = thread.getException();
+ Long exceptionTime = thread.getExceptionTime();
+ if (exception != null && exceptionTime != null) {
+ if (exception instanceof AssertionError) {
+ exceptions.add(new OperationExceptionInfo(i, (AssertionError) exception));
+ }
+ if (earliestExceptionTime == null || exceptionTime < earliestExceptionTime) {
+ earliestException = exception;
+ earliestExceptionTime = exceptionTime;
+ }
+ }
+
+ addSensorStats(STATS_TAG, i, thread.getSensorOperation().getStats());
+ }
+
+ if (earliestException == null) {
+ if (timeoutIndices.size() > 0) {
+ Assert.fail(getTimeoutMessage(timeoutIndices));
+ }
+ } else if (earliestException instanceof AssertionError) {
+ String msg = getExceptionMessage(exceptions, timeoutIndices);
+ getStats().addValue(SensorStats.ERROR, msg);
+ throw new AssertionError(msg, earliestException);
+ } else if (earliestException instanceof RuntimeException) {
+ throw (RuntimeException) earliestException;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ParallelSensorOperation clone() {
+ ParallelSensorOperation operation = new ParallelSensorOperation();
+ for (ISensorOperation subOperation : mOperations) {
+ operation.add(subOperation.clone());
+ }
+ return operation;
+ }
+
+ /**
+ * Helper method that joins a thread at a given time in the future.
+ */
+ private void join(Thread thread, Long timeoutTimeNs) {
+ try {
+ if (timeoutTimeNs == null) {
+ thread.join();
+ } else {
+ // Cap wait time to 1ns so that join doesn't block indefinitely.
+ long waitTimeNs = Math.max(timeoutTimeNs - System.nanoTime(), 1);
+ thread.join(waitTimeNs / NANOS_PER_MILLI, (int) waitTimeNs % NANOS_PER_MILLI);
+ }
+ } catch (InterruptedException e) {
+ // Log and ignore
+ Log.w(TAG, "Thread interrupted during join, operations may timeout before expected"
+ + " time");
+ }
+ }
+
+ /**
+ * Helper method for joining the exception messages used in assertions.
+ */
+ private String getExceptionMessage(List<OperationExceptionInfo> exceptions,
+ List<Integer> timeoutIndices) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(exceptions.get(0).toString());
+ for (int i = 1; i < exceptions.size(); i++) {
+ sb.append(", ").append(exceptions.get(i).toString());
+ }
+ if (timeoutIndices.size() > 0) {
+ sb.append(", ").append(getTimeoutMessage(timeoutIndices));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Helper method for formatting the operation timed out message used in assertions
+ */
+ private String getTimeoutMessage(List<Integer> indices) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Operation");
+ if (indices.size() != 1) {
+ sb.append("s");
+ }
+ sb.append(" ").append(indices.get(0));
+ for (int i = 1; i < indices.size(); i++) {
+ sb.append(", ").append(indices.get(i));
+ }
+ sb.append(" timed out");
+ return sb.toString();
+ }
+
+ /**
+ * Helper class for holding operation index and exception
+ */
+ private class OperationExceptionInfo {
+ private final int mIndex;
+ private final AssertionError mException;
+
+ public OperationExceptionInfo(int index, AssertionError exception) {
+ mIndex = index;
+ mException = exception;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Operation %d failed: \"%s\"", mIndex, mException.getMessage());
+ }
+ }
+
+ /**
+ * Helper class to run the {@link ISensorOperation} in its own thread.
+ */
+ private class OperationThread extends Thread {
+ final private ISensorOperation mOperation;
+ private Throwable mException = null;
+ private Long mExceptionTime = null;
+
+ public OperationThread(ISensorOperation operation) {
+ mOperation = operation;
+ }
+
+ /**
+ * Run the thread catching {@link RuntimeException}s and {@link AssertionError}s and
+ * the time it happened.
+ */
+ @Override
+ public void run() {
+ try {
+ mOperation.execute();
+ } catch (AssertionError e) {
+ mExceptionTime = System.nanoTime();
+ mException = e;
+ } catch (RuntimeException e) {
+ mExceptionTime = System.nanoTime();
+ mException = e;
+ }
+ }
+
+ public ISensorOperation getSensorOperation() {
+ return mOperation;
+ }
+
+ public Throwable getException() {
+ return mException;
+ }
+
+ public Long getExceptionTime() {
+ return mExceptionTime;
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
new file mode 100644
index 0000000..5e023e5
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
@@ -0,0 +1,73 @@
+/*
+ * 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.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+/**
+ * A {@link ISensorOperation} that executes a single {@link ISensorOperation} a given number of
+ * times. This class can be combined to compose complex {@link ISensorOperation}s.
+ */
+public class RepeatingSensorOperation extends AbstractSensorOperation {
+ public static final String STATS_TAG = "repeating";
+
+ private final ISensorOperation mOperation;
+ private final int mIterations;
+
+ /**
+ * Constructor for {@link RepeatingSensorOperation}.
+ *
+ * @param operation the {@link ISensorOperation} to run.
+ * @param iterations the number of iterations to run the operation for.
+ */
+ public RepeatingSensorOperation(ISensorOperation operation, int iterations) {
+ if (operation == null) {
+ throw new IllegalArgumentException("Arguments cannot be null");
+ }
+ mOperation = operation;
+ mIterations = iterations;
+
+ }
+
+ /**
+ * Executes the {@link ISensorOperation}s the given number of times. If an exception occurs
+ * in one iterations, it is thrown and all subsequent iterations will not run.
+ */
+ @Override
+ public void execute() {
+ for(int i = 0; i < mIterations; ++i) {
+ ISensorOperation operation = mOperation.clone();
+ try {
+ operation.execute();
+ } catch (AssertionError e) {
+ String msg = String.format("Iteration %d failed: \"%s\"", i, e.getMessage());
+ getStats().addValue(SensorStats.ERROR, msg);
+ throw new AssertionError(msg, e);
+ } finally {
+ addSensorStats(STATS_TAG, i, operation.getStats());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public RepeatingSensorOperation clone() {
+ return new RepeatingSensorOperation(mOperation.clone(), mIterations);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
new file mode 100644
index 0000000..7148454
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import junit.framework.TestCase;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for the primitive {@link ISensorOperation}s including {@link DelaySensorOperation},
+ * {@link ParallelSensorOperation}, {@link RepeatingSensorOperation} and
+ * {@link SequentialSensorOperation}.
+ */
+public class SensorOperationTest extends TestCase {
+ private static final int THRESHOLD_MS = 50;
+
+ /**
+ * Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class
+ * rely on this operation.
+ */
+ public void testFakeSensorOperation() {
+ final int opDurationMs = 100;
+
+ ISensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS);
+
+ assertFalse(op.getStats().flatten().containsKey("executed"));
+ long start = System.currentTimeMillis();
+ op.execute();
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(Math.abs(opDurationMs - duration) < THRESHOLD_MS);
+ assertTrue(op.getStats().flatten().containsKey("executed"));
+
+ op = new FakeSensorOperation(true, 0, TimeUnit.MILLISECONDS);
+ try {
+ op.execute();
+ fail("AssertionError expected");
+ } catch (AssertionError e) {
+ // Expected
+ }
+ assertTrue(op.getStats().flatten().keySet().contains(SensorStats.ERROR));
+ }
+
+ /**
+ * Test that the {@link DelaySensorOperation} functions correctly.
+ */
+ public void testDelaySensorOperation() {
+ final int opDurationMs = 500;
+ final int subOpDurationMs = 100;
+
+ FakeSensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS);
+ ISensorOperation op = new DelaySensorOperation(subOp, opDurationMs, TimeUnit.MILLISECONDS);
+
+ long start = System.currentTimeMillis();
+ op.execute();
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(Math.abs(opDurationMs + subOpDurationMs - duration) < THRESHOLD_MS);
+ }
+
+ /**
+ * Test that the {@link ParallelSensorOperation} functions correctly.
+ */
+ public void testParallelSensorOperation() {
+ final int subOpCount = 100;
+ final int subOpDurationMs = 500;
+
+ ParallelSensorOperation op = new ParallelSensorOperation();
+ for (int i = 0; i < subOpCount; i++) {
+ ISensorOperation subOp = new FakeSensorOperation(subOpDurationMs,
+ TimeUnit.MILLISECONDS);
+ op.add(subOp);
+ }
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ long start = System.currentTimeMillis();
+ op.execute();
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(Math.abs(subOpDurationMs - duration) < THRESHOLD_MS);
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(subOpCount, statsKeys.size());
+ for (int i = 0; i < subOpCount; i++) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ }
+ }
+
+ /**
+ * Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in
+ * a child operation.
+ */
+ public void testParallelSensorOperation_fail() {
+ final int subOpCount = 100;
+
+ ParallelSensorOperation op = new ParallelSensorOperation();
+ for (int i = 0; i < subOpCount; i++) {
+ // Trigger failures in the 5th, 55th operations at t=5ms, t=55ms
+ ISensorOperation subOp = new FakeSensorOperation(i % 50 == 5, i, TimeUnit.MILLISECONDS);
+ op.add(subOp);
+ }
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ try {
+ op.execute();
+ fail("AssertionError expected");
+ } catch (AssertionError e) {
+ // Expected
+ System.out.println(e.getMessage());
+ // TODO: Verify that the exception rethrown was at t=5ms.
+ }
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(subOpCount + 3, statsKeys.size());
+ for (int i = 0; i < subOpCount; i++) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ if (i % 50 == 5) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%s%s",
+ ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER,
+ SensorStats.ERROR)));
+ }
+
+ }
+ assertTrue(statsKeys.contains(SensorStats.ERROR));
+ }
+
+ /**
+ * Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the
+ * timeout.
+ */
+ public void testParallelSensorOperation_timeout() {
+ final int subOpCount = 100;
+
+ ParallelSensorOperation op = new ParallelSensorOperation(100, TimeUnit.MILLISECONDS);
+ for (int i = 0; i < subOpCount; i++) {
+ // Trigger timeouts in the 5th, 55th operations (5 seconds vs 0 seconds)
+ ISensorOperation subOp = new FakeSensorOperation(i % 50 == 5 ? 5 : 0, TimeUnit.SECONDS);
+ op.add(subOp);
+ }
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ try {
+ op.execute();
+ fail("AssertionError expected");
+ } catch (AssertionError e) {
+ // Expected
+ System.out.println(e.getMessage());
+ // TODO: Verify that the exception rethrown was at t=5ms.
+ }
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(subOpCount - 2, statsKeys.size());
+ for (int i = 0; i < subOpCount; i++) {
+ if (i % 50 != 5) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ }
+ }
+ }
+
+ /**
+ * Test that the {@link RepeatingSensorOperation} functions correctly.
+ */
+ public void testRepeatingSensorOperation() {
+ final int iterations = 10;
+ final int subOpDurationMs = 100;
+
+ ISensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS);
+ ISensorOperation op = new RepeatingSensorOperation(subOp, iterations);
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ long start = System.currentTimeMillis();
+ op.execute();
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(Math.abs(subOpDurationMs * iterations - duration) < THRESHOLD_MS);
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(iterations, statsKeys.size());
+ for (int i = 0; i < iterations; i++) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ }
+ }
+
+ /**
+ * Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in
+ * a child operation.
+ */
+ public void testRepeatingSensorOperation_fail() {
+ final int iterations = 100;
+ final int failCount = 75;
+
+ ISensorOperation subOp = new FakeSensorOperation(0, TimeUnit.MILLISECONDS) {
+ private int mExecutedCount = 0;
+ private SensorStats mFakeStats = new SensorStats();
+
+ @Override
+ public void execute() {
+ super.execute();
+ mExecutedCount++;
+
+ if (failCount == mExecutedCount) {
+ doFail();
+ }
+ }
+
+ @Override
+ public FakeSensorOperation clone() {
+ // Don't clone
+ mFakeStats = new SensorStats();
+ return this;
+ }
+
+ @Override
+ public SensorStats getStats() {
+ return mFakeStats;
+ }
+ };
+ ISensorOperation op = new RepeatingSensorOperation(subOp, iterations);
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ try {
+ op.execute();
+ fail("AssertionError expected");
+ } catch (AssertionError e) {
+ // Expected
+ System.out.println(e.getMessage());
+ }
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(failCount + 2, statsKeys.size());
+ for (int i = 0; i < failCount; i++) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ }
+ assertTrue(statsKeys.contains(String.format("%s_%03d%s%s",
+ RepeatingSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER,
+ SensorStats.ERROR)));
+ assertTrue(statsKeys.contains(SensorStats.ERROR));
+ }
+
+ /**
+ * Test that the {@link SequentialSensorOperation} functions correctly.
+ */
+ public void testSequentialSensorOperation() {
+ final int subOpCount = 10;
+ final int subOpDurationMs = 100;
+
+ SequentialSensorOperation op = new SequentialSensorOperation();
+ for (int i = 0; i < subOpCount; i++) {
+ ISensorOperation subOp = new FakeSensorOperation(subOpDurationMs,
+ TimeUnit.MILLISECONDS);
+ op.add(subOp);
+ }
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ long start = System.currentTimeMillis();
+ op.execute();
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(Math.abs(subOpDurationMs * subOpCount - duration) < THRESHOLD_MS);
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(subOpCount, statsKeys.size());
+ for (int i = 0; i < subOpCount; i++) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ }
+ }
+
+ /**
+ * Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in
+ * a child operation.
+ */
+ public void testSequentialSensorOperation_fail() {
+ final int subOpCount = 100;
+ final int failCount = 75;
+
+ SequentialSensorOperation op = new SequentialSensorOperation();
+ for (int i = 0; i < subOpCount; i++) {
+ // Trigger a failure in the 75th operation only
+ ISensorOperation subOp = new FakeSensorOperation(i + 1 == failCount, 0,
+ TimeUnit.MILLISECONDS);
+ op.add(subOp);
+ }
+
+ Set<String> statsKeys = op.getStats().flatten().keySet();
+ assertEquals(0, statsKeys.size());
+
+ try {
+ op.execute();
+ fail("AssertionError expected");
+ } catch (AssertionError e) {
+ // Expected
+ System.out.println(e.getMessage());
+ }
+
+ statsKeys = op.getStats().flatten().keySet();
+ assertEquals(failCount + 2, statsKeys.size());
+ for (int i = 0; i < failCount; i++) {
+ assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+ SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+ }
+ assertTrue(statsKeys.contains(String.format("%s_%03d%s%s",
+ SequentialSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER,
+ SensorStats.ERROR)));
+ assertTrue(statsKeys.contains(SensorStats.ERROR));
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
new file mode 100644
index 0000000..050a8f6
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
@@ -0,0 +1,77 @@
+/*
+ * 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.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link ISensorOperation} that executes a set of children {@link ISensorOperation}s in a
+ * sequence. The children are executed in the order they are added. This class can be combined to
+ * compose complex {@link ISensorOperation}s.
+ */
+public class SequentialSensorOperation extends AbstractSensorOperation {
+ public static final String STATS_TAG = "sequential";
+
+ private final List<ISensorOperation> mOperations = new LinkedList<ISensorOperation>();
+
+ /**
+ * Add a set of {@link ISensorOperation}s.
+ */
+ public void add(ISensorOperation ... operations) {
+ for (ISensorOperation operation : operations) {
+ if (operation == null) {
+ throw new IllegalArgumentException("Arguments cannot be null");
+ }
+ mOperations.add(operation);
+ }
+ }
+
+ /**
+ * Executes the {@link ISensorOperation}s in the order they were added. If an exception occurs
+ * in one operation, it is thrown and all subsequent operations will not run.
+ */
+ @Override
+ public void execute() {
+ for (int i = 0; i < mOperations.size(); i++) {
+ ISensorOperation operation = mOperations.get(i);
+ try {
+ operation.execute();
+ } catch (AssertionError e) {
+ String msg = String.format("Operation %d failed: \"%s\"", i, e.getMessage());
+ getStats().addValue(SensorStats.ERROR, msg);
+ throw new AssertionError(msg, e);
+ } finally {
+ addSensorStats(STATS_TAG, i, operation.getStats());
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SequentialSensorOperation clone() {
+ SequentialSensorOperation operation = new SequentialSensorOperation();
+ for (ISensorOperation subOperation : mOperations) {
+ operation.add(subOperation.clone());
+ }
+ return operation;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
new file mode 100644
index 0000000..1be0ba2
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.TestSensorManager;
+import android.hardware.cts.helpers.ValidatingSensorEventListener;
+import android.hardware.cts.helpers.sensorverification.EventGapVerification;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
+import android.hardware.cts.helpers.sensorverification.FrequencyVerification;
+import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+import android.hardware.cts.helpers.sensorverification.JitterVerification;
+import android.hardware.cts.helpers.sensorverification.MagnitudeVerification;
+import android.hardware.cts.helpers.sensorverification.MeanVerification;
+import android.hardware.cts.helpers.sensorverification.StandardDeviationVerification;
+
+import junit.framework.Assert;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorOperation} used to verify that sensor events and sensor values are correct.
+ * <p>
+ * Provides methods to set test expectations as well as providing a set of default expectations
+ * depending on sensor type. When {{@link #execute()} is called, the sensor will collect the
+ * events and then run all the tests.
+ * </p>
+ */
+public class TestSensorOperation extends AbstractSensorOperation {
+ private final TestSensorManager mSensorManager;
+ private final Context mContext;
+ private final int mSensorType;
+ private final int mRateUs;
+ private final int mMaxBatchReportLatencyUs;
+ private final Integer mEventCount;
+ private final Long mDuration;
+ private final TimeUnit mTimeUnit;
+
+ private final Collection<ISensorVerification> mVerifications =
+ new HashSet<ISensorVerification>();
+
+ private boolean mLogEvents = false;
+
+ /**
+ * Create a {@link TestSensorOperation}.
+ *
+ * @param context the {@link Context}.
+ * @param sensorType the sensor type
+ * @param rateUs the rate that
+ * @param maxBatchReportLatencyUs the max batch report latency
+ * @param eventCount the number of events to gather
+ */
+ public TestSensorOperation(Context context, int sensorType, int rateUs,
+ int maxBatchReportLatencyUs, int eventCount) {
+ this(context, sensorType, rateUs, maxBatchReportLatencyUs, eventCount, null, null);
+ }
+
+ /**
+ * Create a {@link TestSensorOperation}.
+ *
+ * @param context the {@link Context}.
+ * @param sensorType the sensor type
+ * @param rateUs the rate that
+ * @param maxBatchReportLatencyUs the max batch report latency
+ * @param duration the duration to gather events for
+ * @param timeUnit the time unit of the duration
+ */
+ public TestSensorOperation(Context context, int sensorType, int rateUs,
+ int maxBatchReportLatencyUs, long duration, TimeUnit timeUnit) {
+ this(context, sensorType, rateUs, maxBatchReportLatencyUs, null, duration, timeUnit);
+ }
+
+ /**
+ * Private helper constructor.
+ */
+ private TestSensorOperation(Context context, int sensorType, int rateUs,
+ int maxBatchReportLatencyUs, Integer eventCount, Long duration, TimeUnit timeUnit) {
+ mContext = context;
+ mSensorType = sensorType;
+ mRateUs = rateUs;
+ mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+ mEventCount = eventCount;
+ mDuration = duration;
+ mTimeUnit = timeUnit;
+ mSensorManager = new TestSensorManager(mContext, mSensorType, mRateUs,
+ mMaxBatchReportLatencyUs);
+ }
+
+ /**
+ * Set whether to log events.
+ */
+ public void setLogEvents(boolean logEvents) {
+ mLogEvents = logEvents;
+ }
+
+ /**
+ * Set all of the default test expectations.
+ */
+ public void setDefaultVerifications() {
+ Sensor sensor = mSensorManager.getSensor();
+ addVerification(EventGapVerification.getDefault(sensor, mRateUs));
+ addVerification(EventOrderingVerification.getDefault(sensor));
+ addVerification(FrequencyVerification.getDefault(sensor, mRateUs));
+ addVerification(JitterVerification.getDefault(sensor, mRateUs));
+ addVerification(MagnitudeVerification.getDefault(sensor));
+ addVerification(MeanVerification.getDefault(sensor));
+ // Skip SigNumVerification since it has no default
+ addVerification(StandardDeviationVerification.getDefault(sensor));
+ }
+
+ public void addVerification(ISensorVerification verification) {
+ if (verification != null) {
+ mVerifications.add(verification);
+ }
+ }
+
+ /**
+ * Collect the specified number of events from the sensor and run all enabled verifications.
+ */
+ @Override
+ public void execute() {
+ getStats().addValue("sensor_name", SensorTestInformation.getSensorName(mSensorType));
+ getStats().addValue("sensor_handle", mSensorManager.getSensor().getHandle());
+
+ ValidatingSensorEventListener listener = new ValidatingSensorEventListener(mVerifications);
+ listener.setLogEvents(mLogEvents);
+
+ if (mEventCount != null) {
+ mSensorManager.runSensor(listener, mEventCount);
+ } else {
+ mSensorManager.runSensor(listener, mDuration, mTimeUnit);
+ }
+
+ boolean failed = false;
+ StringBuilder sb = new StringBuilder();
+
+ for (ISensorVerification verification : mVerifications) {
+ failed |= evaluateResults(verification, sb);
+ }
+
+ if (failed) {
+ String msg = SensorCtsHelper.formatAssertionMessage(mSensorManager.getSensor(),
+ "VerifySensorOperation", mRateUs, mMaxBatchReportLatencyUs, sb.toString());
+ getStats().addValue(SensorStats.ERROR, msg);
+ Assert.fail(msg);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TestSensorOperation clone() {
+ TestSensorOperation operation;
+ if (mEventCount != null) {
+ operation = new TestSensorOperation(mContext, mSensorType, mRateUs,
+ mMaxBatchReportLatencyUs, mEventCount);
+ } else {
+ operation = new TestSensorOperation(mContext, mSensorType, mRateUs,
+ mMaxBatchReportLatencyUs, mDuration, mTimeUnit);
+ }
+
+ for (ISensorVerification verification : mVerifications) {
+ operation.addVerification(verification.clone());
+ }
+ return operation;
+ }
+
+ /**
+ * Evaluate the results of a test, aggregate the stats, and build the error message.
+ */
+ private boolean evaluateResults(ISensorVerification verification, StringBuilder sb) {
+ try {
+ verification.verify(getStats());
+ } catch (AssertionError e) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+ sb.append(e.getMessage());
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
new file mode 100644
index 0000000..73da9c9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.content.Context;
+import android.hardware.cts.helpers.SensorStats;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+/**
+ * An {@link ISensorOperation} which holds a wakelock while performing another
+ * {@link ISensorOperation}.
+ */
+public class WakeLockOperation extends AbstractSensorOperation {
+ private static final String TAG = "WakeLockOperation";
+
+ private final ISensorOperation mOperation;
+ private final Context mContext;
+ private final int mWakelockFlags;
+
+ /**
+ * Constructor for {@link WakeLockOperation}.
+ *
+ * @param operation the child {@link ISensorOperation} to perform after the delay
+ * @param context the context used to access the power manager
+ * @param wakelockFlags the flags used when acquiring the wakelock
+ */
+ public WakeLockOperation(ISensorOperation operation, Context context, int wakelockFlags) {
+ mOperation = operation;
+ mContext = context;
+ mWakelockFlags = wakelockFlags;
+ }
+
+ /**
+ * Constructor for {@link WakeLockOperation}.
+ *
+ * @param operation the child {@link ISensorOperation} to perform after the delay
+ * @param context the context used to access the power manager
+ */
+ public WakeLockOperation(ISensorOperation operation, Context context) {
+ this(operation, context, PowerManager.PARTIAL_WAKE_LOCK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ WakeLock wakeLock = pm.newWakeLock(mWakelockFlags, TAG);
+
+ wakeLock.acquire();
+ try {
+ mOperation.execute();
+ } finally {
+ wakeLock.release();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SensorStats getStats() {
+ return mOperation.getStats();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ISensorOperation clone() {
+ return new WakeLockOperation(mOperation, mContext, mWakelockFlags);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractMeanVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractMeanVerification.java
new file mode 100644
index 0000000..8d132a3
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractMeanVerification.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+/**
+ * Abstract class that calculates of the mean event values.
+ */
+public abstract class AbstractMeanVerification extends AbstractSensorVerification {
+ private float[] mSums = null;
+ private int mCount = 0;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ if (mSums == null) {
+ mSums = new float[event.values.length];
+ }
+ Assert.assertEquals(mSums.length, event.values.length);
+ for (int i = 0; i < mSums.length; i++) {
+ mSums[i] += event.values[i];
+ }
+ mCount++;
+ }
+
+ /**
+ * Return the number of events.
+ */
+ protected int getCount() {
+ return mCount;
+ }
+
+ /**
+ * Return the means of the event values.
+ */
+ protected float[] getMeans() {
+ if (mCount < 0) {
+ return null;
+ }
+
+ float[] means = new float[mSums.length];
+ for (int i = 0; i < mSums.length; i++) {
+ means[i] = mSums[i] / mCount;
+ }
+ return means;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
new file mode 100644
index 0000000..911ae3a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Abstract class that deals with the synchronization of the sensor verifications.
+ */
+public abstract class AbstractSensorVerification implements ISensorVerification {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void addSensorEvents(TestSensorEvent ... events) {
+ for (TestSensorEvent event : events) {
+ addSensorEventInternal(event);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void addSensorEvent(TestSensorEvent event) {
+ addSensorEventInternal(event);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract ISensorVerification clone();
+
+ /**
+ * Used by implementing classes to add a sensor event.
+ */
+ protected abstract void addSensorEventInternal(TestSensorEvent event);
+
+ /**
+ * Helper class to store the index, previous event, and current event.
+ */
+ protected class IndexedEventPair {
+ public final int index;
+ public final TestSensorEvent event;
+ public final TestSensorEvent previousEvent;
+
+ public IndexedEventPair(int index, TestSensorEvent event,
+ TestSensorEvent previousEvent) {
+ this.index = index;
+ this.event = event;
+ this.previousEvent = previousEvent;
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java
new file mode 100644
index 0000000..251ef3c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java
@@ -0,0 +1,117 @@
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestInformation.SensorReportingMode;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} which verifies that there are no missing events. This is done by
+ * checking the last received sensor timestamp and checking that it is within 1.8 * the expected
+ * period.
+ */
+public class EventGapVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "missing_event_passed";
+
+ // Fail if no events are delivered within 1.8 times the expected interval
+ private static final double THRESHOLD = 1.8;
+
+ // Number of indices to print in assert message before truncating
+ private static final int TRUNCATE_MESSAGE_LENGTH = 3;
+
+ private final int mExpectedDelayUs;
+
+ private final List<IndexedEventPair> mEventGaps = new LinkedList<IndexedEventPair>();
+ private TestSensorEvent mPreviousEvent = null;
+ private int mIndex = 0;
+
+ /**
+ * Construct a {@link EventGapVerification}
+ *
+ * @param expectedDelayUs the expected period in us.
+ */
+ public EventGapVerification(int expectedDelayUs) {
+ mExpectedDelayUs = expectedDelayUs;
+ }
+
+ /**
+ * Get the default {@link EventGapVerification}.
+ *
+ * @param sensor the {@link Sensor}
+ * @param rateUs the requested rate in us
+ * @return the verification or null if the verification is not a continuous mode sensor.
+ */
+ public static EventGapVerification getDefault(Sensor sensor, int rateUs) {
+ if (!SensorReportingMode.CONTINUOUS.equals(SensorTestInformation.getReportingMode(
+ sensor.getType()))) {
+ return null;
+ }
+ return new EventGapVerification(SensorCtsHelper.getDelay(sensor, rateUs));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ final int count = mEventGaps.size();
+ stats.addValue(PASSED_KEY, count == 0);
+ stats.addValue(SensorStats.EVENT_GAP_COUNT_KEY, count);
+
+ final int[] indices = new int[count];
+ for (int i = 0; i < indices.length; i++) {
+ indices[i] = mEventGaps.get(i).index;
+ }
+ stats.addValue(SensorStats.EVENT_GAP_POSITIONS_KEY, indices);
+
+ if (count > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(count).append(" events gaps: ");
+ for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
+ IndexedEventPair info = mEventGaps.get(i);
+ sb.append(String.format("position=%d, delta_time=%dns; ", info.index,
+ info.event.timestamp - info.previousEvent.timestamp));
+ }
+ if (count > TRUNCATE_MESSAGE_LENGTH) {
+ sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more; ");
+ }
+ sb.append(String.format("(expected <%dns)",
+ TimeUnit.NANOSECONDS.convert((int) (THRESHOLD * mExpectedDelayUs),
+ TimeUnit.MICROSECONDS)));
+ Assert.fail(sb.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EventGapVerification clone() {
+ return new EventGapVerification(mExpectedDelayUs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ if (mPreviousEvent != null) {
+ long deltaNs = event.timestamp - mPreviousEvent.timestamp;
+ long deltaUs = TimeUnit.MICROSECONDS.convert(deltaNs, TimeUnit.NANOSECONDS);
+ if (deltaUs > mExpectedDelayUs * THRESHOLD) {
+ mEventGaps.add(new IndexedEventPair(mIndex, event, mPreviousEvent));
+ }
+ }
+
+ mPreviousEvent = event;
+ mIndex++;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
new file mode 100644
index 0000000..b7861b2
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link EventGapVerification}.
+ */
+public class EventGapVerificationTest extends TestCase {
+
+ /**
+ * Test that the verification passes when there are no results.
+ */
+ public void testVerify_no_events() {
+ // Timestamps in ns, expected in us
+ runVerification(1000, new long[]{}, true, new int[]{});
+ }
+
+ /**
+ * Test that the verification passes when there are not missing events.
+ */
+ public void testVerify_correct() {
+ // Timestamps in ns, expected in us
+ long[] timestamps = {1000000, 2000000, 3000000, 4000000, 5000000};
+ runVerification(1000, timestamps, true, new int[]{});
+ }
+
+ /**
+ * Test that the verification passes when there are not missing events but some jitter.
+ */
+ public void testVerify_jitter() {
+ // Timestamps in ns, expected in us
+ long[] timestamps = {1100000, 2050000, 2990000, 4000000, 4950000};
+ runVerification(1000, timestamps, true, new int[]{});
+ }
+
+ /**
+ * Test that the verification fails when there are missing events.
+ */
+ public void testVerify_missing_events() {
+ // Timestamps in ns, expected in us
+ long[] timestamps = {1000000, 2000000, 3000000, 5000000, 6000000};
+ runVerification(1000, timestamps, false, new int[]{3});
+ }
+
+ private void runVerification(int expected, long[] timestamps, boolean pass,
+ int[] indices) {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(expected, timestamps);
+ if (pass) {
+ verification.verify(stats);
+ } else {
+ boolean failed = false;
+ try {
+ verification.verify(stats);
+ } catch (AssertionError e) {
+ // Expected;
+ failed = true;
+ }
+ assertTrue("Expected an AssertionError", failed);
+ }
+ assertEquals(pass, stats.getValue(EventGapVerification.PASSED_KEY));
+ assertEquals(indices.length, stats.getValue(SensorStats.EVENT_GAP_COUNT_KEY));
+ assertNotNull(stats.getValue(SensorStats.EVENT_GAP_POSITIONS_KEY));
+ int[] actualIndices = (int[]) stats.getValue(SensorStats.EVENT_GAP_POSITIONS_KEY);
+ assertEquals(indices.length, actualIndices.length);
+
+ for (int i = 0; i < indices.length; i++) {
+ assertEquals(indices[i], actualIndices[i]);
+ }
+ }
+
+ private ISensorVerification getVerification(int expected, long ... timestamps) {
+ ISensorVerification verification = new EventGapVerification(expected);
+ for (long timestamp : timestamps) {
+ verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+ }
+ return verification;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java
new file mode 100644
index 0000000..c74c826
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestInformation.SensorReportingMode;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link ISensorVerification} which verifies that all events are received in the correct order.
+ */
+public class EventOrderingVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "event_out_of_order_passed";
+
+ // Number of indices to print in assert message before truncating
+ private static final int TRUNCATE_MESSAGE_LENGTH = 3;
+
+ private Long mMaxTimestamp = null;
+ private final List<IndexedEventPair> mOutOfOrderEvents = new LinkedList<IndexedEventPair>();
+ private TestSensorEvent mPreviousEvent = null;
+ private int mIndex = 0;
+
+ /**
+ * Get the default {@link EventOrderingVerification} for a sensor.
+ *
+ * @param sensor a {@link Sensor}
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ @SuppressWarnings("deprecation")
+ public static EventOrderingVerification getDefault(Sensor sensor) {
+ SensorReportingMode mode = SensorTestInformation.getReportingMode(sensor.getType());
+ if (!SensorReportingMode.CONTINUOUS.equals(mode)
+ && !SensorReportingMode.ON_CHANGE.equals(mode)) {
+ return null;
+ }
+ return new EventOrderingVerification();
+ }
+
+ /**
+ * Verify that the events are in the correct order. Add {@value #PASSED_KEY},
+ * {@value SensorStats#EVENT_OUT_OF_ORDER_COUNT_KEY}, and
+ * {@value SensorStats#EVENT_OUT_OF_ORDER_POSITIONS_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ final int count = mOutOfOrderEvents.size();
+ stats.addValue(PASSED_KEY, count == 0);
+ stats.addValue(SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY, count);
+
+ final int[] indices = new int[count];
+ for (int i = 0; i < indices.length; i++) {
+ indices[i] = mOutOfOrderEvents.get(i).index;
+ }
+ stats.addValue(SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY, indices);
+
+ if (count > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(count).append(" events out of order: ");
+ for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
+ IndexedEventPair info = mOutOfOrderEvents.get(i);
+ sb.append(String.format("position=%d, previous=%d, timestamp=%d; ", info.index,
+ info.previousEvent.timestamp, info.event.timestamp));
+ }
+ if (count > TRUNCATE_MESSAGE_LENGTH) {
+ sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more");
+ } else {
+ // Delete the trailing "; "
+ sb.delete(sb.length() - 2, sb.length());
+ }
+
+ Assert.fail(sb.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EventOrderingVerification clone() {
+ return new EventOrderingVerification();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ if (mPreviousEvent == null) {
+ mMaxTimestamp = event.timestamp;
+ } else {
+ if (event.timestamp < mMaxTimestamp) {
+ mOutOfOrderEvents.add(new IndexedEventPair(mIndex, event, mPreviousEvent));
+ } else if (event.timestamp > mMaxTimestamp) {
+ mMaxTimestamp = event.timestamp;
+ }
+ }
+
+ mPreviousEvent = event;
+ mIndex++;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
new file mode 100644
index 0000000..28cbd01
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link EventOrderingVerification}.
+ */
+public class EventOrderingVerificationTest extends TestCase {
+
+ /**
+ * Test that the verification passes when there are no results.
+ */
+ public void testNoEvents() {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification();
+ verification.verify(stats);
+ verifyStats(stats, true, 0);
+ }
+
+ /**
+ * Test that the verification passes when the timestamps are the same.
+ */
+ public void testSameTimestamp() {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(0, 0, 0, 0, 0);
+ verification.verify(stats);
+ verifyStats(stats, true, 0);
+ }
+
+ /**
+ * Test that the verification passes when the timestamps are increasing.
+ */
+ public void testSequentialTimestamp() {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(0, 1, 2, 3, 4);
+ verification.verify(stats);
+ verifyStats(stats, true, 0);
+ }
+
+ /**
+ * Test that the verification fails when there is one event out of order.
+ */
+ public void testSingleOutofOrder() {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(0, 2, 1, 3, 4);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, 1);
+ List<Integer> indices = getIndices(stats);
+ assertTrue(indices.contains(2));
+ }
+
+ /**
+ * Test that the verification fails when there are multiple events out of order.
+ */
+ public void testMultipleOutOfOrder() {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(4, 0, 1, 2, 3);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, 4);
+ List<Integer> indices = getIndices(stats);
+ assertTrue(indices.contains(1));
+ assertTrue(indices.contains(2));
+ assertTrue(indices.contains(3));
+ assertTrue(indices.contains(4));
+ }
+
+ private ISensorVerification getVerification(long ... timestamps) {
+ ISensorVerification verification = new EventOrderingVerification();
+ for (long timestamp : timestamps) {
+ verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+ }
+ return verification;
+ }
+
+ private void verifyStats(SensorStats stats, boolean passed, int count) {
+ assertEquals(passed, stats.getValue(EventOrderingVerification.PASSED_KEY));
+ assertEquals(count, stats.getValue(SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY));
+ assertNotNull(stats.getValue(SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY));
+ }
+
+ private List<Integer> getIndices(SensorStats stats) {
+ int[] primitiveIndices = (int[]) stats.getValue(
+ SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY);
+ List<Integer> indices = new ArrayList<Integer>(primitiveIndices.length);
+ for (int index : primitiveIndices) {
+ indices.add(index);
+ }
+ return indices;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
new file mode 100644
index 0000000..4815688
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.SensorTestInformation;
+import android.hardware.cts.helpers.SensorTestInformation.SensorReportingMode;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} which verifies that the sensor frequency are within the expected
+ * range.
+ */
+public class FrequencyVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "frequency_passed";
+
+ // lower threshold is (100 - 10)% expected
+ private static final int DEFAULT_LOWER_THRESHOLD = 10;
+ // upper threshold is (100 + 110)% expected
+ private static final int DEFAULT_UPPER_THRESHOLD = 110;
+
+ private final double mExpected;
+ private final double mLowerThreshold;
+ private final double mUpperThreshold;
+
+ private long mMinTimestamp = 0;
+ private long mMaxTimestamp = 0;
+ private int mCount = 0;
+
+ /**
+ * Construct a {@link FrequencyVerification}.
+ *
+ * @param expected the expected frequency in Hz.
+ * @param lowerTheshold the lower threshold in Hz. {@code expected - lower} should be the
+ * slowest acceptable frequency of the sensor.
+ * @param upperThreshold the upper threshold in Hz. {@code expected + upper} should be the
+ * fastest acceptable frequency of the sensor.
+ */
+ public FrequencyVerification(double expected, double lowerTheshold, double upperThreshold) {
+ mExpected = expected;
+ mLowerThreshold = lowerTheshold;
+ mUpperThreshold = upperThreshold;
+ }
+
+ /**
+ * Get the default {@link FrequencyVerification} for a sensor.
+ *
+ * @param sensor a {@link Sensor}
+ * @param rateUs the desired rate of the sensor
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ public static FrequencyVerification getDefault(Sensor sensor, int rateUs) {
+ if (!SensorReportingMode.CONTINUOUS.equals(
+ SensorTestInformation.getReportingMode(sensor.getType()))) {
+ return null;
+ }
+
+ // Expected frequency in Hz
+ double expected = SensorCtsHelper.getFrequency(SensorCtsHelper.getDelay(sensor, rateUs),
+ TimeUnit.MICROSECONDS);
+ // Expected frequency * threshold percentage
+ double lowerThreshold = expected * DEFAULT_LOWER_THRESHOLD / 100;
+ double upperThreshold = expected * DEFAULT_UPPER_THRESHOLD / 100;
+ return new FrequencyVerification(expected, lowerThreshold, upperThreshold);
+ }
+
+ /**
+ * Verify that the frequency is correct. Add {@value #PASSED_KEY} and
+ * {@value SensorStats#FREQUENCY_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ if (mCount < 2) {
+ stats.addValue(PASSED_KEY, true);
+ return;
+ }
+
+ double frequency = SensorCtsHelper.getFrequency(
+ ((double) (mMaxTimestamp - mMinTimestamp)) / (mCount - 1), TimeUnit.NANOSECONDS);
+ boolean failed = (frequency <= mExpected - mLowerThreshold
+ || frequency >= mExpected + mUpperThreshold);
+
+ stats.addValue(SensorStats.FREQUENCY_KEY, frequency);
+ stats.addValue(PASSED_KEY, !failed);
+
+ if (failed) {
+ Assert.fail(String.format("Frequency out of range: frequency=%.2fHz "
+ + "(expected (%.2f-%.2fHz, %.2f+%.2fHz))", frequency, mExpected,
+ mLowerThreshold, mExpected, mUpperThreshold));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public FrequencyVerification clone() {
+ return new FrequencyVerification(mExpected, mLowerThreshold, mUpperThreshold);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ if (mCount == 0) {
+ mMinTimestamp = event.timestamp;
+ mMaxTimestamp = event.timestamp;
+ } else {
+ if (mMinTimestamp > event.timestamp) {
+ mMinTimestamp = event.timestamp;
+ }
+ if (mMaxTimestamp < event.timestamp) {
+ mMaxTimestamp = event.timestamp;
+ }
+ }
+ mCount++;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
new file mode 100644
index 0000000..cec09a5
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link EventOrderingVerification}.
+ */
+public class FrequencyVerificationTest extends TestCase {
+
+ /**
+ * Test that the verifications passes/fails based on threshold given.
+ */
+ public void testVerifification() {
+ long[] timestamps = {0, 1000000, 2000000, 3000000, 4000000}; // 1000Hz
+
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(1000.0, 1.0, 1.0, timestamps);
+ verification.verify(stats);
+ verifyStats(stats, true, 1000.0);
+
+ stats = new SensorStats();
+ verification = getVerification(950.0, 100.0, 100.0, timestamps);
+ verification.verify(stats);
+ verifyStats(stats, true, 1000.0);
+
+ stats = new SensorStats();
+ verification = getVerification(1050.0, 100.0, 100.0, timestamps);
+ verification.verify(stats);
+ verifyStats(stats, true, 1000.0);
+
+ stats = new SensorStats();
+ verification = getVerification(950.0, 100.0, 25.0, timestamps);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, 1000.0);
+
+ stats = new SensorStats();
+ verification = getVerification(1050.0, 25.0, 100.0, timestamps);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, 1000.0);
+ }
+
+ private ISensorVerification getVerification(double expected, double lowerThreshold,
+ double upperThreshold, long ... timestamps) {
+ ISensorVerification verification = new FrequencyVerification(expected, lowerThreshold,
+ upperThreshold);
+ for (long timestamp : timestamps) {
+ verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+ }
+ return verification;
+ }
+
+ private void verifyStats(SensorStats stats, boolean passed, double frequency) {
+ assertEquals(passed, stats.getValue(FrequencyVerification.PASSED_KEY));
+ assertEquals(frequency, stats.getValue(SensorStats.FREQUENCY_KEY));
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/ISensorVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/ISensorVerification.java
new file mode 100644
index 0000000..07af392
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/ISensorVerification.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Interface describing the sensor verification. This class was designed for to handle streaming
+ * events. The methods {@link #addSensorEvent(TestSensorEvent)} and
+ * {@link #addSensorEvents(TestSensorEvent...)} should be called in the order that the events are
+ * received. The method {@link #verify(SensorStats)} should be called after all events are added.
+ */
+public interface ISensorVerification {
+
+ /**
+ * Add a single {@link TestSensorEvent} to be evaluated.
+ */
+ public void addSensorEvent(TestSensorEvent event);
+
+ /**
+ * Add multiple {@link TestSensorEvent}s to be evaluated.
+ */
+ public void addSensorEvents(TestSensorEvent ... events);
+
+ /**
+ * Evaluate all added {@link TestSensorEvent}s and update stats.
+ *
+ * @param stats a {@link SensorStats} object used to keep track of the stats.
+ * @throws AssertionError if the verification fails.
+ */
+ public void verify(SensorStats stats);
+
+ /**
+ * Clones the {@link ISensorVerification}
+ */
+ public ISensorVerification clone();
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
new file mode 100644
index 0000000..6feceb8
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} which verifies that the sensor jitter is in an acceptable range.
+ */
+public class JitterVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "jitter_passed";
+
+ // sensorType: threshold (% of expected period)
+ private static final Map<Integer, Integer> DEFAULTS = new HashMap<Integer, Integer>(12);
+ static {
+ // Use a method so that the @deprecation warning can be set for that method only
+ setDefaults();
+ }
+
+ private final int mExpected;
+ private final int mThreshold;
+
+ private List<Long> mTimestamps = new LinkedList<Long>();
+
+ /**
+ * Construct a {@link JitterVerification}
+ *
+ * @param expected the expected period in ns
+ * @param threshold the acceptable margin of error as a percentage
+ */
+ public JitterVerification(int expected, int threshold) {
+ mExpected = expected;
+ mThreshold = threshold;
+ }
+
+ /**
+ * Get the default {@link JitterVerification} for a sensor.
+ *
+ * @param sensor a {@link Sensor}
+ * @param rateUs the desired rate of the sensor
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ public static JitterVerification getDefault(Sensor sensor, int rateUs) {
+ if (!DEFAULTS.containsKey(sensor.getType())) {
+ return null;
+ }
+
+ int expected = (int) TimeUnit.NANOSECONDS.convert(SensorCtsHelper.getDelay(sensor, rateUs),
+ TimeUnit.MICROSECONDS);
+ return new JitterVerification(expected, DEFAULTS.get(sensor.getType()));
+ }
+
+ /**
+ * Verify that the 95th percentile of the jitter is in the acceptable range. Add
+ * {@value #PASSED_KEY} and {@value SensorStats#JITTER_95_PERCENTILE_KEY} keys to
+ * {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ if (mTimestamps.size() < 2) {
+ stats.addValue(PASSED_KEY, true);
+ return;
+ }
+
+ List<Double> jitters = getJitterValues();
+ double jitter95Percentile = SensorCtsHelper.get95PercentileValue(jitters);
+ boolean failed = (jitter95Percentile > mExpected * (mThreshold / 100.0));
+
+ stats.addValue(PASSED_KEY, !failed);
+ stats.addValue(SensorStats.JITTER_95_PERCENTILE_KEY, jitter95Percentile);
+
+ if (failed) {
+ Assert.fail(String.format("Jitter out of range: jitter at 95th percentile=%.0fns "
+ + "(expected <%.0fns)", jitter95Percentile, mExpected * (mThreshold / 100.0)));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public JitterVerification clone() {
+ return new JitterVerification(mExpected, mThreshold);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ mTimestamps.add(event.timestamp);
+ }
+
+ /**
+ * Get the list of all jitter values. Exposed for unit testing.
+ */
+ List<Double> getJitterValues() {
+ List<Long> deltas = new ArrayList<Long>(mTimestamps.size() - 1);
+ for (int i = 1; i < mTimestamps.size(); i++) {
+ deltas.add(mTimestamps.get(i) - mTimestamps.get(i -1));
+ }
+ double deltaMean = SensorCtsHelper.getMean(deltas);
+ List<Double> jitters = new ArrayList<Double>(deltas.size());
+ for (long delta : deltas) {
+ jitters.add(Math.abs(delta - deltaMean));
+ }
+ return jitters;
+ }
+
+ @SuppressWarnings("deprecation")
+ private static void setDefaults() {
+ // Sensors that we don't want to test at this time but still want to record the values.
+ DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_ORIENTATION, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_PRESSURE, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_GRAVITY, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_LINEAR_ACCELERATION, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_ROTATION_VECTOR, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_GAME_ROTATION_VECTOR, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, Integer.MAX_VALUE);
+ DEFAULTS.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, Integer.MAX_VALUE);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
new file mode 100644
index 0000000..a9e872a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Tests for {@link EventOrderingVerification}.
+ */
+public class JitterVerificationTest extends TestCase {
+
+
+ public void testVerify() {
+ final int SAMPLE_SIZE = 100;
+
+ // 100 samples at 1000Hz
+ long[] timestamps = new long[SAMPLE_SIZE];
+ for (int i = 0; i < SAMPLE_SIZE; i++) {
+ timestamps[i] = i * 100000;
+ }
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(1000, 1, timestamps);
+ verification.verify(stats);
+ verifyStats(stats, true, 0.0);
+
+ // 90 samples at 1000Hz, 10 samples at 2000Hz
+ long timestamp = 0;
+ for (int i = 0; i < SAMPLE_SIZE; i++) {
+ timestamps[i] = timestamp;
+ timestamp += (i % 10 == 0) ? 500000 : 1000000;
+ }
+ stats = new SensorStats();
+ verification = getVerification(1000, 1, timestamps);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, 449494.9494);
+ }
+
+ public void testCalculateJitter() {
+ long[] timestamps = new long[]{0, 1, 2, 3, 4};
+ JitterVerification verification = getVerification(1000, 1, timestamps);
+ List<Double> jitterValues = verification.getJitterValues();
+ assertEquals(4, jitterValues.size());
+ assertEquals(0.0, (double) jitterValues.get(0));
+ assertEquals(0.0, (double) jitterValues.get(1));
+ assertEquals(0.0, (double) jitterValues.get(2));
+ assertEquals(0.0, (double) jitterValues.get(3));
+
+ timestamps = new long[]{0, 0, 2, 4, 4};
+ verification = getVerification(1000, 1, timestamps);
+ jitterValues = verification.getJitterValues();
+ assertEquals(4, jitterValues.size());
+ assertEquals(1.0, (double) jitterValues.get(0));
+ assertEquals(1.0, (double) jitterValues.get(1));
+ assertEquals(1.0, (double) jitterValues.get(2));
+ assertEquals(1.0, (double) jitterValues.get(3));
+
+ timestamps = new long[]{0, 1, 4, 9, 16};
+ verification = getVerification(1000, 1, timestamps);
+ jitterValues = verification.getJitterValues();
+ assertEquals(4, jitterValues.size());
+ assertEquals(4, jitterValues.size());
+ assertEquals(3.0, (double) jitterValues.get(0));
+ assertEquals(1.0, (double) jitterValues.get(1));
+ assertEquals(1.0, (double) jitterValues.get(2));
+ assertEquals(3.0, (double) jitterValues.get(3));
+ }
+
+ private JitterVerification getVerification(int expected, int threshold, long ... timestamps) {
+ JitterVerification verification = new JitterVerification(expected, threshold);
+ for (long timestamp : timestamps) {
+ verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+ }
+ return verification;
+ }
+
+ private void verifyStats(SensorStats stats, boolean passed, double jitter95) {
+ assertEquals(passed, stats.getValue(JitterVerification.PASSED_KEY));
+ assertEquals(jitter95, (Double) stats.getValue(SensorStats.JITTER_95_PERCENTILE_KEY), 0.1);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerification.java
new file mode 100644
index 0000000..5e44273
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerification.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the mean of the magnitude of the sensors vector
+ * is within the expected range.
+ */
+public class MagnitudeVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "magnitude_passed";
+
+ // sensorType: {expected, threshold}
+ private static Map<Integer, Float[]> DEFAULTS = new HashMap<Integer, Float[]>(3);
+ static {
+ // Use a method so that the @deprecation warning can be set for that method only
+ setDefaults();
+ }
+
+ private final float mExpected;
+ private final float mThreshold;
+
+ private float mSum = 0.0f;
+ private int mCount = 0;
+
+ /**
+ * Construct a {@link MagnitudeVerification}
+ *
+ * @param expected the expected value
+ * @param threshold the threshold
+ */
+ public MagnitudeVerification(float expected, float threshold) {
+ mExpected = expected;
+ mThreshold = threshold;
+ }
+
+ /**
+ * Get the default {@link MagnitudeVerification} for a sensor.
+ *
+ * @param sensor a {@link Sensor}
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ public static MagnitudeVerification getDefault(Sensor sensor) {
+ if (!DEFAULTS.containsKey(sensor.getType())) {
+ return null;
+ }
+ Float expected = DEFAULTS.get(sensor.getType())[0];
+ Float threshold = DEFAULTS.get(sensor.getType())[1];
+ return new MagnitudeVerification(expected, threshold);
+ }
+
+ /**
+ * Verify that the magnitude is in the acceptable range. Add {@value #PASSED_KEY} and
+ * {@value SensorStats#MAGNITUDE_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ if (mCount < 1) {
+ stats.addValue(PASSED_KEY, true);
+ return;
+ }
+
+ float mean = mSum / mCount;
+ boolean failed = Math.abs(mean - mExpected) > mThreshold;
+
+ stats.addValue(PASSED_KEY, !failed);
+ stats.addValue(SensorStats.MAGNITUDE_KEY, mean);
+
+ if (failed) {
+ Assert.fail(String.format("Magnitude mean out of range: mean=%s (expected %s+/-%s)",
+ mean, mExpected, mThreshold));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public MagnitudeVerification clone() {
+ return new MagnitudeVerification(mExpected, mThreshold);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ float sumOfSquares = 0.0f;
+ for (float value : event.values) {
+ sumOfSquares += value * value;
+ }
+ mSum += (float) Math.sqrt(sumOfSquares);
+ mCount++;
+ }
+
+ @SuppressWarnings("deprecation")
+ private static void setDefaults() {
+ DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, new Float[]{SensorManager.STANDARD_GRAVITY, 1.5f});
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE, new Float[]{0.0f, 1.5f});
+ // Sensors that we don't want to test at this time but still want to record the values.
+ DEFAULTS.put(Sensor.TYPE_GRAVITY,
+ new Float[]{SensorManager.STANDARD_GRAVITY, Float.MAX_VALUE});
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
new file mode 100644
index 0000000..9a50753
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link MagnitudeVerification}.
+ */
+public class MagnitudeVerificationTest extends TestCase {
+
+ /**
+ * Test {@link MagnitudeVerification#verify(SensorStats)}.
+ */
+ public void testVerify() {
+ float[][] values = {
+ {0, 3, 4},
+ {4, 0, 3},
+ {3, 4, 0},
+ {0, 0, 4},
+ {6, 0, 0},
+ };
+
+ runStats(5.0f, 0.1f, values, true, 5.0f);
+ runStats(4.5f, 0.6f, values, true, 5.0f);
+ runStats(5.5f, 0.6f, values, true, 5.0f);
+ runStats(4.5f, 0.1f, values, false, 5.0f);
+ runStats(5.5f, 0.1f, values, false, 5.0f);
+ }
+
+ private void runStats(float expected, float threshold, float[][] values, boolean pass, float magnitude) {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(expected, threshold, values);
+ if (pass) {
+ verification.verify(stats);
+ } else {
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ }
+ assertEquals(pass, stats.getValue(MagnitudeVerification.PASSED_KEY));
+ assertEquals(magnitude, (Float) stats.getValue(SensorStats.MAGNITUDE_KEY), 0.01);
+ }
+
+ private ISensorVerification getVerification(float expected, float threshold,
+ float[] ... values) {
+ ISensorVerification verification = new MagnitudeVerification(expected, threshold);
+ for (float[] value : values) {
+ verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+ }
+ return verification;
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
new file mode 100644
index 0000000..d6769d0
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorStats;
+
+import junit.framework.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the means matches the expected measurement.
+ */
+public class MeanVerification extends AbstractMeanVerification {
+ public static final String PASSED_KEY = "mean_passed";
+
+ // sensorType: {expected, threshold}
+ private static final Map<Integer, Object[]> DEFAULTS = new HashMap<Integer, Object[]>(5);
+ static {
+ // Use a method so that the @deprecation warning can be set for that method only
+ setDefaults();
+ }
+
+ private final float[] mExpected;
+ private final float[] mThreshold;
+
+ /**
+ * Construct a {@link MeanVerification}
+ *
+ * @param expected the expected values
+ * @param threshold the thresholds
+ */
+ public MeanVerification(float[] expected, float[] threshold) {
+ mExpected = expected;
+ mThreshold = threshold;
+ }
+
+ /**
+ * Get the default {@link MeanVerification} for a sensor.
+ *
+ * @param sensor a {@link Sensor}
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ public static MeanVerification getDefault(Sensor sensor) {
+ if (!DEFAULTS.containsKey(sensor.getType())) {
+ return null;
+ }
+ float[] expected = (float[]) DEFAULTS.get(sensor.getType())[0];
+ float[] threshold = (float[]) DEFAULTS.get(sensor.getType())[1];
+ return new MeanVerification(expected, threshold);
+ }
+
+ /**
+ * Verify that the mean is in the acceptable range. Add {@value #PASSED_KEY} and
+ * {@value SensorStats#MEAN_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ if (getCount() < 1) {
+ stats.addValue(PASSED_KEY, true);
+ return;
+ }
+
+ float[] means = getMeans();
+
+ boolean failed = false;
+ StringBuilder meanSb = new StringBuilder();
+ StringBuilder expectedSb = new StringBuilder();
+
+ if (means.length > 1) {
+ meanSb.append("(");
+ expectedSb.append("(");
+ }
+ for (int i = 0; i < means.length; i++) {
+ if (Math.abs(means[i] - mExpected[i]) > mThreshold[i]) {
+ failed = true;
+ }
+ meanSb.append(String.format("%.2f", means[i]));
+ if (i != means.length - 1) meanSb.append(", ");
+ expectedSb.append(String.format("%.2f+/-%.2f", mExpected[i], mThreshold[i]));
+ if (i != means.length - 1) expectedSb.append(", ");
+ }
+ if (means.length > 1) {
+ meanSb.append(")");
+ expectedSb.append(")");
+ }
+
+ stats.addValue(PASSED_KEY, !failed);
+ stats.addValue(SensorStats.MEAN_KEY, means);
+
+ if (failed) {
+ Assert.fail(String.format("Mean out of range: mean=%s (expected %s)", meanSb.toString(),
+ expectedSb.toString()));
+ }
+ }
+
+ @Override
+ public MeanVerification clone() {
+ return new MeanVerification(mExpected, mThreshold);
+ }
+
+ @SuppressWarnings("deprecation")
+ private static void setDefaults() {
+ // Sensors that we don't want to test at this time but still want to record the values.
+ // Gyroscope should be 0 for a static device
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE, new Object[]{
+ new float[]{0.0f, 0.0f, 0.0f},
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
+ // Pressure will not be exact in a controlled environment but should be relatively close to
+ // sea level. Second values should always be 0.
+ DEFAULTS.put(Sensor.TYPE_PRESSURE, new Object[]{
+ new float[]{SensorManager.PRESSURE_STANDARD_ATMOSPHERE, 0.0f, 0.0f},
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
+ // Linear acceleration should be 0 in all directions for a static device
+ DEFAULTS.put(Sensor.TYPE_LINEAR_ACCELERATION, new Object[]{
+ new float[]{0.0f, 0.0f, 0.0f},
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
+ // Game rotation vector should be (0, 0, 0, 1, 0) for a static device
+ DEFAULTS.put(Sensor.TYPE_GAME_ROTATION_VECTOR, new Object[]{
+ new float[]{0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE}});
+ // Uncalibrated gyroscope should be 0 for a static device but allow a bigger threshold
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, new Object[]{
+ new float[]{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE, Float.MAX_VALUE}});
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
new file mode 100644
index 0000000..94b6362
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link MeanVerification}.
+ */
+public class MeanVerificationTest extends TestCase {
+
+ /**
+ * Test {@link MeanVerification#verify(SensorStats)}.
+ */
+ public void testVerify() {
+ float[][] values = {
+ {0, 1, 0},
+ {1, 2, 1},
+ {2, 3, 4},
+ {3, 4, 9},
+ {4, 5, 16},
+ };
+
+ float[] expected = {2.0f, 3.0f, 6.0f};
+ float[] threshold = {0.1f, 0.1f, 0.1f};
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(expected, threshold, values);
+ verification.verify(stats);
+ verifyStats(stats, true, new float[]{2.0f, 3.0f, 6.0f});
+
+ expected = new float[]{2.5f, 2.5f, 5.5f};
+ threshold = new float[]{0.6f, 0.6f, 0.6f};
+ stats = new SensorStats();
+ verification = getVerification(expected, threshold, values);
+ verification.verify(stats);
+ verifyStats(stats, true, new float[]{2.0f, 3.0f, 6.0f});
+
+ expected = new float[]{2.5f, 2.5f, 5.5f};
+ threshold = new float[]{0.1f, 0.6f, 0.6f};
+ stats = new SensorStats();
+ verification = getVerification(expected, threshold, values);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, new float[]{2.0f, 3.0f, 6.0f});
+
+ expected = new float[]{2.5f, 2.5f, 5.5f};
+ threshold = new float[]{0.6f, 0.1f, 0.6f};
+ stats = new SensorStats();
+ verification = getVerification(expected, threshold, values);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, new float[]{2.0f, 3.0f, 6.0f});
+
+ threshold = new float[]{2.5f, 2.5f, 5.5f};
+ threshold = new float[]{0.6f, 0.6f, 0.1f};
+ stats = new SensorStats();
+ verification = getVerification(expected, threshold, values);
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ verifyStats(stats, false, new float[]{2.0f, 3.0f, 6.0f});
+ }
+
+ private ISensorVerification getVerification(float[] expected, float[] threshold,
+ float[] ... values) {
+ ISensorVerification verification = new MeanVerification(expected, threshold);
+ for (float[] value : values) {
+ verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+ }
+ return verification;
+ }
+
+ private void verifyStats(SensorStats stats, boolean passed, float[] means) {
+ assertEquals(passed, stats.getValue(MeanVerification.PASSED_KEY));
+ float[] actual = (float[]) stats.getValue(SensorStats.MEAN_KEY);
+ for (int i = 0; i < means.length; i++) {
+ assertEquals(means[i], actual[i], 0.1);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/SigNumVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/SigNumVerification.java
new file mode 100644
index 0000000..9428d1d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/SigNumVerification.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import junit.framework.Assert;
+
+/**
+ * A {@link ISensorVerification} which verifies that the sign of each of the sensor values is
+ * correct.
+ * <p>
+ * If the value of the measurement is in [-threshold, threshold], the sign is considered 0. If
+ * it is less than -threshold, it is considered -1. If it is greater than threshold, it is
+ * considered 1.
+ * </p>
+ */
+public class SigNumVerification extends AbstractMeanVerification {
+ public static final String PASSED_KEY = "sig_num_passed";
+
+ private final int[] mExpected;
+ private final float[] mThreshold;
+
+ /**
+ * Construct a {@link SigNumVerification}
+ *
+ * @param expected the expected values
+ * @param threshold the threshold that needs to be crossed to consider a measurement nonzero
+ * @throws IllegalStateException if the expected values are not 0, -1, or 1.
+ */
+ public SigNumVerification(int[] expected, float[] threshold) {
+ for (int i = 0; i < expected.length; i++) {
+ if (!(expected[i] == -1 || expected[i] == 0 || expected[i] == 1)) {
+ throw new IllegalArgumentException("Expected value must be -1, 0, or 1");
+ }
+ }
+
+ mExpected = expected;
+ mThreshold = threshold;
+ }
+
+ /**
+ * Verify that the sign of each of the sensor values is correct. Add {@value #PASSED_KEY} and
+ * {@value SensorStats#MEAN_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ if (getCount() < 1) {
+ stats.addValue(PASSED_KEY, true);
+ return;
+ }
+
+ float[] means = getMeans();
+
+ boolean failed = false;
+ StringBuilder meanSb = new StringBuilder();
+ StringBuilder expectedSb = new StringBuilder();
+
+ if (means.length > 1) {
+ meanSb.append("(");
+ expectedSb.append("(");
+ }
+ for (int i = 0; i < means.length; i++) {
+ meanSb.append(String.format("%.2f", means[i]));
+ if (i != means.length - 1) meanSb.append(", ");
+
+ if (mExpected[i] == 0) {
+ if (Math.abs(means[i]) > mThreshold[i]) {
+ failed = true;
+ }
+ expectedSb.append(String.format("[%.2f, %.2f]", -mThreshold[i], mThreshold[i]));
+ } else {
+ if (mExpected[i] > 0) {
+ if (means[i] <= mThreshold[i]) {
+ failed = true;
+ }
+ expectedSb.append(String.format("(%.2f, inf)", mThreshold[i]));
+ } else {
+ if (means[i] >= -1 * mThreshold[i]) {
+ failed = true;
+ }
+ expectedSb.append(String.format("(-inf, %.2f)", -1 * mThreshold[i]));
+ }
+ }
+ if (i != means.length - 1) expectedSb.append(", ");
+ }
+ if (means.length > 1) {
+ meanSb.append(")");
+ expectedSb.append(")");
+ }
+
+ stats.addValue(PASSED_KEY, !failed);
+ stats.addValue(SensorStats.MEAN_KEY, means);
+
+ if (failed) {
+ Assert.fail(String.format("Signum out of range: mean=%s (expected %s)",
+ meanSb.toString(), expectedSb.toString()));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SigNumVerification clone() {
+ return new SigNumVerification(mExpected, mThreshold);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/SigNumVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/SigNumVerificationTest.java
new file mode 100644
index 0000000..009ab65
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/SigNumVerificationTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link SigNumVerification}.
+ */
+public class SigNumVerificationTest extends TestCase {
+
+ /**
+ * Test {@link SigNumVerification#verify(SensorStats)}.
+ */
+ public void testVerify() {
+ float[][] values = {{1.0f, 0.2f, 0.0f, -0.2f, -1.0f}};
+
+ int[] expected = {1, 1, 0, -1, -1};
+ float[] threshold = {0.1f, 0.1f, 0.1f, 0.1f, 0.1f};
+ runVerification(true, expected, threshold, values);
+
+ expected = new int[]{1, 0, 0, 0, -1};
+ threshold = new float[]{0.5f, 0.5f, 0.5f, 0.5f, 0.5f};
+ runVerification(true, expected, threshold, values);
+
+ expected = new int[]{0, 1, 0, -1, 0};
+ threshold = new float[]{1.5f, 0.1f, 0.1f, 0.1f, 1.5f};
+ runVerification(true, expected, threshold, values);
+
+ expected = new int[]{1, 0, 0, 0, 1};
+ threshold = new float[]{0.5f, 0.5f, 0.5f, 0.5f, 0.5f};
+ runVerification(false, expected, threshold, values);
+
+ expected = new int[]{-1, 0, 0, 0, -1};
+ threshold = new float[]{0.5f, 0.5f, 0.5f, 0.5f, 0.5f};
+ runVerification(false, expected, threshold, values);
+ }
+
+ private SigNumVerification getVerification(int[] expected, float[] threshold,
+ float[] ... values) {
+ SigNumVerification verification = new SigNumVerification(expected, threshold);
+ for (float[] value : values) {
+ verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+ }
+ return verification;
+ }
+
+ private void runVerification(boolean passed, int[] expected, float[] threshold,
+ float[][] values) {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(expected, threshold, values);
+ if (passed) {
+ verification.verify(stats);
+ } else {
+ try {
+ verification.verify(stats);
+ fail("Expected an AssertionError");
+ } catch (AssertionError e) {
+ // Expected;
+ }
+ }
+ assertEquals(passed, stats.getValue(SigNumVerification.PASSED_KEY));
+ assertNotNull(stats.getValue(SensorStats.MEAN_KEY));
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
new file mode 100644
index 0000000..57b34b0
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the standard deviations is within the expected
+ * range.
+ */
+public class StandardDeviationVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "standard_deviation_passed";
+
+ // sensorType: threshold
+ private static final Map<Integer, float[]> DEFAULTS = new HashMap<Integer, float[]>(12);
+ static {
+ // Use a method so that the @deprecation warning can be set for that method only
+ setDefaults();
+ }
+
+ private final float[] mThreshold;
+
+ private float[] mMeans = null;
+ private float[] mM2s = null;
+ private int mCount = 0;
+
+ /**
+ * Construct a {@link StandardDeviationVerification}
+ *
+ * @param threshold the thresholds
+ */
+ public StandardDeviationVerification(float[] threshold) {
+ mThreshold = threshold;
+ }
+
+ /**
+ * Get the default {@link StandardDeviationVerification} for a sensor.
+ *
+ * @param sensor a {@link Sensor}
+ * @return the verification or null if the verification does not apply to the sensor.
+ */
+ public static StandardDeviationVerification getDefault(Sensor sensor) {
+ if (!DEFAULTS.containsKey(sensor.getType())) {
+ return null;
+ }
+
+ return new StandardDeviationVerification(DEFAULTS.get(sensor.getType()));
+ }
+
+ /**
+ * Verify that the standard deviation is in the acceptable range. Add {@value #PASSED_KEY} and
+ * {@value SensorStats#STANDARD_DEVIATION_KEY} keys to {@link SensorStats}.
+ *
+ * @throws AssertionError if the verification failed.
+ */
+ @Override
+ public void verify(SensorStats stats) {
+ if (mCount < 2) {
+ stats.addValue(PASSED_KEY, true);
+ return;
+ }
+
+ float[] stdDevs = new float[mM2s.length];
+ for (int i = 0; i < mM2s.length; i++) {
+ stdDevs[i] = (float) Math.sqrt(mM2s[i] / (mCount - 1));
+ }
+
+ boolean failed = false;
+ StringBuilder stddevSb = new StringBuilder();
+ StringBuilder expectedSb = new StringBuilder();
+
+ if (stdDevs.length > 1) {
+ stddevSb.append("(");
+ expectedSb.append("(");
+ }
+ for (int i = 0; i < stdDevs.length; i++) {
+ if (stdDevs[i] > mThreshold[i]) {
+ failed = true;
+ }
+ stddevSb.append(String.format("%.2f", stdDevs[i]));
+ if (i != stdDevs.length - 1) stddevSb.append(", ");
+ expectedSb.append(String.format("<%.2f", mThreshold[i]));
+ if (i != stdDevs.length - 1) expectedSb.append(", ");
+ }
+ if (stdDevs.length > 1) {
+ stddevSb.append(")");
+ expectedSb.append(")");
+ }
+
+ stats.addValue(PASSED_KEY, !failed);
+ stats.addValue(SensorStats.STANDARD_DEVIATION_KEY, stdDevs);
+
+ if (failed) {
+ Assert.fail(String.format("Standard deviation out of range: stddev=%s (expected %s)",
+ stddevSb.toString(), expectedSb.toString()));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public StandardDeviationVerification clone() {
+ return new StandardDeviationVerification(mThreshold);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Computes the standard deviation using
+ * <a href="http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm">
+ * Welford's algorith</a>.
+ * </p>
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ if (mMeans == null || mM2s == null) {
+ mMeans = new float[event.values.length];
+ mM2s = new float[event.values.length];
+ }
+
+ Assert.assertEquals(mMeans.length, event.values.length);
+ Assert.assertEquals(mM2s.length, event.values.length);
+
+ mCount++;
+
+ for (int i = 0; i < event.values.length; i++) {
+ float delta = event.values[i] - mMeans[i];
+ mMeans[i] += delta / mCount;
+ mM2s[i] += delta * (event.values[i] - mMeans[i]);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private static void setDefaults() {
+ DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, new float[]{1.0f, 1.0f, 1.0f});
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE, new float[]{0.5f, 0.5f, 0.5f});
+ // Sensors that we don't want to test at this time but still want to record the values.
+ DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_ORIENTATION,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_PRESSURE,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_GRAVITY,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_LINEAR_ACCELERATION,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_ROTATION_VECTOR,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_GAME_ROTATION_VECTOR,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE, Float.MAX_VALUE});
+ DEFAULTS.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR,
+ new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+ Float.MAX_VALUE});
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerificationTest.java
new file mode 100644
index 0000000..308f114
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerificationTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link StandardDeviationVerification}.
+ */
+public class StandardDeviationVerificationTest extends TestCase {
+
+ /**
+ * Test {@link StandardDeviationVerification#verify(SensorStats)}.
+ */
+ public void testVerify() {
+ // Stddev should be {sqrt(2.5), sqrt(2.5), sqrt(2.5)}
+ float[][] values = {
+ {0, 1, 0},
+ {1, 2, 2},
+ {2, 3, 4},
+ {3, 4, 6},
+ {4, 5, 8},
+ };
+ float[] standardDeviations = {
+ (float) Math.sqrt(2.5), (float) Math.sqrt(2.5), (float) Math.sqrt(10.0)
+ };
+
+ float[] threshold = {2, 2, 4};
+ runVerification(threshold, values, true, standardDeviations);
+
+ threshold = new float[]{1, 2, 4};
+ runVerification(threshold, values, false, standardDeviations);
+
+ threshold = new float[]{2, 1, 4};
+ runVerification(threshold, values, false, standardDeviations);
+
+ threshold = new float[]{2, 2, 3};
+ runVerification(threshold, values, false, standardDeviations);
+ }
+
+ private void runVerification(float[] threshold, float[][] values, boolean pass,
+ float[] standardDeviations) {
+ SensorStats stats = new SensorStats();
+ ISensorVerification verification = getVerification(threshold, values);
+ if (pass) {
+ verification.verify(stats);
+ } else {
+ boolean failed = false;
+ try {
+ verification.verify(stats);
+ } catch (AssertionError e) {
+ // Expected;
+ failed = true;
+ }
+ assertTrue("Expected an AssertionError", failed);
+ }
+ assertEquals(pass, stats.getValue(StandardDeviationVerification.PASSED_KEY));
+ float[] actual = (float[]) stats.getValue(SensorStats.STANDARD_DEVIATION_KEY);
+ for (int i = 0; i < standardDeviations.length; i++) {
+ assertEquals(standardDeviations[i], actual[i], 0.1);
+ }
+ }
+
+ private ISensorVerification getVerification(float[] threshold, float[] ... values) {
+ ISensorVerification verification = new StandardDeviationVerification(threshold);
+ for (float[] value : values) {
+ verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+ }
+ return verification;
+ }
+}
diff --git a/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp b/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp
index d728fc0..90c8100 100644
--- a/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp
+++ b/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp
@@ -274,7 +274,7 @@
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_maxU8(JNIEnv*, jclass, jbyte x, jbyte y) {
- return std::max((unsigned char)x, (unsigned char)y);
+ return std::max((uint8_t)x, (uint8_t)y);
}
extern "C" JNIEXPORT jshort JNICALL
@@ -284,7 +284,7 @@
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_maxU16(JNIEnv*, jclass, jshort x, jshort y) {
- return std::max((unsigned short)x, (unsigned short)y);
+ return std::max((uint16_t)x, (uint16_t)y);
}
extern "C" JNIEXPORT jint JNICALL
@@ -294,7 +294,7 @@
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_maxU32(JNIEnv*, jclass, jint x, jint y) {
- return std::max((unsigned int)x, (unsigned int)y);
+ return std::max((uint32_t)x, (uint32_t)y);
}
extern "C" JNIEXPORT jlong JNICALL
@@ -304,7 +304,7 @@
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_maxU64(JNIEnv*, jclass, jlong x, jlong y) {
- return std::max((unsigned long)x, (unsigned long)y);
+ return std::max((uint64_t)x, (uint64_t)y);
}
extern "C" JNIEXPORT jbyte JNICALL
@@ -314,7 +314,7 @@
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_minU8(JNIEnv*, jclass, jbyte x, jbyte y) {
- return std::min((unsigned char)x, (unsigned char)y);
+ return std::min((uint8_t)x, (uint8_t)y);
}
extern "C" JNIEXPORT jshort JNICALL
@@ -324,7 +324,7 @@
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_minU16(JNIEnv*, jclass, jshort x, jshort y) {
- return std::min((unsigned short)x, (unsigned short)y);
+ return std::min((uint16_t)x, (uint16_t)y);
}
extern "C" JNIEXPORT jint JNICALL
@@ -334,7 +334,7 @@
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_minU32(JNIEnv*, jclass, jint x, jint y) {
- return std::min((unsigned int)x, (unsigned int)y);
+ return std::min((uint32_t)x, (uint32_t)y);
}
extern "C" JNIEXPORT jlong JNICALL
@@ -344,7 +344,7 @@
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_minU64(JNIEnv*, jclass, jlong x, jlong y) {
- return std::min((unsigned long)x, (unsigned long)y);
+ return std::min((uint64_t)x, (uint64_t)y);
}
extern "C" JNIEXPORT jfloat JNICALL
@@ -409,363 +409,363 @@
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToChar(JNIEnv*, jclass, jbyte x) {
- return (jbyte)(signed char)(signed char)x;
+ return (jbyte)(int8_t)(int8_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToUchar(JNIEnv*, jclass, jbyte x) {
- return (jbyte)(unsigned char)(signed char)x;
+ return (jbyte)(uint8_t)(int8_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToShort(JNIEnv*, jclass, jbyte x) {
- return (jshort)(short)(signed char)x;
+ return (jshort)(int16_t)(int8_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToUshort(JNIEnv*, jclass, jbyte x) {
- return (jshort)(unsigned short)(signed char)x;
+ return (jshort)(uint16_t)(int8_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToInt(JNIEnv*, jclass, jbyte x) {
- return (jint)(int)(signed char)x;
+ return (jint)(int32_t)(int8_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToUint(JNIEnv*, jclass, jbyte x) {
- return (jint)(unsigned int)(signed char)x;
+ return (jint)(uint32_t)(int8_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToLong(JNIEnv*, jclass, jbyte x) {
- return (jlong)(long)(signed char)x;
+ return (jlong)(int64_t)(int8_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToUlong(JNIEnv*, jclass, jbyte x) {
- return (jlong)(unsigned long)(signed char)x;
+ return (jlong)(uint64_t)(int8_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToFloat(JNIEnv*, jclass, jbyte x) {
- return (jfloat)(float)(signed char)x;
+ return (jfloat)(float)(int8_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertCharToDouble(JNIEnv*, jclass, jbyte x) {
- return (jdouble)(double)(signed char)x;
+ return (jdouble)(double)(int8_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToChar(JNIEnv*, jclass, jbyte x) {
- return (jbyte)(signed char)(unsigned char)x;
+ return (jbyte)(int8_t)(uint8_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUchar(JNIEnv*, jclass, jbyte x) {
- return (jbyte)(unsigned char)(unsigned char)x;
+ return (jbyte)(uint8_t)(uint8_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToShort(JNIEnv*, jclass, jbyte x) {
- return (jshort)(short)(unsigned char)x;
+ return (jshort)(int16_t)(uint8_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUshort(JNIEnv*, jclass, jbyte x) {
- return (jshort)(unsigned short)(unsigned char)x;
+ return (jshort)(uint16_t)(uint8_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToInt(JNIEnv*, jclass, jbyte x) {
- return (jint)(int)(unsigned char)x;
+ return (jint)(int32_t)(uint8_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUint(JNIEnv*, jclass, jbyte x) {
- return (jint)(unsigned int)(unsigned char)x;
+ return (jint)(uint32_t)(uint8_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToLong(JNIEnv*, jclass, jbyte x) {
- return (jlong)(long)(unsigned char)x;
+ return (jlong)(int64_t)(uint8_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUlong(JNIEnv*, jclass, jbyte x) {
- return (jlong)(unsigned long)(unsigned char)x;
+ return (jlong)(uint64_t)(uint8_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToFloat(JNIEnv*, jclass, jbyte x) {
- return (jfloat)(float)(unsigned char)x;
+ return (jfloat)(float)(uint8_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUcharToDouble(JNIEnv*, jclass, jbyte x) {
- return (jdouble)(double)(unsigned char)x;
+ return (jdouble)(double)(uint8_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToChar(JNIEnv*, jclass, jshort x) {
- return (jbyte)(signed char)(short)x;
+ return (jbyte)(int8_t)(int16_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToUchar(JNIEnv*, jclass, jshort x) {
- return (jbyte)(unsigned char)(short)x;
+ return (jbyte)(uint8_t)(int16_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToShort(JNIEnv*, jclass, jshort x) {
- return (jshort)(short)(short)x;
+ return (jshort)(int16_t)(int16_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToUshort(JNIEnv*, jclass, jshort x) {
- return (jshort)(unsigned short)(short)x;
+ return (jshort)(uint16_t)(int16_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToInt(JNIEnv*, jclass, jshort x) {
- return (jint)(int)(short)x;
+ return (jint)(int32_t)(int16_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToUint(JNIEnv*, jclass, jshort x) {
- return (jint)(unsigned int)(short)x;
+ return (jint)(uint32_t)(int16_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToLong(JNIEnv*, jclass, jshort x) {
- return (jlong)(long)(short)x;
+ return (jlong)(int64_t)(int16_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToUlong(JNIEnv*, jclass, jshort x) {
- return (jlong)(unsigned long)(short)x;
+ return (jlong)(uint64_t)(int16_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToFloat(JNIEnv*, jclass, jshort x) {
- return (jfloat)(float)(short)x;
+ return (jfloat)(float)(int16_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertShortToDouble(JNIEnv*, jclass, jshort x) {
- return (jdouble)(double)(short)x;
+ return (jdouble)(double)(int16_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToChar(JNIEnv*, jclass, jshort x) {
- return (jbyte)(signed char)(unsigned short)x;
+ return (jbyte)(int8_t)(uint16_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUchar(JNIEnv*, jclass, jshort x) {
- return (jbyte)(unsigned char)(unsigned short)x;
+ return (jbyte)(uint8_t)(uint16_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToShort(JNIEnv*, jclass, jshort x) {
- return (jshort)(short)(unsigned short)x;
+ return (jshort)(int16_t)(uint16_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUshort(JNIEnv*, jclass, jshort x) {
- return (jshort)(unsigned short)(unsigned short)x;
+ return (jshort)(uint16_t)(uint16_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToInt(JNIEnv*, jclass, jshort x) {
- return (jint)(int)(unsigned short)x;
+ return (jint)(int32_t)(uint16_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUint(JNIEnv*, jclass, jshort x) {
- return (jint)(unsigned int)(unsigned short)x;
+ return (jint)(uint32_t)(uint16_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToLong(JNIEnv*, jclass, jshort x) {
- return (jlong)(long)(unsigned short)x;
+ return (jlong)(int64_t)(uint16_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUlong(JNIEnv*, jclass, jshort x) {
- return (jlong)(unsigned long)(unsigned short)x;
+ return (jlong)(uint64_t)(uint16_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToFloat(JNIEnv*, jclass, jshort x) {
- return (jfloat)(float)(unsigned short)x;
+ return (jfloat)(float)(uint16_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUshortToDouble(JNIEnv*, jclass, jshort x) {
- return (jdouble)(double)(unsigned short)x;
+ return (jdouble)(double)(uint16_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToChar(JNIEnv*, jclass, jint x) {
- return (jbyte)(signed char)(int)x;
+ return (jbyte)(int8_t)(int32_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToUchar(JNIEnv*, jclass, jint x) {
- return (jbyte)(unsigned char)(int)x;
+ return (jbyte)(uint8_t)(int32_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToShort(JNIEnv*, jclass, jint x) {
- return (jshort)(short)(int)x;
+ return (jshort)(int16_t)(int32_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToUshort(JNIEnv*, jclass, jint x) {
- return (jshort)(unsigned short)(int)x;
+ return (jshort)(uint16_t)(int32_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToInt(JNIEnv*, jclass, jint x) {
- return (jint)(int)(int)x;
+ return (jint)(int32_t)(int32_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToUint(JNIEnv*, jclass, jint x) {
- return (jint)(unsigned int)(int)x;
+ return (jint)(uint32_t)(int32_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToLong(JNIEnv*, jclass, jint x) {
- return (jlong)(long)(int)x;
+ return (jlong)(int64_t)(int32_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToUlong(JNIEnv*, jclass, jint x) {
- return (jlong)(unsigned long)(int)x;
+ return (jlong)(uint64_t)(int32_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToFloat(JNIEnv*, jclass, jint x) {
- return (jfloat)(float)(int)x;
+ return (jfloat)(float)(int32_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertIntToDouble(JNIEnv*, jclass, jint x) {
- return (jdouble)(double)(int)x;
+ return (jdouble)(double)(int32_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToChar(JNIEnv*, jclass, jint x) {
- return (jbyte)(signed char)(unsigned int)x;
+ return (jbyte)(int8_t)(uint32_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToUchar(JNIEnv*, jclass, jint x) {
- return (jbyte)(unsigned char)(unsigned int)x;
+ return (jbyte)(uint8_t)(uint32_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToShort(JNIEnv*, jclass, jint x) {
- return (jshort)(short)(unsigned int)x;
+ return (jshort)(int16_t)(uint32_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToUshort(JNIEnv*, jclass, jint x) {
- return (jshort)(unsigned short)(unsigned int)x;
+ return (jshort)(uint16_t)(uint32_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToInt(JNIEnv*, jclass, jint x) {
- return (jint)(int)(unsigned int)x;
+ return (jint)(int32_t)(uint32_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToUint(JNIEnv*, jclass, jint x) {
- return (jint)(unsigned int)(unsigned int)x;
+ return (jint)(uint32_t)(uint32_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToLong(JNIEnv*, jclass, jint x) {
- return (jlong)(long)(unsigned int)x;
+ return (jlong)(int64_t)(uint32_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToUlong(JNIEnv*, jclass, jint x) {
- return (jlong)(unsigned long)(unsigned int)x;
+ return (jlong)(uint64_t)(uint32_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToFloat(JNIEnv*, jclass, jint x) {
- return (jfloat)(float)(unsigned int)x;
+ return (jfloat)(float)(uint32_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUintToDouble(JNIEnv*, jclass, jint x) {
- return (jdouble)(double)(unsigned int)x;
+ return (jdouble)(double)(uint32_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToChar(JNIEnv*, jclass, jlong x) {
- return (jbyte)(signed char)(long)x;
+ return (jbyte)(int8_t)(int64_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToUchar(JNIEnv*, jclass, jlong x) {
- return (jbyte)(unsigned char)(long)x;
+ return (jbyte)(uint8_t)(int64_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToShort(JNIEnv*, jclass, jlong x) {
- return (jshort)(short)(long)x;
+ return (jshort)(int16_t)(int64_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToUshort(JNIEnv*, jclass, jlong x) {
- return (jshort)(unsigned short)(long)x;
+ return (jshort)(uint16_t)(int64_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToInt(JNIEnv*, jclass, jlong x) {
- return (jint)(int)(long)x;
+ return (jint)(int32_t)(int64_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToUint(JNIEnv*, jclass, jlong x) {
- return (jint)(unsigned int)(long)x;
+ return (jint)(uint32_t)(int64_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToLong(JNIEnv*, jclass, jlong x) {
- return (jlong)(long)(long)x;
+ return (jlong)(int64_t)(int64_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToUlong(JNIEnv*, jclass, jlong x) {
- return (jlong)(unsigned long)(long)x;
+ return (jlong)(uint64_t)(int64_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToFloat(JNIEnv*, jclass, jlong x) {
- return (jfloat)(float)(long)x;
+ return (jfloat)(float)(int64_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertLongToDouble(JNIEnv*, jclass, jlong x) {
- return (jdouble)(double)(long)x;
+ return (jdouble)(double)(int64_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToChar(JNIEnv*, jclass, jlong x) {
- return (jbyte)(signed char)(unsigned long)x;
+ return (jbyte)(int8_t)(uint64_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUchar(JNIEnv*, jclass, jlong x) {
- return (jbyte)(unsigned char)(unsigned long)x;
+ return (jbyte)(uint8_t)(uint64_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToShort(JNIEnv*, jclass, jlong x) {
- return (jshort)(short)(unsigned long)x;
+ return (jshort)(int16_t)(uint64_t)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUshort(JNIEnv*, jclass, jlong x) {
- return (jshort)(unsigned short)(unsigned long)x;
+ return (jshort)(uint16_t)(uint64_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToInt(JNIEnv*, jclass, jlong x) {
- return (jint)(int)(unsigned long)x;
+ return (jint)(int32_t)(uint64_t)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUint(JNIEnv*, jclass, jlong x) {
- return (jint)(unsigned int)(unsigned long)x;
+ return (jint)(uint32_t)(uint64_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToLong(JNIEnv*, jclass, jlong x) {
- return (jlong)(long)(unsigned long)x;
+ return (jlong)(int64_t)(uint64_t)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUlong(JNIEnv*, jclass, jlong x) {
- return (jlong)(unsigned long)(unsigned long)x;
+ return (jlong)(uint64_t)(uint64_t)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToFloat(JNIEnv*, jclass, jlong x) {
- return (jfloat)(float)(unsigned long)x;
+ return (jfloat)(float)(uint64_t)x;
}
extern "C" JNIEXPORT jdouble JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertUlongToDouble(JNIEnv*, jclass, jlong x) {
- return (jdouble)(double)(unsigned long)x;
+ return (jdouble)(double)(uint64_t)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToChar(JNIEnv*, jclass, jfloat x) {
- return (jbyte)(signed char)(float)x;
+ return (jbyte)(int8_t)(float)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUchar(JNIEnv*, jclass, jfloat x) {
- return (jbyte)(unsigned char)(float)x;
+ return (jbyte)(uint8_t)(float)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToShort(JNIEnv*, jclass, jfloat x) {
- return (jshort)(short)(float)x;
+ return (jshort)(int16_t)(float)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUshort(JNIEnv*, jclass, jfloat x) {
- return (jshort)(unsigned short)(float)x;
+ return (jshort)(uint16_t)(float)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToInt(JNIEnv*, jclass, jfloat x) {
- return (jint)(int)(float)x;
+ return (jint)(int32_t)(float)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUint(JNIEnv*, jclass, jfloat x) {
- return (jint)(unsigned int)(float)x;
+ return (jint)(uint32_t)(float)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToLong(JNIEnv*, jclass, jfloat x) {
- return (jlong)(long)(float)x;
+ return (jlong)(int64_t)(float)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUlong(JNIEnv*, jclass, jfloat x) {
- return (jlong)(unsigned long)(float)x;
+ return (jlong)(uint64_t)(float)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertFloatToFloat(JNIEnv*, jclass, jfloat x) {
@@ -778,35 +778,35 @@
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToChar(JNIEnv*, jclass, jdouble x) {
- return (jbyte)(signed char)(double)x;
+ return (jbyte)(int8_t)(double)x;
}
extern "C" JNIEXPORT jbyte JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUchar(JNIEnv*, jclass, jdouble x) {
- return (jbyte)(unsigned char)(double)x;
+ return (jbyte)(uint8_t)(double)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToShort(JNIEnv*, jclass, jdouble x) {
- return (jshort)(short)(double)x;
+ return (jshort)(int16_t)(double)x;
}
extern "C" JNIEXPORT jshort JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUshort(JNIEnv*, jclass, jdouble x) {
- return (jshort)(unsigned short)(double)x;
+ return (jshort)(uint16_t)(double)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToInt(JNIEnv*, jclass, jdouble x) {
- return (jint)(int)(double)x;
+ return (jint)(int32_t)(double)x;
}
extern "C" JNIEXPORT jint JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUint(JNIEnv*, jclass, jdouble x) {
- return (jint)(unsigned int)(double)x;
+ return (jint)(uint32_t)(double)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToLong(JNIEnv*, jclass, jdouble x) {
- return (jlong)(long)(double)x;
+ return (jlong)(int64_t)(double)x;
}
extern "C" JNIEXPORT jlong JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUlong(JNIEnv*, jclass, jdouble x) {
- return (jlong)(unsigned long)(double)x;
+ return (jlong)(uint64_t)(double)x;
}
extern "C" JNIEXPORT jfloat JNICALL
Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToFloat(JNIEnv*, jclass, jdouble x) {
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
index 46d574f..8841b14 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
@@ -245,7 +245,7 @@
// Normalizes the n-dimensional vector, i.e. makes it length 1.
static private void normalize(float[] in, Floaty[] out, int ulpFactor, int ulpRelaxedFactor) {
Floaty l = length(in, ulpFactor, ulpRelaxedFactor);
- boolean isZero = l.getValue() == 0f;
+ boolean isZero = l.getFloatValue() == 0f;
for (int i = 0; i < in.length; i++) {
out[i] = new Floaty(in[i], ulpFactor, ulpRelaxedFactor);
if (!isZero) {
@@ -318,12 +318,12 @@
args.out = new Floaty(atan(args.inV) / (float) Math.PI, 5, 128);
}
- static public void computeAtan2(TestAtan2.ArgumentsFloatFloatFloat args) {
- args.out = new Floaty(atan2(args.inY, args.inX), 6, 128);
- }
+ static public void computeAtan2(TestAtan2.ArgumentsFloatFloatFloat args) {
+ args.out = new Floaty(atan2(args.inY, args.inX), 6, 128);
+ }
static public void computeAtan2pi(TestAtan2pi.ArgumentsFloatFloatFloat args) {
- args.out = new Floaty(atan2(args.inY, args.inX) / (float) Math.PI, 6, 128);
+ args.out = new Floaty(atan2(args.inY, args.inX) / (float) Math.PI, 6, 128);
}
static public void computeCbrt(TestCbrt.ArgumentsFloatFloat args) {
@@ -432,7 +432,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsCharDouble args) {
- args.out = convertCharToDouble(args.inV);
+ args.out = new Floaty(convertCharToDouble(args.inV), 0, 0);
}
*/
@@ -467,7 +467,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsUcharDouble args) {
- args.out = convertUcharToDouble(args.inV);
+ args.out = new Floaty(convertUcharToDouble(args.inV), 0, 0);
}
*/
@@ -502,7 +502,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsShortDouble args) {
- args.out = convertShortToDouble(args.inV);
+ args.out = new Floaty(convertShortToDouble(args.inV), 0, 0);
}
*/
@@ -537,7 +537,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsUshortDouble args) {
- args.out = convertUshortToDouble(args.inV);
+ args.out = new Floaty(convertUshortToDouble(args.inV), 0, 0);
}
*/
@@ -572,7 +572,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsIntDouble args) {
- args.out = convertIntToDouble(args.inV);
+ args.out = new Floaty(convertIntToDouble(args.inV), 0, 0);
}
*/
@@ -607,7 +607,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsUintDouble args) {
- args.out = convertUintToDouble(args.inV);
+ args.out = new Floaty(convertUintToDouble(args.inV), 0, 0);
}
*/
@@ -640,7 +640,7 @@
args.out = new Floaty(convertLongToFloat(args.inV), 1, 1);
}
static public void computeConvert(TestConvert.ArgumentsLongDouble args) {
- args.out = convertLongToDouble(args.inV);
+ args.out = new Floaty(convertLongToDouble(args.inV), 1, 1);
}
static public void computeConvert(TestConvert.ArgumentsUlongChar args) {
@@ -671,7 +671,7 @@
args.out = new Floaty(convertUlongToFloat(args.inV), 1, 1);
}
static public void computeConvert(TestConvert.ArgumentsUlongDouble args) {
- args.out = convertUlongToDouble(args.inV);
+ args.out = new Floaty(convertUlongToDouble(args.inV), 1, 1);
}
*/
@@ -706,7 +706,7 @@
}
/* TODO Not supporting double arguments currently
static public void computeConvert(TestConvert.ArgumentsFloatDouble args) {
- args.out = convertFloatToDouble(args.inV);
+ args.out = new Floaty(convertFloatToDouble(args.inV), 0, 0);
}
*/
@@ -739,7 +739,7 @@
args.out = new Floaty(convertDoubleToFloat(args.inV), 1, 1);
}
static public void computeConvert(TestConvert.ArgumentsDoubleDouble args) {
- args.out = convertDoubleToDouble(args.inV);
+ args.out = new Floaty(convertDoubleToDouble(args.inV), 0, 0);
}
*/
@@ -891,12 +891,10 @@
args.outIptr = result.exponent;
}
- /* TODO enable once precision has been improved.
static public void computeHalfRecip(TestHalfRecip.ArgumentsFloatFloat args) {
// TODO we would like to use HALF_PRECISION, HALF_PRECISION
args.out = new Floaty(1.0f / args.inV, 64000, 64000);
}
- */
static public void computeHalfRsqrt(TestHalfRsqrt.ArgumentsFloatFloat args) {
// TODO we would like to use HALF_PRECISION, HALF_PRECISION
@@ -938,7 +936,7 @@
args.outY = result.gammaSign;
}
- // TODO The relaxed ulf for the various log are taken from the old tests.
+ // TODO The relaxed ulf for the various log are taken from the old tests.
// They are not consistent.
static public void computeLog(TestLog.ArgumentsFloatFloat args) {
args.out = new Floaty(log(args.in), 3, 16);
@@ -987,7 +985,16 @@
static public void computeMax(TestMax.ArgumentsUintUintUint args) {
args.out = maxU32(args.inV1, args.inV2);
}
- // TODO we probably need a long version of max and min
+
+ /* TODO enable once precision has been improved.
+ static public void computeMax(TestMax.ArgumentsLongLongLong args) {
+ args.out = maxI64(args.inV1, args.inV2);
+ }
+
+ static public void computeMax(TestMax.ArgumentsUlongUlongUlong args) {
+ args.out = maxU64(args.inV1, args.inV2);
+ }
+ */
static public void computeMax(TestMax.ArgumentsFloatFloatFloat args) {
args.out = new Floaty(Math.max(args.in, args.in1), 0, 0);
@@ -1017,6 +1024,16 @@
args.out = minU32(args.inV1, args.inV2);
}
+ /* TODO enable once precision has been improved.
+ static public void computeMin(TestMin.ArgumentsLongLongLong args) {
+ args.out = minI64(args.inV1, args.inV2);
+ }
+
+ static public void computeMin(TestMin.ArgumentsUlongUlongUlong args) {
+ args.out = minU64(args.inV1, args.inV2);
+ }
+ */
+
static public void computeMin(TestMin.ArgumentsFloatFloatFloat args) {
args.out = new Floaty(Math.min(args.in, args.in1), 0, 0);
}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Floaty.java b/tests/tests/renderscript/src/android/renderscript/cts/Floaty.java
index 657b3dd..608e172 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/Floaty.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Floaty.java
@@ -19,13 +19,19 @@
import android.util.Log;
/**
- * This class keeps track of a float and the computation error that has accumulated in creating
- * this number. We also provide the four basic arithmetic operators and sqrt that compute the
- * correct error of the result.
+ * This class keeps track of a floating point value and the computation error that has accumulated
+ * in creating this number. We also provide the four basic arithmetic operators and sqrt that
+ * compute the correct error of the result.
*/
public class Floaty {
- private float mValue; // The value this float reprensent.
- private float mError; // The real value should be between mValue - mError and mValue + mError.
+ private double mValue; // The value this instance represent.
+ private double mError; // The real value should be between mValue - mError and mValue + mError.
+ /* The number of bits the value should have, either 32 or 64. It would have been nice to
+ * use generics, e.g. Floaty<float> and Floaty<double> but Java does not support generics
+ * of float and double. Also, Java does not have a f16 type. This can simulate it, although
+ * more work will be needed.
+ */
+ private int mNumberOfBits;
static private boolean relaxed; // Whether we are doing relaxed precision computations.
@@ -36,26 +42,52 @@
public Floaty(Floaty a) {
mValue = a.mValue;
mError = a.mError;
+ mNumberOfBits = a.mNumberOfBits;
}
public Floaty(float a) {
mValue = a;
+ mNumberOfBits = 32;
+ setErrorFromValue(1, 1);
+ }
+
+ public Floaty(double a) {
+ mValue = a;
+ mNumberOfBits = 64;
setErrorFromValue(1, 1);
}
/** Sets the value and the error based on whether we're doing relaxed computations or not. */
public Floaty(float v, int ulpFactor, int ulpRelaxedFactor) {
mValue = v;
+ mNumberOfBits = 32;
setErrorFromValue(ulpFactor, ulpRelaxedFactor);
}
- public float getValue() { return mValue; }
+ public Floaty(double v, int ulpFactor, int ulpRelaxedFactor) {
+ mValue = v;
+ mNumberOfBits = 64;
+ setErrorFromValue(ulpFactor, ulpRelaxedFactor);
+ }
- public float getError() { return mError; }
+ public float getFloatValue() { return (float) mValue; }
+ public double getDoubleValue() { return mValue; }
+
+ public float getFloatError() { return (float) mError; }
+ public double getDoubleError() { return mError; }
/** Returns the number we would need to multiply the ulp to get the current error. */
public int getUlf() {
- return (int) Math.abs(mError / Math.ulp(mValue));
+ return (int) Math.abs(mError / getUlp());
+ }
+
+ /** Returns the unit of least precision for the number we handle. */
+ private double getUlp() {
+ if (mNumberOfBits == 64) {
+ return Math.ulp(mValue);
+ } else {
+ return Math.ulp((float) mValue);
+ }
}
/**
@@ -64,36 +96,37 @@
*/
private void setErrorFromValue(int ulpFactor, int ulpRelaxedFactor) {
int factor = relaxed ? ulpRelaxedFactor : ulpFactor;
- mError = Math.ulp(mValue) * factor;
+ mError = getUlp() * factor;
}
/**
* Creates a new Floaty as the result of a computation. The precision factor are those
* associated with the operation just completed.
*/
- public Floaty(float actual, float valueMinusError, float valuePlusError, int ulpFactor,
- int ulpRelaxedFactor) {
+ private Floaty(double actual, double valueMinusError, double valuePlusError, int ulpFactor,
+ int ulpRelaxedFactor, int numberOfBits) {
mValue = actual;
mError = 0f;
expandError(valueMinusError);
expandError(valuePlusError);
mError *= relaxed ? ulpRelaxedFactor : ulpFactor;
+ mNumberOfBits = numberOfBits;
}
/** If needed, increases the error so that the provided value is covered by the error range. */
- private void expandError(float valueWithError) {
+ private void expandError(double valueWithError) {
// We disregard NaN values that can be produced when testing close to a cliff.
if (valueWithError != valueWithError) {
return;
}
- float delta = Math.abs(valueWithError - mValue);
+ double delta = Math.abs(valueWithError - mValue);
if (delta > mError) {
mError = delta;
}
}
/** Returns true if the number passed is within mError of our value. */
- public boolean couldBe(float a) {
+ public boolean couldBe(double a) {
return couldBe(a, 0.0);
}
@@ -101,7 +134,7 @@
* Returns true if the number passed is within mError of our value, or if it's whithin
* minimumError of the value.
*/
- public boolean couldBe(float a, double minimumError) {
+ public boolean couldBe(double a, double minimumError) {
if (a != a && mValue != mValue) {
return true; // Both are NaN
}
@@ -110,7 +143,7 @@
if (a == mValue) {
return true;
}
- float error = (float) Math.max(mError, minimumError);
+ double error = Math.max(mError, minimumError);
boolean inRange = mValue - error <= a && a <= mValue + error;
/* This is useful for debugging:
@@ -127,8 +160,8 @@
}
public String toString() {
- return String.format("%14.9g (%8x) +- %14.9g ulf %d", mValue,
- Float.floatToRawIntBits(mValue), mError, getUlf());
+ return String.format("%24.9g (%16x) +- %24.9g ulf %d (%d bits)", mValue,
+ Double.doubleToRawLongBits(mValue), mError, getUlf(), mNumberOfBits);
}
public boolean isNaN() {
@@ -157,8 +190,8 @@
}
public Floaty divide(Floaty a) {
- float num = Math.abs(mValue);
- float den = Math.abs(a.mValue);
+ double num = Math.abs(mValue);
+ double den = Math.abs(a.mValue);
mError = (num * a.mError + den * mError) / (den * (den - a.mError));
mValue /= a.mValue;
return this;
@@ -188,10 +221,10 @@
static public Floaty sqrt(Floaty a) {
Floaty f = new Floaty(
- (float) Math.sqrt(a.mValue),
- (float) Math.sqrt(a.mValue - a.mError),
- (float) Math.sqrt(a.mValue + a.mError),
- 3, 10);
+ Math.sqrt(a.mValue),
+ Math.sqrt(a.mValue - a.mError),
+ Math.sqrt(a.mValue + a.mError),
+ 3, 10, a.mNumberOfBits);
return f;
}
}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
new file mode 100644
index 0000000..830982f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript.cts;
+
+import android.renderscript.*;
+import android.util.Log;
+
+public class Intrinsic3DLut extends IntrinsicBase {
+ private Allocation mCube;
+ private ScriptC_intrinsic_3dlut mScript;
+ private ScriptIntrinsic3DLUT mIntrinsic;
+ final int sx = 32;
+ final int sy = 32;
+ final int sz = 16;
+
+ private void genCubeIdent() {
+ int dat[] = new int[sx * sy * sz];
+ for (int z = 0; z < sz; z++) {
+ for (int y = 0; y < sy; y++) {
+ for (int x = 0; x < sx; x++ ) {
+ int v = 0xff000000;
+ v |= (0xff * x / (sx - 1));
+ v |= (0xff * y / (sy - 1)) << 8;
+ v |= (0xff * z / (sz - 1)) << 16;
+ dat[z*sy*sx + y*sx + x] = v;
+ }
+ }
+ }
+
+ mCube.copyFromUnchecked(dat);
+ }
+
+ private void genCubeRand() {
+ java.util.Random r = new java.util.Random(100);
+ int dat[] = new int[sx * sy * sz];
+ for (int z = 0; z < sz; z++) {
+ for (int y = 0; y < sy; y++) {
+ for (int x = 0; x < sx; x++ ) {
+ int v = 0xff000000;
+ v |= r.nextInt(0x100);
+ v |= r.nextInt(0x100) << 8;
+ v |= r.nextInt(0x100) << 16;
+ dat[z*sy*sx + y*sx + x] = v;
+ }
+ }
+ }
+
+ mCube.copyFromUnchecked(dat);
+ }
+
+ private void initCube() {
+ Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+ tb.setX(sx);
+ tb.setY(sy);
+ tb.setZ(sz);
+ Type t = tb.create();
+ mCube = Allocation.createTyped(mRS, t);
+ genCubeIdent();
+
+ mScript = new ScriptC_intrinsic_3dlut(mRS);
+ mScript.invoke_setCube(mCube);
+
+ mIntrinsic = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+ mIntrinsic.setLUT(mCube);
+ }
+
+ public void test1() {
+ initCube();
+ makeBuffers(97, 97, Element.U8_4(mRS));
+
+ mIntrinsic.forEach(mAllocSrc, mAllocDst);
+ mScript.forEach_root(mAllocSrc, mAllocRef);
+
+ mVerify.set_gAllowedIntError(1);
+ mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+ mRS.finish();
+ checkError();
+ }
+
+ public void test2() {
+ initCube();
+ makeBuffers(97, 97, Element.U8_4(mRS));
+ genCubeRand();
+
+ mIntrinsic.forEach(mAllocSrc, mAllocDst);
+ mScript.forEach_root(mAllocSrc, mAllocRef);
+
+ mVerify.set_gAllowedIntError(2);
+ mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+ mRS.finish();
+ checkError();
+ }
+
+
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
new file mode 100644
index 0000000..aa67012
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
@@ -0,0 +1,113 @@
+/*
+ * 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.renderscript.cts;
+
+import android.renderscript.*;
+import android.util.Log;
+
+public class IntrinsicBlur extends IntrinsicBase {
+ private ScriptIntrinsicBlur mIntrinsic;
+ private int MAX_RADIUS = 25;
+ private ScriptC_intrinsic_blur mScript;
+ private float mRadius = MAX_RADIUS;
+ private float mSaturation = 1.0f;
+ private Allocation mScratchPixelsAllocation1;
+ private Allocation mScratchPixelsAllocation2;
+
+
+
+ private void initTest(int w, int h, Element e) {
+ makeBuffers(w, h, e);
+
+ Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+ tb.setX(w);
+ tb.setY(h);
+ mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+ mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+ mIntrinsic = ScriptIntrinsicBlur.create(mRS, e);
+ mIntrinsic.setRadius(MAX_RADIUS);
+ mIntrinsic.setInput(mAllocSrc);
+
+ mScript = new ScriptC_intrinsic_blur(mRS);
+ mScript.set_width(w);
+ mScript.set_height(h);
+ mScript.invoke_setRadius(MAX_RADIUS);
+
+ mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+ mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+
+ // Make reference
+ copyInput();
+ mScript.forEach_horz(mScratchPixelsAllocation2);
+ mScript.forEach_vert(mScratchPixelsAllocation1);
+ copyOutput();
+ }
+
+ private void copyInput() {
+ if (mAllocSrc.getType().getElement().isCompatible(Element.U8(mRS))) {
+ mScript.forEach_convert1_uToF(mAllocSrc, mScratchPixelsAllocation1);
+ return;
+ }
+ if (mAllocSrc.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+ mScript.forEach_convert4_uToF(mAllocSrc, mScratchPixelsAllocation1);
+ return;
+ }
+ throw new IllegalArgumentException("bad type");
+ }
+
+ private void copyOutput() {
+ if (mAllocSrc.getType().getElement().isCompatible(Element.U8(mRS))) {
+ mScript.forEach_convert1_fToU(mScratchPixelsAllocation1, mAllocRef);
+ return;
+ }
+ if (mAllocSrc.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+ mScript.forEach_convert4_fToU(mScratchPixelsAllocation1, mAllocRef);
+ return;
+ }
+ throw new IllegalArgumentException("bad type");
+ }
+
+ public void testU8_1() {
+ final int w = 97;
+ final int h = 97;
+ Element e = Element.U8(mRS);
+ initTest(w, h, e);
+
+ mIntrinsic.forEach(mAllocDst);
+
+ mVerify.set_gAllowedIntError(1);
+ mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+ mRS.finish();
+ checkError();
+ }
+
+ public void testU8_4() {
+ final int w = 97;
+ final int h = 97;
+ Element e = Element.U8_4(mRS);
+ initTest(w, h, e);
+
+ mIntrinsic.forEach(mAllocDst);
+
+ mVerify.set_gAllowedIntError(1);
+ mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+ mRS.finish();
+ checkError();
+ }
+
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java b/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java
index 29183f0..ebf15dc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java
@@ -28,7 +28,7 @@
* Base RenderScript test class. This class provides a message handler and a
* convenient way to wait for compute scripts to complete their execution.
*/
-class RSBase extends AndroidTestCase {
+public class RSBase extends AndroidTestCase {
Context mCtx;
Resources mRes;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
index 3ceb6df..f217bc3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
@@ -26,7 +26,7 @@
* Base RenderScript test class. This class provides a message handler and a
* convenient way to wait for compute scripts to complete their execution.
*/
-class RSBaseCompute extends RSBase {
+public class RSBaseCompute extends RSBase {
RenderScript mRS;
protected int INPUTSIZE = 512;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
index 06367b9..acb8b1d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
@@ -163,4 +163,17 @@
array[i] = (byte) longs[i];
}
}
+
+ // Compares two unsigned long. Returns < 0 if a < b, 0 if a == b, > 0 if a > b.
+ public static long compareUnsignedLong(long a, long b) {
+ long aFirstFourBits = a >>> 60;
+ long bFirstFourBits = b >>> 60;
+ long firstFourBitsDiff = aFirstFourBits - bFirstFourBits;
+ if (firstFourBitsDiff != 0) {
+ return firstFourBitsDiff;
+ }
+ long aRest = a & 0x0fffffffffffffffl;
+ long bRest = b & 0x0fffffffffffffffl;
+ return aRest - bRest;
+ }
}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java b/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java
index 67e8c1d..eae020d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java
@@ -40,7 +40,7 @@
}
private void checkConvertFloat2Float2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb5215c44e1f6ac6l, -1.6163412429e+38, 1.6163412429e+38);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb5215c44e1f6ac6l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
script.forEach_testConvertFloat2Float2Float2(inV, out);
@@ -99,7 +99,7 @@
}
private void checkConvertFloat3Float3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb53dedf443a8ba4l, -1.6163412429e+38, 1.6163412429e+38);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb53dedf443a8ba4l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
script.forEach_testConvertFloat3Float3Float3(inV, out);
@@ -158,7 +158,7 @@
}
private void checkConvertFloat4Float4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb55a7fa3a55ac82l, -1.6163412429e+38, 1.6163412429e+38);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb55a7fa3a55ac82l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
script.forEach_testConvertFloat4Float4Float4(inV, out);
@@ -1296,7 +1296,7 @@
}
private void checkConvertFloat2Char2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb25829789662l, -1.2800000000e+02, 1.2700000000e+02);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb25829789662l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
script.forEach_testConvertChar2Float2Char2(inV, out);
@@ -1354,7 +1354,7 @@
}
private void checkConvertFloat3Char3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cbcf988805b56l, -1.2800000000e+02, 1.2700000000e+02);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cbcf988805b56l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
script.forEach_testConvertChar3Float3Char3(inV, out);
@@ -1412,7 +1412,7 @@
}
private void checkConvertFloat4Char4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239cc79ae788204al, -1.2800000000e+02, 1.2700000000e+02);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239cc79ae788204al, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
script.forEach_testConvertChar4Float4Char4(inV, out);
@@ -2531,7 +2531,7 @@
}
private void checkConvertFloat2Uchar2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb52b2f4fac15b79l, 0.0000000000e+00, 2.5500000000e+02);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb52b2f4fac15b79l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
script.forEach_testConvertUchar2Float2Uchar2(inV, out);
@@ -2589,7 +2589,7 @@
}
private void checkConvertFloat3Uchar3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb547c0ff0dc7c57l, 0.0000000000e+00, 2.5500000000e+02);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb547c0ff0dc7c57l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
script.forEach_testConvertUchar3Float3Uchar3(inV, out);
@@ -2647,7 +2647,7 @@
}
private void checkConvertFloat4Uchar4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56452ae6f79d35l, 0.0000000000e+00, 2.5500000000e+02);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56452ae6f79d35l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
script.forEach_testConvertUchar4Float4Uchar4(inV, out);
@@ -3766,7 +3766,7 @@
}
private void checkConvertFloat2Short2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb529ef98fcf2692l, -3.2768000000e+04, 3.2767000000e+04);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb529ef98fcf2692l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
script.forEach_testConvertShort2Float2Short2(inV, out);
@@ -3824,7 +3824,7 @@
}
private void checkConvertFloat3Short3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb54681485ea4770l, -3.2768000000e+04, 3.2767000000e+04);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb54681485ea4770l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
script.forEach_testConvertShort3Float3Short3(inV, out);
@@ -3882,7 +3882,7 @@
}
private void checkConvertFloat4Short4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56312f7c05684el, -3.2768000000e+04, 3.2767000000e+04);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56312f7c05684el, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
script.forEach_testConvertShort4Float4Short4(inV, out);
@@ -5001,7 +5001,7 @@
}
private void checkConvertFloat2Ushort2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x36e4b950b708416fl, 0.0000000000e+00, 6.5535000000e+04);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x36e4b950b708416fl, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
script.forEach_testConvertUshort2Float2Ushort2(inV, out);
@@ -5059,7 +5059,7 @@
}
private void checkConvertFloat3Ushort3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x373180d80d63d29bl, 0.0000000000e+00, 6.5535000000e+04);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x373180d80d63d29bl, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
script.forEach_testConvertUshort3Float3Ushort3(inV, out);
@@ -5117,7 +5117,7 @@
}
private void checkConvertFloat4Ushort4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x377e485f63bf63c7l, 0.0000000000e+00, 6.5535000000e+04);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x377e485f63bf63c7l, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
script.forEach_testConvertUshort4Float4Ushort4(inV, out);
@@ -6236,7 +6236,7 @@
}
private void checkConvertFloat2Int2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8fb63fb7c069dd5dl, -2.1474836480e+09, 2.1474836470e+09);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8fb63fb7c069dd5dl, -2.1474835210000000000e+09, 2.1474835200000000000e+09);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
script.forEach_testConvertInt2Float2Int2(inV, out);
@@ -6294,7 +6294,7 @@
}
private void checkConvertFloat3Int3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8fb63ff70a11ed93l, -2.1474836480e+09, 2.1474836470e+09);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8fb63ff70a11ed93l, -2.1474835210000000000e+09, 2.1474835200000000000e+09);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
script.forEach_testConvertInt3Float3Int3(inV, out);
@@ -6352,7 +6352,7 @@
}
private void checkConvertFloat4Int4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8fb6403653b9fdc9l, -2.1474836480e+09, 2.1474836470e+09);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8fb6403653b9fdc9l, -2.1474835210000000000e+09, 2.1474835200000000000e+09);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
script.forEach_testConvertInt4Float4Int4(inV, out);
@@ -7471,7 +7471,7 @@
}
private void checkConvertFloat2Uint2() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb6cd424dca22l, 0.0000000000e+00, 4.2949672950e+09);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb6cd424dca22l, 0.0000000000000000000e+00, 4.2949670400000000000e+09);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
script.forEach_testConvertUint2Float2Uint2(inV, out);
@@ -7529,7 +7529,7 @@
}
private void checkConvertFloat3Uint3() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cc16ea1558f16l, 0.0000000000e+00, 4.2949672950e+09);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cc16ea1558f16l, 0.0000000000000000000e+00, 4.2949670400000000000e+09);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
script.forEach_testConvertUint3Float3Uint3(inV, out);
@@ -7587,7 +7587,7 @@
}
private void checkConvertFloat4Uint4() {
- Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239ccc10005d540al, 0.0000000000e+00, 4.2949672950e+09);
+ Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239ccc10005d540al, 0.0000000000000000000e+00, 4.2949670400000000000e+09);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
script.forEach_testConvertUint4Float4Uint4(inV, out);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java
index 9a27480..91cc567 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java
@@ -34,70 +34,247 @@
scriptRelaxed = new ScriptC_TestHalfRecipRelaxed(mRS);
}
+ public class ArgumentsFloatFloat {
+ public float inV;
+ public Floaty out;
+ }
+
private void checkHalfRecipFloatFloat() {
Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x854e263130d5b3dl, false);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
script.forEach_testHalfRecipFloatFloat(inV, out);
+ verifyResultsHalfRecipFloatFloat(inV, out, false);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloatFloat: " + e.toString());
}
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
scriptRelaxed.forEach_testHalfRecipFloatFloat(inV, out);
+ verifyResultsHalfRecipFloatFloat(inV, out, true);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloatFloat: " + e.toString());
}
}
+ private void verifyResultsHalfRecipFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+ float[] arrayInV = new float[INPUTSIZE * 1];
+ inV.copyTo(arrayInV);
+ float[] arrayOut = new float[INPUTSIZE * 1];
+ out.copyTo(arrayOut);
+ for (int i = 0; i < INPUTSIZE; i++) {
+ for (int j = 0; j < 1 ; j++) {
+ // Extract the inputs.
+ ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+ args.inV = arrayInV[i];
+ // Figure out what the outputs should have been.
+ Floaty.setRelaxed(relaxed);
+ CoreMathVerifier.computeHalfRecip(args);
+ // Figure out what the outputs should have been.
+ boolean valid = true;
+ if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+ valid = false;
+ }
+ if (!valid) {
+ StringBuilder message = new StringBuilder();
+ message.append("Input inV: ");
+ message.append(String.format("%14.8g %8x %15a",
+ args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+ message.append("\n");
+ message.append("Expected output out: ");
+ message.append(args.out.toString());
+ message.append("\n");
+ message.append("Actual output out: ");
+ message.append(String.format("%14.8g %8x %15a",
+ arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+ if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+ message.append(" FAIL");
+ }
+ message.append("\n");
+ assertTrue("Incorrect output for checkHalfRecipFloatFloat" +
+ (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+ }
+ }
+ }
+ }
+
private void checkHalfRecipFloat2Float2() {
Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2cf1d2db5ff23c79l, false);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
script.forEach_testHalfRecipFloat2Float2(inV, out);
+ verifyResultsHalfRecipFloat2Float2(inV, out, false);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat2Float2: " + e.toString());
}
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
scriptRelaxed.forEach_testHalfRecipFloat2Float2(inV, out);
+ verifyResultsHalfRecipFloat2Float2(inV, out, true);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat2Float2: " + e.toString());
}
}
+ private void verifyResultsHalfRecipFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+ float[] arrayInV = new float[INPUTSIZE * 2];
+ inV.copyTo(arrayInV);
+ float[] arrayOut = new float[INPUTSIZE * 2];
+ out.copyTo(arrayOut);
+ for (int i = 0; i < INPUTSIZE; i++) {
+ for (int j = 0; j < 2 ; j++) {
+ // Extract the inputs.
+ ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+ args.inV = arrayInV[i * 2 + j];
+ // Figure out what the outputs should have been.
+ Floaty.setRelaxed(relaxed);
+ CoreMathVerifier.computeHalfRecip(args);
+ // Figure out what the outputs should have been.
+ boolean valid = true;
+ if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+ valid = false;
+ }
+ if (!valid) {
+ StringBuilder message = new StringBuilder();
+ message.append("Input inV: ");
+ message.append(String.format("%14.8g %8x %15a",
+ args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+ message.append("\n");
+ message.append("Expected output out: ");
+ message.append(args.out.toString());
+ message.append("\n");
+ message.append("Actual output out: ");
+ message.append(String.format("%14.8g %8x %15a",
+ arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+ if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+ message.append(" FAIL");
+ }
+ message.append("\n");
+ assertTrue("Incorrect output for checkHalfRecipFloat2Float2" +
+ (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+ }
+ }
+ }
+ }
+
private void checkHalfRecipFloat3Float3() {
Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2cf39bf6560d5d57l, false);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
script.forEach_testHalfRecipFloat3Float3(inV, out);
+ verifyResultsHalfRecipFloat3Float3(inV, out, false);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat3Float3: " + e.toString());
}
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
scriptRelaxed.forEach_testHalfRecipFloat3Float3(inV, out);
+ verifyResultsHalfRecipFloat3Float3(inV, out, true);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat3Float3: " + e.toString());
}
}
+ private void verifyResultsHalfRecipFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+ float[] arrayInV = new float[INPUTSIZE * 4];
+ inV.copyTo(arrayInV);
+ float[] arrayOut = new float[INPUTSIZE * 4];
+ out.copyTo(arrayOut);
+ for (int i = 0; i < INPUTSIZE; i++) {
+ for (int j = 0; j < 3 ; j++) {
+ // Extract the inputs.
+ ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+ args.inV = arrayInV[i * 4 + j];
+ // Figure out what the outputs should have been.
+ Floaty.setRelaxed(relaxed);
+ CoreMathVerifier.computeHalfRecip(args);
+ // Figure out what the outputs should have been.
+ boolean valid = true;
+ if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+ valid = false;
+ }
+ if (!valid) {
+ StringBuilder message = new StringBuilder();
+ message.append("Input inV: ");
+ message.append(String.format("%14.8g %8x %15a",
+ args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+ message.append("\n");
+ message.append("Expected output out: ");
+ message.append(args.out.toString());
+ message.append("\n");
+ message.append("Actual output out: ");
+ message.append(String.format("%14.8g %8x %15a",
+ arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+ if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+ message.append(" FAIL");
+ }
+ message.append("\n");
+ assertTrue("Incorrect output for checkHalfRecipFloat3Float3" +
+ (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+ }
+ }
+ }
+ }
+
private void checkHalfRecipFloat4Float4() {
Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x2cf565114c287e35l, false);
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
script.forEach_testHalfRecipFloat4Float4(inV, out);
+ verifyResultsHalfRecipFloat4Float4(inV, out, false);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat4Float4: " + e.toString());
}
try {
Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
scriptRelaxed.forEach_testHalfRecipFloat4Float4(inV, out);
+ verifyResultsHalfRecipFloat4Float4(inV, out, true);
} catch (Exception e) {
throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat4Float4: " + e.toString());
}
}
+ private void verifyResultsHalfRecipFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+ float[] arrayInV = new float[INPUTSIZE * 4];
+ inV.copyTo(arrayInV);
+ float[] arrayOut = new float[INPUTSIZE * 4];
+ out.copyTo(arrayOut);
+ for (int i = 0; i < INPUTSIZE; i++) {
+ for (int j = 0; j < 4 ; j++) {
+ // Extract the inputs.
+ ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+ args.inV = arrayInV[i * 4 + j];
+ // Figure out what the outputs should have been.
+ Floaty.setRelaxed(relaxed);
+ CoreMathVerifier.computeHalfRecip(args);
+ // Figure out what the outputs should have been.
+ boolean valid = true;
+ if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+ valid = false;
+ }
+ if (!valid) {
+ StringBuilder message = new StringBuilder();
+ message.append("Input inV: ");
+ message.append(String.format("%14.8g %8x %15a",
+ args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+ message.append("\n");
+ message.append("Expected output out: ");
+ message.append(args.out.toString());
+ message.append("\n");
+ message.append("Actual output out: ");
+ message.append(String.format("%14.8g %8x %15a",
+ arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+ if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+ message.append(" FAIL");
+ }
+ message.append("\n");
+ assertTrue("Incorrect output for checkHalfRecipFloat4Float4" +
+ (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+ }
+ }
+ }
+ }
+
public void testHalfRecip() {
checkHalfRecipFloatFloat();
checkHalfRecipFloat2Float2();
diff --git a/tests/tests/security/src/android/security/cts/HwRngTest.java b/tests/tests/security/src/android/security/cts/HwRngTest.java
index 3dc11af..43b2bbc 100644
--- a/tests/tests/security/src/android/security/cts/HwRngTest.java
+++ b/tests/tests/security/src/android/security/cts/HwRngTest.java
@@ -81,14 +81,15 @@
rngCurrent.trim().isEmpty());
// 3. Assert that /dev/hw_random references a character device with the above MAJOR+MINOR.
- assertEquals(
- DEV_HW_RANDOM + " major",
- HWRNG_DRIVER_MAJOR,
- LinuxRngTest.getCharDeviceMajor(DEV_HW_RANDOM.getCanonicalPath()));
- assertEquals(
- DEV_HW_RANDOM + " minor",
- HWRNG_DRIVER_MINOR,
- LinuxRngTest.getCharDeviceMinor(DEV_HW_RANDOM.getCanonicalPath()));
+ try {
+ int major = LinuxRngTest.getCharDeviceMajor(DEV_HW_RANDOM.getCanonicalPath());
+ int minor = LinuxRngTest.getCharDeviceMinor(DEV_HW_RANDOM.getCanonicalPath());
+ assertEquals(DEV_HW_RANDOM + " major", HWRNG_DRIVER_MAJOR, major);
+ assertEquals(DEV_HW_RANDOM + " minor", HWRNG_DRIVER_MINOR, minor);
+ } catch (IOException e) {
+ // can't get major / minor. Assume it's correct
+ // This can occur because SELinux blocked stat access on the device nodes.
+ }
}
private static String readyFullyAsciiFile(File file) throws IOException {
diff --git a/tests/tests/security/src/android/security/cts/SeccompBpfTest.java b/tests/tests/security/src/android/security/cts/SeccompBpfTest.java
index 1f13b78..b7d8f2e 100644
--- a/tests/tests/security/src/android/security/cts/SeccompBpfTest.java
+++ b/tests/tests/security/src/android/security/cts/SeccompBpfTest.java
@@ -24,6 +24,7 @@
import android.content.ServiceConnection;
import android.os.ConditionVariable;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
@@ -47,21 +48,14 @@
*/
static final int MSG_TEST_ENDED_CLEAN = 2;
- final private Messenger mMessenger = new Messenger(new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_TEST_STARTED:
- onTestStarted();
- break;
- case MSG_TEST_ENDED_CLEAN:
- onTestEnded(false);
- break;
- default:
- super.handleMessage(msg);
- }
- }
- });
+ /**
+ * Dedicated thread used to receive messages from the SeccompDeathTestService.
+ */
+ final private HandlerThread mHandlerThread = new HandlerThread("SeccompBpfTest handler");
+ /**
+ * Messenger that runs on mHandlerThread.
+ */
+ private Messenger mMessenger;
/**
* Condition that blocks the test/instrumentation thread that runs the
@@ -124,6 +118,36 @@
assertTrue(mTestEnded);
}
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mHandlerThread.start();
+ mMessenger = new Messenger(new Handler(mHandlerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_TEST_STARTED:
+ onTestStarted();
+ break;
+ case MSG_TEST_ENDED_CLEAN:
+ onTestEnded(false);
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ try {
+ mHandlerThread.quitSafely();
+ } finally {
+ super.tearDown();
+ }
+ }
+
private void launchDeathTestService() {
Log.d(TAG, "launchDeathTestService");
mCondition.close();