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