am ab31d6de: Merge "CameraITS: adjust yuv plus raw tests settings" into lmp-sprout-dev
* commit 'ab31d6deb2db262a9ab109eaba4963938a8c9995':
CameraITS: adjust yuv plus raw tests settings
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 dfcf120..4a0c135 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
@@ -97,7 +97,7 @@
Sensor.TYPE_ACCELEROMETER,
SensorManager.SENSOR_DELAY_FASTEST);
TestSensorOperation verifyMeasurements =
- new TestSensorOperation(environment, 100 /* event count */);
+ TestSensorOperation.createOperation(environment, 100 /* event count */);
verifyMeasurements.addVerification(new MeanVerification(
expectations,
new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
index 6f0a7aa..2d58c64 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
@@ -22,9 +22,7 @@
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.cts.helpers.TestSensorEnvironment;
-import android.hardware.cts.helpers.sensoroperations.TestSensorFlushOperation;
import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
-import android.hardware.cts.helpers.sensoroperations.VerifiableSensorOperation;
import java.util.concurrent.TimeUnit;
@@ -128,7 +126,7 @@
int testDurationSec = maxBatchReportLatencySec + BATCHING_PADDING_TIME_S;
TestSensorOperation operation =
- new TestSensorOperation(environment, testDurationSec,TimeUnit.SECONDS);
+ TestSensorOperation.createOperation(environment, testDurationSec,TimeUnit.SECONDS);
return executeTest(operation);
}
@@ -145,12 +143,12 @@
maxBatchReportLatencyUs);
int flushDurationSec = maxBatchReportLatencySec / 2;
- TestSensorFlushOperation operation =
- new TestSensorFlushOperation(environment, flushDurationSec, TimeUnit.SECONDS);
+ TestSensorOperation operation = TestSensorOperation
+ .createFlushOperation(environment, flushDurationSec, TimeUnit.SECONDS);
return executeTest(operation);
}
- private String executeTest(VerifiableSensorOperation operation) throws InterruptedException {
+ private String executeTest(TestSensorOperation operation) throws InterruptedException {
operation.addDefaultVerifications();
operation.setLogEvents(true);
operation.execute();
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 4b2a7f4..d6ec951 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
@@ -156,8 +156,8 @@
getApplicationContext(),
Sensor.TYPE_GYROSCOPE,
SensorManager.SENSOR_DELAY_FASTEST);
- TestSensorOperation sensorOperation =
- new TestSensorOperation(environment, ROTATION_COLLECTION_SEC, TimeUnit.SECONDS);
+ TestSensorOperation sensorOperation = TestSensorOperation
+ .createOperation(environment, ROTATION_COLLECTION_SEC, TimeUnit.SECONDS);
int gyroscopeAxes = environment.getSensorAxesCount();
int[] expectationsDeg = getExpectationsDeg(gyroscopeAxes, rotationAxis, expectationDeg);
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 553147b..1ec5dc1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
@@ -79,7 +79,7 @@
Sensor.TYPE_MAGNETIC_FIELD,
SensorManager.SENSOR_DELAY_FASTEST);
TestSensorOperation verifyNorm =
- new TestSensorOperation(environment, 100 /* event count */);
+ TestSensorOperation.createOperation(environment, 100 /* event count */);
float expectedMagneticFieldEarth =
(SensorManager.MAGNETIC_FIELD_EARTH_MAX + SensorManager.MAGNETIC_FIELD_EARTH_MIN) / 2;
@@ -124,7 +124,7 @@
Sensor.TYPE_MAGNETIC_FIELD,
SensorManager.SENSOR_DELAY_FASTEST);
TestSensorOperation verifyStdDev =
- new TestSensorOperation(environment, 100 /* event count */);
+ TestSensorOperation.createOperation(environment, 100 /* event count */);
verifyStdDev.addVerification(new StandardDeviationVerification(
new float[]{2f, 2f, 2f} /* uT */));
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
index 687826c..bd47024 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
@@ -20,9 +20,7 @@
import android.hardware.SensorManager;
import android.hardware.cts.helpers.SensorStats;
import android.hardware.cts.helpers.TestSensorEnvironment;
-import android.hardware.cts.helpers.sensoroperations.TestSensorFlushOperation;
import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
-import android.hardware.cts.helpers.sensoroperations.VerifiableSensorOperation;
import android.hardware.cts.helpers.sensorverification.ISensorVerification;
import java.util.concurrent.TimeUnit;
@@ -263,7 +261,7 @@
rateUs,
maxBatchReportLatencyUs);
TestSensorOperation operation =
- new TestSensorOperation(environment, testDurationSec, TimeUnit.SECONDS);
+ TestSensorOperation.createOperation(environment, testDurationSec, TimeUnit.SECONDS);
executeTest(environment, operation, false /* flushExpected */);
}
@@ -279,15 +277,15 @@
shouldEmulateSensorUnderLoad(),
rateUs,
maxBatchReportLatencyUs);
- TestSensorFlushOperation operation =
- new TestSensorFlushOperation(environment, flushDurationSec, TimeUnit.SECONDS);
+ TestSensorOperation operation = TestSensorOperation
+ .createFlushOperation(environment, flushDurationSec, TimeUnit.SECONDS);
executeTest(environment, operation, true /* flushExpected */);
}
private void executeTest(
TestSensorEnvironment environment,
- VerifiableSensorOperation operation,
+ TestSensorOperation operation,
boolean flushExpected) throws Throwable {
operation.addDefaultVerifications();
operation.setLogEvents(true);
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index 50cb12d..4dfa16e 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -24,7 +24,6 @@
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.sensoroperations.VerifiableSensorOperation;
import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
import java.util.Random;
@@ -81,7 +80,7 @@
shouldEmulateSensorUnderLoad(),
SensorManager.SENSOR_DELAY_FASTEST);
TestSensorOperation continuousOperation =
- new TestSensorOperation(environment, 100 /* eventCount */);
+ TestSensorOperation.createOperation(environment, 100 /* eventCount */);
continuousOperation.addVerification(new EventOrderingVerification());
operation.add(new RepeatingSensorOperation(continuousOperation, ITERATIONS));
@@ -93,7 +92,7 @@
sensor.getMinDelay(),
MAX_REPORTING_LATENCY_US);
TestSensorOperation batchingOperation =
- new TestSensorOperation(batchingEnvironment, 100 /* eventCount */);
+ TestSensorOperation.createOperation(batchingEnvironment, 100 /* eventCount */);
batchingOperation.addVerification(new EventOrderingVerification());
operation.add(new RepeatingSensorOperation(batchingOperation, ITERATIONS));
}
@@ -145,7 +144,7 @@
generateSamplingRateInUs(sensorType),
generateReportLatencyInUs());
TestSensorOperation sensorOperation =
- new TestSensorOperation(environment, 100 /* eventCount */);
+ TestSensorOperation.createOperation(environment, 100 /* eventCount */);
sensorOperation.addVerification(new EventOrderingVerification());
sequentialOperation.add(sensorOperation);
}
@@ -229,7 +228,7 @@
shouldEmulateSensorUnderLoad(),
SensorManager.SENSOR_DELAY_FASTEST);
TestSensorOperation tester =
- new TestSensorOperation(testerEnvironment, 100 /* event count */);
+ TestSensorOperation.createOperation(testerEnvironment, 100 /* event count */);
tester.addVerification(new EventOrderingVerification());
TestSensorEnvironment testeeEnvironment = new TestSensorEnvironment(
@@ -237,8 +236,8 @@
sensorTypeTestee,
shouldEmulateSensorUnderLoad(),
SensorManager.SENSOR_DELAY_FASTEST);
- VerifiableSensorOperation testee =
- new TestSensorOperation(testeeEnvironment, 100 /* event count */);
+ TestSensorOperation testee =
+ TestSensorOperation.createOperation(testeeEnvironment, 100 /* event count */);
testee.addVerification(new EventOrderingVerification());
ParallelSensorOperation operation = new ParallelSensorOperation();
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
index d8b8e51..08d06c6 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
@@ -18,6 +18,8 @@
import com.android.cts.util.TimeoutReq;
+import junit.framework.Assert;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
@@ -27,44 +29,70 @@
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
+import android.hardware.cts.helpers.SensorNotSupportedException;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEventListener;
+import android.hardware.cts.helpers.TestSensorManager;
+import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.EventGapVerification;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
+import android.hardware.cts.helpers.sensorverification.EventTimestampSynchronizationVerification;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log;
+import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class SensorTest extends SensorTestCase {
- private SensorManager mSensorManager;
- private TriggerListener mTriggerListener;
- private SensorListener mSensorListener;
- private List<Sensor> mSensorList;
private static final String TAG = "SensorTest";
+
// Test only SDK defined sensors. Any sensors with type > 100 are ignored.
private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;
- private static final long TIMEOUT_TOLERANCE_US = TimeUnit.SECONDS.toMicros(5);
- private static final double MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE = 0.9;
+
private PowerManager.WakeLock mWakeLock;
+ private SensorManager mSensorManager;
+ private NullTriggerEventListener mNullTriggerEventListener;
+ private NullSensorEventListener mNullSensorEventListener;
+ private List<Sensor> mSensorList;
@Override
protected void setUp() throws Exception {
- super.setUp();
- mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
- mTriggerListener = new TriggerListener();
- mSensorListener = new SensorListener();
- mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
- PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
+ Context context = getContext();
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ mNullTriggerEventListener = new NullTriggerEventListener();
+ mNullSensorEventListener = new NullSensorEventListener();
+
+ mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ assertNotNull("SensorList was null.", mSensorList);
+ if (mSensorList.isEmpty()) {
+ // several devices will not have sensors, so we need to skip the tests in those cases
+ throw new SensorTestStateNotSupportedException(
+ "Sensors are not available in the system.");
+ }
+
+ mWakeLock.acquire();
}
+ @Override
+ protected void tearDown(){
+ if (mWakeLock != null && mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+
+ @SuppressWarnings("deprecation")
public void testSensorOperations() {
// Because we can't know every sensors unit details, so we can't assert
// get values with specified values.
- List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
- assertNotNull(sensors);
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SENSOR_ACCELEROMETER);
@@ -149,7 +177,6 @@
}
assertTrue(sensors.get(0).getName() + " defined as non-wake-up sensor",
sensors.get(0).isWakeUpSensor());
- return;
}
// Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
@@ -207,372 +234,137 @@
public void testRequestTriggerWithNonTriggerSensor() {
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- boolean result;
- if (sensor != null) {
- result = mSensorManager.requestTriggerSensor(mTriggerListener, sensor);
- assertFalse(result);
+ if (sensor == null) {
+ throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
}
+ boolean result = mSensorManager.requestTriggerSensor(mNullTriggerEventListener, sensor);
+ assertFalse(result);
}
public void testCancelTriggerWithNonTriggerSensor() {
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- boolean result;
- if (sensor != null) {
- result = mSensorManager.cancelTriggerSensor(mTriggerListener, sensor);
- assertFalse(result);
+ if (sensor == null) {
+ throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
}
+ boolean result = mSensorManager.cancelTriggerSensor(mNullTriggerEventListener, sensor);
+ assertFalse(result);
}
public void testRegisterWithTriggerSensor() {
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
- boolean result;
- if (sensor != null) {
- result = mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_NORMAL);
- assertFalse(result);
+ if (sensor == null) {
+ throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
}
+ boolean result = mSensorManager.registerListener(
+ mNullSensorEventListener,
+ sensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ assertFalse(result);
}
public void testRegisterTwiceWithSameSensor() {
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- boolean result;
- if (sensor != null) {
- result = mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_NORMAL);
- assertTrue(result);
- result = mSensorManager.registerListener(mSensorListener, sensor,
- SensorManager.SENSOR_DELAY_NORMAL);
- assertFalse(result);
+ if (sensor == null) {
+ throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
}
+
+ boolean result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ assertTrue(result);
+
+ result = mSensorManager.registerListener(mNullSensorEventListener, sensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ assertFalse(result);
}
- class SensorEventTimeStampListener implements SensorEventListener {
- SensorEventTimeStampListener(long eventReportLatencyNs, CountDownLatch latch) {
- mEventReportLatencyNs = eventReportLatencyNs;
- mPrevTimeStampNs = -1;
- mLatch = latch;
- numErrors = 0;
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (mPrevTimeStampNs == -1) {
- mPrevTimeStampNs = event.timestamp;
- return;
- }
- long currTimeStampNs = event.timestamp;
- if (currTimeStampNs <= mPrevTimeStampNs) {
- Log.w(TAG, "Timestamps not monotonically increasing curr_ts_ns=" +
- event.timestamp + " prev_ts_ns=" + mPrevTimeStampNs);
- numErrors++;
- mPrevTimeStampNs = currTimeStampNs;
- return;
- }
- mLatch.countDown();
-
- final long elapsedRealtimeNs = SystemClock.elapsedRealtimeNanos();
-
- if (elapsedRealtimeNs <= currTimeStampNs) {
- Log.w(TAG, "Timestamps into the future curr elapsedRealTimeNs=" + elapsedRealtimeNs
- + " current sensor ts_ns=" + currTimeStampNs);
- ++numErrors;
- } else if (elapsedRealtimeNs-currTimeStampNs > SYNC_TOLERANCE + mEventReportLatencyNs) {
- Log.w(TAG, "Timestamp sync error elapsedRealTimeNs=" + elapsedRealtimeNs +
- " curr_ts_ns=" + currTimeStampNs +
- " diff_ns=" + (elapsedRealtimeNs - currTimeStampNs) +
- " SYNC_TOLERANCE_NS=" + SYNC_TOLERANCE +
- " eventReportLatencyNs=" + mEventReportLatencyNs);
- ++numErrors;
- }
- mPrevTimeStampNs = currTimeStampNs;
- }
-
- public int getNumErrors() {
- return numErrors;
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- private int numErrors;
- private long mEventReportLatencyNs;
- private long mPrevTimeStampNs;
- private final CountDownLatch mLatch;
- private final long SYNC_TOLERANCE = 500000000L; // 500 milli seconds approx.
- }
-
- // Register for each sensor and compare the timestamps of SensorEvents that you get with
- // elapsedRealTimeNano.
+ // TODO: remove when parametized tests are supported and EventTimestampSynchronization
+ // verification is added to default verifications
@TimeoutReq(minutes=60)
public void testSensorTimeStamps() throws Exception {
- final int numEvents = 2000;
- try {
- mWakeLock.acquire();
- int numErrors = 0;
- for (Sensor sensor : mSensorList) {
- // Skip OEM defined sensors and non continuous sensors.
- if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
- continue;
- }
-
- for (int iterations = 0; iterations < 2; ++iterations) {
- // Test in both batch mode and non-batch mode for every sensor.
- long maxBatchReportLatencyNs = 10000000000L; // 10 secs
- if (iterations % 2 == 0) maxBatchReportLatencyNs = 0;
-
- final long samplingPeriodNs = (long)(TimeUnit.MICROSECONDS.toNanos(
- sensor.getMinDelay())/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE);
- // If there is a FIFO and a wake-lock is held, events will be reported when
- // the batch timeout expires or when the FIFO is full which ever occurs
- // earlier.
- final long eventReportLatencyNs = Math.min(maxBatchReportLatencyNs,
- sensor.getFifoMaxEventCount() * samplingPeriodNs);
-
- final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
- SensorEventTimeStampListener listener = new SensorEventTimeStampListener(
- eventReportLatencyNs, eventsRemaining);
-
- Log.i(TAG, "Running timeStamp test on " + sensor.getName());
- boolean result = mSensorManager.registerListener(listener, sensor,
- SensorManager.SENSOR_DELAY_FASTEST,
- (int)maxBatchReportLatencyNs/1000);
- assertTrue("Sensor registerListener failed ", result);
-
- long timeToWaitUs = samplingPeriodNs/1000 + eventReportLatencyNs/1000 +
- TIMEOUT_TOLERANCE_US;
- long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
- (int)(eventReportLatencyNs/1000), eventsRemaining);
-
- mSensorManager.unregisterListener(listener);
- if (eventsRemaining.getCount() > 0) {
- failTimedOut(sensor.getName(), (double) totalTimeWaitedUs/1000,
- numEvents, (double) sensor.getMinDelay()/1000,
- eventsRemaining.getCount(),
- numEvents - eventsRemaining.getCount());
- }
- if (listener.getNumErrors() > 5) {
- fail("Check logcat. Timestamp test failed. numErrors=" +
- listener.getNumErrors() + " " + sensor.getName() +
- " maxBatchReportLatencyNs=" + maxBatchReportLatencyNs +
- " samplingPeriodNs=" + sensor.getMinDelay());
- numErrors += listener.getNumErrors();
- } else {
- Log.i(TAG, "TimeStamp test PASS'd on " + sensor.getName());
- }
- }
- }
- } finally {
- mWakeLock.release();
+ ArrayList<Throwable> errorsFound = new ArrayList<>();
+ for (Sensor sensor : mSensorList) {
+ // test both continuous and batching mode sensors
+ verifyLongActivation(sensor, 0 /* maxReportLatencyUs */, errorsFound);
+ verifyLongActivation(sensor, (int) TimeUnit.SECONDS.toMicros(10), errorsFound);
}
+ assertOnErrors(errorsFound);
}
- private void failTimedOut(String sensorName, double totalTimeWaitedMs, int numEvents,
- double minDelayMs, long eventsRemaining, long eventsReceived) {
- final String TIMED_OUT_FORMAT = "Timed out waiting for events from %s " +
- "waited for time=%.1fms to receive totalEvents=%d at samplingRate=%.1fHz" +
- " remainingEvents=%d received events=%d";
- fail(String.format(TIMED_OUT_FORMAT, sensorName, totalTimeWaitedMs, numEvents,
- 1000/minDelayMs, eventsRemaining, eventsReceived));
- }
-
- // Register for updates from each continuous mode sensor, wait for N events, call flush and
- // wait for flushCompleteEvent before unregistering for the sensor.
+ // TODO: remove when parameterized tests are supported (see SensorBatchingTests.java)
@TimeoutReq(minutes=20)
public void testBatchAndFlush() throws Exception {
- try {
- mWakeLock.acquire();
- for (Sensor sensor : mSensorList) {
- // Skip ONLY one-shot sensors.
- if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
- registerListenerCallFlush(sensor, null);
- }
- }
- } finally {
- mWakeLock.release();
+ ArrayList<Throwable> errorsFound = new ArrayList<>();
+ for (Sensor sensor : mSensorList) {
+ verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound);
}
+ assertOnErrors(errorsFound);
}
- // Same as testBatchAndFlush but using Handler version of the API to register for sensors.
- // onSensorChanged is now called on a background thread.
+ /**
+ * Verifies that sensor events arrive in the given message queue (Handler).
+ */
@TimeoutReq(minutes=10)
public void testBatchAndFlushWithHandler() throws Exception {
- try {
- mWakeLock.acquire();
- HandlerThread handlerThread = new HandlerThread("sensorThread");
- handlerThread.start();
- Handler handler = new Handler(handlerThread.getLooper());
- for (Sensor sensor : mSensorList) {
- // Skip ONLY one-shot sensors.
- if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
- registerListenerCallFlush(sensor, handler);
- }
+ Sensor sensor = null;
+ for (Sensor s : mSensorList) {
+ if (s.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
+ sensor = s;
+ break;
}
- } finally {
- mWakeLock.release();
}
+ if (sensor == null) {
+ throw new SensorTestStateNotSupportedException(
+ "There are no Continuous sensors in the device.");
+ }
+
+ TestSensorEnvironment environment = new TestSensorEnvironment(
+ getContext(),
+ sensor,
+ SensorManager.SENSOR_DELAY_FASTEST,
+ (int) TimeUnit.SECONDS.toMicros(5));
+ TestSensorManager sensorManager = new TestSensorManager(environment);
+
+ HandlerThread handlerThread = new HandlerThread("sensorThread");
+ handlerThread.start();
+ Handler handler = new Handler(handlerThread.getLooper());
+ TestSensorEventListener listener = new TestSensorEventListener(handler);
+
+ sensorManager.registerListener(listener);
+ listener.waitForEvents(1);
+ sensorManager.requestFlush();
+ listener.waitForFlushComplete();
+ listener.assertEventsReceivedInHandler();
}
- private void registerListenerCallFlush(Sensor sensor, Handler handler)
- throws InterruptedException {
- if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
- return;
- }
- final int numEvents = 500;
- final int rateUs = 0; // DELAY_FASTEST
- final int maxBatchReportLatencyUs = 10000000;
- final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
- final CountDownLatch flushReceived = new CountDownLatch(1);
- SensorEventListener2 listener = new SensorEventListener2() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- eventsRemaining.countDown();
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- @Override
- public void onFlushCompleted(Sensor sensor) {
- flushReceived.countDown();
- }
- };
- // Consider only continuous mode sensors for testing registerListener.
- // For on-change sensors, call registerListener() so that the listener is associated
- // with the sensor so that flush(listener) can be called on it.
- try {
- Log.i(TAG, "testBatch " + sensor.getName());
- boolean result = mSensorManager.registerListener(listener, sensor,
- rateUs, maxBatchReportLatencyUs, handler);
- assertTrue("registerListener failed " + sensor.getName(), result);
-
- // Wait for 500 events or N seconds before the test times out.
- if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
- // Wait for approximately the time required to generate these events + a tolerance
- // of 10 seconds.
- long timeToWaitUs =
- numEvents*(long)(sensor.getMinDelay()/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE)
- + maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
-
- long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
- maxBatchReportLatencyUs, eventsRemaining);
- if (eventsRemaining.getCount() > 0) {
- failTimedOut(sensor.getName(), (double)totalTimeWaitedUs/1000, numEvents,
- (double)sensor.getMinDelay()/1000,
- eventsRemaining.getCount(), numEvents - eventsRemaining.getCount());
- }
- }
- Log.i(TAG, "testFlush " + sensor.getName());
- result = mSensorManager.flush(listener);
- assertTrue("flush failed " + sensor.getName(), result);
- boolean collectedAllEvents = flushReceived.await(TIMEOUT_TOLERANCE_US,
- TimeUnit.MICROSECONDS);
- if (!collectedAllEvents) {
- fail("Timed out waiting for flushCompleteEvent from " + sensor.getName() +
- " waitedFor="+ TIMEOUT_TOLERANCE_US/1000 + "ms");
- }
- Log.i(TAG, "testBatchAndFlush PASS " + sensor.getName());
- } finally {
- mSensorManager.unregisterListener(listener);
- }
- }
-
- // Wait till the CountDownLatch counts down to zero. If the events are not delivered within
- // timetoWaitUs, wait an additional maxReportLantencyUs and check if the sensor is streaming
- // data or not. If the sensor is not streaming at all, fail the test or else wait in increments
- // of maxReportLantencyUs to collect sensor events.
- private long waitToCollectAllEvents(long timeToWaitUs, int maxReportLatencyUs,
- CountDownLatch eventsRemaining)
- throws InterruptedException {
- boolean collectedAllEvents = false;
- long totalTimeWaitedUs = 0;
- long remainingEvents;
- final long INCREMENTAL_WAIT_US = maxReportLatencyUs + TimeUnit.SECONDS.toMicros(1);
- do {
- totalTimeWaitedUs += timeToWaitUs;
- remainingEvents = eventsRemaining.getCount();
- collectedAllEvents = eventsRemaining.await(timeToWaitUs, TimeUnit.MICROSECONDS);
- timeToWaitUs = INCREMENTAL_WAIT_US;
- } while (!collectedAllEvents &&
- (remainingEvents - eventsRemaining.getCount() >=(long)INCREMENTAL_WAIT_US/1000000));
- return totalTimeWaitedUs;
- }
-
- // Call registerListener for multiple sensors at a time and call flush.
+ // TODO: after L release move to SensorBatchingTests and run in all sensors with default
+ // verifications enabled
public void testBatchAndFlushWithMutipleSensors() throws Exception {
- final int MAX_SENSORS = 3;
- int numSensors = mSensorList.size() < MAX_SENSORS ? mSensorList.size() : MAX_SENSORS;
- if (numSensors == 0) {
- return;
+ final int maxSensors = 3;
+ final int maxReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(10);
+ int sensorsCount = mSensorList.size();
+ int numSensors = sensorsCount < maxSensors ? sensorsCount : maxSensors;
+
+ StringBuilder builder = new StringBuilder();
+ ParallelSensorOperation parallelSensorOperation = new ParallelSensorOperation();
+ for (int i = 0; i < sensorsCount && numSensors > 0; ++i) {
+ Sensor sensor = mSensorList.get(i);
+ // skip all non-continuous sensors
+ if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
+ TestSensorEnvironment environment = new TestSensorEnvironment(
+ getContext(),
+ sensor,
+ shouldEmulateSensorUnderLoad(),
+ SensorManager.SENSOR_DELAY_FASTEST,
+ maxReportLatencyUs);
+ FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */);
+ parallelSensorOperation.add(new TestSensorOperation(environment, executor));
+ --numSensors;
+ builder.append(sensor.getName()).append(", ");
+ }
}
- final int numEvents = 500;
- int rateUs = 0; // DELAY_FASTEST
- final int maxBatchReportLatencyUs = 10000000;
- final CountDownLatch eventsRemaining = new CountDownLatch(numSensors * numEvents);
- final CountDownLatch flushReceived = new CountDownLatch(numSensors);
- SensorEventListener2 listener = new SensorEventListener2() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- eventsRemaining.countDown();
- }
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- @Override
- public void onFlushCompleted(Sensor sensor) {
- flushReceived.countDown();
- }
- };
-
- try {
- mWakeLock.acquire();
- StringBuilder registeredSensors = new StringBuilder(30);
- for (Sensor sensor : mSensorList) {
- // Skip all non-continuous sensors.
- if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
- continue;
- }
- rateUs = Math.max(sensor.getMinDelay(), rateUs);
- boolean result = mSensorManager.registerListener(listener, sensor,
- SensorManager.SENSOR_DELAY_FASTEST, maxBatchReportLatencyUs);
- assertTrue("registerListener failed for " + sensor.getName(), result);
- registeredSensors.append(sensor.getName());
- registeredSensors.append(" ");
- if (--numSensors == 0) {
- break;
- }
- }
- if (registeredSensors.toString().isEmpty()) {
- return;
- }
-
- Log.i(TAG, "testBatchAndFlushWithMutipleSensors " + registeredSensors);
- long timeToWaitUs =
- numEvents*(long)(rateUs/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE) +
- maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
- long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs, maxBatchReportLatencyUs,
- eventsRemaining);
- if (eventsRemaining.getCount() > 0) {
- failTimedOut(registeredSensors.toString(), (double)totalTimeWaitedUs/1000,
- numEvents, (double)rateUs/1000, eventsRemaining.getCount(),
- numEvents - eventsRemaining.getCount());
- }
- boolean result = mSensorManager.flush(listener);
- assertTrue("flush failed " + registeredSensors.toString(), result);
- boolean collectedFlushEvent =
- flushReceived.await(TIMEOUT_TOLERANCE_US, TimeUnit.MICROSECONDS);
- if (!collectedFlushEvent) {
- fail("Timed out waiting for flushCompleteEvent from " +
- registeredSensors.toString() + " waited for=" + timeToWaitUs/1000 + "ms");
- }
- Log.i(TAG, "testBatchAndFlushWithMutipleSensors PASS'd");
- } finally {
- mSensorManager.unregisterListener(listener);
- mWakeLock.release();
- }
+ Log.i(TAG, "Testing batch/flush for sensors: " + builder);
+ parallelSensorOperation.execute();
}
private void assertSensorValues(Sensor sensor) {
@@ -583,8 +375,8 @@
assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
" " + sensor.getName(), sensor.getResolution() >= 0);
assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
- assertTrue("Version must be positive version=" + sensor.getVersion() + " " +
- sensor.getName(), sensor.getVersion() > 0);
+ assertTrue("Version must be positive version=" + sensor.getVersion() + " " +
+ sensor.getName(), sensor.getVersion() > 0);
int fifoMaxEventCount = sensor.getFifoMaxEventCount();
int fifoReservedEventCount = sensor.getFifoReservedEventCount();
assertTrue(fifoMaxEventCount >= 0);
@@ -617,19 +409,142 @@
assertEquals(sensors, mSensorManager.getSensors());
}
- class TriggerListener extends TriggerEventListener {
- @Override
- public void onTrigger(TriggerEvent event) {
+ /**
+ * Verifies that a continuous sensor produces events that have timestamps synchronized with
+ * {@link SystemClock#elapsedRealtimeNanos()}.
+ */
+ private void verifyLongActivation(
+ Sensor sensor,
+ int maxReportLatencyUs,
+ ArrayList<Throwable> errorsFound) throws InterruptedException {
+ if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
+ return;
+ }
+
+ try {
+ TestSensorEnvironment environment = new TestSensorEnvironment(
+ getContext(),
+ sensor,
+ shouldEmulateSensorUnderLoad(),
+ SensorManager.SENSOR_DELAY_FASTEST,
+ maxReportLatencyUs);
+ TestSensorOperation operation =
+ TestSensorOperation.createOperation(environment, 20, TimeUnit.SECONDS);
+ operation.addVerification(EventGapVerification.getDefault(environment));
+ operation.addVerification(EventOrderingVerification.getDefault(environment));
+ operation.addVerification(
+ EventTimestampSynchronizationVerification.getDefault(environment));
+
+ Log.i(TAG, "Running timestamp test on: " + sensor.getName());
+ operation.execute();
+ } catch (InterruptedException e) {
+ // propagate so the test can stop
+ throw e;
+ } catch (Throwable e) {
+ errorsFound.add(e);
+ Log.e(TAG, e.getMessage());
}
}
- class SensorListener implements SensorEventListener {
- @Override
- public void onSensorChanged(SensorEvent event) {
+ /**
+ * Verifies that a client can listen for events, and that
+ * {@link SensorManager#flush(SensorEventListener)} will trigger the appropriate notification
+ * for {@link SensorEventListener2#onFlushCompleted(Sensor)}.
+ */
+ private void verifyRegisterListenerCallFlush(
+ Sensor sensor,
+ Handler handler,
+ ArrayList<Throwable> errorsFound)
+ throws InterruptedException {
+ if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+ return;
}
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ try {
+ TestSensorEnvironment environment = new TestSensorEnvironment(
+ getContext(),
+ sensor,
+ shouldEmulateSensorUnderLoad(),
+ SensorManager.SENSOR_DELAY_FASTEST,
+ (int) TimeUnit.SECONDS.toMicros(10));
+ FlushExecutor executor = new FlushExecutor(environment, 500 /* eventCount */);
+ TestSensorOperation operation = new TestSensorOperation(environment, executor, handler);
+
+ Log.i(TAG, "Running flush test on: " + sensor.getName());
+ operation.execute();
+ } catch (InterruptedException e) {
+ // propagate so the test can stop
+ throw e;
+ } catch (Throwable e) {
+ errorsFound.add(e);
+ Log.e(TAG, e.getMessage());
}
}
+
+ private void assertOnErrors(List<Throwable> errorsFound) {
+ if (!errorsFound.isEmpty()) {
+ StringBuilder builder = new StringBuilder();
+ for (Throwable error : errorsFound) {
+ builder.append(error.getMessage()).append("\n");
+ }
+ Assert.fail(builder.toString());
+ }
+ }
+
+ /**
+ * A delegate that drives the execution of Batch/Flush tests.
+ * It performs several operations in order:
+ * - registration
+ * - for continuous sensors it first ensures that the FIFO is filled
+ * - if events do not arrive on time, an assert will be triggered
+ * - requests flush of sensor data
+ * - waits for {@link SensorEventListener2#onFlushCompleted(Sensor)}
+ * - if the event does not arrive, an assert will be triggered
+ */
+ private class FlushExecutor implements TestSensorOperation.Executor {
+ private final TestSensorEnvironment mEnvironment;
+ private final int mEventCount;
+
+ public FlushExecutor(TestSensorEnvironment environment, int eventCount) {
+ mEnvironment = environment;
+ mEventCount = eventCount;
+ }
+
+ /**
+ * Consider only continuous mode sensors for testing register listener.
+ *
+ * For on-change sensors, we only use
+ * {@link TestSensorManager#registerListener(TestSensorEventListener)} to associate the
+ * listener with the sensor. So that {@link TestSensorManager#requestFlush()} can be
+ * invoked on it.
+ */
+ @Override
+ public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
+ throws InterruptedException {
+ int sensorReportingMode = mEnvironment.getSensor().getReportingMode();
+ try {
+ sensorManager.registerListener(listener);
+ if (sensorReportingMode == Sensor.REPORTING_MODE_CONTINUOUS) {
+ listener.waitForEvents(mEventCount);
+ }
+ sensorManager.requestFlush();
+ listener.waitForFlushComplete();
+ } finally {
+ sensorManager.unregisterListener();
+ }
+ }
+ }
+
+ private class NullTriggerEventListener extends TriggerEventListener {
+ @Override
+ public void onTrigger(TriggerEvent event) {}
+ }
+
+ private class NullSensorEventListener implements SensorEventListener {
+ @Override
+ public void onSensorChanged(SensorEvent event) {}
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+ }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
index 3bd4a03..a98dc59 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
@@ -541,7 +541,8 @@
sensorType,
shouldEmulateSensorUnderLoad(),
rateUs);
- TestSensorOperation op = new TestSensorOperation(environment, 5, TimeUnit.SECONDS);
+ TestSensorOperation op =
+ TestSensorOperation.createOperation(environment, 5, TimeUnit.SECONDS);
op.addDefaultVerifications();
op.setLogEvents(true);
try {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
index ca7d133..3bedc05 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
@@ -17,7 +17,6 @@
package android.hardware.cts.helpers;
import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener2;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,21 +31,6 @@
private final ArrayList<TestSensorEvent> mSensorEventsList = new ArrayList<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
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java
index b3b8559..0f84ee6 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java
@@ -51,7 +51,8 @@
*/
public void execute() throws Throwable {
CollectingSensorEventListener calibratedTestListener = new CollectingSensorEventListener();
- CollectingSensorEventListener uncalibratedTestListener = new CollectingSensorEventListener();
+ CollectingSensorEventListener uncalibratedTestListener =
+ new CollectingSensorEventListener();
mCalibratedSensorManager.registerListener(calibratedTestListener);
mUncalibratedSensorManager.registerListener(uncalibratedTestListener);
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 a79e5b1..e89b473 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -192,7 +192,7 @@
TestSensorEnvironment environment,
String extras) {
return String.format(
- "%s | sensor='%s', samplingPeriodUs=%d, maxReportLatencyUs=%d | %s",
+ "%s | sensor='%s', samplingPeriod=%dus, maxReportLatency=%dus | %s",
label,
environment.getSensor().getName(),
environment.getRequestedSamplingPeriodUs(),
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
index 7be6c0c..6f98e86 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
@@ -40,14 +40,15 @@
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 EVENT_TIME_SYNCHRONIZATION_COUNT_KEY =
+ "event_time_synchronization_count";
+ public static final String EVENT_TIME_SYNCHRONIZATION_POSITIONS_KEY =
+ "event_time_synchronization_positions";
public static final String FREQUENCY_KEY = "frequency";
public static final String JITTER_95_PERCENTILE_PERCENT_KEY = "jitter_95_percentile_percent";
public static final String MEAN_KEY = "mean";
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
index 8f33f92..5be30a4 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
@@ -28,6 +28,13 @@
* The environment is self contained and carries its state around all the sensor test framework.
*/
public class TestSensorEnvironment {
+
+ /**
+ * It represents the fraction of the expected sampling frequency, at which the sensor can
+ * actually produce events.
+ */
+ private static final float MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER = 0.9f;
+
private final Context mContext;
private final Sensor mSensor;
private final boolean mSensorMightHaveMoreListeners;
@@ -40,7 +47,10 @@
* @param context The context for the test
* @param sensorType The type of the sensor under test
* @param samplingPeriodUs The requested collection period for the sensor under test
+ *
+ * @deprecated Use variants with {@link Sensor} objects.
*/
+ @Deprecated
public TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs) {
this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs);
}
@@ -52,7 +62,10 @@
* @param sensorType The type of the sensor under test
* @param samplingPeriodUs The requested collection period for the sensor under test
* @param maxReportLatencyUs The requested collection report latency for the sensor under test
+ *
+ * @deprecated Use variants with {@link Sensor} objects.
*/
+ @Deprecated
public TestSensorEnvironment(
Context context,
int sensorType,
@@ -72,7 +85,10 @@
* @param sensorType The type of the sensor under test
* @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
* @param samplingPeriodUs The requested collection period for the sensor under test
+ *
+ * @deprecated Use variants with {@link Sensor} objects.
*/
+ @Deprecated
public TestSensorEnvironment(
Context context,
int sensorType,
@@ -93,7 +109,10 @@
* @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
* @param samplingPeriodUs The requested collection period for the sensor under test
* @param maxReportLatencyUs The requested collection report latency for the sensor under test
+ *
+ * @deprecated Use variants with {@link Sensor} objects.
*/
+ @Deprecated
public TestSensorEnvironment(
Context context,
int sensorType,
@@ -112,6 +131,26 @@
*
* @param context The context for the test
* @param sensor The sensor under test
+ * @param samplingPeriodUs The requested collection period for the sensor under test
+ * @param maxReportLatencyUs The requested collection report latency for the sensor under test
+ */
+ public TestSensorEnvironment(
+ Context context,
+ Sensor sensor,
+ int samplingPeriodUs,
+ int maxReportLatencyUs) {
+ this(context,
+ sensor,
+ false /* sensorMightHaveMoreListeners */,
+ samplingPeriodUs,
+ maxReportLatencyUs);
+ }
+
+ /**
+ * Constructs an environment for sensor testing.
+ *
+ * @param context The context for the test
+ * @param sensor The sensor under test
* @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load (this
* usually implies that there are several listeners
* requesting different sampling periods)
@@ -171,7 +210,8 @@
* data at different sampling rates (the rates are unknown); false otherwise.
*/
public boolean isSensorSamplingRateOverloaded() {
- return mSensorMightHaveMoreListeners && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST;
+ return mSensorMightHaveMoreListeners
+ && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST;
}
/**
@@ -197,6 +237,15 @@
}
/**
+ * @return The actual sampling period at which a sensor can sample data. This value is a
+ * fraction of {@link #getExpectedSamplingPeriodUs()}.
+ */
+ public int getMaximumExpectedSamplingPeriodUs() {
+ int expectedSamplingPeriodUs = getExpectedSamplingPeriodUs();
+ return (int) (expectedSamplingPeriodUs / MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER);
+ }
+
+ /**
* @return The number of axes in the coordinate system of the sensor under test.
*/
public int getSensorAxesCount() {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
index 9b3a5e4..ae36e6a 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -21,9 +21,12 @@
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener2;
+import android.os.Handler;
+import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -36,13 +39,16 @@
*/
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 static final long EVENT_TIMEOUT_US = TimeUnit.SECONDS.toMicros(5);
+ private static final long FLUSH_TIMEOUT_US = TimeUnit.SECONDS.toMicros(10);
+
+ private final ArrayList<CountDownLatch> mEventLatches = new ArrayList<CountDownLatch>();
+ private final ArrayList<CountDownLatch> mFlushLatches = new ArrayList<CountDownLatch>();
private final SensorEventListener2 mListener;
+ private final Handler mHandler;
- private volatile CountDownLatch mEventLatch;
- private volatile CountDownLatch mFlushLatch = new CountDownLatch(1);
+ private volatile boolean mEventsReceivedInHandler = true;
private volatile TestSensorEnvironment mEnvironment;
private volatile boolean mLogEvents;
@@ -50,13 +56,28 @@
* Construct a {@link TestSensorEventListener}.
*/
public TestSensorEventListener() {
- this(null);
+ this(null /* listener */, null /* handler */);
+ }
+
+ /**
+ * Construct a {@link TestSensorEventListener} with a {@link Handler}.
+ */
+ public TestSensorEventListener(Handler handler) {
+ this(null /* listener */, handler);
}
/**
* Construct a {@link TestSensorEventListener} that wraps a {@link SensorEventListener2}.
*/
public TestSensorEventListener(SensorEventListener2 listener) {
+ this(listener, null /* handler */);
+ }
+
+ /**
+ * Construct a {@link TestSensorEventListener} that wraps a {@link SensorEventListener2}, and it
+ * has a {@link Handler}.
+ */
+ public TestSensorEventListener(SensorEventListener2 listener, Handler handler) {
if (listener != null) {
mListener = listener;
} else {
@@ -67,6 +88,14 @@
public void onAccuracyChanged(Sensor sensor, int i) {}
};
}
+ mHandler = handler;
+ }
+
+ /**
+ * @return The handler (if any) associated with the instance.
+ */
+ public Handler getHandler() {
+ return mHandler;
}
/**
@@ -88,6 +117,7 @@
*/
@Override
public void onSensorChanged(SensorEvent event) {
+ checkHandler();
mListener.onSensorChanged(event);
if (mLogEvents) {
Log.v(LOG_TAG, String.format(
@@ -98,9 +128,10 @@
Arrays.toString(event.values)));
}
- CountDownLatch eventLatch = mEventLatch;
- if(eventLatch != null) {
- eventLatch.countDown();
+ synchronized (mEventLatches) {
+ for (CountDownLatch latch : mEventLatches) {
+ latch.countDown();
+ }
}
}
@@ -109,6 +140,7 @@
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ checkHandler();
mListener.onAccuracyChanged(sensor, accuracy);
}
@@ -117,12 +149,14 @@
*/
@Override
public void onFlushCompleted(Sensor sensor) {
- CountDownLatch latch = mFlushLatch;
- mFlushLatch = new CountDownLatch(1);
- if(latch != null) {
- latch.countDown();
- }
+ checkHandler();
mListener.onFlushCompleted(sensor);
+
+ synchronized (mFlushLatches) {
+ for (CountDownLatch latch : mFlushLatches) {
+ latch.countDown();
+ }
+ }
}
/**
@@ -131,13 +165,23 @@
* @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} µs
*/
public void waitForFlushComplete() throws InterruptedException {
- CountDownLatch latch = mFlushLatch;
- if(latch == null) {
- return;
+ CountDownLatch latch = new CountDownLatch(1);
+ synchronized (mFlushLatches) {
+ mFlushLatches.add(latch);
}
- Assert.assertTrue(
- SensorCtsHelper.formatAssertionMessage("WaitForFlush", mEnvironment),
- latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
+
+ try {
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "WaitForFlush",
+ mEnvironment,
+ "timeout=%dus",
+ FLUSH_TIMEOUT_US);
+ Assert.assertTrue(message, latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
+ } finally {
+ synchronized (mFlushLatches) {
+ mFlushLatches.remove(latch);
+ }
+ }
}
/**
@@ -146,22 +190,34 @@
* @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} µs
*/
public void waitForEvents(int eventCount) throws InterruptedException {
- mEventLatch = new CountDownLatch(eventCount);
+ CountDownLatch eventLatch = new CountDownLatch(eventCount);
+ synchronized (mEventLatches) {
+ mEventLatches.add(eventLatch);
+ }
try {
- int rateUs = mEnvironment.getExpectedSamplingPeriodUs();
- // Timeout is 2 * event count * expected period + batch timeout + default wait
- long timeoutUs = (2 * eventCount * rateUs)
+ long samplingPeriodUs = mEnvironment.getMaximumExpectedSamplingPeriodUs();
+ // timeout is 2 * event count * expected period + batch timeout + default wait
+ // we multiply by two as not to raise an error in this function even if the events are
+ // streaming at a lower rate than expected, as long as it's not streaming twice as slow
+ // as expected
+ long timeoutUs = (2 * eventCount * samplingPeriodUs)
+ mEnvironment.getMaxReportLatencyUs()
+ EVENT_TIMEOUT_US;
- String message = SensorCtsHelper.formatAssertionMessage(
- "WaitForEvents",
- mEnvironment,
- "requested:%d, received:%d",
- eventCount,
- eventCount - mEventLatch.getCount());
- Assert.assertTrue(message, mEventLatch.await(timeoutUs, TimeUnit.MICROSECONDS));
+ boolean success = eventLatch.await(timeoutUs, TimeUnit.MICROSECONDS);
+ if (!success) {
+ String message = SensorCtsHelper.formatAssertionMessage(
+ "WaitForEvents",
+ mEnvironment,
+ "requested=%d, received=%d, timeout=%dus",
+ eventCount,
+ eventCount - eventLatch.getCount(),
+ timeoutUs);
+ Assert.fail(message);
+ }
} finally {
- mEventLatch = null;
+ synchronized (mEventLatches) {
+ mEventLatches.remove(eventLatch);
+ }
}
}
@@ -171,4 +227,22 @@
public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
SensorCtsHelper.sleep(duration, timeUnit);
}
+
+ /**
+ * Asserts that sensor events arrived in the proper thread if a {@link Handler} was associated
+ * with the current instance.
+ *
+ * If no events were received this assertion will be evaluated to {@code true}.
+ */
+ public void assertEventsReceivedInHandler() {
+ Assert.assertTrue(
+ "Events did not arrive in the Looper associated with the given Handler.",
+ mEventsReceivedInHandler);
+ }
+
+ private void checkHandler() {
+ if (mHandler != null) {
+ mEventsReceivedInHandler &= (mHandler.getLooper() == Looper.myLooper());
+ }
+ }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
index dc40ff4..a611bfc 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
@@ -19,35 +19,18 @@
import junit.framework.Assert;
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 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>
+ * 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.
+ *
+ * NOTE: this class is expected to mirror {@link SensorManager} operations, and perform the
+ * required test verifications along with them.
*/
public class TestSensorManager {
private static final String LOG_TAG = "TestSensorManager";
@@ -55,7 +38,7 @@
private final SensorManager mSensorManager;
private final TestSensorEnvironment mEnvironment;
- private TestSensorEventListener mTestSensorEventListener;
+ private volatile TestSensorEventListener mTestSensorEventListener;
/**
* @deprecated Use {@link #TestSensorManager(TestSensorEnvironment)} instead.
@@ -90,7 +73,7 @@
return;
}
- mTestSensorEventListener = listener != null ? listener : new TestSensorEventListener();
+ mTestSensorEventListener = listener;
mTestSensorEventListener.setEnvironment(mEnvironment);
String message = SensorCtsHelper.formatAssertionMessage("registerListener", mEnvironment);
@@ -98,7 +81,8 @@
mTestSensorEventListener,
mEnvironment.getSensor(),
mEnvironment.getRequestedSamplingPeriodUs(),
- mEnvironment.getMaxReportLatencyUs());
+ mEnvironment.getMaxReportLatencyUs(),
+ listener.getHandler());
Assert.assertTrue(message, result);
}
@@ -110,136 +94,24 @@
Log.w(LOG_TAG, "No listener registered, returning.");
return;
}
-
- mSensorManager.unregisterListener(
- mTestSensorEventListener,
- mEnvironment.getSensor());
+ mSensorManager.unregisterListener(mTestSensorEventListener, mEnvironment.getSensor());
+ mTestSensorEventListener.assertEventsReceivedInHandler();
mTestSensorEventListener = null;
}
/**
- * Wait for a specific number of events.
- */
- public void waitForEvents(int eventCount) throws InterruptedException {
- 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) throws InterruptedException {
- 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
+ * @throws AssertionError if {@link SensorManager#flush(SensorEventListener)} fails.
*/
- public void startFlush() {
+ public void requestFlush() {
if (mTestSensorEventListener == null) {
+ Log.w(LOG_TAG, "No listener registered, returning.");
return;
}
-
Assert.assertTrue(
SensorCtsHelper.formatAssertionMessage("Flush", mEnvironment),
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)
- throws InterruptedException {
- 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)
- throws InterruptedException {
- if (mTestSensorEventListener != null) {
- Log.w(LOG_TAG, "Listener already registered, returning.");
- return;
- }
- try {
- registerListener(listener);
- waitForEvents(duration, timeUnit);
- } finally {
- unregisterListener();
- }
- }
-
- /**
- * Registers a listener, waits for a specific duration, calls flush, and waits for flush to
- * complete.
- */
- public void runSensorAndFlush(
- TestSensorEventListener listener,
- long duration,
- TimeUnit timeUnit) throws InterruptedException {
- if (mTestSensorEventListener != null) {
- Log.w(LOG_TAG, "Listener already registered, returning.");
- return;
- }
-
- try {
- registerListener(listener);
- SensorCtsHelper.sleep(duration, timeUnit);
- startFlush();
- listener.waitForFlushComplete();
- } finally {
- unregisterListener();
- }
- }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
index 299f470..7572dc7 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
@@ -17,11 +17,11 @@
package android.hardware.cts.helpers;
import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener2;
import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+import android.os.Handler;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.LinkedList;
/**
* A {@link TestSensorEventListener} which performs validations on the received events on the fly.
@@ -30,42 +30,17 @@
*/
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]));
- }
+ private final ArrayList<ISensorVerification> mVerifications =
+ new ArrayList<ISensorVerification>();
/**
* Construct a {@link ValidatingSensorEventListener}.
*/
- public ValidatingSensorEventListener(ISensorVerification ... verifications) {
- this(null, verifications);
- }
-
- /**
- * Construct a {@link ValidatingSensorEventListener}.
- */
- public ValidatingSensorEventListener(Collection<ISensorVerification> verifications) {
- this(null, verifications);
+ public ValidatingSensorEventListener(
+ Collection<ISensorVerification> verifications,
+ Handler handler) {
+ super(handler);
+ mVerifications.addAll(verifications);
}
/**
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
deleted file mode 100644
index d5aa4b9..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.TestSensorEnvironment;
-import android.hardware.cts.helpers.TestSensorEventListener;
-
-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, call flush, and then run all the tests.
- * </p>
- */
-public class TestSensorFlushOperation extends VerifiableSensorOperation {
- private final Long mDuration;
- private final TimeUnit mTimeUnit;
-
- /**
- * Create a {@link TestSensorOperation}.
- *
- * @param environment the test environment
- * @param duration the duration to gather events before calling {@code SensorManager.flush()}
- * @param timeUnit the time unit of the duration
- */
- public TestSensorFlushOperation(
- TestSensorEnvironment environment,
- long duration,
- TimeUnit timeUnit) {
- super(environment);
- mDuration = duration;
- mTimeUnit = timeUnit;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
- mSensorManager.runSensorAndFlush(listener, mDuration, mTimeUnit);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected VerifiableSensorOperation doClone() {
- return new TestSensorFlushOperation(mEnvironment, mDuration,mTimeUnit);
- }
-}
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
index 695e1a7..6e53dbb 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
@@ -16,9 +16,27 @@
package android.hardware.cts.helpers.sensoroperations;
+import junit.framework.Assert;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
import android.hardware.cts.helpers.TestSensorEnvironment;
import android.hardware.cts.helpers.TestSensorEventListener;
+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.EventTimestampSynchronizationVerification;
+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 android.os.Handler;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.concurrent.TimeUnit;
/**
@@ -29,70 +47,204 @@
* events and then run all the tests.
* </p>
*/
-public class TestSensorOperation extends VerifiableSensorOperation {
- private final Integer mEventCount;
- private final Long mDuration;
- private final TimeUnit mTimeUnit;
+public class TestSensorOperation extends AbstractSensorOperation {
+ private final Collection<ISensorVerification> mVerifications =
+ new HashSet<ISensorVerification>();
+
+ private final TestSensorManager mSensorManager;
+ private final TestSensorEnvironment mEnvironment;
+ private final Executor mExecutor;
+ private final Handler mHandler;
+
+ private boolean mLogEvents;
/**
- * Create a {@link TestSensorOperation}.
- *
- * @param environment the test environment
- * @param eventCount the number of events to gather
+ * An interface that defines an abstraction for operations to be performed by the
+ * {@link TestSensorOperation}.
*/
- public TestSensorOperation(TestSensorEnvironment environment, int eventCount) {
- this(environment, eventCount, null /* duration */, null /* timeUnit */);
+ public interface Executor {
+ void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
+ throws InterruptedException;
}
/**
* Create a {@link TestSensorOperation}.
- *
- * @param environment the test environment
- * @param duration the duration to gather events for
- * @param timeUnit the time unit of the duration
+ */
+ public TestSensorOperation(TestSensorEnvironment environment, Executor executor) {
+ this(environment, executor, null /* handler */);
+ }
+
+ /**
+ * Create a {@link TestSensorOperation}.
*/
public TestSensorOperation(
TestSensorEnvironment environment,
- long duration,
- TimeUnit timeUnit) {
- this(environment, null /* eventCount */, duration, timeUnit);
+ Executor executor,
+ Handler handler) {
+ mEnvironment = environment;
+ mExecutor = executor;
+ mHandler = handler;
+ mSensorManager = new TestSensorManager(mEnvironment);
}
/**
- * Private helper constructor.
+ * Set whether to log events.
*/
- private TestSensorOperation(
+ public void setLogEvents(boolean logEvents) {
+ mLogEvents = logEvents;
+ }
+
+ /**
+ * Set all of the default test expectations.
+ */
+ public void addDefaultVerifications() {
+ addVerification(EventGapVerification.getDefault(mEnvironment));
+ addVerification(EventOrderingVerification.getDefault(mEnvironment));
+ addVerification(FrequencyVerification.getDefault(mEnvironment));
+ addVerification(JitterVerification.getDefault(mEnvironment));
+ addVerification(MagnitudeVerification.getDefault(mEnvironment));
+ addVerification(MeanVerification.getDefault(mEnvironment));
+ addVerification(StandardDeviationVerification.getDefault(mEnvironment));
+ addVerification(EventTimestampSynchronizationVerification.getDefault(mEnvironment));
+ }
+
+ 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() throws InterruptedException {
+ getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
+
+ ValidatingSensorEventListener listener =
+ new ValidatingSensorEventListener(mVerifications, mHandler);
+ listener.setLogEvents(mLogEvents);
+
+ mExecutor.execute(mSensorManager, listener);
+
+ boolean failed = false;
+ StringBuilder sb = new StringBuilder();
+ for (ISensorVerification verification : mVerifications) {
+ failed |= evaluateResults(verification, sb);
+ }
+
+ if (failed) {
+ String msg = SensorCtsHelper
+ .formatAssertionMessage("VerifySensorOperation", mEnvironment, sb.toString());
+ getStats().addValue(SensorStats.ERROR, msg);
+ Assert.fail(msg);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TestSensorOperation clone() {
+ TestSensorOperation operation = new TestSensorOperation(mEnvironment, mExecutor);
+ 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(mEnvironment, getStats());
+ } catch (AssertionError e) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+ sb.append(e.getMessage());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Creates an operation that will wait for a given amount of events to arrive.
+ *
+ * @param environment The test environment.
+ * @param eventCount The number of events to wait for.
+ */
+ public static TestSensorOperation createOperation(
TestSensorEnvironment environment,
- Integer eventCount,
- Long duration,
- TimeUnit timeUnit) {
- super(environment);
- mEventCount = eventCount;
- mDuration = duration;
- mTimeUnit = timeUnit;
+ final int eventCount) {
+ Executor executor = new Executor() {
+ @Override
+ public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
+ throws InterruptedException {
+ try {
+ sensorManager.registerListener(listener);
+ listener.waitForEvents(eventCount);
+ } finally {
+ sensorManager.unregisterListener();
+ }
+ }
+ };
+ return new TestSensorOperation(environment, executor);
}
/**
- * {@inheritDoc}
+ * Creates an operation that will wait for a given amount of time to collect events.
+ *
+ * @param environment The test environment.
+ * @param duration The duration to wait for events.
+ * @param timeUnit The time unit for {@code duration}.
*/
- @Override
- protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
- if (mEventCount != null) {
- mSensorManager.runSensor(listener, mEventCount);
- } else {
- mSensorManager.runSensor(listener, mDuration, mTimeUnit);
- }
+ public static TestSensorOperation createOperation(
+ TestSensorEnvironment environment,
+ final long duration,
+ final TimeUnit timeUnit) {
+ Executor executor = new Executor() {
+ @Override
+ public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
+ throws InterruptedException {
+ try {
+ sensorManager.registerListener(listener);
+ listener.waitForEvents(duration, timeUnit);
+ } finally {
+ sensorManager.unregisterListener();
+ }
+ }
+ };
+ return new TestSensorOperation(environment, executor);
}
/**
- * {@inheritDoc}
+ * Creates an operation that will wait for a given amount of time before calling
+ * {@link TestSensorManager#requestFlush()}.
+ *
+ * @param environment The test environment.
+ * @param duration The duration to wait before calling {@link TestSensorManager#requestFlush()}.
+ * @param timeUnit The time unit for {@code duration}.
*/
- @Override
- protected VerifiableSensorOperation doClone() {
- if (mEventCount != null) {
- return new TestSensorOperation(mEnvironment, mEventCount);
- } else {
- return new TestSensorOperation(mEnvironment, mDuration, mTimeUnit);
- }
+ public static TestSensorOperation createFlushOperation(
+ TestSensorEnvironment environment,
+ final long duration,
+ final TimeUnit timeUnit) {
+ Executor executor = new Executor() {
+ @Override
+ public void execute(TestSensorManager sensorManager, TestSensorEventListener listener)
+ throws InterruptedException {
+ try {
+ sensorManager.registerListener(listener);
+ SensorCtsHelper.sleep(duration, timeUnit);
+ sensorManager.requestFlush();
+ listener.waitForFlushComplete();
+ } finally {
+ sensorManager.unregisterListener();
+ }
+ }
+ };
+ return new TestSensorOperation(environment, executor);
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
deleted file mode 100644
index 57018eb..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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 junit.framework.Assert;
-
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorStats;
-import android.hardware.cts.helpers.TestSensorEnvironment;
-import android.hardware.cts.helpers.TestSensorEventListener;
-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 java.util.Collection;
-import java.util.HashSet;
-
-/**
- * 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 abstract class VerifiableSensorOperation extends AbstractSensorOperation {
- protected final TestSensorManager mSensorManager;
- protected final TestSensorEnvironment mEnvironment;
-
- private final Collection<ISensorVerification> mVerifications =
- new HashSet<ISensorVerification>();
-
- private boolean mLogEvents = false;
-
- /**
- * Create a {@link TestSensorOperation}.
- *
- * @param environment the test environment
- */
- public VerifiableSensorOperation(TestSensorEnvironment environment) {
- mEnvironment = environment;
- mSensorManager = new TestSensorManager(mEnvironment);
- }
-
- /**
- * Set whether to log events.
- */
- public void setLogEvents(boolean logEvents) {
- mLogEvents = logEvents;
- }
-
- /**
- * Set all of the default test expectations.
- */
- public void addDefaultVerifications() {
- addVerification(EventGapVerification.getDefault(mEnvironment));
- addVerification(EventOrderingVerification.getDefault(mEnvironment));
- addVerification(FrequencyVerification.getDefault(mEnvironment));
- addVerification(JitterVerification.getDefault(mEnvironment));
- addVerification(MagnitudeVerification.getDefault(mEnvironment));
- addVerification(MeanVerification.getDefault(mEnvironment));
- // Skip SigNumVerification since it has no default
- addVerification(StandardDeviationVerification.getDefault(mEnvironment));
- }
-
- 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() throws InterruptedException {
- getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
-
- ValidatingSensorEventListener listener = new ValidatingSensorEventListener(mVerifications);
- listener.setLogEvents(mLogEvents);
-
- doExecute(listener);
-
- boolean failed = false;
- StringBuilder sb = new StringBuilder();
- for (ISensorVerification verification : mVerifications) {
- failed |= evaluateResults(verification, sb);
- }
-
- if (failed) {
- String msg = SensorCtsHelper
- .formatAssertionMessage("VerifySensorOperation", mEnvironment, sb.toString());
- getStats().addValue(SensorStats.ERROR, msg);
- Assert.fail(msg);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public VerifiableSensorOperation clone() {
- VerifiableSensorOperation operation = doClone();
- for (ISensorVerification verification : mVerifications) {
- operation.addVerification(verification.clone());
- }
- return operation;
- }
-
- /**
- * Execute operations in a {@link TestSensorManager}.
- */
- protected abstract void doExecute(TestSensorEventListener listener) throws InterruptedException;
-
- /**
- * Clone the subclass operation.
- */
- protected abstract VerifiableSensorOperation doClone();
-
- /**
- * Evaluate the results of a test, aggregate the stats, and build the error message.
- */
- private boolean evaluateResults(ISensorVerification verification, StringBuilder sb) {
- try {
- verification.verify(mEnvironment, 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/sensorverification/AbstractSensorVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
index 911ae3a..acf71bb 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
@@ -18,6 +18,8 @@
import android.hardware.cts.helpers.TestSensorEvent;
+import java.util.List;
+
/**
* Abstract class that deals with the synchronization of the sensor verifications.
*/
@@ -52,18 +54,38 @@
*/
protected abstract void addSensorEventInternal(TestSensorEvent event);
+ protected <TEvent extends IndexedEvent> int[] getIndexArray(List<TEvent> indexedEvents) {
+ int eventsCount = indexedEvents.size();
+ int[] indices = new int[eventsCount];
+ for (int i = 0; i < eventsCount; i++) {
+ indices[i] = indexedEvents.get(i).index;
+ }
+ return indices;
+ }
+
+ /**
+ * Helper class to store the index and current event.
+ * Events are added to the verification in the order they are generated, the index represents
+ * the position of the given event, in the list of added events.
+ */
+ protected class IndexedEvent {
+ public final int index;
+ public final TestSensorEvent event;
+
+ public IndexedEvent(int index, TestSensorEvent event) {
+ this.index = index;
+ this.event = event;
+ }
+ }
+
/**
* Helper class to store the index, previous event, and current event.
*/
- protected class IndexedEventPair {
- public final int index;
- public final TestSensorEvent event;
+ protected class IndexedEventPair extends IndexedEvent {
public final TestSensorEvent previousEvent;
- public IndexedEventPair(int index, TestSensorEvent event,
- TestSensorEvent previousEvent) {
- this.index = index;
- this.event = event;
+ public IndexedEventPair(int index, TestSensorEvent event, TestSensorEvent previousEvent) {
+ super(index, 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
index 156afa8..b692f0f 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java
@@ -63,19 +63,14 @@
public void verify(TestSensorEnvironment environment, SensorStats stats) {
if (environment.isSensorSamplingRateOverloaded()) {
// the verification is not reliable on environments under load
- stats.addValue(PASSED_KEY, true);
+ stats.addValue(PASSED_KEY, "skipped (under load)");
return;
}
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);
+ stats.addValue(SensorStats.EVENT_GAP_POSITIONS_KEY, getIndexArray(mEventGaps));
if (count > 0) {
StringBuilder sb = new StringBuilder();
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
index 6598725..7b77ead 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java
@@ -75,12 +75,9 @@
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);
+ stats.addValue(
+ SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY,
+ getIndexArray(mOutOfOrderEvents));
if (count > 0) {
StringBuilder sb = new StringBuilder();
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventTimestampSynchronizationVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventTimestampSynchronizationVerification.java
new file mode 100644
index 0000000..d4a1f38
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventTimestampSynchronizationVerification.java
@@ -0,0 +1,153 @@
+/*
+ * 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 junit.framework.Assert;
+
+import android.hardware.SensorEvent;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+import android.os.SystemClock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} which verifies that the timestamp of the {@link SensorEvent} is
+ * synchronized with {@link SystemClock#elapsedRealtimeNanos()}, based on a given threshold.
+ */
+public class EventTimestampSynchronizationVerification extends AbstractSensorVerification {
+ public static final String PASSED_KEY = "timestamp_synchronization_passed";
+
+ // number of indices to print in assertion message before truncating
+ private static final int TRUNCATE_MESSAGE_LENGTH = 3;
+
+ private static final long DEFAULT_THRESHOLD_NS = TimeUnit.MILLISECONDS.toNanos(500);
+
+ private final ArrayList<TestSensorEvent> mCollectedEvents = new ArrayList<TestSensorEvent>();
+
+ private final long mMaximumSynchronizationErrorNs;
+ private final long mReportLatencyNs;
+
+ /**
+ * Constructs an instance of {@link EventTimestampSynchronizationVerification}.
+ *
+ * @param maximumSynchronizationErrorNs The valid threshold for timestamp synchronization.
+ * @param reportLatencyNs The latency on which batching events are received
+ */
+ public EventTimestampSynchronizationVerification(
+ long maximumSynchronizationErrorNs,
+ long reportLatencyNs) {
+ mMaximumSynchronizationErrorNs = maximumSynchronizationErrorNs;
+ mReportLatencyNs = reportLatencyNs;
+ }
+
+ /**
+ * Gets a default {@link EventTimestampSynchronizationVerification}.
+ *
+ * @param environment The test environment
+ * @return The verification or null if the verification is not supported in the given
+ * environment.
+ */
+ public static EventTimestampSynchronizationVerification getDefault(
+ TestSensorEnvironment environment) {
+ int reportLatencyUs = environment.getMaxReportLatencyUs();
+ int fifoMaxEventCount = environment.getSensor().getFifoMaxEventCount();
+ if (fifoMaxEventCount > 0) {
+ int fifoBasedReportLatencyUs =
+ fifoMaxEventCount * environment.getMaximumExpectedSamplingPeriodUs();
+ reportLatencyUs = Math.min(reportLatencyUs, fifoBasedReportLatencyUs);
+
+ }
+ long reportLatencyNs = TimeUnit.MICROSECONDS.toNanos(reportLatencyUs);
+ return new EventTimestampSynchronizationVerification(DEFAULT_THRESHOLD_NS, reportLatencyNs);
+ }
+
+ @Override
+ public void verify(TestSensorEnvironment environment, SensorStats stats) {
+ StringBuilder errorMessageBuilder =
+ new StringBuilder(" event timestamp synchronization failures: ");
+ List<IndexedEvent> failures = verifyTimestampSynchronization(errorMessageBuilder);
+
+ int failuresCount = failures.size();
+ stats.addValue(SensorStats.EVENT_TIME_SYNCHRONIZATION_COUNT_KEY, failuresCount);
+ stats.addValue(
+ SensorStats.EVENT_TIME_SYNCHRONIZATION_POSITIONS_KEY,
+ getIndexArray(failures));
+
+ boolean success = failures.isEmpty();
+ stats.addValue(PASSED_KEY, success);
+ errorMessageBuilder.insert(0, failuresCount);
+ Assert.assertTrue(errorMessageBuilder.toString(), success);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public EventTimestampSynchronizationVerification clone() {
+ return new EventTimestampSynchronizationVerification(
+ mMaximumSynchronizationErrorNs,
+ mReportLatencyNs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void addSensorEventInternal(TestSensorEvent event) {
+ mCollectedEvents.add(event);
+ }
+
+ /**
+ * Verifies timestamp synchronization for all sensor events.
+ * The verification accounts for a lower and upper threshold, such thresholds are adjusted for
+ * batching cases.
+ *
+ * @param builder A string builder to store error messaged found in the collected sensor events.
+ * @return A list of events tha failed the verification.
+ */
+ private List<IndexedEvent> verifyTimestampSynchronization(StringBuilder builder) {
+ int collectedEventsCount = mCollectedEvents.size();
+ ArrayList<IndexedEvent> failures = new ArrayList<IndexedEvent>();
+
+ for (int i = 0; i < collectedEventsCount; ++i) {
+ TestSensorEvent event = mCollectedEvents.get(i);
+ long eventTimestampNs = event.timestamp;
+ long receivedTimestampNs = event.receivedTimestamp;
+ long upperThresholdNs = receivedTimestampNs;
+ long lowerThresholdNs = receivedTimestampNs - mMaximumSynchronizationErrorNs
+ - mReportLatencyNs;
+
+ if (eventTimestampNs < lowerThresholdNs || eventTimestampNs > upperThresholdNs) {
+ if (failures.size() < TRUNCATE_MESSAGE_LENGTH) {
+ builder.append("position=").append(i);
+ builder.append(", timestamp=").append(eventTimestampNs).append("ns");
+ builder.append(", expected=[").append(lowerThresholdNs);
+ builder.append(", ").append(upperThresholdNs).append("]ns; ");
+ }
+ failures.add(new IndexedEvent(i, event));
+ }
+ }
+ if (failures.size() >= TRUNCATE_MESSAGE_LENGTH) {
+ builder.append("more; ");
+ }
+ return failures;
+ }
+}
diff --git a/tests/tests/media/res/raw/sine1khzm40db.wav b/tests/tests/media/res/raw/sine1khzm40db.wav
new file mode 100644
index 0000000..ba541c4
--- /dev/null
+++ b/tests/tests/media/res/raw/sine1khzm40db.wav
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/VisualizerTest.java b/tests/tests/media/src/android/media/cts/VisualizerTest.java
index 8c91e9b..871f602 100644
--- a/tests/tests/media/src/android/media/cts/VisualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VisualizerTest.java
@@ -16,10 +16,15 @@
package android.media.cts;
+import com.android.cts.media.R;
+
+import android.content.Context;
import android.media.audiofx.AudioEffect;
import android.media.AudioFormat;
import android.media.AudioManager;
+import android.media.MediaPlayer;
import android.media.audiofx.Visualizer;
+import android.media.audiofx.Visualizer.MeasurementPeakRms;
import android.os.Looper;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -126,7 +131,7 @@
// 2 - check capture
//----------------------------------
- //Test case 2.0: test cature in polling mode
+ //Test case 2.0: test capture in polling mode
public void test2_0PollingCapture() throws Exception {
if (!hasAudioOutput()) {
return;
@@ -217,6 +222,113 @@
}
//-----------------------------------------------------------------
+ // 3 - check measurement mode MEASUREMENT_MODE_NONE
+ //----------------------------------
+
+ //Test case 3.0: test setting NONE measurement mode
+ public void test3_0MeasurementModeNone() throws Exception {
+ try {
+ getVisualizer(0);
+ mVisualizer.setEnabled(true);
+ assertTrue("visualizer not enabled", mVisualizer.getEnabled());
+ Thread.sleep(100);
+
+ int status = mVisualizer.setMeasurementMode(Visualizer.MEASUREMENT_MODE_NONE);
+ assertEquals("setMeasurementMode for NONE doesn't report success",
+ Visualizer.SUCCESS, status);
+
+ int mode = mVisualizer.getMeasurementMode();
+ assertEquals("getMeasurementMode reports NONE",
+ Visualizer.MEASUREMENT_MODE_NONE, mode);
+
+ } catch (IllegalStateException e) {
+ fail("method called in wrong state");
+ } catch (InterruptedException e) {
+ fail("sleep() interrupted");
+ } finally {
+ releaseVisualizer();
+ }
+ }
+
+ //-----------------------------------------------------------------
+ // 4 - check measurement mode MEASUREMENT_MODE_PEAK_RMS
+ //----------------------------------
+
+ //Test case 4.0: test setting peak / RMS measurement mode
+ public void test4_0MeasurementModePeakRms() throws Exception {
+ try {
+ getVisualizer(0);
+ mVisualizer.setEnabled(true);
+ assertTrue("visualizer not enabled", mVisualizer.getEnabled());
+ Thread.sleep(100);
+
+ int status = mVisualizer.setMeasurementMode(Visualizer.MEASUREMENT_MODE_PEAK_RMS);
+ assertEquals("setMeasurementMode for PEAK_RMS doesn't report success",
+ Visualizer.SUCCESS, status);
+
+ int mode = mVisualizer.getMeasurementMode();
+ assertEquals("getMeasurementMode doesn't report PEAK_RMS",
+ Visualizer.MEASUREMENT_MODE_PEAK_RMS, mode);
+
+ } catch (IllegalStateException e) {
+ fail("method called in wrong state");
+ } catch (InterruptedException e) {
+ fail("sleep() interrupted");
+ } finally {
+ releaseVisualizer();
+ }
+ }
+
+ //Test case 4.1: test measurement of peak / RMS
+ public void test4_1MeasurePeakRms() throws Exception {
+ try {
+ // this test will play a 1kHz sine wave with peaks at -40dB
+ MediaPlayer mp = MediaPlayer.create(getContext(), R.raw.sine1khzm40db);
+ final int EXPECTED_PEAK_MB = -4015;
+ final int EXPECTED_RMS_MB = -4300;
+ final int MAX_MEASUREMENT_ERROR_MB = 1500;
+ assertNotNull("null MediaPlayer", mp);
+
+ AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ assertNotNull("null AudioManager", am);
+ int originalVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC,
+ am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
+ getVisualizer(mp.getAudioSessionId());
+ mp.setLooping(true);
+ mp.start();
+
+ mVisualizer.setEnabled(true);
+ assertTrue("visualizer not enabled", mVisualizer.getEnabled());
+ Thread.sleep(100);
+ int status = mVisualizer.setMeasurementMode(Visualizer.MEASUREMENT_MODE_PEAK_RMS);
+ // make sure we're playing long enough so the measurement is valid
+ Thread.sleep(500);
+ assertEquals("setMeasurementMode() for PEAK_RMS doesn't report success",
+ Visualizer.SUCCESS, status);
+ MeasurementPeakRms measurement = new MeasurementPeakRms();
+ status = mVisualizer.getMeasurementPeakRms(measurement);
+ assertEquals("getMeasurementPeakRms() reports failure",
+ Visualizer.SUCCESS, status);
+ Log.i("VisTest", "peak="+measurement.mPeak+" rms="+measurement.mRms);
+ int deltaPeak = Math.abs(measurement.mPeak - EXPECTED_PEAK_MB);
+ int deltaRms = Math.abs(measurement.mRms - EXPECTED_RMS_MB);
+ assertTrue("peak deviation in mB=" + deltaPeak, deltaPeak < MAX_MEASUREMENT_ERROR_MB);
+ assertTrue("RMS deviation in mB=" + deltaRms, deltaRms < MAX_MEASUREMENT_ERROR_MB);
+ mp.stop();
+ mp.release();
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, originalVolume, 0);
+
+ } catch (IllegalStateException e) {
+ fail("method called in wrong state");
+ } catch (InterruptedException e) {
+ fail("sleep() interrupted");
+ } finally {
+ releaseVisualizer();
+ }
+ }
+
+ //-----------------------------------------------------------------
// private methods
//----------------------------------
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestVLoad.java b/tests/tests/renderscript/src/android/renderscript/cts/TestVLoad.java
new file mode 100644
index 0000000..a2d22d9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestVLoad.java
@@ -0,0 +1,371 @@
+ /*
+ * 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.*;
+
+public class TestVLoad extends RSBaseCompute {
+
+ private ScriptC_vload script;
+ private ScriptC_vload_relaxed scriptRelaxed;
+ Allocation walkAlloc;
+ Allocation inAlloc;
+ Allocation outAlloc;
+ private static java.util.Random random = new java.util.Random();
+
+ final int w = 253;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ random.setSeed(10);
+ script = new ScriptC_vload(mRS);
+ scriptRelaxed = new ScriptC_vload_relaxed(mRS);
+ }
+
+
+
+ protected void createWalk() {
+ int tmp[] = new int[w];
+ boolean b[] = new boolean[w];
+ int toCopy = w;
+ int i = 0;
+
+ while (toCopy > 0) {
+ int x = random.nextInt(w);
+
+ //android.util.Log.v("rs", "x " + x + ", y " + y + ", toCopy " + toCopy);
+ while ((x < w) && b[x]) {
+ x++;
+ if (x >= w) {
+ x = 0;
+ }
+ }
+
+ int maxsize = 1;
+ b[x] = true;
+ if ((x+1 < w) && !b[x+1]) {
+ maxsize ++;
+ b[x+1] = true;
+ if ((x+2 < w) && !b[x+2]) {
+ maxsize ++;
+ b[x+2] = true;
+ if ((x+3 < w) && !b[x+3]) {
+ maxsize ++;
+ b[x+3] = true;
+ }
+ }
+ }
+
+ toCopy -= maxsize;
+ tmp[i] = x | (maxsize << 16);
+ android.util.Log.v("rs", "x " + x + ", vec " + maxsize);
+ i++;
+ }
+
+ walkAlloc = Allocation.createSized(mRS, Element.I32(mRS), i);
+ walkAlloc.copy1DRangeFrom(0, i, tmp);
+ }
+
+ private void testSetup(Type t) {
+ createWalk();
+
+ inAlloc = Allocation.createTyped(mRS, t);
+ outAlloc = Allocation.createTyped(mRS, t);
+ script.set_gAllocIn(inAlloc);
+ script.set_gAllocOut(outAlloc);
+ scriptRelaxed.set_gAllocIn(inAlloc);
+ scriptRelaxed.set_gAllocOut(outAlloc);
+ }
+
+ private void verify(byte[] a1, byte[] a2, String s) {
+ outAlloc.copyTo(a2);
+ for (int i=0; i < w; i++) {
+ if (a1[i] != a2[i]) {
+ throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+ }
+ a2[i] = 0;
+ }
+ outAlloc.copyFrom(a2);
+ }
+
+ private void verify(short[] a1, short[] a2, String s) {
+ outAlloc.copyTo(a2);
+ for (int i=0; i < w; i++) {
+ if (a1[i] != a2[i]) {
+ throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+ }
+ a2[i] = 0;
+ }
+ outAlloc.copyFrom(a2);
+ }
+
+ private void verify(int[] a1, int[] a2, String s) {
+ outAlloc.copyTo(a2);
+ for (int i=0; i < w; i++) {
+ if (a1[i] != a2[i]) {
+ throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+ }
+ a2[i] = 0;
+ }
+ outAlloc.copyFrom(a2);
+ }
+
+ private void verify(long[] a1, long[] a2, String s) {
+ outAlloc.copyTo(a2);
+ for (int i=0; i < w; i++) {
+ if (a1[i] != a2[i]) {
+ throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+ }
+ a2[i] = 0;
+ }
+ outAlloc.copyFrom(a2);
+ }
+
+ private void verify(float[] a1, float[] a2, String s) {
+ outAlloc.copyTo(a2);
+ for (int i=0; i < w; i++) {
+ if (a1[i] != a2[i]) {
+ throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+ }
+ a2[i] = 0;
+ }
+ outAlloc.copyFrom(a2);
+ }
+
+ private void verify(double[] a1, double[] a2, String s) {
+ outAlloc.copyTo(a2);
+ for (int i=0; i < w; i++) {
+ if (a1[i] != a2[i]) {
+ throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+ }
+ a2[i] = 0;
+ }
+ outAlloc.copyFrom(a2);
+ }
+
+ private byte[] randomByteArray(int len) {
+ byte t[] = new byte[len];
+ random.nextBytes(t);
+ inAlloc.copyFrom(t);
+ return t;
+ }
+
+ private short[] randomShortArray(int len) {
+ short t[] = new short[len];
+ for (int i = 0; i < t.length; i++) {
+ t[i] = (short)(random.nextInt() & 0xffff);
+ }
+ inAlloc.copyFrom(t);
+ return t;
+ }
+
+ private int[] randomIntArray(int len) {
+ int t[] = new int[len];
+ for (int i = 0; i < t.length; i++) {
+ t[i] = random.nextInt();
+ }
+ inAlloc.copyFrom(t);
+ return t;
+ }
+
+ private long[] randomLongArray(int len) {
+ long t[] = new long[len];
+ for (int i = 0; i < t.length; i++) {
+ t[i] = random.nextLong();
+ }
+ inAlloc.copyFrom(t);
+ return t;
+ }
+
+ public void testVload_char() {
+ testSetup(Type.createX(mRS, Element.I8(mRS), w));
+ byte tmp[] = randomByteArray(w);
+ byte tmp2[] = new byte[w];
+ script.forEach_copy2d_char(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch char: ");
+ }
+
+ public void testVload_uchar() {
+ testSetup(Type.createX(mRS, Element.I8(mRS), w));
+ byte tmp[] = randomByteArray(w);
+ byte tmp2[] = new byte[w];
+ script.forEach_copy2d_uchar(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch uchar: ");
+ }
+
+ public void testVload_char_relaxed() {
+ testSetup(Type.createX(mRS, Element.I8(mRS), w));
+ byte tmp[] = randomByteArray(w);
+ byte tmp2[] = new byte[w];
+ scriptRelaxed.forEach_copy2d_char(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed char: ");
+ }
+
+ public void testVload_uchar_relaxed() {
+ testSetup(Type.createX(mRS, Element.I8(mRS), w));
+ byte tmp[] = randomByteArray(w);
+ byte tmp2[] = new byte[w];
+ scriptRelaxed.forEach_copy2d_uchar(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed uchar: ");
+ }
+
+ public void testVload_short() {
+ testSetup(Type.createX(mRS, Element.I16(mRS), w));
+ short tmp[] = randomShortArray(w);
+ short tmp2[] = new short[w];
+ script.forEach_copy2d_short(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch short: ");
+ }
+
+ public void testVload_ushort() {
+ testSetup(Type.createX(mRS, Element.I16(mRS), w));
+ short tmp[] = randomShortArray(w);
+ short tmp2[] = new short[w];
+ script.forEach_copy2d_ushort(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch ushort: ");
+ }
+
+ public void testVload_short_relaxed() {
+ testSetup(Type.createX(mRS, Element.I16(mRS), w));
+ short tmp[] = randomShortArray(w);
+ short tmp2[] = new short[w];
+ scriptRelaxed.forEach_copy2d_short(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed short: ");
+ }
+
+ public void testVload_ushort_relaxed() {
+ testSetup(Type.createX(mRS, Element.I16(mRS), w));
+ short tmp[] = randomShortArray(w);
+ short tmp2[] = new short[w];
+ scriptRelaxed.forEach_copy2d_ushort(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch ushort: ");
+ }
+
+ public void testVload_int() {
+ testSetup(Type.createX(mRS, Element.I32(mRS), w));
+ int tmp[] = randomIntArray(w);
+ int tmp2[] = new int[w];
+ script.forEach_copy2d_int(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch int: ");
+ }
+
+ public void testVload_uint() {
+ testSetup(Type.createX(mRS, Element.I32(mRS), w));
+ int tmp[] = randomIntArray(w);
+ int tmp2[] = new int[w];
+ script.forEach_copy2d_uint(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch uint: ");
+ }
+
+ public void testVload_int_relaxed() {
+ testSetup(Type.createX(mRS, Element.I32(mRS), w));
+ int tmp[] = randomIntArray(w);
+ int tmp2[] = new int[w];
+ scriptRelaxed.forEach_copy2d_int(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed int: ");
+ }
+
+ public void testVload_uint_relaxed() {
+ testSetup(Type.createX(mRS, Element.I32(mRS), w));
+ int tmp[] = randomIntArray(w);
+ int tmp2[] = new int[w];
+ scriptRelaxed.forEach_copy2d_uint(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch uint: ");
+ }
+
+ public void testVload_long() {
+ testSetup(Type.createX(mRS, Element.I64(mRS), w));
+ long tmp[] = randomLongArray(w);
+ long tmp2[] = new long[w];
+ script.forEach_copy2d_long(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch long: ");
+ }
+
+ public void testVload_ulong() {
+ testSetup(Type.createX(mRS, Element.I64(mRS), w));
+ long tmp[] = randomLongArray(w);
+ long tmp2[] = new long[w];
+ script.forEach_copy2d_ulong(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch ulong: ");
+ }
+ public void testVload_long_relaxed() {
+ testSetup(Type.createX(mRS, Element.I64(mRS), w));
+ long tmp[] = randomLongArray(w);
+ long tmp2[] = new long[w];
+ scriptRelaxed.forEach_copy2d_long(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed long: ");
+ }
+ public void testVload_ulong_relaxed() {
+ testSetup(Type.createX(mRS, Element.I64(mRS), w));
+ long tmp[] = randomLongArray(w);
+ long tmp2[] = new long[w];
+ scriptRelaxed.forEach_copy2d_ulong(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch ulong: ");
+ }
+
+ public void testVload_float() {
+ testSetup(Type.createX(mRS, Element.F32(mRS), w));
+ float tmp[] = new float[w];
+ float tmp2[] = new float[w];
+ for (int i=0; i < w; i++) {
+ tmp[i] = random.nextFloat();
+ }
+ inAlloc.copyFrom(tmp);
+ script.forEach_copy2d_float(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch float: ");
+ }
+
+ public void testVload_float_relaxed() {
+ testSetup(Type.createX(mRS, Element.F32(mRS), w));
+ float tmp[] = new float[w];
+ float tmp2[] = new float[w];
+ for (int i=0; i < w; i++) {
+ tmp[i] = random.nextFloat();
+ }
+ inAlloc.copyFrom(tmp);
+ scriptRelaxed.forEach_copy2d_float(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed float: ");
+ }
+
+ public void testVload_double() {
+ testSetup(Type.createX(mRS, Element.F64(mRS), w));
+ double tmp[] = new double[w];
+ double tmp2[] = new double[w];
+ for (int i=0; i < w; i++) {
+ tmp[i] = random.nextDouble();
+ }
+ inAlloc.copyFrom(tmp);
+ script.forEach_copy2d_double(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch double: ");
+ }
+
+ public void testVload_double_relaxed() {
+ testSetup(Type.createX(mRS, Element.F64(mRS), w));
+ double tmp[] = new double[w];
+ double tmp2[] = new double[w];
+ for (int i=0; i < w; i++) {
+ tmp[i] = random.nextDouble();
+ }
+ inAlloc.copyFrom(tmp);
+ scriptRelaxed.forEach_copy2d_double(walkAlloc);
+ verify(tmp, tmp2, "Data mismatch relaxed double: ");
+ }
+
+}
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/vload.rs b/tests/tests/renderscript/src/android/renderscript/cts/vload.rs
new file mode 100644
index 0000000..cdf5fd1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/vload.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+rs_allocation gAllocIn;
+rs_allocation gAllocOut;
+
+
+
+#define COPY_2D(ty) \
+ void __attribute__((kernel)) copy2d_##ty(int xy_v) { \
+ int lx = xy_v & 0xff; \
+ int vecsize = (xy_v & 0xff0000) >> 16; \
+ switch(vecsize) { \
+ case 1: { \
+ ty i = rsGetElementAt_##ty(gAllocIn, lx); \
+ rsSetElementAt_##ty(gAllocOut, i, lx); \
+ } break; \
+ case 2: { \
+ ty##2 i = rsAllocationVLoadX_##ty##2(gAllocIn, lx); \
+ rsAllocationVStoreX_##ty##2(gAllocOut, i, lx); \
+ } break; \
+ case 3: { \
+ ty##3 i = rsAllocationVLoadX_##ty##3(gAllocIn, lx); \
+ rsAllocationVStoreX_##ty##3(gAllocOut, i, lx); \
+ } break; \
+ case 4: { \
+ ty##4 i = rsAllocationVLoadX_##ty##4(gAllocIn, lx); \
+ rsAllocationVStoreX_##ty##4(gAllocOut, i, lx); \
+ } break; \
+ } \
+ }
+
+COPY_2D(char)
+COPY_2D(uchar)
+COPY_2D(short)
+COPY_2D(ushort)
+COPY_2D(int)
+COPY_2D(uint)
+COPY_2D(long)
+COPY_2D(ulong)
+
+COPY_2D(float)
+COPY_2D(double)
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/vload_relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/vload_relaxed.rs
new file mode 100644
index 0000000..61940ba
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/vload_relaxed.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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+#pragma rs_fp_relaxed
+
+rs_allocation gAllocIn;
+rs_allocation gAllocOut;
+
+
+
+#define COPY_2D(ty) \
+ void __attribute__((kernel)) copy2d_##ty(int xy_v) { \
+ int lx = xy_v & 0xff; \
+ int vecsize = (xy_v & 0xff0000) >> 16; \
+ switch(vecsize) { \
+ case 1: { \
+ ty i = rsGetElementAt_##ty(gAllocIn, lx); \
+ rsSetElementAt_##ty(gAllocOut, i, lx); \
+ } break; \
+ case 2: { \
+ ty##2 i = rsAllocationVLoadX_##ty##2(gAllocIn, lx); \
+ rsAllocationVStoreX_##ty##2(gAllocOut, i, lx); \
+ } break; \
+ case 3: { \
+ ty##3 i = rsAllocationVLoadX_##ty##3(gAllocIn, lx); \
+ rsAllocationVStoreX_##ty##3(gAllocOut, i, lx); \
+ } break; \
+ case 4: { \
+ ty##4 i = rsAllocationVLoadX_##ty##4(gAllocIn, lx); \
+ rsAllocationVStoreX_##ty##4(gAllocOut, i, lx); \
+ } break; \
+ } \
+ }
+
+COPY_2D(char)
+COPY_2D(uchar)
+COPY_2D(short)
+COPY_2D(ushort)
+COPY_2D(int)
+COPY_2D(uint)
+COPY_2D(long)
+COPY_2D(ulong)
+
+COPY_2D(float)
+COPY_2D(double)
+