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