Merge "camera2: Update openCamera calls now that it is async" into klp-dev
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 77bd2fb..5acb29c 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target android-ex-camera2
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
index f94c80c..818a98e 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -46,7 +46,7 @@
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
     private CameraManager mCameraManager;
-    private CameraDevice.CameraDeviceListener mMockDeviceListener;
+    private CameraDevice.StateListener mMockDeviceListener;
     private CameraTestThread mLooperThread;
     private Handler mCallbackHandler;
 
@@ -120,13 +120,17 @@
 
     /**
      * This class need to be public because spy need access it.
+     *
+     * <p><b>Warning</b>: {@link #onOpened} does nothing, so only use this with the
+     * {@link CameraTestUtils#openCamera}
+     * If using this with {@link CameraManager#openDevice} directly,
+     * remember to implement openCamera!</p>
      */
-    public class SimpleDeviceListener extends CameraDevice.CameraDeviceListener {
+    public class SimpleDeviceListener extends CameraDevice.StateListener {
         private final Object mIdleLock = new Object();
         private boolean mIdle = false;
 
         public SimpleDeviceListener() {
-
         }
 
         // Wait for idle to occur, with a timeout in milliseconds.
@@ -158,7 +162,7 @@
         }
 
         @Override
-        public void onCameraIdle(CameraDevice camera) {
+        public void onIdle(CameraDevice camera) {
             synchronized(mIdleLock) {
                 mIdle = true;
                 mIdleLock.notifyAll();
@@ -166,15 +170,21 @@
         }
 
         @Override
-        public void onCameraDisconnected(CameraDevice camera) {
+        public void onDisconnected(CameraDevice camera) {
             // Not expecting disconnections
             mErrorTriggered = true;
         }
 
         @Override
-        public void onCameraError(CameraDevice camera, int error) {
+        public void onError(CameraDevice camera, int error) {
             mErrorTriggered = true;
         }
+
+        @Override
+        public void onOpened(CameraDevice camera) {
+            // Do nothing. Handled by CameraTestUtils#openCamera
+            // TODO: If using this listener with CameraManager#openCamera, IMPLEMENT THIS.
+        }
     }
 
     public void testCameraDeviceCreateCaptureBuilder() throws Exception {
@@ -182,7 +192,7 @@
         for (int i = 0; i < ids.length; i++) {
             CameraDevice camera = null;
             try {
-                camera = mCameraManager.openCamera(ids[i]);
+                camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mCallbackHandler);
                 assertNotNull(
                         String.format("Failed to open camera device ID: %s", ids[i]), camera);
 
@@ -214,7 +224,7 @@
         for (int i = 0; i < ids.length; i++) {
             CameraDevice camera = null;
             try {
-                camera = mCameraManager.openCamera(ids[i]);
+                camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mCallbackHandler);
                 assertNotNull(
                         String.format("Failed to open camera device %s", ids[i]), camera);
 
@@ -239,7 +249,8 @@
         for (int i = 0; i < ids.length; i++) {
             CameraDevice camera = null;
             try {
-                camera = mCameraManager.openCamera(ids[i]);
+                camera = CameraTestUtils.openCamera(mCameraManager, ids[i],
+                        mMockDeviceListener, mCallbackHandler);
                 assertNotNull(
                         String.format("Failed to open camera device %s", ids[i]), camera);
 
@@ -247,10 +258,9 @@
                  * Test: that the error listener can be set without problems.
                  * Also, wait some time to check if device doesn't run into error.
                  */
-                camera.setDeviceListener(mMockDeviceListener, mCallbackHandler);
                 SystemClock.sleep(ERROR_LISTENER_WAIT_TIMEOUT_MS);
                 verify(mMockDeviceListener, never())
-                        .onCameraError(
+                        .onError(
                                 any(CameraDevice.class),
                                 anyInt());
             }
@@ -300,10 +310,10 @@
         for (int i = 0; i < ids.length; i++) {
             CameraDevice camera = null;
             try {
-                camera = mCameraManager.openCamera(ids[i]);
+                camera = CameraTestUtils.openCamera(mCameraManager, ids[i],
+                        mMockDeviceListener, mCallbackHandler);
                 assertNotNull(
                         String.format("Failed to open camera device %s", ids[i]), camera);
-                camera.setDeviceListener(mMockDeviceListener, mCallbackHandler);
 
                 prepareCapture(camera);
 
@@ -335,7 +345,7 @@
                     captureBurstShot(camera, ids[i], mTemplates, mTemplates.length, repeating);
                 }
                 verify(mMockDeviceListener, never())
-                        .onCameraError(
+                        .onError(
                                 any(CameraDevice.class),
                                 anyInt());
             }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
index c2e0d0f..086a4f3 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -40,6 +40,8 @@
     private PackageManager mPackageManager;
     private CameraManager mCameraManager;
     private NoopCameraListener mListener;
+    private CameraTestThread mLooperThread;
+    private Handler mHandler;
 
     @Override
     public void setContext(Context context) {
@@ -54,10 +56,16 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mLooperThread = new CameraTestThread();
+        mHandler = mLooperThread.start();
     }
 
     @Override
     protected void tearDown() throws Exception {
+        mLooperThread.close();
+        mHandler = null;
+
         super.tearDown();
     }
 
@@ -98,7 +106,7 @@
     public void testCameraManagerGetCameraProperties() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull(
                 String.format("Failed to open camera device ID: %s", ids[i]), camera);
             try {
@@ -136,7 +144,7 @@
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
             for (int j = 0; j < NUM_CAMERA_REOPENS; j++) {
-                CameraDevice camera = mCameraManager.openCamera(ids[i]);
+                CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
                 assertNotNull(
                     String.format("Failed to open camera device ID: %s", ids[i]), camera);
                 camera.close();
@@ -154,7 +162,7 @@
         try {
             for (int i = 0; i < ids.length; i++) {
                 try {
-                    cameras[i] = mCameraManager.openCamera(ids[i]);
+                    cameras[i] = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
 
                     /**
                      * If the camera can't be opened, should throw an exception, rather than
@@ -190,12 +198,12 @@
         CameraDevice[] cameras = new CameraDevice[2];
         if (ids.length > 0) {
             try {
-                cameras[0] = mCameraManager.openCamera(ids[0]);
+                cameras[0] = CameraTestUtils.openCamera(mCameraManager, ids[0], mHandler);
                 assertNotNull(
                     String.format("Failed to open camera device ID: %s", ids[0]),
                     cameras[0]);
                 try {
-                    cameras[1] = mCameraManager.openCamera(ids[0]);
+                    cameras[1] = CameraTestUtils.openCamera(mCameraManager, ids[0], mHandler);
                     fail(String.format("Opened the same camera device twice ID: %s",
                         ids[0]));
                 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraPropertiesTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraPropertiesTest.java
index a5576d9..6a402de 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraPropertiesTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraPropertiesTest.java
@@ -28,6 +28,7 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraProperties;
+import android.os.Handler;
 import android.test.AndroidTestCase;
 
 /**
@@ -36,6 +37,9 @@
 public class CameraPropertiesTest extends AndroidTestCase {
     private CameraManager mCameraManager;
 
+    private CameraTestThread mLooperThread;
+    private Handler mHandler;
+
     @Override
     public void setContext(Context context) {
         super.setContext(context);
@@ -46,17 +50,23 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mLooperThread = new CameraTestThread();
+        mHandler = mLooperThread.start();
     }
 
     @Override
     protected void tearDown() throws Exception {
+        mLooperThread.close();
+        mHandler = null;
+
         super.tearDown();
     }
 
     public void testCameraPropertiesAndroidControlAeAvailableAntibandingModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -75,7 +85,7 @@
     public void testCameraPropertiesAndroidControlAeAvailableTargetFpsRanges() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -94,7 +104,7 @@
     public void testCameraPropertiesAndroidControlAeCompensationRange() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -113,7 +123,7 @@
     public void testCameraPropertiesAndroidControlAeCompensationStep() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -132,7 +142,7 @@
     public void testCameraPropertiesAndroidControlAfAvailableModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -151,7 +161,7 @@
     public void testCameraPropertiesAndroidControlAvailableEffects() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -170,7 +180,7 @@
     public void testCameraPropertiesAndroidControlAvailableSceneModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -189,7 +199,7 @@
     public void testCameraPropertiesAndroidControlAvailableVideoStabilizationModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -208,7 +218,7 @@
     public void testCameraPropertiesAndroidControlAwbAvailableModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -227,7 +237,7 @@
     public void testCameraPropertiesAndroidControlMaxRegions() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -246,7 +256,7 @@
     public void testCameraPropertiesAndroidFlashInfoAvailable() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -265,7 +275,7 @@
     public void testCameraPropertiesAndroidJpegAvailableThumbnailSizes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -284,7 +294,7 @@
     public void testCameraPropertiesAndroidLensFacing() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -303,7 +313,7 @@
     public void testCameraPropertiesAndroidLensInfoAvailableApertures() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -322,7 +332,7 @@
     public void testCameraPropertiesAndroidLensInfoAvailableFilterDensities() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -341,7 +351,7 @@
     public void testCameraPropertiesAndroidLensInfoAvailableFocalLengths() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -360,7 +370,7 @@
     public void testCameraPropertiesAndroidLensInfoAvailableOpticalStabilization() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -379,7 +389,7 @@
     public void testCameraPropertiesAndroidLensInfoHyperfocalDistance() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -398,7 +408,7 @@
     public void testCameraPropertiesAndroidLensInfoMinimumFocusDistance() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -417,7 +427,7 @@
     public void testCameraPropertiesAndroidLensInfoShadingMapSize() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -436,7 +446,7 @@
     public void testCameraPropertiesAndroidRequestMaxNumOutputStreams() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -455,7 +465,7 @@
     public void testCameraPropertiesAndroidScalerAvailableFormats() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -474,7 +484,7 @@
     public void testCameraPropertiesAndroidScalerAvailableJpegMinDurations() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -493,7 +503,7 @@
     public void testCameraPropertiesAndroidScalerAvailableJpegSizes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -512,7 +522,7 @@
     public void testCameraPropertiesAndroidScalerAvailableMaxDigitalZoom() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -531,7 +541,7 @@
     public void testCameraPropertiesAndroidScalerAvailableProcessedMinDurations() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -550,7 +560,7 @@
     public void testCameraPropertiesAndroidScalerAvailableProcessedSizes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -569,7 +579,7 @@
     public void testCameraPropertiesAndroidSensorBaseGainFactor() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -588,7 +598,7 @@
     public void testCameraPropertiesAndroidSensorMaxAnalogSensitivity() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -607,7 +617,7 @@
     public void testCameraPropertiesAndroidSensorOrientation() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -626,7 +636,7 @@
     public void testCameraPropertiesAndroidSensorInfoActiveArraySize() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -645,7 +655,7 @@
     public void testCameraPropertiesAndroidSensorInfoSensitivityRange() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -664,7 +674,7 @@
     public void testCameraPropertiesAndroidSensorInfoExposureTimeRange() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -683,7 +693,7 @@
     public void testCameraPropertiesAndroidSensorInfoMaxFrameDuration() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -702,7 +712,7 @@
     public void testCameraPropertiesAndroidSensorInfoPhysicalSize() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -721,7 +731,7 @@
     public void testCameraPropertiesAndroidStatisticsInfoAvailableFaceDetectModes() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -740,7 +750,7 @@
     public void testCameraPropertiesAndroidStatisticsInfoMaxFaceCount() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -759,7 +769,7 @@
     public void testCameraPropertiesAndroidTonemapMaxCurvePoints() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
@@ -778,7 +788,7 @@
     public void testCameraPropertiesAndroidInfoSupportedHardwareLevel() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = mCameraManager.openCamera(ids[i]);
+            CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
             assertNotNull("Failed to open camera", camera);
             CameraProperties props;
             try {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index 293811a..5c1ec91 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -17,14 +17,20 @@
 package android.hardware.camera2.cts;
 
 import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CameraProperties;
 import android.hardware.camera2.Size;
 import android.media.Image;
 import android.media.Image.Plane;
+import android.os.Handler;
 import android.util.Log;
 
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+
 import junit.framework.Assert;
 
 import java.io.FileOutputStream;
@@ -40,6 +46,73 @@
     private static final String TAG = "CameraTestUtils";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
+    /**
+     * Provide a default implementation of CameraDevice.StateListener that does nothing.
+     */
+    public abstract static class DeviceStateListener extends CameraDevice.StateListener {
+        public DeviceStateListener() {
+        }
+
+        @Override
+        public void onOpened(CameraDevice camera) {
+            // Do nothing. It should be handled by #openCamera
+        }
+
+        @Override
+        public void onDisconnected(CameraDevice camera) {
+            // Do nothing
+        }
+
+        @Override
+        public void onError(CameraDevice camera, int error) {
+            // Do nothing
+        }
+    }
+
+    /**
+     * Block until the camera is opened.
+     *
+     * <p>Don't use this to test #onDisconnected/#onError since this will throw
+     * an AssertionError if it fails to open the camera device.</p>
+     *
+     * @return CameraDevice opened camera device
+     * @throws BlockingOpenException
+     *
+     * @throws AssertionError if the camera fails to open (or times out)
+     */
+    public static CameraDevice openCamera(CameraManager manager, String cameraId,
+            CameraDevice.StateListener listener, Handler handler) throws CameraAccessException,
+            BlockingOpenException {
+
+        /**
+         * Although camera2 API allows 'null' Handler (it will just use the current
+         * thread's Looper), this is not what we want for CTS.
+         *
+         * In CTS the default looper is used only to process events in between test runs,
+         * so anything sent there would not be executed inside a test and the test would fail.
+         *
+         * In this case, BlockingCameraManager#openCamera performs the check for us.
+         */
+        return (new BlockingCameraManager(manager)).openCamera(cameraId, listener, handler);
+    }
+
+
+    /**
+     * Block until the camera is opened.
+     *
+     * <p>Don't use this to test #onDisconnected/#onError since this will throw
+     * an AssertionError if it fails to open the camera device.</p>
+     *
+     * @return CameraDevice opened camera device
+     *
+     * @throws AssertionError if the camera fails to open (or times out)
+     */
+    public static CameraDevice openCamera(CameraManager manager, String cameraId, Handler handler)
+            throws CameraAccessException,
+            BlockingOpenException {
+        return openCamera(manager, cameraId, /*listener*/null, handler);
+    }
+
     public static <T> void assertArrayNotEmpty(T arr, String message) {
         assertTrue(message, arr != null && Array.getLength(arr) > 0);
     }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
index e891ca2..a03f51b 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -35,6 +35,8 @@
 import android.util.Log;
 import android.view.Surface;
 
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -167,7 +169,7 @@
 
     private class SimpleImageListener implements ImageReader.OnImageAvailableListener {
         private int mPendingImages = 0;
-        private Object mImageSyncObject = new Object();
+        private final Object mImageSyncObject = new Object();
 
         @Override
         public void onImageAvailable(ImageReader reader) {
@@ -260,7 +262,7 @@
         }
     }
 
-    private void stopCapture() throws Exception{
+    private void stopCapture() throws CameraAccessException {
         mCamera.stopRepeating();
         mCamera.waitUntilIdle();
         mReader.close();
@@ -268,19 +270,22 @@
         mListener = null;
     }
 
-    private void openDevice(String cameraId) throws Exception{
+    private void openDevice(String cameraId) {
         if (mCamera != null) {
             throw new IllegalStateException("Already have open camera device");
         }
         try {
-            mCamera = mCameraManager.openCamera(cameraId);
+            mCamera = openCamera(mCameraManager, cameraId, mHandler);
         } catch (CameraAccessException e) {
             mCamera = null;
             fail("Fail to open camera, " + Log.getStackTraceString(e));
+        } catch (BlockingOpenException e) {
+            mCamera = null;
+            fail("Fail to open camera, " + Log.getStackTraceString(e));
         }
     }
 
-    private void closeDevice(String cameraId) throws Exception {
+    private void closeDevice(String cameraId) {
         mCamera.close();
         mCamera = null;
     }