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