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