Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.hardware.camera2.cts;
     18 
     19 import static org.mockito.Mockito.*;
     20 import static org.mockito.AdditionalMatchers.not;
     21 import static org.mockito.AdditionalMatchers.and;
     22 
     23 import android.content.Context;
     24 import android.content.pm.PackageManager;
     25 import android.hardware.camera2.CameraAccessException;
     26 import android.hardware.camera2.CameraCharacteristics;
     27 import android.hardware.camera2.CameraDevice;
     28 import android.hardware.camera2.CameraDevice.StateCallback;
     29 import android.hardware.camera2.CameraManager;
     30 import android.hardware.camera2.cts.CameraTestUtils.MockStateCallback;
     31 import android.hardware.camera2.cts.helpers.CameraErrorCollector;
     32 import android.os.Handler;
     33 import android.os.HandlerThread;
     34 import android.test.AndroidTestCase;
     35 import android.util.Log;
     36 
     37 import com.android.ex.camera2.blocking.BlockingStateCallback;
     38 
     39 import org.mockito.ArgumentCaptor;
     40 import org.mockito.InOrder;
     41 
     42 import java.util.ArrayList;
     43 import java.util.Arrays;
     44 import java.util.HashSet;
     45 import java.util.List;
     46 import java.util.concurrent.LinkedBlockingQueue;
     47 
     48 /**
     49  * <p>Basic test for CameraManager class.</p>
     50  */
     51 public class CameraManagerTest extends AndroidTestCase {
     52     private static final String TAG = "CameraManagerTest";
     53     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     54     private static final int NUM_CAMERA_REOPENS = 10;
     55 
     56     private PackageManager mPackageManager;
     57     private CameraManager mCameraManager;
     58     private NoopCameraListener mListener;
     59     private HandlerThread mHandlerThread;
     60     private Handler mHandler;
     61     private BlockingStateCallback mCameraListener;
     62     private CameraErrorCollector mCollector;
     63 
     64     @Override
     65     public void setContext(Context context) {
     66         super.setContext(context);
     67         mCameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
     68         assertNotNull("Can't connect to camera manager", mCameraManager);
     69         mPackageManager = context.getPackageManager();
     70         assertNotNull("Can't get package manager", mPackageManager);
     71         mListener = new NoopCameraListener();
     72     }
     73 
     74     @Override
     75     protected void setUp() throws Exception {
     76         super.setUp();
     77 
     78         /**
     79          * Workaround for mockito and JB-MR2 incompatibility
     80          *
     81          * Avoid java.lang.IllegalArgumentException: dexcache == null
     82          * https://code.google.com/p/dexmaker/issues/detail?id=2
     83          */
     84         System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
     85 
     86         mCameraListener = spy(new BlockingStateCallback());
     87 
     88         mHandlerThread = new HandlerThread(TAG);
     89         mHandlerThread.start();
     90         mHandler = new Handler(mHandlerThread.getLooper());
     91         mCollector = new CameraErrorCollector();
     92     }
     93 
     94     @Override
     95     protected void tearDown() throws Exception {
     96         mHandlerThread.quitSafely();
     97         mHandler = null;
     98 
     99         try {
    100             mCollector.verify();
    101         } catch (Throwable e) {
    102             // When new Exception(e) is used, exception info will be printed twice.
    103             throw new Exception(e.getMessage());
    104         } finally {
    105             super.tearDown();
    106         }
    107     }
    108 
    109     /**
    110      * Verifies that the reason is in the range of public-only codes.
    111      */
    112     private static int checkCameraAccessExceptionReason(CameraAccessException e) {
    113         int reason = e.getReason();
    114 
    115         switch (reason) {
    116             case CameraAccessException.CAMERA_DISABLED:
    117             case CameraAccessException.CAMERA_DISCONNECTED:
    118             case CameraAccessException.CAMERA_ERROR:
    119                 return reason;
    120         }
    121 
    122         fail("Invalid CameraAccessException code: " + reason);
    123 
    124         return -1; // unreachable
    125     }
    126 
    127     public void testCameraManagerGetDeviceIdList() throws Exception {
    128 
    129         // Test: that the getCameraIdList method runs without exceptions.
    130         String[] ids = mCameraManager.getCameraIdList();
    131         if (VERBOSE) Log.v(TAG, "CameraManager ids: " + Arrays.toString(ids));
    132 
    133         /**
    134          * Test: that if there is at least one reported id, then the system must have
    135          * the FEATURE_CAMERA_ANY feature.
    136          */
    137         assertTrue("System camera feature and camera id list don't match",
    138                 ids.length == 0 ||
    139                 mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));
    140 
    141         /**
    142          * Test: that if the device has front or rear facing cameras, then there
    143          * must be matched system features.
    144          */
    145         for (int i = 0; i < ids.length; i++) {
    146             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
    147             assertNotNull("Can't get camera characteristics for camera " + ids[i], props);
    148             Integer lensFacing = props.get(CameraCharacteristics.LENS_FACING);
    149             assertNotNull("Can't get lens facing info", lensFacing);
    150             if (lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
    151                 assertTrue("System doesn't have front camera feature",
    152                         mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
    153                         mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
    154             } else if (lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
    155                 assertTrue("System doesn't have back camera feature",
    156                         mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA));
    157             } else {
    158                 fail("Unknown camera lens facing " + lensFacing.toString());
    159             }
    160         }
    161 
    162         /**
    163          * Test: that if there is one camera device, then the system must have some
    164          * specific features.
    165          */
    166         assertTrue("Missing system feature: FEATURE_CAMERA_ANY",
    167                ids.length == 0
    168             || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));
    169         assertTrue("Missing system feature: FEATURE_CAMERA or FEATURE_CAMERA_FRONT",
    170                ids.length == 0
    171             || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
    172             || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT));
    173     }
    174 
    175     // Test: that properties can be queried from each device, without exceptions.
    176     public void testCameraManagerGetCameraCharacteristics() throws Exception {
    177         String[] ids = mCameraManager.getCameraIdList();
    178         for (int i = 0; i < ids.length; i++) {
    179             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
    180             assertNotNull(
    181                     String.format("Can't get camera characteristics from: ID %s", ids[i]), props);
    182         }
    183     }
    184 
    185     // Test: that an exception is thrown if an invalid device id is passed down.
    186     public void testCameraManagerInvalidDevice() throws Exception {
    187         String[] ids = mCameraManager.getCameraIdList();
    188         // Create an invalid id by concatenating all the valid ids together.
    189         StringBuilder invalidId = new StringBuilder();
    190         invalidId.append("INVALID");
    191         for (int i = 0; i < ids.length; i++) {
    192             invalidId.append(ids[i]);
    193         }
    194 
    195         try {
    196             mCameraManager.getCameraCharacteristics(
    197                 invalidId.toString());
    198             fail(String.format("Accepted invalid camera ID: %s", invalidId.toString()));
    199         } catch (IllegalArgumentException e) {
    200             // This is the exception that should be thrown in this case.
    201         }
    202     }
    203 
    204     // Test: that each camera device can be opened one at a time, several times.
    205     public void testCameraManagerOpenCamerasSerially() throws Exception {
    206         String[] ids = mCameraManager.getCameraIdList();
    207         for (int i = 0; i < ids.length; i++) {
    208             for (int j = 0; j < NUM_CAMERA_REOPENS; j++) {
    209                 CameraDevice camera = null;
    210                 try {
    211                     MockStateCallback mockListener = MockStateCallback.mock();
    212                     mCameraListener = new BlockingStateCallback(mockListener);
    213 
    214                     mCameraManager.openCamera(ids[i], mCameraListener, mHandler);
    215 
    216                     // Block until unConfigured
    217                     mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
    218                             CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    219 
    220                     // Ensure state transitions are in right order:
    221                     // -- 1) Opened
    222                     // Ensure no other state transitions have occurred:
    223                     camera = verifyCameraStateOpened(ids[i], mockListener);
    224                 } finally {
    225                     if (camera != null) {
    226                         camera.close();
    227                     }
    228                 }
    229             }
    230         }
    231     }
    232 
    233     /**
    234      * Test: one or more camera devices can be open at the same time, or the right error state
    235      * is set if this can't be done.
    236      */
    237     public void testCameraManagerOpenAllCameras() throws Exception {
    238         String[] ids = mCameraManager.getCameraIdList();
    239         assertNotNull("Camera ids shouldn't be null", ids);
    240 
    241         // Skip test if the device doesn't have multiple cameras.
    242         if (ids.length <= 1) {
    243             return;
    244         }
    245 
    246         List<CameraDevice> cameraList = new ArrayList<CameraDevice>();
    247         List<MockStateCallback> listenerList = new ArrayList<MockStateCallback>();
    248         List<BlockingStateCallback> blockingListenerList = new ArrayList<BlockingStateCallback>();
    249         try {
    250             for (int i = 0; i < ids.length; i++) {
    251                 // Ignore state changes from other cameras
    252                 MockStateCallback mockListener = MockStateCallback.mock();
    253                 mCameraListener = new BlockingStateCallback(mockListener);
    254 
    255                 /**
    256                  * Track whether or not we got a synchronous error from openCamera.
    257                  *
    258                  * A synchronous error must also be accompanied by an asynchronous
    259                  * StateCallback#onError callback.
    260                  */
    261                 boolean expectingError = false;
    262 
    263                 String cameraId = ids[i];
    264                 try {
    265                     mCameraManager.openCamera(cameraId, mCameraListener,
    266                             mHandler);
    267                 } catch (CameraAccessException e) {
    268                     if (checkCameraAccessExceptionReason(e) == CameraAccessException.CAMERA_ERROR) {
    269                         expectingError = true;
    270                     } else {
    271                         // TODO: We should handle a Disabled camera by passing here and elsewhere
    272                         fail("Camera must not be disconnected or disabled for this test" + ids[i]);
    273                     }
    274                 }
    275 
    276                 List<Integer> expectedStates = new ArrayList<Integer>();
    277                 expectedStates.add(BlockingStateCallback.STATE_OPENED);
    278                 expectedStates.add(BlockingStateCallback.STATE_ERROR);
    279                 int state = mCameraListener.waitForAnyOfStates(
    280                         expectedStates, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    281 
    282                 // It's possible that we got an asynchronous error transition only. This is ok.
    283                 if (expectingError) {
    284                     assertEquals("Throwing a CAMERA_ERROR exception must be accompanied with a " +
    285                             "StateCallback#onError callback",
    286                             BlockingStateCallback.STATE_ERROR, state);
    287                 }
    288 
    289                 /**
    290                  * Two situations are considered passing:
    291                  * 1) The camera opened successfully.
    292                  *     => No error must be set.
    293                  * 2) The camera did not open because there were too many other cameras opened.
    294                  *     => Only MAX_CAMERAS_IN_USE error must be set.
    295                  *
    296                  * Any other situation is considered a failure.
    297                  *
    298                  * For simplicity we treat disconnecting asynchronously as a failure, so
    299                  * camera devices should not be physically unplugged during this test.
    300                  */
    301 
    302                 CameraDevice camera;
    303                 if (state == BlockingStateCallback.STATE_ERROR) {
    304                     // Camera did not open because too many other cameras were opened
    305                     // => onError called exactly once with a non-null camera
    306                     assertTrue("At least one camera must be opened successfully",
    307                             cameraList.size() > 0);
    308 
    309                     ArgumentCaptor<CameraDevice> argument =
    310                             ArgumentCaptor.forClass(CameraDevice.class);
    311 
    312                     verify(mockListener)
    313                             .onError(
    314                                     argument.capture(),
    315                                     eq(CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE));
    316                     verifyNoMoreInteractions(mockListener);
    317 
    318                     camera = argument.getValue();
    319                     assertNotNull("Expected a non-null camera for the error transition for ID: "
    320                             + ids[i], camera);
    321                 } else if (state == BlockingStateCallback.STATE_OPENED) {
    322                     // Camera opened successfully.
    323                     // => onOpened called exactly once
    324                     camera = verifyCameraStateOpened(cameraId,
    325                             mockListener);
    326                 } else {
    327                     fail("Unexpected state " + state);
    328                     camera = null; // unreachable. but need this for java compiler
    329                 }
    330 
    331                 // Keep track of cameras so we can close it later
    332                 cameraList.add(camera);
    333                 listenerList.add(mockListener);
    334                 blockingListenerList.add(mCameraListener);
    335             }
    336         } finally {
    337             for (CameraDevice camera : cameraList) {
    338                 camera.close();
    339             }
    340             for (BlockingStateCallback blockingListener : blockingListenerList) {
    341                 blockingListener.waitForState(
    342                         BlockingStateCallback.STATE_CLOSED,
    343                         CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    344             }
    345         }
    346 
    347         /*
    348          * Ensure that no state transitions have bled through from one camera to another
    349          * after closing the cameras.
    350          */
    351         int i = 0;
    352         for (MockStateCallback listener : listenerList) {
    353             CameraDevice camera = cameraList.get(i);
    354 
    355             verify(listener).onClosed(eq(camera));
    356             verifyNoMoreInteractions(listener);
    357             i++;
    358             // Only a #close can happen on the camera since we were done with it.
    359             // Also nothing else should've happened between the close and the open.
    360         }
    361     }
    362 
    363     /**
    364      * Verifies the camera in this listener was opened and then unconfigured exactly once.
    365      *
    366      * <p>This assumes that no other action to the camera has been done (e.g.
    367      * it hasn't been configured, or closed, or disconnected). Verification is
    368      * performed immediately without any timeouts.</p>
    369      *
    370      * <p>This checks that the state has previously changed first for opened and then unconfigured.
    371      * Any other state transitions will fail. A test failure is thrown if verification fails.</p>
    372      *
    373      * @param cameraId Camera identifier
    374      * @param listener Listener which was passed to {@link CameraManager#openCamera}
    375      *
    376      * @return The camera device (non-{@code null}).
    377      */
    378     private static CameraDevice verifyCameraStateOpened(String cameraId,
    379             MockStateCallback listener) {
    380         ArgumentCaptor<CameraDevice> argument =
    381                 ArgumentCaptor.forClass(CameraDevice.class);
    382         InOrder inOrder = inOrder(listener);
    383 
    384         /**
    385          * State transitions (in that order):
    386          *  1) onOpened
    387          *
    388          * No other transitions must occur for successful #openCamera
    389          */
    390         inOrder.verify(listener)
    391                 .onOpened(argument.capture());
    392 
    393         CameraDevice camera = argument.getValue();
    394         assertNotNull(
    395                 String.format("Failed to open camera device ID: %s", cameraId),
    396                 camera);
    397 
    398         // Do not use inOrder here since that would skip anything called before onOpened
    399         verifyNoMoreInteractions(listener);
    400 
    401         return camera;
    402     }
    403 
    404     /**
    405      * Test: that opening the same device multiple times and make sure the right
    406      * error state is set.
    407      */
    408     public void testCameraManagerOpenCameraTwice() throws Exception {
    409         String[] ids = mCameraManager.getCameraIdList();
    410 
    411         // Test across every camera device.
    412         for (int i = 0; i < ids.length; ++i) {
    413             CameraDevice successCamera = null;
    414             mCollector.setCameraId(ids[i]);
    415 
    416             try {
    417                 MockStateCallback mockSuccessListener = MockStateCallback.mock();
    418                 MockStateCallback mockFailListener = MockStateCallback.mock();
    419 
    420                 BlockingStateCallback successListener =
    421                         new BlockingStateCallback(mockSuccessListener);
    422                 BlockingStateCallback failListener =
    423                         new BlockingStateCallback(mockFailListener);
    424 
    425                 mCameraManager.openCamera(ids[i], successListener, mHandler);
    426                 mCameraManager.openCamera(ids[i], failListener,
    427                         mHandler);
    428 
    429                 successListener.waitForState(BlockingStateCallback.STATE_OPENED,
    430                         CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    431                 ArgumentCaptor<CameraDevice> argument =
    432                         ArgumentCaptor.forClass(CameraDevice.class);
    433                 verify(mockSuccessListener, atLeastOnce()).onOpened(argument.capture());
    434                 verify(mockSuccessListener, atLeastOnce()).onDisconnected(argument.capture());
    435 
    436                 failListener.waitForState(BlockingStateCallback.STATE_OPENED,
    437                         CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    438                 verify(mockFailListener, atLeastOnce()).onOpened(argument.capture());
    439 
    440                 successCamera = verifyCameraStateOpened(
    441                         ids[i], mockFailListener);
    442 
    443                 verifyNoMoreInteractions(mockFailListener);
    444             } finally {
    445                 if (successCamera != null) {
    446                     successCamera.close();
    447                 }
    448             }
    449         }
    450     }
    451 
    452     private class NoopCameraListener extends CameraManager.AvailabilityCallback {
    453         @Override
    454         public void onCameraAvailable(String cameraId) {
    455             // No-op
    456         }
    457 
    458         @Override
    459         public void onCameraUnavailable(String cameraId) {
    460             // No-op
    461         }
    462     }
    463 
    464     /**
    465      * Test: that the APIs to register and unregister a listener run successfully;
    466      * doesn't test that the listener actually gets invoked at the right time.
    467      * Registering a listener multiple times should have no effect, and unregistering
    468      * a listener that isn't registered should have no effect.
    469      */
    470     public void testCameraManagerListener() throws Exception {
    471         mCameraManager.unregisterAvailabilityCallback(mListener);
    472         mCameraManager.registerAvailabilityCallback(mListener, mHandler);
    473         mCameraManager.registerAvailabilityCallback(mListener, mHandler);
    474         mCameraManager.unregisterAvailabilityCallback(mListener);
    475         mCameraManager.unregisterAvailabilityCallback(mListener);
    476     }
    477 
    478     /**
    479      * Test that the availability callbacks fire when expected
    480      */
    481     public void testCameraManagerListenerCallbacks() throws Exception {
    482         final int AVAILABILITY_TIMEOUT_MS = 10;
    483 
    484         final LinkedBlockingQueue<String> availableEventQueue = new LinkedBlockingQueue<>();
    485         final LinkedBlockingQueue<String> unavailableEventQueue = new LinkedBlockingQueue<>();
    486 
    487         CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
    488             @Override
    489             public void onCameraAvailable(String cameraId) {
    490                 availableEventQueue.offer(cameraId);
    491             }
    492 
    493             @Override
    494             public void onCameraUnavailable(String cameraId) {
    495                 unavailableEventQueue.offer(cameraId);
    496             }
    497         };
    498 
    499         mCameraManager.registerAvailabilityCallback(ac, mHandler);
    500         String[] cameras = mCameraManager.getCameraIdList();
    501 
    502         if (cameras.length == 0) {
    503             Log.i(TAG, "No cameras present, skipping test");
    504             return;
    505         }
    506 
    507         // Verify we received available for all cameras' initial state in a reasonable amount of time
    508         HashSet<String> expectedAvailableCameras = new HashSet<String>(Arrays.asList(cameras));
    509         while (expectedAvailableCameras.size() > 0) {
    510             String id = availableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
    511                     java.util.concurrent.TimeUnit.MILLISECONDS);
    512             assertTrue("Did not receive initial availability notices for some cameras",
    513                        id != null);
    514             expectedAvailableCameras.remove(id);
    515         }
    516         // Verify no unavailable cameras were reported
    517         assertTrue("Some camera devices are initially unavailable",
    518                 unavailableEventQueue.size() == 0);
    519 
    520         // Verify transitions for individual cameras
    521         for (String id : cameras) {
    522             MockStateCallback mockListener = MockStateCallback.mock();
    523             mCameraListener = new BlockingStateCallback(mockListener);
    524 
    525             mCameraManager.openCamera(id, mCameraListener, mHandler);
    526 
    527             // Block until opened
    528             mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
    529                     CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    530             // Then verify only open happened, and get the camera handle
    531             CameraDevice camera = verifyCameraStateOpened(id, mockListener);
    532 
    533             // Verify that we see the expected 'unavailable' event.
    534             String candidateId = unavailableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
    535                     java.util.concurrent.TimeUnit.MILLISECONDS);
    536             assertTrue(String.format("Received unavailability notice for wrong ID " +
    537                             "(expected %s, got %s)", id, candidateId),
    538                     id.equals(candidateId));
    539             assertTrue("Availability events received unexpectedly",
    540                     availableEventQueue.size() == 0);
    541 
    542             // Verify that we see the expected 'available' event after closing the camera
    543 
    544             camera.close();
    545 
    546             mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
    547                     CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);
    548 
    549             candidateId = availableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
    550                     java.util.concurrent.TimeUnit.MILLISECONDS);
    551             assertTrue(String.format("Received availability notice for wrong ID " +
    552                             "(expected %s, got %s)", id, candidateId),
    553                     id.equals(candidateId));
    554             assertTrue("Unavailability events received unexpectedly",
    555                     unavailableEventQueue.size() == 0);
    556 
    557         }
    558 
    559         // Verify that we can unregister the listener and see no more events
    560         assertTrue("Availability events received unexpectedly",
    561                 availableEventQueue.size() == 0);
    562         assertTrue("Unavailability events received unexpectedly",
    563                     unavailableEventQueue.size() == 0);
    564 
    565         mCameraManager.unregisterAvailabilityCallback(ac);
    566 
    567         {
    568             // Open an arbitrary camera and make sure we don't hear about it
    569 
    570             MockStateCallback mockListener = MockStateCallback.mock();
    571             mCameraListener = new BlockingStateCallback(mockListener);
    572 
    573             mCameraManager.openCamera(cameras[0], mCameraListener, mHandler);
    574 
    575             // Block until opened
    576             mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
    577                     CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
    578             // Then verify only open happened, and close the camera
    579             CameraDevice camera = verifyCameraStateOpened(cameras[0], mockListener);
    580 
    581             camera.close();
    582 
    583             mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
    584                     CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);
    585 
    586             // No unavailability or availability callback should have occured
    587             String candidateId = unavailableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
    588                     java.util.concurrent.TimeUnit.MILLISECONDS);
    589             assertTrue(String.format("Received unavailability notice for ID %s unexpectedly ",
    590                             candidateId),
    591                     candidateId == null);
    592 
    593             candidateId = availableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
    594                     java.util.concurrent.TimeUnit.MILLISECONDS);
    595             assertTrue(String.format("Received availability notice for ID %s unexpectedly ",
    596                             candidateId),
    597                     candidateId == null);
    598 
    599 
    600         }
    601 
    602     } // testCameraManagerListenerCallbacks
    603 
    604 }
    605