Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2018 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.cts;
     18 
     19 import android.hardware.Camera;
     20 import android.hardware.Camera.AutoFocusCallback;
     21 import android.hardware.Camera.ErrorCallback;
     22 import android.hardware.Camera.PictureCallback;
     23 import android.hardware.Camera.PreviewCallback;
     24 import android.os.Looper;
     25 import android.util.Log;
     26 
     27 import java.util.concurrent.locks.Condition;
     28 import java.util.concurrent.locks.Lock;
     29 import java.util.concurrent.locks.ReentrantLock;
     30 
     31 import junit.framework.TestCase;
     32 
     33 public class CameraTestCase extends TestCase {
     34     private static final String TAG = "CameraTestCase";
     35     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     36 
     37     protected static final int NO_ERROR = -1;
     38     protected static final long WAIT_FOR_COMMAND_TO_COMPLETE_NS = 5000000000L;
     39     protected static final long WAIT_FOR_FOCUS_TO_COMPLETE_NS = 5000000000L;
     40     protected static final long WAIT_FOR_SNAPSHOT_TO_COMPLETE_NS = 5000000000L;
     41     protected Looper mLooper = null;
     42 
     43     protected int mCameraErrorCode;
     44     protected Camera mCamera;
     45 
     46     /**
     47      * Initializes the message looper so that the Camera object can
     48      * receive the callback messages.
     49      */
     50     protected void initializeMessageLooper(final int cameraId) throws InterruptedException {
     51         Lock startLock = new ReentrantLock();
     52         Condition startDone = startLock.newCondition();
     53         mCameraErrorCode = NO_ERROR;
     54         new Thread() {
     55             @Override
     56             public void run() {
     57                 // Set up a looper to be used by camera.
     58                 Looper.prepare();
     59                 // Save the looper so that we can terminate this thread
     60                 // after we are done with it.
     61                 mLooper = Looper.myLooper();
     62                 try {
     63                     mCamera = Camera.open(cameraId);
     64                     mCamera.setErrorCallback(new ErrorCallback() {
     65                         @Override
     66                         public void onError(int error, Camera camera) {
     67                             mCameraErrorCode = error;
     68                         }
     69                     });
     70                 } catch (RuntimeException e) {
     71                     Log.e(TAG, "Fail to open camera." + e);
     72                 }
     73                 startLock.lock();
     74                 startDone.signal();
     75                 startLock.unlock();
     76                 Looper.loop(); // Blocks forever until Looper.quit() is called.
     77                 if (VERBOSE) Log.v(TAG, "initializeMessageLooper: quit.");
     78             }
     79         }.start();
     80 
     81         startLock.lock();
     82         try {
     83             if (startDone.awaitNanos(WAIT_FOR_COMMAND_TO_COMPLETE_NS) <= 0L) {
     84                 fail("initializeMessageLooper: start timeout");
     85             }
     86         } finally {
     87             startLock.unlock();
     88         }
     89 
     90         assertNotNull("Fail to open camera.", mCamera);
     91     }
     92 
     93     /**
     94      * Terminates the message looper thread, optionally allowing evict error
     95      */
     96     protected void terminateMessageLooper() throws Exception {
     97         mLooper.quit();
     98         // Looper.quit() is asynchronous. The looper may still has some
     99         // preview callbacks in the queue after quit is called. The preview
    100         // callback still uses the camera object (setHasPreviewCallback).
    101         // After camera is released, RuntimeException will be thrown from
    102         // the method. So we need to join the looper thread here.
    103         mLooper.getThread().join();
    104         mCamera.release();
    105         mCamera = null;
    106         assertEquals("Got camera error callback.", NO_ERROR, mCameraErrorCode);
    107     }
    108 
    109     /**
    110      * Start preview and wait for the first preview callback, which indicates the
    111      * preview becomes active.
    112      */
    113     protected void startPreview() throws InterruptedException {
    114         Lock previewLock = new ReentrantLock();
    115         Condition previewDone = previewLock.newCondition();
    116 
    117         mCamera.setPreviewCallback(new PreviewCallback() {
    118             @Override
    119             public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
    120                 previewLock.lock();
    121                 previewDone.signal();
    122                 previewLock.unlock();
    123             }
    124         });
    125         mCamera.startPreview();
    126 
    127         previewLock.lock();
    128         try {
    129             if (previewDone.awaitNanos(WAIT_FOR_COMMAND_TO_COMPLETE_NS) <= 0L) {
    130                 fail("Preview done timeout");
    131             }
    132         } finally {
    133             previewLock.unlock();
    134         }
    135 
    136         mCamera.setPreviewCallback(null);
    137     }
    138 
    139     /**
    140      * Trigger and wait for autofocus to complete.
    141      */
    142     protected void autoFocus() throws InterruptedException {
    143         Lock focusLock = new ReentrantLock();
    144         Condition focusDone = focusLock.newCondition();
    145 
    146         mCamera.autoFocus(new AutoFocusCallback() {
    147             @Override
    148             public void onAutoFocus(boolean success, Camera camera) {
    149                 focusLock.lock();
    150                 focusDone.signal();
    151                 focusLock.unlock();
    152             }
    153         });
    154 
    155         focusLock.lock();
    156         try {
    157             if (focusDone.awaitNanos(WAIT_FOR_FOCUS_TO_COMPLETE_NS) <= 0L) {
    158                 fail("Autofocus timeout");
    159             }
    160         } finally {
    161             focusLock.unlock();
    162         }
    163     }
    164 
    165     /**
    166      * Trigger and wait for snapshot to finish.
    167      */
    168     protected void takePicture() throws InterruptedException {
    169         Lock snapshotLock = new ReentrantLock();
    170         Condition snapshotDone = snapshotLock.newCondition();
    171 
    172         mCamera.takePicture(/*shutterCallback*/ null, /*rawPictureCallback*/ null,
    173                 new PictureCallback() {
    174             @Override
    175             public void onPictureTaken(byte[] rawData, Camera camera) {
    176                 snapshotLock.lock();
    177                 try {
    178                     if (rawData == null) {
    179                         fail("Empty jpeg data");
    180                     }
    181                     snapshotDone.signal();
    182                 } finally {
    183                     snapshotLock.unlock();
    184                 }
    185             }
    186         });
    187 
    188         snapshotLock.lock();
    189         try {
    190             if (snapshotDone.awaitNanos(WAIT_FOR_SNAPSHOT_TO_COMPLETE_NS) <= 0L) {
    191                 fail("TakePicture timeout");
    192             }
    193         } finally {
    194             snapshotLock.unlock();
    195         }
    196     }
    197 
    198 }
    199