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.CAMERA_CLOSE_TIMEOUT_MS;
20 import static android.hardware.camera2.cts.CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS;
21 import static android.hardware.camera2.cts.CameraTestUtils.PREVIEW_SIZE_BOUND;
22 import static android.hardware.camera2.cts.CameraTestUtils.assertNotNull;
23 import static android.hardware.camera2.cts.CameraTestUtils.checkSessionConfigurationSupported;
24 import static android.hardware.camera2.cts.CameraTestUtils.fail;
25 import static android.hardware.camera2.cts.CameraTestUtils.getPreviewSizeBound;
26 import static android.hardware.camera2.cts.CameraTestUtils.getSupportedPreviewSizes;
27 import static android.hardware.camera2.cts.CameraTestUtils.getSupportedStillSizes;
28 import static android.hardware.camera2.cts.CameraTestUtils.getSupportedVideoSizes;
29 
30 import static com.android.ex.camera2.blocking.BlockingStateCallback.STATE_CLOSED;
31 
32 import static junit.framework.Assert.assertTrue;
33 
34 import android.content.Context;
35 import android.content.pm.PackageManager;
36 import android.graphics.ColorSpace;
37 import android.graphics.Rect;
38 import android.hardware.camera2.CameraCaptureSession;
39 import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
40 import android.hardware.camera2.CameraCharacteristics;
41 import android.hardware.camera2.CameraDevice;
42 import android.hardware.camera2.CaptureRequest;
43 import android.hardware.camera2.cts.Camera2ParameterizedTestCase;
44 import android.hardware.camera2.cts.CameraTestUtils;
45 import android.hardware.camera2.cts.helpers.CameraErrorCollector;
46 import android.hardware.camera2.cts.helpers.StaticMetadata;
47 import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
48 import android.hardware.camera2.params.InputConfiguration;
49 import android.hardware.camera2.params.OutputConfiguration;
50 import android.hardware.camera2.params.SessionConfiguration;
51 import android.media.Image;
52 import android.media.Image.Plane;
53 import android.media.ImageReader;
54 import android.os.Handler;
55 import android.os.HandlerThread;
56 import android.util.Log;
57 import android.util.Size;
58 import android.view.Surface;
59 import android.view.WindowManager;
60 
61 import com.android.ex.camera2.blocking.BlockingSessionCallback;
62 import com.android.ex.camera2.blocking.BlockingStateCallback;
63 
64 import java.io.File;
65 import java.nio.ByteBuffer;
66 import java.util.ArrayList;
67 import java.util.Arrays;
68 import java.util.HashMap;
69 import java.util.HashSet;
70 import java.util.List;
71 import java.util.Set;
72 
73 // TODO: Can we de-duplicate this with Camera2AndroidBasicTestCase keeping in mind CtsVerifier ?
74 public class Camera2AndroidTestCase extends Camera2ParameterizedTestCase {
75     private static final String TAG = "Camera2AndroidTestCase";
76     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
77 
78     // include both standalone camera IDs and "hidden" physical camera IDs
79     private String[] mAllCameraIds;
80 
81     // Default capture size: VGA size is required by CDD.
82     protected static final Size DEFAULT_CAPTURE_SIZE = new Size(640, 480);
83     protected static final int CAPTURE_WAIT_TIMEOUT_MS = 7000;
84 
85     protected CameraDevice mCamera;
86     protected CameraCaptureSession mCameraSession;
87     protected BlockingSessionCallback mCameraSessionListener;
88     protected BlockingStateCallback mCameraListener;
89     protected HashMap<String, StaticMetadata> mAllStaticInfo;
90     protected ImageReader mReader;
91     protected Surface mReaderSurface;
92     protected Handler mHandler;
93     protected HandlerThread mHandlerThread;
94     protected StaticMetadata mStaticInfo;
95     protected CameraErrorCollector mCollector;
96     protected List<Size> mOrderedPreviewSizes; // In descending order.
97     protected List<Size> mOrderedVideoSizes; // In descending order.
98     protected List<Size> mOrderedStillSizes; // In descending order.
99     protected String mDebugFileNameBase;
100 
101     protected WindowManager mWindowManager;
102 
103     // Request templates that are unsupported by LEGACY mode.
104     protected static Set<Integer> sLegacySkipTemplates = new HashSet<>();
105     static {
106         sLegacySkipTemplates.add(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
107         sLegacySkipTemplates.add(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
108         sLegacySkipTemplates.add(CameraDevice.TEMPLATE_MANUAL);
109     }
110 
111 
112     /**
113      * Set up the camera2 test case required environments, including CameraManager,
114      * HandlerThread, Camera IDs, and CameraStateCallback etc.
115      */
116     @Override
setUp()117     public void setUp() throws Exception {
118         setUp(false);
119     }
120 
121     /**
122      * Set up the camera2 test case required environments, including CameraManager,
123      * HandlerThread, Camera IDs, and CameraStateCallback etc.
124      * @param useAll whether all camera ids are to be used for system camera tests
125      */
setUp(boolean useAll)126     public void setUp(boolean useAll) throws Exception {
127         super.setUp(useAll);
128         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
129 
130         mHandlerThread = new HandlerThread(TAG);
131         mHandlerThread.start();
132         mHandler = new Handler(mHandlerThread.getLooper());
133         mCameraListener = new BlockingStateCallback();
134         mCollector = new CameraErrorCollector();
135 
136         File filesDir = mContext.getExternalFilesDir(null);
137         if (filesDir == null || mContext.getPackageManager().isInstantApp()) {
138             filesDir = mContext.getFilesDir();
139         }
140 
141         mDebugFileNameBase = filesDir.getPath();
142 
143         mAllStaticInfo = new HashMap<String, StaticMetadata>();
144         List<String> hiddenPhysicalIds = new ArrayList<>();
145         String[] cameraIdsUnderTest = getCameraIdsUnderTest();
146         for (String cameraId : cameraIdsUnderTest) {
147             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(cameraId);
148             StaticMetadata staticMetadata = new StaticMetadata(props,
149                     CheckLevel.ASSERT, /*collector*/null);
150             mAllStaticInfo.put(cameraId, staticMetadata);
151 
152             for (String physicalId : props.getPhysicalCameraIds()) {
153                 if (!Arrays.asList(cameraIdsUnderTest).contains(physicalId) &&
154                         !hiddenPhysicalIds.contains(physicalId)) {
155                     hiddenPhysicalIds.add(physicalId);
156                     props = mCameraManager.getCameraCharacteristics(physicalId);
157                     staticMetadata = new StaticMetadata(
158                             mCameraManager.getCameraCharacteristics(physicalId),
159                             CheckLevel.ASSERT, /*collector*/null);
160                     mAllStaticInfo.put(physicalId, staticMetadata);
161                 }
162             }
163         }
164         mAllCameraIds = new String[cameraIdsUnderTest.length + hiddenPhysicalIds.size()];
165         System.arraycopy(cameraIdsUnderTest, 0, mAllCameraIds, 0, cameraIdsUnderTest.length);
166         for (int i = 0; i < hiddenPhysicalIds.size(); i++) {
167             mAllCameraIds[cameraIdsUnderTest.length + i] = hiddenPhysicalIds.get(i);
168         }
169     }
170 
171     @Override
tearDown()172     public void tearDown() throws Exception {
173         try {
174             if (mHandlerThread != null) {
175                 mHandlerThread.quitSafely();
176             }
177             mHandler = null;
178             closeDefaultImageReader();
179 
180             if (mCollector != null) {
181                 mCollector.verify();
182             }
183         } catch (Throwable e) {
184             // When new Exception(e) is used, exception info will be printed twice.
185             throw new Exception(e.getMessage());
186         } finally {
187             super.tearDown();
188         }
189     }
190 
getAllCameraIds()191     public String[] getAllCameraIds() throws Exception {
192         // If external camera is supported, verify that it is connected as part of the camera Ids
193         // under test. If the external camera is not connected, an exception will be thrown to
194         // prevent bypassing CTS testing for external camera
195         CameraTestUtils.verifyExternalCameraConnected(mCameraManager.getCameraIdListNoLazy(),
196                 mContext.getPackageManager(), mCameraManager);
197 
198         return mAllCameraIds;
199     }
200 
201     /**
202      * Start capture with given {@link #CaptureRequest}.
203      *
204      * @param request The {@link #CaptureRequest} to be captured.
205      * @param repeating If the capture is single capture or repeating.
206      * @param listener The {@link #CaptureCallback} camera device used to notify callbacks.
207      * @param handler The handler camera device used to post callbacks.
208      */
startCapture(CaptureRequest request, boolean repeating, CaptureCallback listener, Handler handler)209     protected void startCapture(CaptureRequest request, boolean repeating,
210             CaptureCallback listener, Handler handler) throws Exception {
211         if (VERBOSE) Log.v(TAG, "Starting capture from device");
212 
213         if (repeating) {
214             mCameraSession.setRepeatingRequest(request, listener, handler);
215         } else {
216             mCameraSession.capture(request, listener, handler);
217         }
218     }
219 
220     /**
221      * Stop the current active capture.
222      *
223      * @param fast When it is true, {@link CameraDevice#flush} is called, the stop capture
224      * could be faster.
225      */
stopCapture(boolean fast)226     protected void stopCapture(boolean fast) throws Exception {
227         if (VERBOSE) Log.v(TAG, "Stopping capture");
228 
229         if (fast) {
230             /**
231              * Flush is useful for canceling long exposure single capture, it also could help
232              * to make the streaming capture stop sooner.
233              */
234             mCameraSession.abortCaptures();
235             mCameraSessionListener.getStateWaiter().
236                     waitForState(BlockingSessionCallback.SESSION_READY, CAMERA_IDLE_TIMEOUT_MS);
237         } else {
238             mCameraSession.close();
239             mCameraSessionListener.getStateWaiter().
240                     waitForState(BlockingSessionCallback.SESSION_CLOSED, CAMERA_IDLE_TIMEOUT_MS);
241         }
242     }
243 
244     /**
245      * Open a {@link #CameraDevice camera device} and get the StaticMetadata for a given camera id.
246      * The default mCameraListener is used to wait for states.
247      *
248      * @param cameraId The id of the camera device to be opened.
249      */
openDevice(String cameraId)250     protected void openDevice(String cameraId) throws Exception {
251         openDevice(cameraId, /*overrideToPortrait*/false, mCameraListener);
252     }
253 
254     /**
255      * Open a {@link #CameraDevice} and get the StaticMetadata for a given camera id and listener.
256      *
257      * @param cameraId The id of the camera device to be opened.
258      * @param listener The {@link #BlockingStateCallback} used to wait for states.
259      */
openDevice(String cameraId, BlockingStateCallback listener)260     protected void openDevice(String cameraId, BlockingStateCallback listener) throws Exception {
261         openDevice(cameraId, /*overrideToPortrait*/false, listener);
262     }
263 
264     /**
265      * Open a {@link #CameraDevice} and get the StaticMetadata for a given camera id and listener.
266      *
267      * @param cameraId The id of the camera device to be opened.
268      * @param overrideToPortrait Whether to enable the landscape-to-portrait override
269      */
openDevice(String cameraId, boolean overrideToPortrait)270     protected void openDevice(String cameraId, boolean overrideToPortrait) throws Exception {
271         openDevice(cameraId, overrideToPortrait, mCameraListener);
272     }
273 
274     /**
275      * Open a {@link #CameraDevice} and get the StaticMetadata for a given camera id and listener.
276      *
277      * @param cameraId The id of the camera device to be opened.
278      * @param overrideToPortrait Whether to enable the landscape-to-portrait override
279      * @param listener The {@link #BlockingStateCallback} used to wait for states.
280      */
openDevice(String cameraId, boolean overrideToPortrait, BlockingStateCallback listener)281     protected void openDevice(String cameraId, boolean overrideToPortrait,
282             BlockingStateCallback listener) throws Exception {
283         mCamera = CameraTestUtils.openCamera(
284                 mCameraManager, cameraId, overrideToPortrait, listener, mHandler);
285         mCollector.setCameraId(cameraId);
286         mStaticInfo = mAllStaticInfo.get(cameraId);
287         if (mStaticInfo.isColorOutputSupported()) {
288             mOrderedPreviewSizes = getSupportedPreviewSizes(
289                     cameraId, mCameraManager,
290                     getPreviewSizeBound(mWindowManager, PREVIEW_SIZE_BOUND));
291             mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
292             mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
293         }
294 
295         if (VERBOSE) {
296             Log.v(TAG, "Camera " + cameraId + " is opened");
297         }
298     }
299 
300     /**
301      * Create a {@link #CameraCaptureSession} using the currently open camera.
302      *
303      * @param outputSurfaces The set of output surfaces to configure for this session
304      */
createSession(List<Surface> outputSurfaces)305     protected void createSession(List<Surface> outputSurfaces) throws Exception {
306         mCameraSessionListener = new BlockingSessionCallback();
307         mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
308                 mCameraSessionListener, mHandler);
309     }
310 
311     /**
312      * Create a reprocessable {@link #CameraCaptureSession} using the currently open camera.
313      *
314      * @param inputConfiguration The inputConfiguration for this session
315      * @param outputSurfaces The set of output surfaces to configure for this session
316      */
createReprocessableSession(InputConfiguration inputConfig, List<Surface> outputSurfaces)317     protected void createReprocessableSession(InputConfiguration inputConfig,
318             List<Surface> outputSurfaces) throws Exception {
319         mCameraSessionListener = new BlockingSessionCallback();
320         mCameraSession = CameraTestUtils.configureReprocessableCameraSession(
321                 mCamera, inputConfig, outputSurfaces, mCameraSessionListener, mHandler);
322     }
323 
324     /**
325      * Create a {@link #CameraCaptureSession} using the currently open camera with
326      * OutputConfigurations.
327      *
328      * @param outputConfigs The set of output configurations for this session
329      */
createSessionByConfigs(List<OutputConfiguration> outputConfigs)330     protected void createSessionByConfigs(List<OutputConfiguration> outputConfigs) throws Exception {
331         mCameraSessionListener = new BlockingSessionCallback();
332         mCameraSession = CameraTestUtils.configureCameraSessionWithConfig(mCamera, outputConfigs,
333                 mCameraSessionListener, mHandler);
334     }
335 
336     /**
337      * Create a {@link #CameraCaptureSession} using the currently open camera with
338      * OutputConfigurations and a ColorSpace.
339      *
340      * @param outputConfigs The set of output configurations for this session
341      * @param colorSpace The color space for this session
342      */
createSessionByConfigsAndColorSpace(List<OutputConfiguration> outputConfigs, ColorSpace.Named colorSpace)343     protected void createSessionByConfigsAndColorSpace(List<OutputConfiguration> outputConfigs,
344             ColorSpace.Named colorSpace) throws Exception {
345         mCameraSessionListener = new BlockingSessionCallback();
346         mCameraSession = CameraTestUtils.configureCameraSessionWithColorSpace(mCamera,
347                 outputConfigs, mCameraSessionListener, mHandler, colorSpace);
348     }
349 
350     /**
351      * Close a {@link #CameraDevice camera device} and clear the associated StaticInfo field for a
352      * given camera id. The default mCameraListener is used to wait for states.
353      * <p>
354      * This function must be used along with the {@link #openDevice} for the
355      * same camera id.
356      * </p>
357      *
358      * @param cameraId The id of the {@link #CameraDevice camera device} to be closed.
359      */
closeDevice(String cameraId)360     protected void closeDevice(String cameraId) {
361         closeDevice(cameraId, mCameraListener);
362     }
363 
364     /**
365      * Close a {@link #CameraDevice camera device} and clear the associated StaticInfo field for a
366      * given camera id and listener.
367      * <p>
368      * This function must be used along with the {@link #openDevice} for the
369      * same camera id.
370      * </p>
371      *
372      * @param cameraId The id of the camera device to be closed.
373      * @param listener The BlockingStateCallback used to wait for states.
374      */
closeDevice(String cameraId, BlockingStateCallback listener)375     protected void closeDevice(String cameraId, BlockingStateCallback listener) {
376         if (mCamera != null) {
377             if (!cameraId.equals(mCamera.getId())) {
378                 throw new IllegalStateException("Try to close a device that is not opened yet");
379             }
380             mCamera.close();
381             listener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
382             mCamera = null;
383             mCameraSession = null;
384             mCameraSessionListener = null;
385             mStaticInfo = null;
386             mOrderedPreviewSizes = null;
387             mOrderedVideoSizes = null;
388             mOrderedStillSizes = null;
389 
390             if (VERBOSE) {
391                 Log.v(TAG, "Camera " + cameraId + " is closed");
392             }
393         }
394     }
395 
396     /**
397      * Create an {@link ImageReader} object and get the surface.
398      * <p>
399      * This function creates {@link ImageReader} object and surface, then assign
400      * to the default {@link mReader} and {@link mReaderSurface}. It closes the
401      * current default active {@link ImageReader} if it exists.
402      * </p>
403      *
404      * @param size The size of this ImageReader to be created.
405      * @param format The format of this ImageReader to be created
406      * @param maxNumImages The max number of images that can be acquired
407      *            simultaneously.
408      * @param listener The listener used by this ImageReader to notify
409      *            callbacks.
410      */
createDefaultImageReader(Size size, int format, int maxNumImages, ImageReader.OnImageAvailableListener listener)411     protected void createDefaultImageReader(Size size, int format, int maxNumImages,
412             ImageReader.OnImageAvailableListener listener) throws Exception {
413         closeDefaultImageReader();
414 
415         mReader = createImageReader(size, format, maxNumImages, listener);
416         mReaderSurface = mReader.getSurface();
417         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
418     }
419 
420     /**
421      * Create an {@link ImageReader} object and get the surface.
422      * <p>
423      * This function creates {@link ImageReader} object and surface, then assign
424      * to the default {@link mReader} and {@link mReaderSurface}. It closes the
425      * current default active {@link ImageReader} if it exists.
426      * </p>
427      *
428      * @param size The size of this ImageReader to be created.
429      * @param format The format of this ImageReader to be created
430      * @param maxNumImages The max number of images that can be acquired
431      *            simultaneously.
432      * @param usage The usage flag of the ImageReader
433      * @param listener The listener used by this ImageReader to notify
434      *            callbacks.
435      */
createDefaultImageReader(Size size, int format, int maxNumImages, long usage, ImageReader.OnImageAvailableListener listener)436     protected void createDefaultImageReader(Size size, int format, int maxNumImages, long usage,
437             ImageReader.OnImageAvailableListener listener) throws Exception {
438         closeDefaultImageReader();
439 
440         mReader = createImageReader(size, format, maxNumImages, usage, listener);
441         mReaderSurface = mReader.getSurface();
442         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
443     }
444 
445     /**
446      * Create an {@link ImageReader} object.
447      *
448      * <p>This function creates image reader object for given format, maxImages, and size.</p>
449      *
450      * @param size The size of this ImageReader to be created.
451      * @param format The format of this ImageReader to be created
452      * @param maxNumImages The max number of images that can be acquired simultaneously.
453      * @param listener The listener used by this ImageReader to notify callbacks.
454      */
455 
createImageReader(Size size, int format, int maxNumImages, ImageReader.OnImageAvailableListener listener)456     protected ImageReader createImageReader(Size size, int format, int maxNumImages,
457             ImageReader.OnImageAvailableListener listener) throws Exception {
458 
459         ImageReader reader = null;
460         reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
461                 format, maxNumImages);
462 
463         reader.setOnImageAvailableListener(listener, mHandler);
464         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
465         return reader;
466     }
467 
468     /**
469      * Create an {@link ImageReader} object.
470      *
471      * <p>This function creates image reader object for given format, maxImages, usage and size.</p>
472      *
473      * @param size The size of this ImageReader to be created.
474      * @param format The format of this ImageReader to be created
475      * @param maxNumImages The max number of images that can be acquired simultaneously.
476      * @param usage The usage flag of the ImageReader
477      * @param listener The listener used by this ImageReader to notify callbacks.
478      */
479 
createImageReader(Size size, int format, int maxNumImages, long usage, ImageReader.OnImageAvailableListener listener)480     protected ImageReader createImageReader(Size size, int format, int maxNumImages, long usage,
481             ImageReader.OnImageAvailableListener listener) throws Exception {
482         ImageReader reader = null;
483         reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
484                 format, maxNumImages, usage);
485 
486         reader.setOnImageAvailableListener(listener, mHandler);
487         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
488         return reader;
489     }
490 
491     /**
492      * Close the pending images then close current default {@link ImageReader} object.
493      */
closeDefaultImageReader()494     protected void closeDefaultImageReader() {
495         closeImageReader(mReader);
496         mReader = null;
497         mReaderSurface = null;
498     }
499 
500     /**
501      * Close an image reader instance.
502      *
503      * @param reader
504      */
closeImageReader(ImageReader reader)505     protected void closeImageReader(ImageReader reader) {
506         if (reader != null) {
507             reader.close();
508         }
509     }
510 
checkImageReaderSessionConfiguration(String msg)511     protected void checkImageReaderSessionConfiguration(String msg) throws Exception {
512         checkImageReaderSessionConfiguration(msg, /*physicalCameraId*/null);
513     }
514 
checkImageReaderSessionConfiguration(String msg, String physicalCameraId)515     protected void checkImageReaderSessionConfiguration(String msg, String physicalCameraId)
516             throws Exception {
517         List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
518         OutputConfiguration config = new OutputConfiguration(mReaderSurface);
519         if (physicalCameraId != null) {
520             config.setPhysicalCameraId(physicalCameraId);
521         }
522         outputConfigs.add(config);
523         checkSessionConfigurationSupported(mCamera, mHandler, outputConfigs, /*inputConfig*/ null,
524                 SessionConfiguration.SESSION_REGULAR, mCameraManager, /*expectedResult*/ true, msg);
525     }
526 
prepareCaptureRequest()527     protected CaptureRequest prepareCaptureRequest() throws Exception {
528         return prepareCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
529     }
530 
prepareCaptureRequest(int template)531     protected CaptureRequest prepareCaptureRequest(int template) throws Exception {
532         List<Surface> outputSurfaces = new ArrayList<Surface>();
533         Surface surface = mReader.getSurface();
534         assertNotNull("Fail to get surface from ImageReader", surface);
535         outputSurfaces.add(surface);
536         return prepareCaptureRequestForSurfaces(outputSurfaces, template)
537                 .build();
538     }
539 
prepareCaptureRequestForSurfaces(List<Surface> surfaces, int template)540     protected CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces,
541             int template)
542             throws Exception {
543         createSession(surfaces);
544 
545         CaptureRequest.Builder captureBuilder =
546                 mCamera.createCaptureRequest(template);
547         assertNotNull("Fail to get captureRequest", captureBuilder);
548         for (Surface surface : surfaces) {
549             captureBuilder.addTarget(surface);
550         }
551 
552         return captureBuilder;
553     }
554 
prepareCaptureRequestBuilderWithConfig( List<OutputConfiguration> outputConfigs, int template)555     protected CaptureRequest.Builder prepareCaptureRequestBuilderWithConfig(
556             List<OutputConfiguration> outputConfigs, int template) throws Exception {
557         CaptureRequest.Builder captureBuilder =
558                 mCamera.createCaptureRequest(template);
559         assertNotNull("Fail to get captureRequest", captureBuilder);
560         for (OutputConfiguration config : outputConfigs) {
561             for (Surface s : config.getSurfaces()) {
562                 captureBuilder.addTarget(s);
563             }
564         }
565         return captureBuilder;
566     }
567 
prepareCaptureRequestForConfigs( List<OutputConfiguration> outputConfigs, int template)568     protected CaptureRequest.Builder prepareCaptureRequestForConfigs(
569             List<OutputConfiguration> outputConfigs, int template) throws Exception {
570         createSessionByConfigs(outputConfigs);
571         return prepareCaptureRequestBuilderWithConfig(outputConfigs, template);
572     }
573 
prepareCaptureRequestForColorSpace( List<OutputConfiguration> outputConfigs, int template, ColorSpace.Named colorSpace)574     protected CaptureRequest.Builder prepareCaptureRequestForColorSpace(
575             List<OutputConfiguration> outputConfigs, int template, ColorSpace.Named colorSpace)
576             throws Exception {
577         createSessionByConfigsAndColorSpace(outputConfigs, colorSpace);
578         return prepareCaptureRequestBuilderWithConfig(outputConfigs, template);
579     }
580 
581     /**
582      * Test the invalid Image access: accessing a closed image must result in
583      * {@link IllegalStateException}.
584      *
585      * @param closedImage The closed image.
586      * @param closedBuffer The ByteBuffer from a closed Image. buffer invalid
587      *            access will be skipped if it is null.
588      */
imageInvalidAccessTestAfterClose(Image closedImage, Plane closedPlane, ByteBuffer closedBuffer)589     protected void imageInvalidAccessTestAfterClose(Image closedImage,
590             Plane closedPlane, ByteBuffer closedBuffer) {
591         if (closedImage == null) {
592             throw new IllegalArgumentException(" closedImage must be non-null");
593         }
594         if (closedBuffer != null && !closedBuffer.isDirect()) {
595             throw new IllegalArgumentException("The input ByteBuffer should be direct ByteBuffer");
596         }
597 
598         if (closedPlane != null) {
599             // Plane#getBuffer test
600             try {
601                 closedPlane.getBuffer(); // An ISE should be thrown here.
602                 fail("Image should throw IllegalStateException when calling getBuffer"
603                         + " after the image is closed");
604             } catch (IllegalStateException e) {
605                 // Expected.
606             }
607 
608             // Plane#getPixelStride test
609             try {
610                 closedPlane.getPixelStride(); // An ISE should be thrown here.
611                 fail("Image should throw IllegalStateException when calling getPixelStride"
612                         + " after the image is closed");
613             } catch (IllegalStateException e) {
614                 // Expected.
615             }
616 
617             // Plane#getRowStride test
618             try {
619                 closedPlane.getRowStride(); // An ISE should be thrown here.
620                 fail("Image should throw IllegalStateException when calling getRowStride"
621                         + " after the image is closed");
622             } catch (IllegalStateException e) {
623                 // Expected.
624             }
625         }
626 
627         // ByteBuffer access test
628         if (closedBuffer != null) {
629             try {
630                 closedBuffer.get(); // An ISE should be thrown here.
631                 fail("Image should throw IllegalStateException when accessing a byte buffer"
632                         + " after the image is closed");
633             } catch (IllegalStateException e) {
634                 // Expected.
635             }
636         }
637 
638         // Image#getFormat test
639         try {
640             closedImage.getFormat();
641             fail("Image should throw IllegalStateException when calling getFormat"
642                     + " after the image is closed");
643         } catch (IllegalStateException e) {
644             // Expected.
645         }
646 
647         // Image#getWidth test
648         try {
649             closedImage.getWidth();
650             fail("Image should throw IllegalStateException when calling getWidth"
651                     + " after the image is closed");
652         } catch (IllegalStateException e) {
653             // Expected.
654         }
655 
656         // Image#getHeight test
657         try {
658             closedImage.getHeight();
659             fail("Image should throw IllegalStateException when calling getHeight"
660                     + " after the image is closed");
661         } catch (IllegalStateException e) {
662             // Expected.
663         }
664 
665         // Image#getTimestamp test
666         try {
667             closedImage.getTimestamp();
668             fail("Image should throw IllegalStateException when calling getTimestamp"
669                     + " after the image is closed");
670         } catch (IllegalStateException e) {
671             // Expected.
672         }
673 
674         // Image#getTimestamp test
675         try {
676             closedImage.getTimestamp();
677             fail("Image should throw IllegalStateException when calling getTimestamp"
678                     + " after the image is closed");
679         } catch (IllegalStateException e) {
680             // Expected.
681         }
682 
683         // Image#getCropRect test
684         try {
685             closedImage.getCropRect();
686             fail("Image should throw IllegalStateException when calling getCropRect"
687                     + " after the image is closed");
688         } catch (IllegalStateException e) {
689             // Expected.
690         }
691 
692         // Image#setCropRect test
693         try {
694             Rect rect = new Rect();
695             closedImage.setCropRect(rect);
696             fail("Image should throw IllegalStateException when calling setCropRect"
697                     + " after the image is closed");
698         } catch (IllegalStateException e) {
699             // Expected.
700         }
701 
702         // Image#getPlanes test
703         try {
704             closedImage.getPlanes();
705             fail("Image should throw IllegalStateException when calling getPlanes"
706                     + " after the image is closed");
707         } catch (IllegalStateException e) {
708             // Expected.
709         }
710     }
711 }
712