1 /*
2  * Copyright (C) 2017 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 #define LOG_TAG "AImageReaderCts"
18 //#define LOG_NDEBUG 0
19 
20 #include <jni.h>
21 #include <stdint.h>
22 #include <unistd.h>
23 
24 #include <algorithm>
25 #include <mutex>
26 #include <string>
27 #include <vector>
28 
29 #include <android/log.h>
30 #include <android/native_window_jni.h>
31 #include <camera/NdkCameraError.h>
32 #include <camera/NdkCameraManager.h>
33 #include <camera/NdkCameraDevice.h>
34 #include <camera/NdkCameraCaptureSession.h>
35 #include <media/NdkImage.h>
36 #include <media/NdkImageReader.h>
37 
38 //#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
39 //#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
40 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
41 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
42 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
43 
44 namespace {
45 
46 static constexpr int kDummyFenceFd = -1;
47 static constexpr int kCaptureWaitUs = 100 * 1000;
48 static constexpr int kCaptureWaitRetry = 10;
49 static constexpr int kTestImageWidth = 640;
50 static constexpr int kTestImageHeight = 480;
51 static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
52 
53 struct FormatUsageCombination {
54     uint64_t format;
55     uint64_t usage;
56 };
57 
58 static constexpr FormatUsageCombination supportedFormatUsage[] = {
59     {AIMAGE_FORMAT_YUV_420_888, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY},
60     {AIMAGE_FORMAT_YUV_420_888, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN},
61     {AIMAGE_FORMAT_JPEG, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY},
62     {AIMAGE_FORMAT_JPEG, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN},
63     {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY},
64     {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN},
65     {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE},
66     {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_VIDEO_ENCODE},
67 };
68 
69 class CameraHelper {
70    public:
CameraHelper(ANativeWindow * imgReaderAnw)71     CameraHelper(ANativeWindow* imgReaderAnw) : mImgReaderAnw(imgReaderAnw) {}
~CameraHelper()72     ~CameraHelper() { closeCamera(); }
73 
initCamera()74     int initCamera() {
75         if (mImgReaderAnw == nullptr) {
76             ALOGE("Cannot initialize camera before image reader get initialized.");
77             return -1;
78         }
79         int ret;
80 
81         mCameraManager = ACameraManager_create();
82         if (mCameraManager == nullptr) {
83             ALOGE("Failed to create ACameraManager.");
84             return -1;
85         }
86 
87         ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
88         if (ret != AMEDIA_OK) {
89             ALOGE("Failed to get cameraIdList: ret=%d", ret);
90             return ret;
91         }
92         if (mCameraIdList->numCameras < 1) {
93             ALOGW("Device has no camera on board.");
94             return 0;
95         }
96 
97         // We always use the first camera.
98         mCameraId = mCameraIdList->cameraIds[0];
99         if (mCameraId == nullptr) {
100             ALOGE("Failed to get cameraId.");
101             return -1;
102         }
103 
104         ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
105         if (ret != AMEDIA_OK || mDevice == nullptr) {
106             ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice);
107             return -1;
108         }
109 
110         ret = ACameraManager_getCameraCharacteristics(mCameraManager, mCameraId, &mCameraMetadata);
111         if (ret != ACAMERA_OK || mCameraMetadata == nullptr) {
112             ALOGE("Get camera %s characteristics failure. ret %d, metadata %p", mCameraId, ret,
113                   mCameraMetadata);
114             return -1;
115         }
116 
117         if (!isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)) {
118             ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
119             return 0;
120         }
121 
122         // Create capture session
123         ret = ACaptureSessionOutputContainer_create(&mOutputs);
124         if (ret != AMEDIA_OK) {
125             ALOGE("ACaptureSessionOutputContainer_create failed, ret=%d", ret);
126             return ret;
127         }
128         ret = ACaptureSessionOutput_create(mImgReaderAnw, &mImgReaderOutput);
129         if (ret != AMEDIA_OK) {
130             ALOGE("ACaptureSessionOutput_create failed, ret=%d", ret);
131             return ret;
132         }
133         ret = ACaptureSessionOutputContainer_add(mOutputs, mImgReaderOutput);
134         if (ret != AMEDIA_OK) {
135             ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
136             return ret;
137         }
138         ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
139         if (ret != AMEDIA_OK) {
140             ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
141             return ret;
142         }
143 
144         // Create capture request
145         ret = ACameraDevice_createCaptureRequest(mDevice, TEMPLATE_STILL_CAPTURE, &mStillRequest);
146         if (ret != AMEDIA_OK) {
147             ALOGE("ACameraDevice_createCaptureRequest failed, ret=%d", ret);
148             return ret;
149         }
150         ret = ACameraOutputTarget_create(mImgReaderAnw, &mReqImgReaderOutput);
151         if (ret != AMEDIA_OK) {
152             ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
153             return ret;
154         }
155         ret = ACaptureRequest_addTarget(mStillRequest, mReqImgReaderOutput);
156         if (ret != AMEDIA_OK) {
157             ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
158             return ret;
159         }
160 
161         mIsCameraReady = true;
162         return 0;
163     }
164 
isCapabilitySupported(acamera_metadata_enum_android_request_available_capabilities_t cap)165     bool isCapabilitySupported(acamera_metadata_enum_android_request_available_capabilities_t cap) {
166         ACameraMetadata_const_entry entry;
167         ACameraMetadata_getConstEntry(
168                 mCameraMetadata, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
169         for (uint32_t i = 0; i < entry.count; i++) {
170             if (entry.data.u8[i] == cap) {
171                 return true;
172             }
173         }
174         return false;
175     }
176 
isCameraReady()177     bool isCameraReady() { return mIsCameraReady; }
178 
closeCamera()179     void closeCamera() {
180         // Destroy capture request
181         if (mReqImgReaderOutput) {
182             ACameraOutputTarget_free(mReqImgReaderOutput);
183             mReqImgReaderOutput = nullptr;
184         }
185         if (mStillRequest) {
186             ACaptureRequest_free(mStillRequest);
187             mStillRequest = nullptr;
188         }
189         // Destroy capture session
190         if (mSession != nullptr) {
191             ACameraCaptureSession_close(mSession);
192             mSession = nullptr;
193         }
194         if (mImgReaderOutput) {
195             ACaptureSessionOutput_free(mImgReaderOutput);
196             mImgReaderOutput = nullptr;
197         }
198         if (mOutputs) {
199             ACaptureSessionOutputContainer_free(mOutputs);
200             mOutputs = nullptr;
201         }
202         // Destroy camera device
203         if (mDevice) {
204             ACameraDevice_close(mDevice);
205             mDevice = nullptr;
206         }
207         if (mCameraMetadata) {
208           ACameraMetadata_free(mCameraMetadata);
209           mCameraMetadata = nullptr;
210         }
211         // Destroy camera manager
212         if (mCameraIdList) {
213             ACameraManager_deleteCameraIdList(mCameraIdList);
214             mCameraIdList = nullptr;
215         }
216         if (mCameraManager) {
217             ACameraManager_delete(mCameraManager);
218             mCameraManager = nullptr;
219         }
220         mIsCameraReady = false;
221     }
222 
takePicture()223     int takePicture() {
224         int seqId;
225         return ACameraCaptureSession_capture(mSession, nullptr, 1, &mStillRequest, &seqId);
226     }
227 
onDeviceDisconnected(void *,ACameraDevice *)228     static void onDeviceDisconnected(void* /*obj*/, ACameraDevice* /*device*/) {}
229 
onDeviceError(void *,ACameraDevice *,int)230     static void onDeviceError(void* /*obj*/, ACameraDevice* /*device*/, int /*errorCode*/) {}
231 
onSessionClosed(void *,ACameraCaptureSession *)232     static void onSessionClosed(void* /*obj*/, ACameraCaptureSession* /*session*/) {}
233 
onSessionReady(void *,ACameraCaptureSession *)234     static void onSessionReady(void* /*obj*/, ACameraCaptureSession* /*session*/) {}
235 
onSessionActive(void *,ACameraCaptureSession *)236     static void onSessionActive(void* /*obj*/, ACameraCaptureSession* /*session*/) {}
237 
238    private:
239     ACameraDevice_StateCallbacks mDeviceCb{this, onDeviceDisconnected,
240                                            onDeviceError};
241     ACameraCaptureSession_stateCallbacks mSessionCb{
242         this, onSessionClosed, onSessionReady, onSessionActive};
243 
244     ANativeWindow* mImgReaderAnw = nullptr;  // not owned by us.
245 
246     // Camera manager
247     ACameraManager* mCameraManager = nullptr;
248     ACameraIdList* mCameraIdList = nullptr;
249     // Camera device
250     ACameraMetadata* mCameraMetadata = nullptr;
251     ACameraDevice* mDevice = nullptr;
252     // Capture session
253     ACaptureSessionOutputContainer* mOutputs = nullptr;
254     ACaptureSessionOutput* mImgReaderOutput = nullptr;
255     ACameraCaptureSession* mSession = nullptr;
256     // Capture request
257     ACaptureRequest* mStillRequest = nullptr;
258     ACameraOutputTarget* mReqImgReaderOutput = nullptr;
259 
260     bool mIsCameraReady = false;
261     const char* mCameraId;
262 };
263 
264 class ImageReaderTestCase {
265    public:
ImageReaderTestCase(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,bool async)266     ImageReaderTestCase(int32_t width,
267                         int32_t height,
268                         int32_t format,
269                         uint64_t usage,
270                         int32_t maxImages,
271                         bool async)
272         : mWidth(width),
273           mHeight(height),
274           mFormat(format),
275           mUsage(usage),
276           mMaxImages(maxImages),
277           mAsync(async) {}
278 
~ImageReaderTestCase()279     ~ImageReaderTestCase() {
280         if (mImgReaderAnw) {
281             AImageReader_delete(mImgReader);
282             // No need to call ANativeWindow_release on imageReaderAnw
283         }
284     }
285 
initImageReader()286     int initImageReader() {
287         if (mImgReader != nullptr || mImgReaderAnw != nullptr) {
288             ALOGE("Cannot re-initalize image reader, mImgReader=%p, mImgReaderAnw=%p", mImgReader,
289                   mImgReaderAnw);
290             return -1;
291         }
292 
293         media_status_t ret = AImageReader_newWithUsage(
294                 mWidth, mHeight, mFormat, mUsage, mMaxImages, &mImgReader);
295         if (ret != AMEDIA_OK || mImgReader == nullptr) {
296             ALOGE("Failed to create new AImageReader, ret=%d, mImgReader=%p", ret, mImgReader);
297             return -1;
298         }
299 
300         ret = AImageReader_setImageListener(mImgReader, &mReaderAvailableCb);
301         if (ret != AMEDIA_OK) {
302             ALOGE("Failed to set image available listener, ret=%d.", ret);
303             return ret;
304         }
305 
306         ret = AImageReader_setBufferRemovedListener(mImgReader, &mReaderDetachedCb);
307         if (ret != AMEDIA_OK) {
308             ALOGE("Failed to set buffer detaching listener, ret=%d.", ret);
309             return ret;
310         }
311 
312         ret = AImageReader_getWindow(mImgReader, &mImgReaderAnw);
313         if (ret != AMEDIA_OK || mImgReaderAnw == nullptr) {
314             ALOGE("Failed to get ANativeWindow from AImageReader, ret=%d, mImgReaderAnw=%p.", ret,
315                   mImgReaderAnw);
316             return -1;
317         }
318 
319         return 0;
320     }
321 
getNativeWindow()322     ANativeWindow* getNativeWindow() { return mImgReaderAnw; }
323 
getAcquiredImageCount()324     int getAcquiredImageCount() {
325         std::lock_guard<std::mutex> lock(mMutex);
326         return mAcquiredImageCount;
327     }
328 
HandleImageAvailable(AImageReader * reader)329     void HandleImageAvailable(AImageReader* reader) {
330         std::lock_guard<std::mutex> lock(mMutex);
331 
332         AImage* outImage = nullptr;
333         media_status_t ret;
334 
335         // Make sure AImage will be deleted automatically when it goes out of
336         // scope.
337         auto imageDeleter = [this](AImage* img) {
338             if (mAsync) {
339                 AImage_deleteAsync(img, kDummyFenceFd);
340             } else {
341                 AImage_delete(img);
342             }
343         };
344         std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter);
345 
346         if (mAsync) {
347             int outFenceFd = 0;
348             // Verity that outFenceFd's value will be changed by
349             // AImageReader_acquireNextImageAsync.
350             ret = AImageReader_acquireNextImageAsync(reader, &outImage, &outFenceFd);
351             if (ret != AMEDIA_OK || outImage == nullptr || outFenceFd != kDummyFenceFd) {
352                 ALOGE("Failed to acquire image, ret=%d, outIamge=%p, outFenceFd=%d.", ret, outImage,
353                       outFenceFd);
354                 return;
355             }
356             img.reset(outImage);
357         } else {
358             ret = AImageReader_acquireNextImage(reader, &outImage);
359             if (ret != AMEDIA_OK || outImage == nullptr) {
360                 ALOGE("Failed to acquire image, ret=%d, outIamge=%p.", ret, outImage);
361                 return;
362             }
363             img.reset(outImage);
364         }
365 
366         AHardwareBuffer* outBuffer = nullptr;
367         ret = AImage_getHardwareBuffer(img.get(), &outBuffer);
368         if (ret != AMEDIA_OK || outBuffer == nullptr) {
369             ALOGE("Faild to get hardware buffer, ret=%d, outBuffer=%p.", ret, outBuffer);
370             return;
371         }
372 
373         // No need to release AHardwareBuffer, since we don't acquire additional
374         // reference to it.
375         AHardwareBuffer_Desc outDesc;
376         AHardwareBuffer_describe(outBuffer, &outDesc);
377         int32_t imageWidth = 0;
378         int32_t imageHeight = 0;
379         int32_t bufferWidth = static_cast<int32_t>(outDesc.width);
380         int32_t bufferHeight = static_cast<int32_t>(outDesc.height);
381 
382         AImage_getWidth(outImage, &imageWidth);
383         AImage_getHeight(outImage, &imageHeight);
384         if (imageWidth != mWidth || imageHeight != mHeight) {
385             ALOGE("Mismatched output image dimension: expected=%dx%d, actual=%dx%d", mWidth,
386                   mHeight, imageWidth, imageHeight);
387             return;
388         }
389 
390         if (mFormat == AIMAGE_FORMAT_RGBA_8888 ||
391             mFormat == AIMAGE_FORMAT_RGBX_8888 ||
392             mFormat == AIMAGE_FORMAT_RGB_888 ||
393             mFormat == AIMAGE_FORMAT_RGB_565 ||
394             mFormat == AIMAGE_FORMAT_RGBA_FP16 ||
395             mFormat == AIMAGE_FORMAT_YUV_420_888) {
396             // Check output buffer dimension for certain formats. Don't do this for blob based
397             // formats.
398             if (bufferWidth != mWidth || bufferHeight != mHeight) {
399                 ALOGE("Mismatched output buffer dimension: expected=%dx%d, actual=%dx%d", mWidth,
400                       mHeight, bufferWidth, bufferHeight);
401                 return;
402             }
403         }
404 
405         if ((outDesc.usage & mUsage) != mUsage) {
406             ALOGE("Mismatched output buffer usage: actual (%" PRIu64 "), expected (%" PRIu64 ")",
407                   outDesc.usage, mUsage);
408             return;
409         }
410 
411         uint8_t* data = nullptr;
412         int dataLength = 0;
413         ret = AImage_getPlaneData(img.get(), 0, &data, &dataLength);
414         if (mUsage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN) {
415             // When we have CPU_READ_OFTEN usage bits, we can lock the image.
416             if (ret != AMEDIA_OK || data == nullptr || dataLength < 0) {
417                 ALOGE("Failed to access CPU data, ret=%d, data=%p, dataLength=%d", ret, data,
418                       dataLength);
419                 return;
420             }
421         } else {
422             if (ret != AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE || data != nullptr || dataLength != 0) {
423                 ALOGE("Shouldn't be able to access CPU data, ret=%d, data=%p, dataLength=%d", ret,
424                       data, dataLength);
425                 return;
426             }
427         }
428         // Only increase mAcquiredImageCount if all checks pass.
429         mAcquiredImageCount++;
430     }
431 
onImageAvailable(void * obj,AImageReader * reader)432     static void onImageAvailable(void* obj, AImageReader* reader) {
433         ImageReaderTestCase* thiz = reinterpret_cast<ImageReaderTestCase*>(obj);
434         thiz->HandleImageAvailable(reader);
435     }
436 
437     static void
onBufferRemoved(void *,AImageReader *,AHardwareBuffer *)438     onBufferRemoved(void* /*obj*/, AImageReader* /*reader*/, AHardwareBuffer* /*buffer*/) {
439         // No-op, just to check the listener can be set properly.
440     }
441 
442    private:
443     int32_t mWidth;
444     int32_t mHeight;
445     int32_t mFormat;
446     uint64_t mUsage;
447     int32_t mMaxImages;
448     bool mAsync;
449 
450     std::mutex mMutex;
451     int mAcquiredImageCount{0};
452 
453     AImageReader* mImgReader = nullptr;
454     ANativeWindow* mImgReaderAnw = nullptr;
455 
456     AImageReader_ImageListener mReaderAvailableCb{this, onImageAvailable};
457     AImageReader_BufferRemovedListener mReaderDetachedCb{this, onBufferRemoved};
458 };
459 
takePictures(uint64_t readerUsage,int readerMaxImages,bool readerAsync,int pictureCount)460 int takePictures(uint64_t readerUsage, int readerMaxImages, bool readerAsync, int pictureCount) {
461     int ret = 0;
462 
463     ImageReaderTestCase testCase(
464             kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
465             readerAsync);
466     ret = testCase.initImageReader();
467     if (ret < 0) {
468         return ret;
469     }
470 
471     CameraHelper cameraHelper(testCase.getNativeWindow());
472     ret = cameraHelper.initCamera();
473     if (ret < 0) {
474         return ret;
475     }
476 
477     if (!cameraHelper.isCameraReady()) {
478         ALOGW("Camera is not ready after successful initialization. It's either due to camera on "
479               "board lacks BACKWARDS_COMPATIBLE capability or the device does not have camera on "
480               "board.");
481         return 0;
482     }
483 
484     for (int i = 0; i < pictureCount; i++) {
485         ret = cameraHelper.takePicture();
486         if (ret < 0) {
487             return ret;
488         }
489     }
490 
491     // Sleep until all capture finished
492     for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
493         usleep(kCaptureWaitUs);
494         if (testCase.getAcquiredImageCount() == pictureCount) {
495             ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
496                   pictureCount);
497             break;
498         }
499     }
500 
501     return testCase.getAcquiredImageCount() == pictureCount ? 0 : -1;
502 }
503 
504 }  // namespace
505 
506 // Test that newWithUsage can create AImageReader correctly.
Java_android_media_cts_NativeImageReaderTest_testSucceedsWithSupportedUsageFormatNative(JNIEnv *,jclass)507 extern "C" jboolean Java_android_media_cts_NativeImageReaderTest_\
508 testSucceedsWithSupportedUsageFormatNative(JNIEnv* /*env*/, jclass /*clazz*/) {
509     static constexpr int kTestImageCount = 8;
510 
511     for (auto& combination : supportedFormatUsage) {
512         AImageReader* outReader;
513         media_status_t ret = AImageReader_newWithUsage(
514                 kTestImageWidth, kTestImageHeight, combination.format, combination.usage,
515                 kTestImageCount, &outReader);
516         if (ret != AMEDIA_OK || outReader == nullptr) {
517             ALOGE("AImageReader_newWithUsage failed with format: %" PRId64 ", usage: %" PRId64 ".",
518                   combination.format, combination.usage);
519             return false;
520         }
521         AImageReader_delete(outReader);
522     }
523 
524     return true;
525 }
526 
Java_android_media_cts_NativeImageReaderTest_testTakePicturesNative(JNIEnv *,jclass)527 extern "C" jboolean Java_android_media_cts_NativeImageReaderTest_\
528 testTakePicturesNative(JNIEnv* /*env*/, jclass /*clazz*/) {
529     for (auto& readerUsage :
530          {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
531         for (auto& readerMaxImages : {1, 4, 8}) {
532             for (auto& readerAsync : {true, false}) {
533                 for (auto& pictureCount : {1, 8, 16}) {
534                     if (takePictures(readerUsage, readerMaxImages, readerAsync, pictureCount)) {
535                         ALOGE("Test takePictures failed for test case usage=%" PRIu64 ", maxImages=%d, "
536                               "async=%d, pictureCount=%d",
537                               readerUsage, readerMaxImages, readerAsync, pictureCount);
538                         return false;
539                     }
540                 }
541             }
542         }
543     }
544     return true;
545 }
546 
Java_android_media_cts_NativeImageReaderTest_testCreateSurfaceNative(JNIEnv * env,jclass)547 extern "C" jobject Java_android_media_cts_NativeImageReaderTest_\
548 testCreateSurfaceNative(JNIEnv* env, jclass /*clazz*/) {
549     static constexpr uint64_t kTestImageUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
550     static constexpr int kTestImageCount = 8;
551 
552     ImageReaderTestCase testCase(
553             kTestImageWidth, kTestImageHeight, kTestImageFormat, kTestImageUsage, kTestImageCount,
554             false);
555     int ret = testCase.initImageReader();
556     if (ret < 0) {
557         ALOGE("Failed to get initialize image reader: ret=%d.", ret);
558         return nullptr;
559     }
560 
561     // No need to release the window as AImageReader_delete takes care of it.
562     ANativeWindow* window = testCase.getNativeWindow();
563     if (window == nullptr) {
564         ALOGE("Failed to get native window for the test case.");
565         return nullptr;
566     }
567 
568     return ANativeWindow_toSurface(env, window);
569 }
570