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