Home | History | Annotate | Download | only in testcases
      1 /*
      2  * Copyright (C) 2014 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.testcases;
     18 
     19 import static android.hardware.camera2.cts.CameraTestUtils.*;
     20 import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
     21 
     22 import android.content.Context;
     23 import android.hardware.camera2.CameraCaptureSession;
     24 import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
     25 import android.hardware.camera2.CameraDevice;
     26 import android.hardware.camera2.CameraManager;
     27 import android.hardware.camera2.CaptureRequest;
     28 import android.util.Size;
     29 import android.hardware.camera2.cts.CameraTestUtils;
     30 import android.hardware.camera2.cts.helpers.CameraErrorCollector;
     31 import android.hardware.camera2.cts.helpers.StaticMetadata;
     32 import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
     33 import android.media.Image;
     34 import android.media.ImageReader;
     35 import android.os.Environment;
     36 import android.os.Handler;
     37 import android.os.HandlerThread;
     38 import android.test.AndroidTestCase;
     39 import android.util.Log;
     40 import android.view.Surface;
     41 
     42 import com.android.ex.camera2.blocking.BlockingSessionCallback;
     43 import com.android.ex.camera2.blocking.BlockingStateCallback;
     44 
     45 import java.util.List;
     46 
     47 public class Camera2AndroidTestCase extends AndroidTestCase {
     48     private static final String TAG = "Camera2AndroidTestCase";
     49     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     50 
     51     protected static final String DEBUG_FILE_NAME_BASE =
     52             Environment.getExternalStorageDirectory().getPath();
     53     // Default capture size: VGA size is required by CDD.
     54     protected static final Size DEFAULT_CAPTURE_SIZE = new Size(640, 480);
     55     protected static final int CAPTURE_WAIT_TIMEOUT_MS = 5000;
     56 
     57     protected CameraManager mCameraManager;
     58     protected CameraDevice mCamera;
     59     protected CameraCaptureSession mCameraSession;
     60     protected BlockingSessionCallback mCameraSessionListener;
     61     protected BlockingStateCallback mCameraListener;
     62     protected String[] mCameraIds;
     63     protected ImageReader mReader;
     64     protected Surface mReaderSurface;
     65     protected Handler mHandler;
     66     protected HandlerThread mHandlerThread;
     67     protected StaticMetadata mStaticInfo;
     68     protected CameraErrorCollector mCollector;
     69     protected List<Size> mOrderedPreviewSizes; // In descending order.
     70     protected List<Size> mOrderedVideoSizes; // In descending order.
     71     protected List<Size> mOrderedStillSizes; // In descending order.
     72 
     73     @Override
     74     public void setContext(Context context) {
     75         super.setContext(context);
     76         mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
     77         assertNotNull("Can't connect to camera manager!", mCameraManager);
     78     }
     79 
     80     /**
     81      * Set up the camera2 test case required environments, including CameraManager,
     82      * HandlerThread, Camera IDs, and CameraStateCallback etc.
     83      */
     84     @Override
     85     protected void setUp() throws Exception {
     86         super.setUp();
     87 
     88         /**
     89          * Workaround for mockito and JB-MR2 incompatibility
     90          *
     91          * Avoid java.lang.IllegalArgumentException: dexcache == null
     92          * https://code.google.com/p/dexmaker/issues/detail?id=2
     93          */
     94         System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
     95 
     96         mCameraIds = mCameraManager.getCameraIdList();
     97         assertNotNull("Camera ids shouldn't be null", mCameraIds);
     98         mHandlerThread = new HandlerThread(TAG);
     99         mHandlerThread.start();
    100         mHandler = new Handler(mHandlerThread.getLooper());
    101         mCameraListener = new BlockingStateCallback();
    102         mCollector = new CameraErrorCollector();
    103     }
    104 
    105     @Override
    106     protected void tearDown() throws Exception {
    107         mHandlerThread.quitSafely();
    108         mHandler = null;
    109         closeDefaultImageReader();
    110 
    111         try {
    112             mCollector.verify();
    113         } catch (Throwable e) {
    114             // When new Exception(e) is used, exception info will be printed twice.
    115             throw new Exception(e.getMessage());
    116         } finally {
    117             super.tearDown();
    118         }
    119     }
    120 
    121     /**
    122      * Start capture with given {@link #CaptureRequest}.
    123      *
    124      * @param request The {@link #CaptureRequest} to be captured.
    125      * @param repeating If the capture is single capture or repeating.
    126      * @param listener The {@link #CaptureCallback} camera device used to notify callbacks.
    127      * @param handler The handler camera device used to post callbacks.
    128      */
    129     protected void startCapture(CaptureRequest request, boolean repeating,
    130             CaptureCallback listener, Handler handler) throws Exception {
    131         if (VERBOSE) Log.v(TAG, "Starting capture from device");
    132 
    133         if (repeating) {
    134             mCameraSession.setRepeatingRequest(request, listener, handler);
    135         } else {
    136             mCameraSession.capture(request, listener, handler);
    137         }
    138     }
    139 
    140     /**
    141      * Stop the current active capture.
    142      *
    143      * @param fast When it is true, {@link CameraDevice#flush} is called, the stop capture
    144      * could be faster.
    145      */
    146     protected void stopCapture(boolean fast) throws Exception {
    147         if (VERBOSE) Log.v(TAG, "Stopping capture");
    148 
    149         if (fast) {
    150             /**
    151              * Flush is useful for canceling long exposure single capture, it also could help
    152              * to make the streaming capture stop sooner.
    153              */
    154             mCameraSession.abortCaptures();
    155             mCameraSessionListener.getStateWaiter().
    156                     waitForState(BlockingSessionCallback.SESSION_READY, CAMERA_IDLE_TIMEOUT_MS);
    157         } else {
    158             mCameraSession.close();
    159             mCameraSessionListener.getStateWaiter().
    160                     waitForState(BlockingSessionCallback.SESSION_CLOSED, CAMERA_IDLE_TIMEOUT_MS);
    161         }
    162     }
    163 
    164     /**
    165      * Open a {@link #CameraDevice camera device} and get the StaticMetadata for a given camera id.
    166      * The default mCameraListener is used to wait for states.
    167      *
    168      * @param cameraId The id of the camera device to be opened.
    169      */
    170     protected void openDevice(String cameraId) throws Exception {
    171         openDevice(cameraId, mCameraListener);
    172     }
    173 
    174     /**
    175      * Open a {@link #CameraDevice} and get the StaticMetadata for a given camera id and listener.
    176      *
    177      * @param cameraId The id of the camera device to be opened.
    178      * @param listener The {@link #BlockingStateCallback} used to wait for states.
    179      */
    180     protected void openDevice(String cameraId, BlockingStateCallback listener) throws Exception {
    181         mCamera = CameraTestUtils.openCamera(
    182                 mCameraManager, cameraId, listener, mHandler);
    183         mCollector.setCameraId(cameraId);
    184         mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
    185                 CheckLevel.ASSERT, /*collector*/null);
    186         mOrderedPreviewSizes = getSupportedPreviewSizes(
    187                 cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
    188         mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
    189         mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
    190 
    191         if (VERBOSE) {
    192             Log.v(TAG, "Camera " + cameraId + " is opened");
    193         }
    194     }
    195 
    196     /**
    197      * Create a {@link #CameraCaptureSession} using the currently open camera.
    198      *
    199      * @param outputSurfaces The set of output surfaces to configure for this session
    200      */
    201     protected void createSession(List<Surface> outputSurfaces) throws Exception {
    202         mCameraSessionListener = new BlockingSessionCallback();
    203         mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
    204                 mCameraSessionListener, mHandler);
    205     }
    206 
    207     /**
    208      * Close a {@link #CameraDevice camera device} and clear the associated StaticInfo field for a
    209      * given camera id. The default mCameraListener is used to wait for states.
    210      * <p>
    211      * This function must be used along with the {@link #openDevice} for the
    212      * same camera id.
    213      * </p>
    214      *
    215      * @param cameraId The id of the {@link #CameraDevice camera device} to be closed.
    216      */
    217     protected void closeDevice(String cameraId) {
    218         closeDevice(cameraId, mCameraListener);
    219     }
    220 
    221     /**
    222      * Close a {@link #CameraDevice camera device} and clear the associated StaticInfo field for a
    223      * given camera id and listener.
    224      * <p>
    225      * This function must be used along with the {@link #openDevice} for the
    226      * same camera id.
    227      * </p>
    228      *
    229      * @param cameraId The id of the camera device to be closed.
    230      * @param listener The BlockingStateCallback used to wait for states.
    231      */
    232     protected void closeDevice(String cameraId, BlockingStateCallback listener) {
    233         if (mCamera != null) {
    234             if (!cameraId.equals(mCamera.getId())) {
    235                 throw new IllegalStateException("Try to close a device that is not opened yet");
    236             }
    237             mCamera.close();
    238             listener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
    239             mCamera = null;
    240             mCameraSession = null;
    241             mCameraSessionListener = null;
    242             mStaticInfo = null;
    243             mOrderedPreviewSizes = null;
    244             mOrderedVideoSizes = null;
    245             mOrderedStillSizes = null;
    246 
    247             if (VERBOSE) {
    248                 Log.v(TAG, "Camera " + cameraId + " is closed");
    249             }
    250         }
    251     }
    252 
    253     /**
    254      * Create an {@link ImageReader} object and get the surface.
    255      * <p>
    256      * This function creates {@link ImageReader} object and surface, then assign
    257      * to the default {@link mReader} and {@link mReaderSurface}. It closes the
    258      * current default active {@link ImageReader} if it exists.
    259      * </p>
    260      *
    261      * @param size The size of this ImageReader to be created.
    262      * @param format The format of this ImageReader to be created
    263      * @param maxNumImages The max number of images that can be acquired
    264      *            simultaneously.
    265      * @param listener The listener used by this ImageReader to notify
    266      *            callbacks.
    267      */
    268     protected void createDefaultImageReader(Size size, int format, int maxNumImages,
    269             ImageReader.OnImageAvailableListener listener) throws Exception {
    270         closeDefaultImageReader();
    271 
    272         mReader = createImageReader(size, format, maxNumImages, listener);
    273         mReaderSurface = mReader.getSurface();
    274         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
    275     }
    276 
    277     /**
    278      * Create an {@link ImageReader} object.
    279      *
    280      * <p>This function creates image reader object for given format, maxImages, and size.</p>
    281      *
    282      * @param size The size of this ImageReader to be created.
    283      * @param format The format of this ImageReader to be created
    284      * @param maxNumImages The max number of images that can be acquired simultaneously.
    285      * @param listener The listener used by this ImageReader to notify callbacks.
    286      */
    287 
    288     protected ImageReader createImageReader(Size size, int format, int maxNumImages,
    289             ImageReader.OnImageAvailableListener listener) throws Exception {
    290 
    291         ImageReader reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
    292                 format, maxNumImages);
    293         reader.setOnImageAvailableListener(listener, mHandler);
    294         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
    295         return reader;
    296     }
    297 
    298     /**
    299      * Close the pending images then close current default {@link ImageReader} object.
    300      */
    301     protected void closeDefaultImageReader() {
    302         closeImageReader(mReader);
    303         mReader = null;
    304         mReaderSurface = null;
    305     }
    306 
    307     /**
    308      * Close an image reader instance.
    309      *
    310      * @param reader
    311      */
    312     protected void closeImageReader(ImageReader reader) {
    313         if (reader != null) {
    314             try {
    315                 // Close all possible pending images first.
    316                 Image image = reader.acquireLatestImage();
    317                 if (image != null) {
    318                     image.close();
    319                 }
    320             } finally {
    321                 reader.close();
    322                 reader = null;
    323             }
    324         }
    325     }
    326 }
    327