Home | History | Annotate | Download | only in helpers
      1 /*
      2  * Copyright 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 package android.hardware.camera2.cts.helpers;
     17 
     18 import android.hardware.camera2.CameraAccessException;
     19 import android.hardware.camera2.CameraCaptureSession;
     20 import android.hardware.camera2.CameraDevice;
     21 import android.hardware.camera2.CaptureFailure;
     22 import android.hardware.camera2.CaptureRequest;
     23 import android.hardware.camera2.TotalCaptureResult;
     24 import android.hardware.camera2.cts.CameraTestUtils;
     25 import android.os.Handler;
     26 import android.util.Log;
     27 import android.util.Pair;
     28 import android.view.Surface;
     29 
     30 import com.android.ex.camera2.blocking.BlockingCaptureCallback;
     31 import com.android.ex.camera2.blocking.BlockingSessionCallback;
     32 import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
     33 
     34 import junit.framework.Assert;
     35 
     36 import org.mockito.Mockito;
     37 
     38 import java.util.List;
     39 import java.util.concurrent.LinkedBlockingQueue;
     40 
     41 import static android.hardware.camera2.cts.helpers.Preconditions.*;
     42 import static org.mockito.Mockito.*;
     43 
     44 /**
     45  * A utility class with common functions setting up sessions and capturing.
     46  */
     47 public class CameraSessionUtils extends Assert {
     48     private static final String TAG = "CameraSessionUtils";
     49     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     50 
     51     /**
     52      * A blocking listener class for synchronously opening and configuring sessions.
     53      */
     54     public static class SessionListener extends BlockingSessionCallback {
     55         private final LinkedBlockingQueue<CameraCaptureSession> mSessionQueue =
     56                 new LinkedBlockingQueue<>();
     57 
     58         /**
     59          * Get a new configured {@link CameraCaptureSession}.
     60          *
     61          * <p>
     62          * This method is blocking, and will time out after
     63          * {@link CameraTestUtils#SESSION_CONFIGURE_TIMEOUT_MS}.
     64          * </p>
     65          *
     66          * @param device the {@link CameraDevice} to open a session for.
     67          * @param outputs the {@link Surface} outputs to configure.
     68          * @param handler the {@link Handler} to use for callbacks.
     69          * @return a configured {@link CameraCaptureSession}.
     70          *
     71          * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
     72          * @throws TimeoutRuntimeException if no result was received before the timeout.
     73          */
     74         public synchronized CameraCaptureSession getConfiguredSession(CameraDevice device,
     75                                                                       List<Surface> outputs,
     76                                                                       Handler handler)
     77                 throws CameraAccessException {
     78             device.createCaptureSession(outputs, this, handler);
     79             getStateWaiter().waitForState(SESSION_CONFIGURED,
     80                     CameraTestUtils.SESSION_CONFIGURE_TIMEOUT_MS);
     81             return mSessionQueue.poll();
     82         }
     83 
     84         @Override
     85         public void onConfigured(CameraCaptureSession session) {
     86             mSessionQueue.offer(session);
     87             super.onConfigured(session);
     88         }
     89     }
     90 
     91     /**
     92      * A blocking listener class for synchronously capturing and results with a session.
     93      */
     94     public static class CaptureCallback extends BlockingCaptureCallback {
     95         private final LinkedBlockingQueue<TotalCaptureResult> mResultQueue =
     96                 new LinkedBlockingQueue<>();
     97         private final LinkedBlockingQueue<Long> mCaptureTimeQueue =
     98                 new LinkedBlockingQueue<>();
     99 
    100         /**
    101          * Capture a new result with the given {@link CameraCaptureSession}.
    102          *
    103          * <p>
    104          * This method is blocking, and will time out after
    105          * {@link CameraTestUtils#CAPTURE_RESULT_TIMEOUT_MS}.
    106          * </p>
    107          *
    108          * @param session the {@link CameraCaptureSession} to use.
    109          * @param request the {@link CaptureRequest} to capture with.
    110          * @param handler the {@link Handler} to use for callbacks.
    111          * @return a {@link Pair} containing the capture result and capture time.
    112          *
    113          * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
    114          * @throws TimeoutRuntimeException if no result was received before the timeout.
    115          */
    116         public synchronized Pair<TotalCaptureResult, Long> getCapturedResult(
    117                 CameraCaptureSession session, CaptureRequest request, Handler handler)
    118                 throws CameraAccessException {
    119             session.capture(request, this, handler);
    120             getStateWaiter().waitForState(CAPTURE_COMPLETED,
    121                     CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS);
    122             return new Pair<>(mResultQueue.poll(), mCaptureTimeQueue.poll());
    123         }
    124 
    125         @Override
    126         public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
    127                                      long timestamp, long frameNumber) {
    128             mCaptureTimeQueue.offer(timestamp);
    129             super.onCaptureStarted(session, request, timestamp, frameNumber);
    130         }
    131 
    132         @Override
    133         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
    134                                        TotalCaptureResult result) {
    135             mResultQueue.offer(result);
    136             super.onCaptureCompleted(session, request, result);
    137         }
    138     }
    139 
    140     /**
    141      * Get a mocked {@link CaptureCallback}.
    142      */
    143     public static CaptureCallback getMockCaptureListener() {
    144         return spy(new CaptureCallback());
    145     }
    146 
    147     /**
    148      * Get a mocked {@link CaptureCallback}.
    149      */
    150     public static SessionListener getMockSessionListener() {
    151         return spy(new SessionListener());
    152     }
    153 
    154     /**
    155      * Configure and return a new {@link CameraCaptureSession}.
    156      *
    157      * <p>
    158      * This will verify that the correct session callbacks are called if a mocked listener is
    159      * passed as the {@code listener} argument. This method is blocking, and will time out after
    160      * {@link CameraTestUtils#SESSION_CONFIGURE_TIMEOUT_MS}.
    161      * </p>
    162      *
    163      * @param listener a {@link SessionListener} to use for callbacks.
    164      * @param device the {@link CameraDevice} to use.
    165      * @param outputs the {@link Surface} outputs to configure.
    166      * @param handler the {@link Handler} to call callbacks on.
    167      * @return a configured {@link CameraCaptureSession}.
    168      *
    169      * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
    170      * @throws TimeoutRuntimeException if no result was received before the timeout.
    171      */
    172     public static CameraCaptureSession configureAndVerifySession(SessionListener listener,
    173                                                                  CameraDevice device,
    174                                                                  List<Surface> outputs,
    175                                                                  Handler handler)
    176             throws CameraAccessException {
    177         checkNotNull(listener);
    178         checkNotNull(device);
    179         checkNotNull(handler);
    180         checkCollectionNotEmpty(outputs, "outputs");
    181         checkCollectionElementsNotNull(outputs, "outputs");
    182 
    183         CameraCaptureSession session = listener.getConfiguredSession(device, outputs, handler);
    184         if (Mockito.mockingDetails(listener).isMock()) {
    185             verify(listener, never()).onConfigureFailed(any(CameraCaptureSession.class));
    186             verify(listener, never()).onClosed(eq(session));
    187             verify(listener, atLeastOnce()).onConfigured(eq(session));
    188         }
    189 
    190         checkNotNull(session);
    191         return session;
    192     }
    193 
    194     /**
    195      * Capture and return a new {@link TotalCaptureResult}.
    196      *
    197      * <p>
    198      * This will verify that the correct capture callbacks are called if a mocked listener is
    199      * passed as the {@code listener} argument. This method is blocking, and will time out after
    200      * {@link CameraTestUtils#CAPTURE_RESULT_TIMEOUT_MS}.
    201      * </p>
    202      *
    203      * @param listener a {@link CaptureCallback} to use for callbacks.
    204      * @param session the {@link CameraCaptureSession} to use.
    205      * @param request the {@link CaptureRequest} to capture with.
    206      * @param handler the {@link Handler} to call callbacks on.
    207      * @return a {@link Pair} containing the capture result and capture time.
    208      *
    209      * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
    210      * @throws TimeoutRuntimeException if no result was received before the timeout.
    211      */
    212     public static Pair<TotalCaptureResult, Long> captureAndVerifyResult(CaptureCallback listener,
    213             CameraCaptureSession session, CaptureRequest request, Handler handler)
    214             throws CameraAccessException {
    215         checkNotNull(listener);
    216         checkNotNull(session);
    217         checkNotNull(request);
    218         checkNotNull(handler);
    219 
    220         Pair<TotalCaptureResult, Long> result = listener.getCapturedResult(session, request,
    221                 handler);
    222         if (Mockito.mockingDetails(listener).isMock()) {
    223             verify(listener, never()).onCaptureFailed(any(CameraCaptureSession.class),
    224                     any(CaptureRequest.class), any(CaptureFailure.class));
    225             verify(listener, atLeastOnce()).onCaptureStarted(eq(session), eq(request),
    226                     anyLong(), anyLong());
    227             verify(listener, atLeastOnce()).onCaptureCompleted(eq(session), eq(request),
    228                     eq(result.first));
    229         }
    230 
    231         checkNotNull(result);
    232         return result;
    233     }
    234 
    235     // Suppress default constructor for noninstantiability
    236     private CameraSessionUtils() { throw new AssertionError(); }
    237 }
    238