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