am 0e8d9cf1: Merge "Make tests more reliable by cleaning up worker threads on cancelation. b/17888343" into lmp-dev
* commit '0e8d9cf18bcc2317785bf74d2e2bacb107f7d5e1':
Make tests more reliable by cleaning up worker threads on cancelation. b/17888343
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 1fbded5..3b74e52 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -469,7 +469,7 @@
<string name="snsr_test_pass">PASS</string>
<string name="snsr_test_skipped">SKIPPED</string>
<string name="snsr_test_fail">FAIL</string>
- <string name="snsr_executing_test">\nExecuting test case \'%1$s\'..\n</string>
+ <string name="snsr_execution_time">Test execution time %1$s sec</string>
<!-- Strings to interact with users in Sensor Tests -->
<string name="snsr_test_play_sound">A sound will be played once the verification is complete...</string>
@@ -479,7 +479,6 @@
<string name="snsr_keep_device_rotating_clockwise">Once the test begins, you will have to keep rotating the device clockwise.</string>
<string name="snsr_wait_for_user">Press \'Next\' to continue.</string>
<string name="snsr_wait_to_begin">Press \'Next\' to begin.</string>
- <string name="snsr_wait_to_complete">Press \'Next\' to complete.</string>
<string name="snsr_on_complete_return">After completing the task, go back to this test.</string>
<string name="snsr_movement_expected">Movement was expected during the test. Found=%1$b.</string>
<string name="snsr_sensor_feature_deactivation">Additionally, turn off any other features installed in the device, that register for sensors. Once you are done, you can continue the test.</string>
@@ -491,7 +490,6 @@
<string name="snsr_setting_auto_rotate_screen_mode">Auto-rotate screen</string>
<string name="snsr_setting_keep_screen_on">Stay awake</string>
<string name="snsr_setting_location_mode">Location</string>
- <string name="snsr_setting_auto_screen_off_mode">Display Sleep</string>
<string name="snsr_pass_on_error">Pass Anyway</string>
<string name="snsr_run_automated_tests">The screen will be turned off to execute the tests,
when tests complete, the device will vibrate and the screen will be turned back on.</string>
@@ -526,7 +524,6 @@
facing the ceiling. Read the instructions for each scenario, before you perform the
test.</string>
<string name="snsr_gyro_device_static">Leave the device static.</string>
- <string name="snsr_gyro_rotate_clockwise">Rotate the device clockwise.</string>
<string name="snsr_gyro_rotate_device">Once you begin the test, you will need to rotate the
device 360deg (one time) in the direction show by the animation, then place it back on the
flat surface.</string>
@@ -550,20 +547,15 @@
<string name="snsr_mag_measurement">-> (%1$.2f, %2$.2f, %3$.2f) : %4$.2f uT</string>
<!-- Sensor Value Accuracy -->
- <string name="snsr_val_acc_test">Sensor Value Accuracy Tests</string>
<string name="snsr_rot_vec_test">Rotation Vector Accuracy Test</string>
- <string name="snsr_collected_events_length">Sensor(%2$s). Collected events expected to be greater than zero. Found=%1$d.</string>
<string name="snsr_event_length">Sensor(%3$s). Event values expected to have size=%1$d. Found=%2$d.</string>
- <string name="snsr_event_length_positive">Sensor(%2$s). Event values expected to have size > 0. Found=%1$d</string>
<string name="snsr_event_value">Sensor(%3$s). Event value[0] expected to be of value=%1$f. Found=%2$f.</string>
<string name="snsr_event_time">Sensor(%5$s). Event timestamp expected to be synchronized with SystemClock.elapsedRealtimeNanos(). Event received at=%1$d. Event timestamp=%2$d. Delta=%3$d. Threshold=%4$d.</string>
- <string name="snsr_event_time_positive">Sensor(%2$s). Event timestamp expected to positive (> 0). Found=%1$d.</string>
<!-- Sensor Batching -->
<string name="snsr_batch_test">Sensor Batching Tests</string>
<string name="snsr_batching_walking_needed">Once the test begins, you will have to take the
device in your hand and walk.</string>
- <string name="snsr_batching_fifo_count">FifoReservedEventCount=%1$d. Expected to be at most FifoMaxEventCount=%2$d.</string>
<!-- Sensor Synchronization -->
<string name="snsr_synch_test">Sensor Synchronization Test</string>
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 4ba38a9..6f0a7aa 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
@@ -19,15 +19,12 @@
import com.android.cts.verifier.R;
import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
-import android.content.Context;
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 android.os.Bundle;
-import android.os.PowerManager;
import java.util.concurrent.TimeUnit;
@@ -51,27 +48,9 @@
// such events to generate
private static final int REPORT_LATENCY_25_SEC = 25;
- private PowerManager.WakeLock mWakeLock;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- protected void activitySetUp() throws InterruptedException {
- PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "BatchingTests");
- mWakeLock.acquire();
- }
-
- @Override
- protected void activityCleanUp() throws InterruptedException {
- mWakeLock.release();
- }
-
// TODO: refactor to discover all available sensors of each type and dynamically generate test
// cases for all of them
+ @SuppressWarnings("unused")
public String testStepCounter_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_STEP_COUNTER,
@@ -79,6 +58,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testStepCounter_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_STEP_COUNTER,
@@ -86,6 +66,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testStepDetector_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_STEP_DETECTOR,
@@ -93,6 +74,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testStepDetector_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_STEP_DETECTOR,
@@ -100,6 +82,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testProximity_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_PROXIMITY,
@@ -107,6 +90,7 @@
R.string.snsr_interaction_needed);
}
+ @SuppressWarnings("unused")
public String testProximity_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_PROXIMITY,
@@ -114,6 +98,7 @@
R.string.snsr_interaction_needed);
}
+ @SuppressWarnings("unused")
public String testLight_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_LIGHT,
@@ -121,6 +106,7 @@
R.string.snsr_interaction_needed);
}
+ @SuppressWarnings("unused")
public String testLight_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_LIGHT,
@@ -164,7 +150,7 @@
return executeTest(operation);
}
- private String executeTest(VerifiableSensorOperation operation) {
+ private String executeTest(VerifiableSensorOperation 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 ac63780..4b2a7f4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
@@ -51,7 +51,7 @@
}
@Override
- protected void activitySetUp() {
+ protected void activitySetUp() throws InterruptedException {
getTestLogger().logInstructions(R.string.snsr_gyro_device_placement);
waitForUserToContinue();
initializeGlSurfaceView(mRenderer);
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 bd18a95..553147b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
@@ -46,7 +46,7 @@
}
@Override
- public void activitySetUp() {
+ public void activitySetUp() throws InterruptedException {
calibrateMagnetometer();
}
@@ -165,7 +165,7 @@
/**
* A routine to help operators calibrate the magnetometer.
*/
- private void calibrateMagnetometer() {
+ private void calibrateMagnetometer() throws InterruptedException {
SensorEventListener2 listener = new SensorEventListener2() {
@Override
public void onSensorChanged(SensorEvent event) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
index cd94128..6b804dd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
@@ -87,7 +87,7 @@
// TODO: take reference value automatically when device is 'still'
clearText();
appendText(R.string.snsr_rotation_vector_set_reference);
- waitForUser();
+ waitForUserToContinue();
clearText();
for (int i = 0; i < MAX_SENSORS_AVAILABLE; ++i) {
@@ -104,7 +104,7 @@
// TODO: take final value automatically when device becomes 'still' at the end
clearText();
appendText(R.string.snsr_rotation_vector_set_final);
- waitForUser();
+ waitForUserToContinue();
clearText();
closeGlSurfaceView();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
index cfc4db0..8370d3e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
@@ -34,11 +34,10 @@
super(SensorPowerTestActivity.class);
}
-
@Override
- public void waitForUserAcknowledgement(final String message) {
+ public void waitForUserAcknowledgement(final String message) throws InterruptedException {
appendText(message);
- waitForUser();
+ waitForUserToContinue();
}
@Override
@@ -63,7 +62,7 @@
}
@Override
- protected void activitySetUp() {
+ protected void activitySetUp() throws InterruptedException {
mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
mScreenManipulator.initialize(this);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
index 1dd5984..683430c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
@@ -7,7 +7,6 @@
import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -137,9 +136,9 @@
public String testCrossSensorSynchronization() throws Throwable {
appendText("This test provides a rough indication of cross-sensor timestamp synchronization.");
appendText("Hold device still in hand and click 'Next'");
- waitForUser();
+ waitForUserToBegin();
clearText();
- appendText("Quickly twist device upside-down and back", Color.GREEN);
+ appendText("Quickly twist device upside-down and back");
startDataCollection();
Thread.sleep(DATA_COLLECTION_TIME_IN_MS);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
index a84a045..faba445 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
@@ -59,6 +59,8 @@
/**
* Test cases.
*/
+
+ @SuppressWarnings("unused")
public String testTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_trigger,
@@ -67,6 +69,7 @@
false /* vibrate */);
}
+ @SuppressWarnings("unused")
public String testNotTriggerAfterCancel() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_cancel,
@@ -78,6 +81,7 @@
/**
* Verifies that Significant Motion is not trigger by the vibrator motion.
*/
+ @SuppressWarnings("unused")
public String testVibratorDoesNotTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_vibration,
@@ -90,6 +94,7 @@
* Verifies that the natural motion of keeping the device in hand does not change the location.
* It ensures that Significant Motion will not trigger in that scenario.
*/
+ @SuppressWarnings("unused")
public String testInHandDoesNotTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_in_hand,
@@ -98,6 +103,7 @@
false /* vibrate */);
}
+ @SuppressWarnings("unused")
public String testSittingDoesNotTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_sitting,
@@ -106,6 +112,7 @@
false /* vibrate */);
}
+ @SuppressWarnings("unused")
public String testTriggerDeactivation() throws Throwable {
SensorTestLogger logger = getTestLogger();
logger.logInstructions(R.string.snsr_significant_motion_test_deactivation);
@@ -167,6 +174,7 @@
}
} finally {
mSensorManager.cancelTriggerSensor(verifier, mSensorSignificantMotion);
+ playSound();
}
return result;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
index 76d12d9..98368c6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
@@ -33,7 +33,6 @@
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.View;
-import android.widget.ScrollView;
import java.util.ArrayList;
import java.util.List;
@@ -86,8 +85,7 @@
"Sensors Step Counter/Detector are not supported.");
}
- ScrollView scrollView = (ScrollView) findViewById(R.id.log_scroll_view);
- scrollView.setOnTouchListener(new View.OnTouchListener() {
+ setLogScrollViewListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// during movement of the device, the ScrollView will detect user taps as attempts
@@ -95,14 +93,27 @@
// to overcome the fact that a ScrollView cannot be disabled from scrolling, we
// listen for ACTION_UP events instead of click events in the child layout
long elapsedTime = SystemClock.elapsedRealtimeNanos();
- if (event.getAction() == MotionEvent.ACTION_UP) {
+ if (event.getAction() != MotionEvent.ACTION_UP) {
+ return false;
+ }
+
+ try {
logUserReportedStep(elapsedTime);
+ } catch (InterruptedException e) {
+ // we cannot propagate the exception in the main thread, so we just catch and
+ // restore the status, we don't need to log as we are terminating anyways
+ Thread.currentThread().interrupt();
}
return false;
}
});
}
+ @Override
+ protected void activityCleanUp() {
+ setLogScrollViewListener(null /* listener */);
+ }
+
public String testWalking() throws Throwable {
return runTest(
R.string.snsr_step_counter_test_walking,
@@ -323,11 +334,10 @@
// TODO: with delayed assertions check events of other types are tracked
}
- private void logUserReportedStep(long timestamp) {
+ private void logUserReportedStep(long timestamp) throws InterruptedException {
if (!mCheckForMotion) {
return;
}
-
playSound();
mTimestampsUserReported.add(timestamp);
getTestLogger().logMessage(R.string.snsr_step_reported, timestamp);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
index d1c06cb..0bf9636 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
@@ -28,13 +28,14 @@
import android.content.Context;
import android.content.Intent;
import android.hardware.cts.helpers.ActivityResultMultiplexedLatch;
-import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
import android.media.MediaPlayer;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
+import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Settings;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -42,8 +43,11 @@
import android.widget.ScrollView;
import android.widget.TextView;
-import java.security.InvalidParameterException;
-import java.util.concurrent.Semaphore;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
/**
* A base Activity that is used to build different methods to execute tests inside CtsVerifier.
@@ -76,10 +80,11 @@
private final int mLayoutId;
private final SensorFeaturesDeactivator mSensorFeaturesDeactivator;
- private final Semaphore mSemaphore = new Semaphore(0);
+ private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
private final SensorTestLogger mTestLogger = new SensorTestLogger();
private final ActivityResultMultiplexedLatch mActivityResultMultiplexedLatch =
new ActivityResultMultiplexedLatch();
+ private final ArrayList<CountDownLatch> mWaitForUserLatches = new ArrayList<CountDownLatch>();
private ScrollView mLogScrollView;
private LinearLayout mLogLayout;
@@ -128,7 +133,13 @@
mGLSurfaceView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
updateNextButton(false /*enabled*/);
- new Thread(this).start();
+ mExecutorService.execute(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mExecutorService.shutdownNow();
}
@Override
@@ -149,7 +160,12 @@
@Override
public void onClick(View target) {
- mSemaphore.release();
+ synchronized (mWaitForUserLatches) {
+ for (CountDownLatch latch : mWaitForUserLatches) {
+ latch.countDown();
+ }
+ mWaitForUserLatches.clear();
+ }
}
@Override
@@ -167,40 +183,36 @@
*/
@Override
public void run() {
+ long startTimeNs = SystemClock.elapsedRealtimeNanos();
String testName = getTestClassName();
- // guarantee the proper clean up of tests based on the operations that successfully ran
- SensorTestDetails testDetails = deactivateSensorFeatures();
- if (testDetails.getResultCode() == SensorTestDetails.ResultCode.PASS) {
- // sensor features
- testDetails = executeActivitySetUp();
- if (testDetails.getResultCode() == SensorTestDetails.ResultCode.PASS) {
- // activity set up
- // TODO: implement execution filters:
- // - execute all tests and report results officially
- // - execute single test or failed tests only
- testDetails = executeTests();
- try {
- activityCleanUp();
- } catch (Throwable e) {
- testDetails = new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[ActivityCleanUp] " + e.getMessage());
- }
- // end activity set up
- }
- try {
- mSensorFeaturesDeactivator.requestToRestoreFeatures();
- } catch (Throwable e) {
- testDetails = new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[RestoreSensorFeatures] " + e.getMessage());
- }
- // end sensor features
+ SensorTestDetails testDetails;
+ try {
+ mSensorFeaturesDeactivator.requestDeactivationOfFeatures();
+ testDetails = new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS);
+ } catch (Throwable e) {
+ testDetails = new SensorTestDetails(testName, "DeactivateSensorFeatures", e);
}
+
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ if (resultCode == SensorTestDetails.ResultCode.SKIPPED) {
+ // this is an invalid state at this point of the test setup
+ throw new IllegalStateException("Deactivation of features cannot skip the test.");
+ }
+ if (resultCode == SensorTestDetails.ResultCode.PASS) {
+ testDetails = executeActivityTests(testName);
+ }
+
+ // we consider all remaining states at this point, because we could have been half way
+ // deactivating features
+ try {
+ mSensorFeaturesDeactivator.requestToRestoreFeatures();
+ } catch (Throwable e) {
+ testDetails = new SensorTestDetails(testName, "RestoreSensorFeatures", e);
+ }
+
mTestLogger.logTestDetails(testDetails);
+ mTestLogger.logExecutionTime(startTimeNs);
// because we cannot enforce test failures in several devices, set the test UI so the
// operator can report the result of the test
@@ -210,6 +222,9 @@
/**
* A general set up routine. It executes only once before the first test case.
*
+ * NOTE: implementers must be aware of the interrupted status of the worker thread, and let
+ * {@link InterruptedException} propagate.
+ *
* @throws Throwable An exception that denotes the failure of set up. No tests will be executed.
*/
protected void activitySetUp() throws Throwable {}
@@ -218,6 +233,11 @@
* A general clean up routine. It executes upon successful execution of {@link #activitySetUp()}
* and after all the test cases.
*
+ * NOTE: implementers must be aware of the interrupted status of the worker thread, and handle
+ * it in two cases:
+ * - let {@link InterruptedException} propagate
+ * - if it is invoked with the interrupted status, prevent from showing any UI
+
* @throws Throwable An exception that will be logged and ignored, for ease of implementation
* by subclasses.
*/
@@ -229,7 +249,7 @@
*
* @return A {@link SensorTestDetails} object containing information about the executed tests.
*/
- protected abstract SensorTestDetails executeTests();
+ protected abstract SensorTestDetails executeTests() throws InterruptedException;
@Override
public SensorTestLogger getTestLogger() {
@@ -237,11 +257,6 @@
}
@Deprecated
- protected void appendText(String text, int textColor) {
- appendText(text);
- }
-
- @Deprecated
protected void appendText(int resId) {
mTestLogger.logInstructions(resId);
}
@@ -268,21 +283,22 @@
*
* @param waitMessageResId The action requested to the operator.
*/
- protected void waitForUser(int waitMessageResId) {
+ protected void waitForUser(int waitMessageResId) throws InterruptedException {
+ CountDownLatch latch = new CountDownLatch(1);
+ synchronized (mWaitForUserLatches) {
+ mWaitForUserLatches.add(latch);
+ }
+
mTestLogger.logInstructions(waitMessageResId);
updateNextButton(true);
- try {
- mSemaphore.acquire();
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "Error on waitForUser", e);
- }
+ latch.await();
updateNextButton(false);
}
/**
* Waits for the operator to acknowledge to begin execution.
*/
- protected void waitForUserToBegin() {
+ protected void waitForUserToBegin() throws InterruptedException {
waitForUser(R.string.snsr_wait_to_begin);
}
@@ -290,20 +306,15 @@
* {@inheritDoc}
*/
@Override
- public void waitForUserToContinue() {
+ public void waitForUserToContinue() throws InterruptedException {
waitForUser(R.string.snsr_wait_for_user);
}
- @Deprecated
- protected void waitForUser() {
- waitForUserToContinue();
- }
-
/**
* {@inheritDoc}
*/
@Override
- public int executeActivity(String action) {
+ public int executeActivity(String action) throws InterruptedException {
return executeActivity(new Intent(action));
}
@@ -311,7 +322,7 @@
* {@inheritDoc}
*/
@Override
- public int executeActivity(Intent intent) {
+ public int executeActivity(Intent intent) throws InterruptedException {
ActivityResultMultiplexedLatch.Latch latch = mActivityResultMultiplexedLatch.bindThread();
startActivityForResult(intent, latch.getRequestCode());
return latch.await();
@@ -352,18 +363,15 @@
/**
* Plays a (default) sound as a notification for the operator.
*/
- protected void playSound() {
+ protected void playSound() throws InterruptedException {
MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_NOTIFICATION_URI);
if (player == null) {
Log.e(LOG_TAG, "MediaPlayer unavailable.");
return;
}
-
player.start();
try {
Thread.sleep(500);
- } catch(InterruptedException e) {
- Log.d(LOG_TAG, "Error on playSound", e);
} finally {
player.stop();
}
@@ -411,10 +419,16 @@
return mTestClass.getName();
}
+ protected void setLogScrollViewListener(View.OnTouchListener listener) {
+ mLogScrollView.setOnTouchListener(listener);
+ }
+
private void setTestResult(SensorTestDetails testDetails) {
+ // the name here, must be the Activity's name because it is what CtsVerifier expects
+ String name = super.getClass().getName();
String summary = mTestLogger.getOverallSummary();
- String name = testDetails.getName();
- switch(testDetails.getResultCode()) {
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ switch(resultCode) {
case SKIPPED:
TestResult.setPassedResult(this, name, summary);
break;
@@ -424,48 +438,50 @@
case FAIL:
TestResult.setFailedResult(this, name, summary);
break;
+ case INTERRUPTED:
+ // do not set a result, just return so the test can complete
+ break;
+ default:
+ throw new IllegalStateException("Unknown ResultCode: " + resultCode);
}
}
- private SensorTestDetails deactivateSensorFeatures() {
- String testName = getTestClassName();
- try {
- mSensorFeaturesDeactivator.requestDeactivationOfFeatures();
- } catch (Throwable e) {
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[DeactivateSensorFeatures] " + e.getMessage());
- }
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.PASS,
- null /* summary */);
- }
-
- private SensorTestDetails executeActivitySetUp() {
- String testName = getTestClassName();
+ private SensorTestDetails executeActivityTests(String testName) {
+ SensorTestDetails testDetails;
try {
activitySetUp();
- } catch (SensorTestStateNotSupportedException e) {
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.SKIPPED,
- e.getMessage());
+ testDetails = new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS);
} catch (Throwable e) {
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[ActivitySetUp] " + e.getMessage());
+ testDetails = new SensorTestDetails(testName, "ActivitySetUp", e);
}
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.PASS,
- null /* summary */);
+
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ if (resultCode == SensorTestDetails.ResultCode.PASS) {
+ // TODO: implement execution filters:
+ // - execute all tests and report results officially
+ // - execute single test or failed tests only
+ try {
+ testDetails = executeTests();
+ } catch (Throwable e) {
+ // we catch and continue because we have to guarantee a proper clean-up sequence
+ testDetails = new SensorTestDetails(testName, "TestExecution", e);
+ }
+ }
+
+ // clean-up executes for all states, even on SKIPPED and INTERRUPTED there might be some
+ // intermediate state that needs to be taken care of
+ try {
+ activityCleanUp();
+ } catch (Throwable e) {
+ testDetails = new SensorTestDetails(testName, "ActivityCleanUp", e);
+ }
+
+ return testDetails;
}
private void promptUserToSetResult(SensorTestDetails testDetails) {
- if (testDetails.getResultCode() == SensorTestDetails.ResultCode.FAIL) {
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ if (resultCode == SensorTestDetails.ResultCode.FAIL) {
mTestLogger.logInstructions(R.string.snsr_test_complete_with_errors);
enableTestResultButton(
mPassButton,
@@ -475,7 +491,7 @@
mFailButton,
R.string.fail_button_text,
testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.FAIL));
- } else {
+ } else if (resultCode != SensorTestDetails.ResultCode.INTERRUPTED) {
mTestLogger.logInstructions(R.string.snsr_test_complete);
enableTestResultButton(
mPassButton,
@@ -548,7 +564,8 @@
public void logTestDetails(SensorTestDetails testDetails) {
String name = testDetails.getName();
String summary = testDetails.getSummary();
- switch (testDetails.getResultCode()) {
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ switch (resultCode) {
case SKIPPED:
logTestSkip(name, summary);
break;
@@ -558,9 +575,11 @@
case FAIL:
logTestFail(name, summary);
break;
+ case INTERRUPTED:
+ // do nothing, the test was interrupted so do we
+ break;
default:
- throw new InvalidParameterException(
- "Invalid SensorTestDetails.ResultCode: " + testDetails.getResultCode());
+ throw new IllegalStateException("Unknown ResultCode: " + resultCode);
}
}
@@ -589,6 +608,17 @@
return mOverallSummaryBuilder.toString();
}
+ void logExecutionTime(long startTimeNs) {
+ if (Thread.currentThread().isInterrupted()) {
+ return;
+ }
+ long executionTimeNs = SystemClock.elapsedRealtimeNanos() - startTimeNs;
+ long executionTimeSec = TimeUnit.NANOSECONDS.toSeconds(executionTimeNs);
+ // TODO: find a way to format times with nanosecond accuracy and longer than 24hrs
+ String formattedElapsedTime = DateUtils.formatElapsedTime(executionTimeSec);
+ logMessage(R.string.snsr_execution_time, formattedElapsedTime);
+ }
+
private void logTestEnd(int textViewResId, String testSummary) {
TextAppender textAppender = new TextAppender(textViewResId);
textAppender.setText(testSummary);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
index 3ef7e21..2ba74e3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
@@ -33,7 +33,7 @@
/**
* Waits for the operator to acknowledge to continue execution.
*/
- void waitForUserToContinue();
+ void waitForUserToContinue() throws InterruptedException;
/**
* @param resId The resource Id to extract.
@@ -55,7 +55,7 @@
* @param action The action to start the Activity.
* @return The Activity's result code.
*/
- int executeActivity(String action);
+ int executeActivity(String action) throws InterruptedException;
/**
* Starts an Activity and blocks until it completes, then it returns its result back to the
@@ -64,7 +64,7 @@
* @param intent The intent to start the Activity.
* @return The Activity's result code.
*/
- int executeActivity(Intent intent);
+ int executeActivity(Intent intent) throws InterruptedException;
/**
* @return The {@link ContentResolver} associated with the test.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
index 35bff24..16c5fcd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
@@ -37,7 +37,6 @@
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
-import android.app.KeyguardManager;
import android.content.Context;
import android.hardware.cts.SensorTestCase;
import android.os.PowerManager;
@@ -67,11 +66,11 @@
}
@Override
- protected void activitySetUp() {
- mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
- mScreenManipulator.initialize(this);
+ protected void activitySetUp() throws InterruptedException {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SensorCtsTests");
+ mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
+ mScreenManipulator.initialize(this);
SensorTestLogger logger = getTestLogger();
logger.logInstructions(R.string.snsr_no_interaction);
@@ -93,7 +92,9 @@
}
});
mScreenManipulator.turnScreenOn();
- mWakeLock.release();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
}
@Override
@@ -101,6 +102,7 @@
super.onDestroy();
if (mScreenManipulator != null) {
mScreenManipulator.releaseScreenOn();
+ mScreenManipulator.close();
}
}
@@ -154,7 +156,7 @@
return new JUnit38ClassRunner(sensorTestSuite);
}
- private boolean hasSuiteMethod(Class testClass) {
+ private boolean hasSuiteMethod(Class<?> testClass) {
try {
testClass.getMethod("suite");
return true;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
index 851d405..5bbaaf7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
@@ -39,6 +39,8 @@
private final Context mContext;
private final TestResult mWrappedTestResult;
+ private volatile boolean mInterrupted;
+
public SensorCtsTestResult(Context context, TestResult testResult) {
mContext = context;
mWrappedTestResult = testResult;
@@ -96,12 +98,23 @@
@Override
public void runProtected(Test test, Protectable protectable) {
- mWrappedTestResult.runProtected(test, protectable);
+ try {
+ protectable.protect();
+ } catch (AssertionFailedError e) {
+ addFailure(test, e);
+ } catch (ThreadDeath e) {
+ throw e;
+ } catch (InterruptedException e) {
+ mInterrupted = true;
+ addError(test, e);
+ } catch (Throwable e) {
+ addError(test, e);
+ }
}
@Override
public boolean shouldStop() {
- return mWrappedTestResult.shouldStop();
+ return mInterrupted || mWrappedTestResult.shouldStop();
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
index 09753cc..a88abd0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
@@ -19,8 +19,6 @@
import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
-import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
-
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -47,29 +45,16 @@
}
/**
- * {@inheritDoc}
- */
- protected SensorCtsVerifierTestActivity(
- Class<? extends SensorCtsVerifierTestActivity> testClass,
- int layoutId) {
- super(testClass, layoutId);
- }
-
- /**
* Executes Semi-automated Sensor tests.
* Execution is driven by this class, and allows discovery of tests using reflection.
*/
@Override
- protected SensorTestDetails executeTests() {
+ protected SensorTestDetails executeTests() throws InterruptedException {
// TODO: use reporting to log individual test results
- StringBuilder overallTestResults = new StringBuilder();
for (Method testMethod : findTestMethods()) {
SensorTestDetails testDetails = executeTest(testMethod);
getTestLogger().logTestDetails(testDetails);
- overallTestResults.append(testDetails.toString());
- overallTestResults.append("\n");
}
-
return new SensorTestDetails(
getApplicationContext(),
getTestClassName(),
@@ -91,34 +76,40 @@
return testMethods;
}
- private SensorTestDetails executeTest(Method testMethod) {
+ private SensorTestDetails executeTest(Method testMethod) throws InterruptedException {
String testMethodName = testMethod.getName();
String testName = String.format("%s#%s", getTestClassName(), testMethodName);
- String testSummary;
- SensorTestDetails.ResultCode testResultCode;
+ SensorTestDetails testDetails;
try {
- getTestLogger().logTestStart(testMethod.getName());
- testSummary = (String) testMethod.invoke(this);
- testResultCode = SensorTestDetails.ResultCode.PASS;
- ++mTestPassedCounter;
+ getTestLogger().logTestStart(testMethodName);
+ String testSummary = (String) testMethod.invoke(this);
+ testDetails =
+ new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS, testSummary);
} catch (InvocationTargetException e) {
// get the inner exception, because we use reflection APIs to execute the test
- Throwable cause = e.getCause();
- testSummary = cause.getMessage();
- if (cause instanceof SensorTestStateNotSupportedException) {
- testResultCode = SensorTestDetails.ResultCode.SKIPPED;
- ++mTestSkippedCounter;
- } else {
- testResultCode = SensorTestDetails.ResultCode.FAIL;
- ++mTestFailedCounter;
- }
+ testDetails = new SensorTestDetails(testName, "TestExecution", e.getCause());
} catch (Throwable e) {
- testSummary = e.getMessage();
- testResultCode = SensorTestDetails.ResultCode.FAIL;
- ++mTestFailedCounter;
+ testDetails = new SensorTestDetails(testName, "TestInfrastructure", e);
}
- return new SensorTestDetails(testName, testResultCode, testSummary);
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ switch(resultCode) {
+ case PASS:
+ ++mTestPassedCounter;
+ break;
+ case SKIPPED:
+ ++mTestSkippedCounter;
+ break;
+ case INTERRUPTED:
+ throw new InterruptedException();
+ case FAIL:
+ ++mTestFailedCounter;
+ break;
+ default:
+ throw new IllegalStateException("Unknown ResultCode: " + resultCode);
+ }
+
+ return testDetails;
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
index 0041aec..ed2fea3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
@@ -53,7 +53,7 @@
public interface HostToDeviceInterface {
void logTestResult(SensorTestDetails testDetails);
void raiseError(String testName, String message) throws Exception;
- void waitForUserAcknowledgement(String message);
+ void waitForUserAcknowledgement(String message) throws InterruptedException;
void logText(String text);
void turnScreenOff();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
index d69d343..65a3a4d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
@@ -48,7 +48,7 @@
mStateContainer = stateContainer;
}
- public synchronized void requestDeactivationOfFeatures() {
+ public synchronized void requestDeactivationOfFeatures() throws InterruptedException {
captureInitialState();
mAirplaneMode.requestToSetMode(mStateContainer, true);
@@ -63,11 +63,17 @@
mStateContainer.waitForUserToContinue();
}
- public synchronized void requestToRestoreFeatures() {
+ public synchronized void requestToRestoreFeatures() throws InterruptedException {
if (!isInitialStateCaptured()) {
return;
}
+ if (Thread.currentThread().isInterrupted()) {
+ // TODO: in the future, if the thread is interrupted, we might need to serialize the
+ // intermediate state we acquired so we can restore when we have a chance
+ return;
+ }
+
mAirplaneMode.requestToResetMode(mStateContainer);
mScreenBrightnessMode.requestToResetMode(mStateContainer);
mAutoRotateScreenMode.requestToResetMode(mStateContainer);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
index 9a0d7e5..82df502 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
@@ -43,7 +43,7 @@
public synchronized void requestToSetMode(
ISensorTestStateContainer stateContainer,
- boolean modeOn) {
+ boolean modeOn) throws InterruptedException {
trySetMode(stateContainer, modeOn);
if (getCurrentSettingMode() != modeOn) {
String message = stateContainer.getString(
@@ -54,11 +54,13 @@
}
}
- public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer) {
+ public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer)
+ throws InterruptedException {
trySetMode(stateContainer, mCapturedModeOn);
}
- private void trySetMode(ISensorTestStateContainer stateContainer, boolean modeOn) {
+ private void trySetMode(ISensorTestStateContainer stateContainer, boolean modeOn)
+ throws InterruptedException {
BaseSensorTestActivity.SensorTestLogger logger = stateContainer.getTestLogger();
String settingName = getSettingName(stateContainer);
if (getCurrentSettingMode() == modeOn) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
index 0263975..835ff56 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
@@ -85,7 +85,8 @@
* NOTE: Initialization will bring up an Activity to let the user activate the Device Admin,
* this method will block until the user completes the operation.
*/
- public synchronized void initialize(ISensorTestStateContainer stateContainer) {
+ public synchronized void initialize(ISensorTestStateContainer stateContainer)
+ throws InterruptedException {
if (!isDeviceAdminInitialized()) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
index dcf6c4a..c88187c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
@@ -22,6 +22,7 @@
import org.junit.runner.Result;
import android.content.Context;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
/**
* A class that holds the result of a Sensor test execution.
@@ -34,7 +35,12 @@
public enum ResultCode {
SKIPPED,
PASS,
- FAIL
+ FAIL,
+ INTERRUPTED
+ }
+
+ public SensorTestDetails(String name, ResultCode resultCode) {
+ this(name, resultCode, null /* summary */);
}
public SensorTestDetails(String name, ResultCode resultCode, String summary) {
@@ -69,6 +75,21 @@
result.getFailureCount());
}
+ public SensorTestDetails(String name, String tag, Throwable cause) {
+ ResultCode resultCode = ResultCode.FAIL;
+ if (cause instanceof InterruptedException) {
+ resultCode = ResultCode.INTERRUPTED;
+ // the interrupted status must be restored, so other routines can consume it
+ Thread.currentThread().interrupt();
+ } else if (cause instanceof SensorTestStateNotSupportedException) {
+ resultCode = ResultCode.SKIPPED;
+ }
+
+ mName = name;
+ mResultCode = resultCode;
+ mSummary = String.format("[%s] %s", tag, cause.getMessage());
+ }
+
public String getName() {
return mName;
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java b/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
index bfc59c4..093a659 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
@@ -16,9 +16,6 @@
package android.hardware.cts.helpers;
-import android.app.Activity;
-import android.util.Log;
-
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
@@ -53,13 +50,8 @@
*
* @return The result code of the Activity executed.
*/
- public int await() {
- try {
- mEntry.latch.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "Error waiting for Activity result.", e);
- return Activity.RESULT_CANCELED;
- }
+ public int await() throws InterruptedException {
+ mEntry.latch.await();
return mEntry.resultCode;
}
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 c11b29f..ca7d133 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
@@ -64,7 +64,7 @@
* </p>
*/
@Override
- public void waitForEvents(int eventCount) {
+ public void waitForEvents(int eventCount) throws InterruptedException {
clearEvents();
super.waitForEvents(eventCount);
}
@@ -76,7 +76,7 @@
* </p>
*/
@Override
- public void waitForEvents(long duration, TimeUnit timeUnit) {
+ public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
clearEvents();
super.waitForEvents(duration, timeUnit);
}
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 1f1b290..a79e5b1 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -26,7 +26,7 @@
/**
* Set of static helper methods for CTS tests.
*/
-//TODO: Refactor this class into several more well defined helper classes
+//TODO: Refactor this class into several more well defined helper classes, look at StatisticsUtils
public class SensorCtsHelper {
private static final long NANOS_PER_MILLI = 1000000;
@@ -143,13 +143,9 @@
/**
* Helper method to sleep for a given duration.
*/
- public static void sleep(long duration, TimeUnit timeUnit) {
+ public static void sleep(long duration, TimeUnit timeUnit) throws InterruptedException {
long durationNs = TimeUnit.NANOSECONDS.convert(duration, timeUnit);
- try {
- Thread.sleep(durationNs / NANOS_PER_MILLI, (int) (durationNs % NANOS_PER_MILLI));
- } catch (InterruptedException e) {
- // Ignore
- }
+ Thread.sleep(durationNs / NANOS_PER_MILLI, (int) (durationNs % NANOS_PER_MILLI));
}
/**
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 4505633..9b3a5e4 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -21,6 +21,7 @@
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener2;
+import android.os.SystemClock;
import android.util.Log;
import java.util.Arrays;
@@ -87,30 +88,20 @@
*/
@Override
public void onSensorChanged(SensorEvent event) {
+ mListener.onSensorChanged(event);
+ if (mLogEvents) {
+ Log.v(LOG_TAG, String.format(
+ "Sensor %d: sensor_timestamp=%dns, received_timestamp=%dns, values=%s",
+ mEnvironment.getSensor().getType(),
+ event.timestamp,
+ SystemClock.elapsedRealtimeNanos(),
+ Arrays.toString(event.values)));
+ }
+
CountDownLatch eventLatch = mEventLatch;
if(eventLatch != null) {
eventLatch.countDown();
}
- mListener.onSensorChanged(event);
- if (mLogEvents) {
- StringBuilder valuesSb = new StringBuilder();
- if (event.values.length == 1) {
- valuesSb.append(String.format("%.2f", event.values[0]));
- } else {
- valuesSb.append("[").append(String.format("%.2f", event.values[0]));
- for (int i = 1; i < event.values.length; i++) {
- valuesSb.append(String.format(", %.2f", event.values[i]));
- }
- valuesSb.append("]");
- }
-
- Log.v(LOG_TAG, String.format(
- "Sensor %d: sensor_timestamp=%d, received_timestamp=%d, values=%s",
- mEnvironment.getSensor().getType(),
- event.timestamp,
- System.nanoTime(),
- Arrays.toString(event.values)));
- }
}
/**
@@ -139,17 +130,14 @@
*
* @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} µs
*/
- public void waitForFlushComplete() {
+ public void waitForFlushComplete() throws InterruptedException {
CountDownLatch latch = mFlushLatch;
- try {
- if(latch != null) {
- Assert.assertTrue(
- SensorCtsHelper.formatAssertionMessage("WaitForFlush", mEnvironment),
- latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
- }
- } catch(InterruptedException e) {
- // Ignore
+ if(latch == null) {
+ return;
}
+ Assert.assertTrue(
+ SensorCtsHelper.formatAssertionMessage("WaitForFlush", mEnvironment),
+ latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
}
/**
@@ -157,15 +145,14 @@
*
* @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} µs
*/
- public void waitForEvents(int eventCount) {
+ public void waitForEvents(int eventCount) throws InterruptedException {
mEventLatch = new CountDownLatch(eventCount);
try {
int rateUs = mEnvironment.getExpectedSamplingPeriodUs();
// Timeout is 2 * event count * expected period + batch timeout + default wait
- long timeoutUs = ((2 * eventCount * rateUs)
+ long timeoutUs = (2 * eventCount * rateUs)
+ mEnvironment.getMaxReportLatencyUs()
- + EVENT_TIMEOUT_US);
-
+ + EVENT_TIMEOUT_US;
String message = SensorCtsHelper.formatAssertionMessage(
"WaitForEvents",
mEnvironment,
@@ -173,8 +160,6 @@
eventCount,
eventCount - mEventLatch.getCount());
Assert.assertTrue(message, mEventLatch.await(timeoutUs, TimeUnit.MICROSECONDS));
- } catch(InterruptedException e) {
- // Ignore
} finally {
mEventLatch = null;
}
@@ -183,7 +168,7 @@
/**
* Collect {@link TestSensorEvent} for a specific duration.
*/
- public void waitForEvents(long duration, TimeUnit timeUnit) {
+ public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
SensorCtsHelper.sleep(duration, timeUnit);
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
index d72a2ce..dc40ff4 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
@@ -120,24 +120,22 @@
/**
* Wait for a specific number of events.
*/
- public void waitForEvents(int eventCount) {
+ 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) {
+ 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);
}
@@ -168,7 +166,6 @@
if (mTestSensorEventListener == null) {
return;
}
-
mTestSensorEventListener.waitForFlushComplete();
}
@@ -185,7 +182,6 @@
if (mTestSensorEventListener == null) {
return;
}
-
startFlush();
waitForFlushCompleted();
}
@@ -193,12 +189,12 @@
/**
* Register a listener, wait for a specific number of events, and then unregister the listener.
*/
- public void runSensor(TestSensorEventListener listener, int eventCount) {
+ 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);
@@ -210,12 +206,12 @@
/**
* Register a listener, wait for a specific duration, and then unregister the listener.
*/
- public void runSensor(TestSensorEventListener listener, long duration, TimeUnit timeUnit) {
+ 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);
@@ -231,7 +227,7 @@
public void runSensorAndFlush(
TestSensorEventListener listener,
long duration,
- TimeUnit timeUnit) {
+ TimeUnit timeUnit) throws InterruptedException {
if (mTestSensorEventListener != null) {
Log.w(LOG_TAG, "Listener already registered, returning.");
return;
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
index 95f1248..88e4954 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
@@ -72,7 +72,7 @@
* {@inheritDoc}
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
// Start alarm
IntentFilter intentFilter = new IntentFilter(ACTION);
BroadcastReceiver receiver = new BroadcastReceiver() {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
index bf43189..b4d1f23 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
@@ -50,8 +50,8 @@
* {@inheritDoc}
*/
@Override
- public void execute() {
- sleep(mDelay, mTimeUnit);
+ public void execute() throws InterruptedException {
+ SensorCtsHelper.sleep(mDelay, mTimeUnit);
mOperation.execute();
}
@@ -70,11 +70,4 @@
public DelaySensorOperation clone() {
return new DelaySensorOperation(mOperation.clone(), mDelay, mTimeUnit);
}
-
- /**
- * Helper method to sleep for a given number of ns. Exposed for unit testing.
- */
- void sleep(long delay, TimeUnit timeUnit) {
- SensorCtsHelper.sleep(delay, timeUnit);
- }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
index 4ae56ea..62a4e9e 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
@@ -38,8 +38,12 @@
/**
* Executes the sensor operation. This may throw {@link RuntimeException}s such as
* {@link AssertionError}s.
+ *
+ * NOTE: the operation is expected to handle interruption by:
+ * - cleaning up on {@link InterruptedException}
+ * - propagating the exception down the stack
*/
- public void execute();
+ public void execute() throws InterruptedException;
/**
* Get the stats for the operation.
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
index 4cca428..5a4466c 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
@@ -16,15 +16,21 @@
package android.hardware.cts.helpers.sensoroperations;
-import android.hardware.cts.helpers.SensorStats;
-import android.util.Log;
-
import junit.framework.Assert;
+import android.hardware.cts.helpers.SensorStats;
+import android.os.SystemClock;
+
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* A {@link ISensorOperation} that executes a set of children {@link ISensorOperation}s in parallel.
@@ -34,9 +40,6 @@
public class ParallelSensorOperation extends AbstractSensorOperation {
public static final String STATS_TAG = "parallel";
- private static final String TAG = "ParallelSensorOperation";
- private static final int NANOS_PER_MILLI = 1000000;
-
private final List<ISensorOperation> mOperations = new LinkedList<ISensorOperation>();
private final Long mTimeout;
private final TimeUnit mTimeUnit;
@@ -44,6 +47,7 @@
/**
* Constructor for the {@link ParallelSensorOperation} without a timeout.
*/
+ // TODO: sensor tests must always provide a timeout to prevent tests from running forever
public ParallelSensorOperation() {
mTimeout = null;
mTimeUnit = null;
@@ -77,57 +81,67 @@
* operations, the first exception will be thrown once all operations are completed.
*/
@Override
- public void execute() {
- Long timeoutTimeNs = null;
- if (mTimeout != null && mTimeUnit != null) {
- timeoutTimeNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
- }
+ public void execute() throws InterruptedException {
+ int operationsCount = mOperations.size();
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(
+ operationsCount,
+ operationsCount,
+ 1 /* keepAliveTime */,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>());
+ executor.allowCoreThreadTimeOut(true);
+ executor.prestartAllCoreThreads();
- List<OperationThread> threadPool = new ArrayList<OperationThread>(mOperations.size());
+ ArrayList<Future<ISensorOperation>> futures = new ArrayList<Future<ISensorOperation>>();
for (final ISensorOperation operation : mOperations) {
- OperationThread thread = new OperationThread(operation);
- thread.start();
- threadPool.add(thread);
+ Future<ISensorOperation> future = executor.submit(new Callable<ISensorOperation>() {
+ @Override
+ public ISensorOperation call() throws Exception {
+ operation.execute();
+ return operation;
+ }
+ });
+ futures.add(future);
}
- List<Integer> timeoutIndices = new ArrayList<Integer>();
- List<OperationExceptionInfo> exceptions = new ArrayList<OperationExceptionInfo>();
- Throwable earliestException = null;
- Long earliestExceptionTime = null;
+ Long executionTimeNs = null;
+ if (mTimeout != null) {
+ executionTimeNs = SystemClock.elapsedRealtimeNanos()
+ + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
+ }
- for (int i = 0; i < threadPool.size(); i++) {
- OperationThread thread = threadPool.get(i);
- join(thread, timeoutTimeNs);
- if (thread.isAlive()) {
+ boolean hasAssertionErrors = false;
+ ArrayList<Integer> timeoutIndices = new ArrayList<Integer>();
+ ArrayList<Throwable> exceptions = new ArrayList<Throwable>();
+ for (int i = 0; i < operationsCount; ++i) {
+ Future<ISensorOperation> future = futures.get(i);
+ try {
+ ISensorOperation operation = getFutureResult(future, executionTimeNs);
+ addSensorStats(STATS_TAG, i, operation.getStats());
+ } catch (ExecutionException e) {
+ // extract the exception thrown by the worker thread
+ Throwable cause = e.getCause();
+ hasAssertionErrors |= (cause instanceof AssertionError);
+ exceptions.add(e.getCause());
+ addSensorStats(STATS_TAG, i, mOperations.get(i).getStats());
+ } catch (TimeoutException e) {
+ // we log, but we also need to interrupt the operation to terminate cleanly
timeoutIndices.add(i);
- thread.interrupt();
+ future.cancel(true /* mayInterruptIfRunning */);
+ } catch (InterruptedException e) {
+ // clean-up after ourselves by interrupting all the worker threads, and propagate
+ // the interruption status, so we stop the outer loop as well
+ executor.shutdownNow();
+ throw e;
}
-
- Throwable exception = thread.getException();
- Long exceptionTime = thread.getExceptionTime();
- if (exception != null && exceptionTime != null) {
- if (exception instanceof AssertionError) {
- exceptions.add(new OperationExceptionInfo(i, (AssertionError) exception));
- }
- if (earliestExceptionTime == null || exceptionTime < earliestExceptionTime) {
- earliestException = exception;
- earliestExceptionTime = exceptionTime;
- }
- }
-
- addSensorStats(STATS_TAG, i, thread.getSensorOperation().getStats());
}
- if (earliestException == null) {
- if (timeoutIndices.size() > 0) {
- Assert.fail(getTimeoutMessage(timeoutIndices));
- }
- } else if (earliestException instanceof AssertionError) {
- String msg = getExceptionMessage(exceptions, timeoutIndices);
- getStats().addValue(SensorStats.ERROR, msg);
- throw new AssertionError(msg, earliestException);
- } else if (earliestException instanceof RuntimeException) {
- throw (RuntimeException) earliestException;
+ String summary = getSummaryMessage(exceptions, timeoutIndices);
+ if (hasAssertionErrors) {
+ getStats().addValue(SensorStats.ERROR, summary);
+ }
+ if (!exceptions.isEmpty() || !timeoutIndices.isEmpty()) {
+ Assert.fail(summary);
}
}
@@ -144,114 +158,39 @@
}
/**
- * Helper method that joins a thread at a given time in the future.
+ * Helper method that waits for a {@link Future} to complete, and returns its result.
*/
- private void join(Thread thread, Long timeoutTimeNs) {
- try {
- if (timeoutTimeNs == null) {
- thread.join();
- } else {
- // Cap wait time to 1ns so that join doesn't block indefinitely.
- long waitTimeNs = Math.max(timeoutTimeNs - System.nanoTime(), 1);
- thread.join(waitTimeNs / NANOS_PER_MILLI, (int) waitTimeNs % NANOS_PER_MILLI);
- }
- } catch (InterruptedException e) {
- // Log and ignore
- Log.w(TAG, "Thread interrupted during join, operations may timeout before expected"
- + " time");
+ private ISensorOperation getFutureResult(Future<ISensorOperation> future, Long timeoutNs)
+ throws ExecutionException, TimeoutException, InterruptedException {
+ if (timeoutNs == null) {
+ return future.get();
}
+ // cap timeout to 1ns so that join doesn't block indefinitely
+ long waitTimeNs = Math.max(timeoutNs - SystemClock.elapsedRealtimeNanos(), 1);
+ return future.get(waitTimeNs, TimeUnit.NANOSECONDS);
}
/**
- * Helper method for joining the exception messages used in assertions.
+ * Helper method for joining the exception and timeout messages used in assertions.
*/
- private String getExceptionMessage(List<OperationExceptionInfo> exceptions,
- List<Integer> timeoutIndices) {
+ private String getSummaryMessage(List<Throwable> exceptions, List<Integer> timeoutIndices) {
StringBuilder sb = new StringBuilder();
- sb.append(exceptions.get(0).toString());
- for (int i = 1; i < exceptions.size(); i++) {
- sb.append(", ").append(exceptions.get(i).toString());
- }
- if (timeoutIndices.size() > 0) {
- sb.append(", ").append(getTimeoutMessage(timeoutIndices));
- }
- return sb.toString();
- }
-
- /**
- * Helper method for formatting the operation timed out message used in assertions
- */
- private String getTimeoutMessage(List<Integer> indices) {
- StringBuilder sb = new StringBuilder();
- sb.append("Operation");
- if (indices.size() != 1) {
- sb.append("s");
- }
- sb.append(" ").append(indices.get(0));
- for (int i = 1; i < indices.size(); i++) {
- sb.append(", ").append(indices.get(i));
- }
- sb.append(" timed out");
- return sb.toString();
- }
-
- /**
- * Helper class for holding operation index and exception
- */
- private class OperationExceptionInfo {
- private final int mIndex;
- private final AssertionError mException;
-
- public OperationExceptionInfo(int index, AssertionError exception) {
- mIndex = index;
- mException = exception;
+ for (Throwable exception : exceptions) {
+ sb.append(exception.toString()).append(", ");
}
- @Override
- public String toString() {
- return String.format("Operation %d failed: \"%s\"", mIndex, mException.getMessage());
- }
- }
-
- /**
- * Helper class to run the {@link ISensorOperation} in its own thread.
- */
- private class OperationThread extends Thread {
- final private ISensorOperation mOperation;
- private Throwable mException = null;
- private Long mExceptionTime = null;
-
- public OperationThread(ISensorOperation operation) {
- mOperation = operation;
- }
-
- /**
- * Run the thread catching {@link RuntimeException}s and {@link AssertionError}s and
- * the time it happened.
- */
- @Override
- public void run() {
- try {
- mOperation.execute();
- } catch (AssertionError e) {
- mExceptionTime = System.nanoTime();
- mException = e;
- } catch (RuntimeException e) {
- mExceptionTime = System.nanoTime();
- mException = e;
+ if (!timeoutIndices.isEmpty()) {
+ sb.append("Operation");
+ if (timeoutIndices.size() != 1) {
+ sb.append("s");
}
+ sb.append(" [");
+ for (Integer index : timeoutIndices) {
+ sb.append(index).append(", ");
+ }
+ sb.append("] timed out");
}
- public ISensorOperation getSensorOperation() {
- return mOperation;
- }
-
- public Throwable getException() {
- return mException;
- }
-
- public Long getExceptionTime() {
- return mExceptionTime;
- }
+ return sb.toString();
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
index 5e023e5..3d682fe 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
@@ -48,7 +48,7 @@
* in one iterations, it is thrown and all subsequent iterations will not run.
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
for(int i = 0; i < mIterations; ++i) {
ISensorOperation operation = mOperation.clone();
try {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
index 15b6978..bc48725 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
@@ -35,7 +35,7 @@
* Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class
* rely on this operation.
*/
- public void testFakeSensorOperation() {
+ public void testFakeSensorOperation() throws InterruptedException {
final int opDurationMs = 100;
ISensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS);
@@ -60,7 +60,7 @@
/**
* Test that the {@link DelaySensorOperation} functions correctly.
*/
- public void testDelaySensorOperation() {
+ public void testDelaySensorOperation() throws InterruptedException {
final int opDurationMs = 500;
final int subOpDurationMs = 100;
@@ -77,7 +77,7 @@
/**
* Test that the {@link ParallelSensorOperation} functions correctly.
*/
- public void testParallelSensorOperation() {
+ public void testParallelSensorOperation() throws InterruptedException {
final int subOpCount = 100;
final int subOpDurationMs = 500;
@@ -118,7 +118,7 @@
* Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testParallelSensorOperation_fail() {
+ public void testParallelSensorOperation_fail() throws InterruptedException {
final int subOpCount = 100;
ParallelSensorOperation op = new ParallelSensorOperation();
@@ -158,7 +158,7 @@
* Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the
* timeout.
*/
- public void testParallelSensorOperation_timeout() {
+ public void testParallelSensorOperation_timeout() throws InterruptedException {
final int subOpCount = 100;
ParallelSensorOperation op = new ParallelSensorOperation(1, TimeUnit.SECONDS);
@@ -192,7 +192,7 @@
/**
* Test that the {@link RepeatingSensorOperation} functions correctly.
*/
- public void testRepeatingSensorOperation() {
+ public void testRepeatingSensorOperation() throws InterruptedException {
final int iterations = 10;
final int subOpDurationMs = 100;
@@ -219,7 +219,7 @@
* Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testRepeatingSensorOperation_fail() {
+ public void testRepeatingSensorOperation_fail() throws InterruptedException {
final int iterations = 100;
final int failCount = 75;
@@ -277,7 +277,7 @@
/**
* Test that the {@link SequentialSensorOperation} functions correctly.
*/
- public void testSequentialSensorOperation() {
+ public void testSequentialSensorOperation() throws InterruptedException {
final int subOpCount = 10;
final int subOpDurationMs = 100;
@@ -308,7 +308,7 @@
* Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testSequentialSensorOperation_fail() {
+ public void testSequentialSensorOperation_fail() throws InterruptedException {
final int subOpCount = 100;
final int failCount = 75;
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
index 050a8f6..2ed0ca6 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
@@ -48,7 +48,7 @@
* in one operation, it is thrown and all subsequent operations will not run.
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
for (int i = 0; i < mOperations.size(); i++) {
ISensorOperation operation = mOperations.get(i);
try {
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
index 1fb6bef..d5aa4b9 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
@@ -53,7 +53,7 @@
* {@inheritDoc}
*/
@Override
- protected void doExecute(TestSensorEventListener listener) {
+ protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
mSensorManager.runSensorAndFlush(listener, 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 6c3851e..695e1a7 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
@@ -76,7 +76,7 @@
* {@inheritDoc}
*/
@Override
- protected void doExecute(TestSensorEventListener listener) {
+ protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
if (mEventCount != null) {
mSensorManager.runSensor(listener, mEventCount);
} else {
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
index c635a75..57018eb 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
@@ -94,7 +94,7 @@
* Collect the specified number of events from the sensor and run all enabled verifications.
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
ValidatingSensorEventListener listener = new ValidatingSensorEventListener(mVerifications);
@@ -131,7 +131,7 @@
/**
* Execute operations in a {@link TestSensorManager}.
*/
- protected abstract void doExecute(TestSensorEventListener listener);
+ protected abstract void doExecute(TestSensorEventListener listener) throws InterruptedException;
/**
* Clone the subclass operation.
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
index 73da9c9..b500ea7 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
@@ -59,7 +59,7 @@
* {@inheritDoc}
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(mWakelockFlags, TAG);