• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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