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