xref: /aosp_15_r20/cts/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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 and get the surface.
470      * <p>
471      * This function creates {@link ImageReader} object and surface, then assign
472      * to the default {@link mReader} and {@link mReaderSurface}. It closes the
473      * current default active {@link ImageReader} if it exists.
474      * </p>
475      *
476      * @param size The size of this ImageReader to be created.
477      * @param format The format of this ImageReader to be created
478      * @param maxNumImages The max number of images that can be acquired
479      *            simultaneously.
480      * @param usage The usage flag of the ImageReader
481      * @param dataspace The image reader dataspace
482      * @param listener The listener used by this ImageReader to notify
483      *            callbacks.
484      */
createDefaultImageReader(Size size, int format, int maxNumImages, long usage, int dataspace, ImageReader.OnImageAvailableListener listener)485     protected void createDefaultImageReader(Size size, int format, int maxNumImages, long usage,
486             int dataspace, ImageReader.OnImageAvailableListener listener) throws Exception {
487         closeDefaultImageReader();
488 
489         ImageReader.Builder builder = new ImageReader.Builder(size.getWidth(),
490                 size.getHeight());
491         builder.setImageFormat(format);
492         builder.setDefaultHardwareBufferFormat(format);
493         builder.setDefaultDataSpace(dataspace);
494         builder.setUsage(usage);
495         builder.setMaxImages(maxNumImages);
496 
497         mReader = builder.build();
498         mReader.setOnImageAvailableListener(listener, mHandler);
499         mReaderSurface = mReader.getSurface();
500         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
501     }
502 
503     /**
504      * Create an {@link ImageReader} object.
505      *
506      * <p>This function creates image reader object for given format, maxImages, usage and size.</p>
507      *
508      * @param size The size of this ImageReader to be created.
509      * @param format The format of this ImageReader to be created
510      * @param maxNumImages The max number of images that can be acquired simultaneously.
511      * @param usage The usage flag of the ImageReader
512      * @param listener The listener used by this ImageReader to notify callbacks.
513      */
514 
createImageReader(Size size, int format, int maxNumImages, long usage, ImageReader.OnImageAvailableListener listener)515     protected ImageReader createImageReader(Size size, int format, int maxNumImages, long usage,
516             ImageReader.OnImageAvailableListener listener) throws Exception {
517         ImageReader reader = null;
518         reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
519                 format, maxNumImages, usage);
520 
521         reader.setOnImageAvailableListener(listener, mHandler);
522         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
523         return reader;
524     }
525 
526     /**
527      * Close the pending images then close current default {@link ImageReader} object.
528      */
closeDefaultImageReader()529     protected void closeDefaultImageReader() {
530         closeImageReader(mReader);
531         mReader = null;
532         mReaderSurface = null;
533     }
534 
535     /**
536      * Close an image reader instance.
537      *
538      * @param reader
539      */
closeImageReader(ImageReader reader)540     protected void closeImageReader(ImageReader reader) {
541         if (reader != null) {
542             reader.close();
543         }
544     }
545 
checkImageReaderSessionConfiguration(String msg)546     protected void checkImageReaderSessionConfiguration(String msg) throws Exception {
547         checkImageReaderSessionConfiguration(msg, /*physicalCameraId*/null);
548     }
549 
checkImageReaderSessionConfiguration(String msg, String physicalCameraId)550     protected void checkImageReaderSessionConfiguration(String msg, String physicalCameraId)
551             throws Exception {
552         List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
553         OutputConfiguration config = new OutputConfiguration(mReaderSurface);
554         if (physicalCameraId != null) {
555             config.setPhysicalCameraId(physicalCameraId);
556         }
557         outputConfigs.add(config);
558         checkSessionConfigurationSupported(mCamera, mHandler, outputConfigs, /*inputConfig*/ null,
559                 SessionConfiguration.SESSION_REGULAR, mCameraManager, /*expectedResult*/ true, msg);
560     }
561 
prepareCaptureRequest()562     protected CaptureRequest prepareCaptureRequest() throws Exception {
563         return prepareCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
564     }
565 
prepareCaptureRequest(int template)566     protected CaptureRequest prepareCaptureRequest(int template) throws Exception {
567         List<Surface> outputSurfaces = new ArrayList<Surface>();
568         Surface surface = mReader.getSurface();
569         assertNotNull("Fail to get surface from ImageReader", surface);
570         outputSurfaces.add(surface);
571         return prepareCaptureRequestForSurfaces(outputSurfaces, template)
572                 .build();
573     }
574 
prepareCaptureRequestForSurfaces(List<Surface> surfaces, int template)575     protected CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces,
576             int template)
577             throws Exception {
578         createSession(surfaces);
579 
580         CaptureRequest.Builder captureBuilder =
581                 mCamera.createCaptureRequest(template);
582         assertNotNull("Fail to get captureRequest", captureBuilder);
583         for (Surface surface : surfaces) {
584             captureBuilder.addTarget(surface);
585         }
586 
587         return captureBuilder;
588     }
589 
prepareCaptureRequestBuilderWithConfig( List<OutputConfiguration> outputConfigs, int template)590     protected CaptureRequest.Builder prepareCaptureRequestBuilderWithConfig(
591             List<OutputConfiguration> outputConfigs, int template) throws Exception {
592         CaptureRequest.Builder captureBuilder =
593                 mCamera.createCaptureRequest(template);
594         assertNotNull("Fail to get captureRequest", captureBuilder);
595         for (OutputConfiguration config : outputConfigs) {
596             for (Surface s : config.getSurfaces()) {
597                 captureBuilder.addTarget(s);
598             }
599         }
600         return captureBuilder;
601     }
602 
prepareCaptureRequestForConfigs( List<OutputConfiguration> outputConfigs, int template)603     protected CaptureRequest.Builder prepareCaptureRequestForConfigs(
604             List<OutputConfiguration> outputConfigs, int template) throws Exception {
605         createSessionByConfigs(outputConfigs);
606         return prepareCaptureRequestBuilderWithConfig(outputConfigs, template);
607     }
608 
prepareCaptureRequestForColorSpace( List<OutputConfiguration> outputConfigs, int template, ColorSpace.Named colorSpace)609     protected CaptureRequest.Builder prepareCaptureRequestForColorSpace(
610             List<OutputConfiguration> outputConfigs, int template, ColorSpace.Named colorSpace)
611             throws Exception {
612         createSessionByConfigsAndColorSpace(outputConfigs, colorSpace);
613         return prepareCaptureRequestBuilderWithConfig(outputConfigs, template);
614     }
615 
616     /**
617      * Test the invalid Image access: accessing a closed image must result in
618      * {@link IllegalStateException}.
619      *
620      * @param closedImage The closed image.
621      * @param closedBuffer The ByteBuffer from a closed Image. buffer invalid
622      *            access will be skipped if it is null.
623      */
imageInvalidAccessTestAfterClose(Image closedImage, Plane closedPlane, ByteBuffer closedBuffer)624     protected void imageInvalidAccessTestAfterClose(Image closedImage,
625             Plane closedPlane, ByteBuffer closedBuffer) {
626         if (closedImage == null) {
627             throw new IllegalArgumentException(" closedImage must be non-null");
628         }
629         if (closedBuffer != null && !closedBuffer.isDirect()) {
630             throw new IllegalArgumentException("The input ByteBuffer should be direct ByteBuffer");
631         }
632 
633         if (closedPlane != null) {
634             // Plane#getBuffer test
635             try {
636                 closedPlane.getBuffer(); // An ISE should be thrown here.
637                 fail("Image should throw IllegalStateException when calling getBuffer"
638                         + " after the image is closed");
639             } catch (IllegalStateException e) {
640                 // Expected.
641             }
642 
643             // Plane#getPixelStride test
644             try {
645                 closedPlane.getPixelStride(); // An ISE should be thrown here.
646                 fail("Image should throw IllegalStateException when calling getPixelStride"
647                         + " after the image is closed");
648             } catch (IllegalStateException e) {
649                 // Expected.
650             }
651 
652             // Plane#getRowStride test
653             try {
654                 closedPlane.getRowStride(); // An ISE should be thrown here.
655                 fail("Image should throw IllegalStateException when calling getRowStride"
656                         + " after the image is closed");
657             } catch (IllegalStateException e) {
658                 // Expected.
659             }
660         }
661 
662         // ByteBuffer access test
663         if (closedBuffer != null) {
664             try {
665                 closedBuffer.get(); // An ISE should be thrown here.
666                 fail("Image should throw IllegalStateException when accessing a byte buffer"
667                         + " after the image is closed");
668             } catch (IllegalStateException e) {
669                 // Expected.
670             }
671         }
672 
673         // Image#getFormat test
674         try {
675             closedImage.getFormat();
676             fail("Image should throw IllegalStateException when calling getFormat"
677                     + " after the image is closed");
678         } catch (IllegalStateException e) {
679             // Expected.
680         }
681 
682         // Image#getWidth test
683         try {
684             closedImage.getWidth();
685             fail("Image should throw IllegalStateException when calling getWidth"
686                     + " after the image is closed");
687         } catch (IllegalStateException e) {
688             // Expected.
689         }
690 
691         // Image#getHeight test
692         try {
693             closedImage.getHeight();
694             fail("Image should throw IllegalStateException when calling getHeight"
695                     + " after the image is closed");
696         } catch (IllegalStateException e) {
697             // Expected.
698         }
699 
700         // Image#getTimestamp test
701         try {
702             closedImage.getTimestamp();
703             fail("Image should throw IllegalStateException when calling getTimestamp"
704                     + " after the image is closed");
705         } catch (IllegalStateException e) {
706             // Expected.
707         }
708 
709         // Image#getTimestamp test
710         try {
711             closedImage.getTimestamp();
712             fail("Image should throw IllegalStateException when calling getTimestamp"
713                     + " after the image is closed");
714         } catch (IllegalStateException e) {
715             // Expected.
716         }
717 
718         // Image#getCropRect test
719         try {
720             closedImage.getCropRect();
721             fail("Image should throw IllegalStateException when calling getCropRect"
722                     + " after the image is closed");
723         } catch (IllegalStateException e) {
724             // Expected.
725         }
726 
727         // Image#setCropRect test
728         try {
729             Rect rect = new Rect();
730             closedImage.setCropRect(rect);
731             fail("Image should throw IllegalStateException when calling setCropRect"
732                     + " after the image is closed");
733         } catch (IllegalStateException e) {
734             // Expected.
735         }
736 
737         // Image#getPlanes test
738         try {
739             closedImage.getPlanes();
740             fail("Image should throw IllegalStateException when calling getPlanes"
741                     + " after the image is closed");
742         } catch (IllegalStateException e) {
743             // Expected.
744         }
745     }
746 }
747