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