1 /*
2 * Copyright (C) 2018 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 "AImageReaderVendorTest"
18 //#define LOG_NDEBUG 0
19
20 #include <stdint.h>
21 #include <unistd.h>
22 #include <gtest/gtest.h>
23
24 #include <algorithm>
25 #include <mutex>
26 #include <string>
27 #include <variant>
28 #include <vector>
29 #include <stdio.h>
30 #include <stdio.h>
31 #include <stdio.h>
32
33 #include <android/log.h>
34 #include <camera/NdkCameraError.h>
35 #include <camera/NdkCameraManager.h>
36 #include <camera/NdkCameraDevice.h>
37 #include <camera/NdkCameraCaptureSession.h>
38 #include <media/NdkImage.h>
39 #include <media/NdkImageReader.h>
40 #include <cutils/native_handle.h>
41 #include <VendorTagDescriptor.h>
42
43 namespace {
44
45 static constexpr int kDummyFenceFd = -1;
46 static constexpr int kCaptureWaitUs = 100 * 1000;
47 static constexpr int kCaptureWaitRetry = 10;
48 static constexpr int kTestImageWidth = 640;
49 static constexpr int kTestImageHeight = 480;
50 static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
51
52 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
53 using ConfiguredWindows = std::set<native_handle_t *>;
54
55 class CameraHelper {
56 public:
CameraHelper(const char * id,ACameraManager * manager)57 CameraHelper(const char* id, ACameraManager *manager) :
58 mImgReaderAnw(nullptr), mCameraId(id), mCameraManager(manager) {}
~CameraHelper()59 ~CameraHelper() { closeCamera(); }
60
61 struct PhysicalImgReaderInfo {
62 const char* physicalCameraId;
63 native_handle_t* anw;
64 };
65
66 // Retaining the error code in case the caller needs to analyze it.
initCamera(native_handle_t * imgReaderAnw,const std::vector<PhysicalImgReaderInfo> & physicalImgReaders,bool usePhysicalSettings)67 std::variant<int, ConfiguredWindows> initCamera(native_handle_t* imgReaderAnw,
68 const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
69 bool usePhysicalSettings) {
70 ConfiguredWindows configuredWindows;
71 if (imgReaderAnw == nullptr) {
72 ALOGE("Cannot initialize camera before image reader get initialized.");
73 return -1;
74 }
75 if (mIsCameraReady) {
76 ALOGE("initCamera should only be called once.");
77 return -1;
78 }
79
80 int ret;
81 mImgReaderAnw = imgReaderAnw;
82
83 ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
84 if (ret != AMEDIA_OK || mDevice == nullptr) {
85 ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice);
86 return ret;
87 }
88
89 // Create capture session
90 ret = ACaptureSessionOutputContainer_create(&mOutputs);
91 if (ret != AMEDIA_OK) {
92 ALOGE("ACaptureSessionOutputContainer_create failed, ret=%d", ret);
93 return ret;
94 }
95 ret = ACaptureSessionOutput_create(mImgReaderAnw, &mImgReaderOutput);
96 if (ret != AMEDIA_OK) {
97 ALOGE("ACaptureSessionOutput_create failed, ret=%d", ret);
98 return ret;
99 }
100 ret = ACaptureSessionOutputContainer_add(mOutputs, mImgReaderOutput);
101 if (ret != AMEDIA_OK) {
102 ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
103 return ret;
104 }
105 configuredWindows.insert(mImgReaderAnw);
106 std::vector<const char*> idPointerList;
107 std::set<const native_handle_t*> physicalStreamMap;
108 for (auto& physicalStream : physicalImgReaders) {
109 ACaptureSessionOutput* sessionOutput = nullptr;
110 ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
111 physicalStream.physicalCameraId, &sessionOutput);
112 if (ret != ACAMERA_OK) {
113 ALOGE("ACaptureSessionPhysicalOutput_create failed, ret=%d", ret);
114 return ret;
115 }
116 ret = ACaptureSessionOutputContainer_add(mOutputs, sessionOutput);
117 if (ret != AMEDIA_OK) {
118 ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
119 return ret;
120 }
121 ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
122 if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
123 ALOGW("ACameraDevice_isSessionConfigurationSupported failed, ret=%d camera id %s",
124 ret, mCameraId);
125 ACaptureSessionOutputContainer_remove(mOutputs, sessionOutput);
126 ACaptureSessionOutput_free(sessionOutput);
127 continue;
128 }
129 configuredWindows.insert(physicalStream.anw);
130 // Assume that at most one physical stream per physical camera.
131 mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
132 idPointerList.push_back(physicalStream.physicalCameraId);
133 physicalStreamMap.insert(physicalStream.anw);
134 mSessionPhysicalOutputs.push_back(sessionOutput);
135 }
136 ACameraIdList cameraIdList;
137 cameraIdList.numCameras = idPointerList.size();
138 cameraIdList.cameraIds = idPointerList.data();
139
140 ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
141 if (ret != AMEDIA_OK) {
142 ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
143 return ret;
144 }
145
146 // Create capture request
147 if (usePhysicalSettings) {
148 ret = ACameraDevice_createCaptureRequest_withPhysicalIds(mDevice,
149 TEMPLATE_STILL_CAPTURE, &cameraIdList, &mStillRequest);
150 } else {
151 ret = ACameraDevice_createCaptureRequest(mDevice,
152 TEMPLATE_STILL_CAPTURE, &mStillRequest);
153 }
154 if (ret != AMEDIA_OK) {
155 ALOGE("ACameraDevice_createCaptureRequest failed, ret=%d", ret);
156 return ret;
157 }
158 ret = ACameraOutputTarget_create(mImgReaderAnw, &mReqImgReaderOutput);
159 if (ret != AMEDIA_OK) {
160 ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
161 return ret;
162 }
163 ret = ACaptureRequest_addTarget(mStillRequest, mReqImgReaderOutput);
164 if (ret != AMEDIA_OK) {
165 ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
166 return ret;
167 }
168
169 for (auto& physicalStream : physicalImgReaders) {
170 if (physicalStreamMap.find(physicalStream.anw) == physicalStreamMap.end()) {
171 ALOGI("Skipping physicalStream anw=%p", physicalStream.anw);
172 continue;
173 }
174 ACameraOutputTarget* outputTarget = nullptr;
175 ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
176 if (ret != AMEDIA_OK) {
177 ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
178 return ret;
179 }
180 ret = ACaptureRequest_addTarget(mStillRequest, outputTarget);
181 if (ret != AMEDIA_OK) {
182 ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
183 return ret;
184 }
185 mReqPhysicalOutputs.push_back(outputTarget);
186 }
187
188 mIsCameraReady = true;
189 return configuredWindows;
190 }
191
192
isCameraReady()193 bool isCameraReady() { return mIsCameraReady; }
194
closeCamera()195 void closeCamera() {
196 // Destroy capture request
197 if (mReqImgReaderOutput) {
198 ACameraOutputTarget_free(mReqImgReaderOutput);
199 mReqImgReaderOutput = nullptr;
200 }
201 for (auto& outputTarget : mReqPhysicalOutputs) {
202 ACameraOutputTarget_free(outputTarget);
203 }
204 mReqPhysicalOutputs.clear();
205 if (mStillRequest) {
206 ACaptureRequest_free(mStillRequest);
207 mStillRequest = nullptr;
208 }
209 // Destroy capture session
210 if (mSession != nullptr) {
211 ACameraCaptureSession_close(mSession);
212 mSession = nullptr;
213 }
214 if (mImgReaderOutput) {
215 ACaptureSessionOutput_free(mImgReaderOutput);
216 mImgReaderOutput = nullptr;
217 }
218 for (auto& extraOutput : mSessionPhysicalOutputs) {
219 ACaptureSessionOutput_free(extraOutput);
220 }
221 mSessionPhysicalOutputs.clear();
222 if (mOutputs) {
223 ACaptureSessionOutputContainer_free(mOutputs);
224 mOutputs = nullptr;
225 }
226 // Destroy camera device
227 if (mDevice) {
228 ACameraDevice_close(mDevice);
229 mDevice = nullptr;
230 }
231 mIsCameraReady = false;
232 }
233
takePicture()234 int takePicture() {
235 int seqId;
236 return ACameraCaptureSession_capture(mSession, &mCaptureCallbacks, 1, &mStillRequest,
237 &seqId);
238 }
239
takeLogicalCameraPicture()240 int takeLogicalCameraPicture() {
241 int seqId;
242 return ACameraCaptureSession_logicalCamera_capture(mSession, &mLogicalCaptureCallbacks,
243 1, &mStillRequest, &seqId);
244 }
245
checkCallbacks(int pictureCount)246 bool checkCallbacks(int pictureCount) {
247 std::lock_guard<std::mutex> lock(mMutex);
248 if (mCompletedCaptureCallbackCount != pictureCount) {
249 ALOGE("Completed capture callaback count not as expected. expected %d actual %d",
250 pictureCount, mCompletedCaptureCallbackCount);
251 return false;
252 }
253 return true;
254 }
255
256 private:
257 ACameraDevice_StateCallbacks mDeviceCb{this, nullptr, nullptr};
258 ACameraCaptureSession_stateCallbacks mSessionCb{ this, nullptr, nullptr, nullptr};
259
260 native_handle_t* mImgReaderAnw = nullptr; // not owned by us.
261
262 // Camera device
263 ACameraDevice* mDevice = nullptr;
264 // Capture session
265 ACaptureSessionOutputContainer* mOutputs = nullptr;
266 ACaptureSessionOutput* mImgReaderOutput = nullptr;
267 std::vector<ACaptureSessionOutput*> mSessionPhysicalOutputs;
268
269 ACameraCaptureSession* mSession = nullptr;
270 // Capture request
271 ACaptureRequest* mStillRequest = nullptr;
272 ACameraOutputTarget* mReqImgReaderOutput = nullptr;
273 std::vector<ACameraOutputTarget*> mReqPhysicalOutputs;
274
275 bool mIsCameraReady = false;
276 const char* mCameraId;
277 ACameraManager* mCameraManager;
278 int mCompletedCaptureCallbackCount = 0;
279 std::mutex mMutex;
280 ACameraCaptureSession_captureCallbacks mCaptureCallbacks = {
281 // TODO: Add tests for other callbacks
282 this, // context
283 nullptr, // onCaptureStarted
284 nullptr, // onCaptureProgressed
285 [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
__anon511359ea0202() 286 const ACameraMetadata *) {
287 CameraHelper *ch = static_cast<CameraHelper *>(ctx);
288 std::lock_guard<std::mutex> lock(ch->mMutex);
289 ch->mCompletedCaptureCallbackCount++;
290 },
291 nullptr, // onCaptureFailed
292 nullptr, // onCaptureSequenceCompleted
293 nullptr, // onCaptureSequenceAborted
294 nullptr, // onCaptureBufferLost
295 };
296
297 std::vector<std::string> mPhysicalCameraIds;
298 ACameraCaptureSession_logicalCamera_captureCallbacks mLogicalCaptureCallbacks = {
299 // TODO: Add tests for other callbacks
300 this, // context
301 nullptr, // onCaptureStarted
302 nullptr, // onCaptureProgressed
303 [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
304 const ACameraMetadata *, size_t physicalResultCount,
__anon511359ea0302() 305 const char** physicalCameraIds, const ACameraMetadata** physicalResults) {
306 CameraHelper *ch = static_cast<CameraHelper *>(ctx);
307 std::lock_guard<std::mutex> lock(ch->mMutex);
308 ASSERT_EQ(physicalResultCount, ch->mPhysicalCameraIds.size());
309 for (size_t i = 0; i < physicalResultCount; i++) {
310 ASSERT_TRUE(physicalCameraIds[i] != nullptr);
311 ASSERT_TRUE(physicalResults[i] != nullptr);
312 ASSERT_NE(std::find(ch->mPhysicalCameraIds.begin(),
313 ch->mPhysicalCameraIds.end(), physicalCameraIds[i]),
314 ch->mPhysicalCameraIds.end());
315
316 // Verify frameNumber and sensorTimestamp exist in physical
317 // result metadata
318 ACameraMetadata_const_entry entry;
319 ACameraMetadata_getConstEntry(
320 physicalResults[i], ACAMERA_SYNC_FRAME_NUMBER, &entry);
321 ASSERT_EQ(entry.count, 1);
322 ACameraMetadata_getConstEntry(
323 physicalResults[i], ACAMERA_SENSOR_TIMESTAMP, &entry);
324 ASSERT_EQ(entry.count, 1);
325 }
326 ch->mCompletedCaptureCallbackCount++;
327 },
328 [] (void * /*ctx*/, ACameraCaptureSession* /*session*/, ACaptureRequest* /*request*/,
__anon511359ea0402() 329 ALogicalCameraCaptureFailure* failure) {
330 if (failure->physicalCameraId) {
331 ALOGD("%s: Physical camera id: %s result failure", __FUNCTION__,
332 failure->physicalCameraId);
333 }
334 },
335 nullptr, // onCaptureSequenceCompleted
336 nullptr, // onCaptureSequenceAborted
337 nullptr, // onCaptureBufferLost
338 };
339 };
340
341 class ImageReaderTestCase {
342 public:
ImageReaderTestCase(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,bool async)343 ImageReaderTestCase(int32_t width,
344 int32_t height,
345 int32_t format,
346 uint64_t usage,
347 int32_t maxImages,
348 bool async)
349 : mWidth(width),
350 mHeight(height),
351 mFormat(format),
352 mUsage(usage),
353 mMaxImages(maxImages),
354 mAsync(async) {}
355
~ImageReaderTestCase()356 ~ImageReaderTestCase() {
357 if (mImgReaderAnw) {
358 AImageReader_delete(mImgReader);
359 // No need to call native_handle_t_release on imageReaderAnw
360 }
361 }
362
initImageReader()363 int initImageReader() {
364 if (mImgReader != nullptr || mImgReaderAnw != nullptr) {
365 ALOGE("Cannot re-initalize image reader, mImgReader=%p, mImgReaderAnw=%p", mImgReader,
366 mImgReaderAnw);
367 return -1;
368 }
369
370 media_status_t ret = AImageReader_newWithUsage(
371 mWidth, mHeight, mFormat, mUsage, mMaxImages, &mImgReader);
372 if (ret != AMEDIA_OK || mImgReader == nullptr) {
373 ALOGE("Failed to create new AImageReader, ret=%d, mImgReader=%p", ret, mImgReader);
374 return -1;
375 }
376
377 ret = AImageReader_setImageListener(mImgReader, &mReaderAvailableCb);
378 if (ret != AMEDIA_OK) {
379 ALOGE("Failed to set image available listener, ret=%d.", ret);
380 return ret;
381 }
382
383 ret = AImageReader_setBufferRemovedListener(mImgReader, &mReaderDetachedCb);
384 if (ret != AMEDIA_OK) {
385 ALOGE("Failed to set buffer detaching listener, ret=%d.", ret);
386 return ret;
387 }
388
389 ret = AImageReader_getWindowNativeHandle(mImgReader, &mImgReaderAnw);
390 if (ret != AMEDIA_OK || mImgReaderAnw == nullptr) {
391 ALOGE("Failed to get native_handle_t from AImageReader, ret=%d, mImgReaderAnw=%p.", ret,
392 mImgReaderAnw);
393 return -1;
394 }
395
396 return 0;
397 }
398
getNativeWindow()399 native_handle_t* getNativeWindow() { return mImgReaderAnw; }
400
getAcquiredImageCount()401 int getAcquiredImageCount() {
402 std::lock_guard<std::mutex> lock(mMutex);
403 return mAcquiredImageCount;
404 }
405
HandleImageAvailable(AImageReader * reader)406 void HandleImageAvailable(AImageReader* reader) {
407 std::lock_guard<std::mutex> lock(mMutex);
408
409 AImage* outImage = nullptr;
410 media_status_t ret;
411
412 // Make sure AImage will be deleted automatically when it goes out of
413 // scope.
414 auto imageDeleter = [this](AImage* img) {
415 if (mAsync) {
416 AImage_deleteAsync(img, kDummyFenceFd);
417 } else {
418 AImage_delete(img);
419 }
420 };
421 std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter);
422
423 if (mAsync) {
424 int outFenceFd = 0;
425 // Verity that outFenceFd's value will be changed by
426 // AImageReader_acquireNextImageAsync.
427 ret = AImageReader_acquireNextImageAsync(reader, &outImage, &outFenceFd);
428 if (ret != AMEDIA_OK || outImage == nullptr || outFenceFd == 0) {
429 ALOGE("Failed to acquire image, ret=%d, outIamge=%p, outFenceFd=%d.", ret, outImage,
430 outFenceFd);
431 return;
432 }
433 img.reset(outImage);
434 } else {
435 ret = AImageReader_acquireNextImage(reader, &outImage);
436 if (ret != AMEDIA_OK || outImage == nullptr) {
437 ALOGE("Failed to acquire image, ret=%d, outIamge=%p.", ret, outImage);
438 return;
439 }
440 img.reset(outImage);
441 }
442
443 AHardwareBuffer* outBuffer = nullptr;
444 ret = AImage_getHardwareBuffer(img.get(), &outBuffer);
445 if (ret != AMEDIA_OK || outBuffer == nullptr) {
446 ALOGE("Faild to get hardware buffer, ret=%d, outBuffer=%p.", ret, outBuffer);
447 return;
448 }
449
450 // No need to release AHardwareBuffer, since we don't acquire additional
451 // reference to it.
452 AHardwareBuffer_Desc outDesc;
453 AHardwareBuffer_describe(outBuffer, &outDesc);
454 int32_t imageWidth = 0;
455 int32_t imageHeight = 0;
456 int32_t bufferWidth = static_cast<int32_t>(outDesc.width);
457 int32_t bufferHeight = static_cast<int32_t>(outDesc.height);
458
459 AImage_getWidth(outImage, &imageWidth);
460 AImage_getHeight(outImage, &imageHeight);
461 if (imageWidth != mWidth || imageHeight != mHeight) {
462 ALOGE("Mismatched output image dimension: expected=%dx%d, actual=%dx%d", mWidth,
463 mHeight, imageWidth, imageHeight);
464 return;
465 }
466
467 if (mFormat == AIMAGE_FORMAT_RGBA_8888 ||
468 mFormat == AIMAGE_FORMAT_RGBX_8888 ||
469 mFormat == AIMAGE_FORMAT_RGB_888 ||
470 mFormat == AIMAGE_FORMAT_RGB_565 ||
471 mFormat == AIMAGE_FORMAT_RGBA_FP16 ||
472 mFormat == AIMAGE_FORMAT_YUV_420_888 ||
473 mFormat == AIMAGE_FORMAT_Y8) {
474 // Check output buffer dimension for certain formats. Don't do this for blob based
475 // formats.
476 if (bufferWidth != mWidth || bufferHeight != mHeight) {
477 ALOGE("Mismatched output buffer dimension: expected=%dx%d, actual=%dx%d", mWidth,
478 mHeight, bufferWidth, bufferHeight);
479 return;
480 }
481 }
482
483 if ((outDesc.usage & mUsage) != mUsage) {
484 ALOGE("Mismatched output buffer usage: actual (%" PRIu64 "), expected (%" PRIu64 ")",
485 outDesc.usage, mUsage);
486 return;
487 }
488
489 uint8_t* data = nullptr;
490 int dataLength = 0;
491 ret = AImage_getPlaneData(img.get(), 0, &data, &dataLength);
492 if (mUsage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN) {
493 // When we have CPU_READ_OFTEN usage bits, we can lock the image.
494 if (ret != AMEDIA_OK || data == nullptr || dataLength < 0) {
495 ALOGE("Failed to access CPU data, ret=%d, data=%p, dataLength=%d", ret, data,
496 dataLength);
497 return;
498 }
499 } else {
500 if (ret != AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE || data != nullptr || dataLength != 0) {
501 ALOGE("Shouldn't be able to access CPU data, ret=%d, data=%p, dataLength=%d", ret,
502 data, dataLength);
503 return;
504 }
505 }
506 // Only increase mAcquiredImageCount if all checks pass.
507 mAcquiredImageCount++;
508 }
509
onImageAvailable(void * obj,AImageReader * reader)510 static void onImageAvailable(void* obj, AImageReader* reader) {
511 ImageReaderTestCase* thiz = reinterpret_cast<ImageReaderTestCase*>(obj);
512 thiz->HandleImageAvailable(reader);
513 }
514
515 static void
onBufferRemoved(void *,AImageReader *,AHardwareBuffer *)516 onBufferRemoved(void* /*obj*/, AImageReader* /*reader*/, AHardwareBuffer* /*buffer*/) {
517 // No-op, just to check the listener can be set properly.
518 }
519
520 private:
521 int32_t mWidth;
522 int32_t mHeight;
523 int32_t mFormat;
524 uint64_t mUsage;
525 int32_t mMaxImages;
526 bool mAsync;
527
528 std::mutex mMutex;
529 int mAcquiredImageCount{0};
530
531 AImageReader* mImgReader = nullptr;
532 native_handle_t* mImgReaderAnw = nullptr;
533
534 AImageReader_ImageListener mReaderAvailableCb{this, onImageAvailable};
535 AImageReader_BufferRemovedListener mReaderDetachedCb{this, onBufferRemoved};
536 };
537
538
539 class AImageReaderVendorTest : public ::testing::Test {
540 public:
SetUp()541 void SetUp() override {
542 mCameraManager = ACameraManager_create();
543 if (mCameraManager == nullptr) {
544 ALOGE("Failed to create ACameraManager.");
545 return;
546 }
547
548 camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
549 if (ret != ACAMERA_OK) {
550 ALOGE("Failed to get cameraIdList: ret=%d", ret);
551 return;
552 }
553 // TODO: Add more rigorous tests for vendor tags
554 ASSERT_NE(VendorTagDescriptorCache::getGlobalVendorTagCache(), nullptr);
555 if (mCameraIdList->numCameras < 1) {
556 ALOGW("Device has no camera on board.");
557 return;
558 }
559 }
TearDown()560 void TearDown() override {
561 // Destroy camera manager
562 if (mCameraIdList) {
563 ACameraManager_deleteCameraIdList(mCameraIdList);
564 mCameraIdList = nullptr;
565 }
566 if (mCameraManager) {
567 ACameraManager_delete(mCameraManager);
568 mCameraManager = nullptr;
569 }
570 }
571
takePictures(const char * id,uint64_t readerUsage,int readerMaxImages,bool readerAsync,int pictureCount)572 bool takePictures(const char* id, uint64_t readerUsage, int readerMaxImages,
573 bool readerAsync, int pictureCount) {
574 int ret = 0;
575
576 ImageReaderTestCase testCase(
577 kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
578 readerAsync);
579 ret = testCase.initImageReader();
580 if (ret < 0) {
581 ALOGE("Unable to initialize ImageReader");
582 return false;
583 }
584
585 CameraHelper cameraHelper(id, mCameraManager);
586 std::variant<int, ConfiguredWindows> retInit =
587 cameraHelper.initCamera(testCase.getNativeWindow(), {}/*physicalImageReaders*/,
588 false/*usePhysicalSettings*/);
589 int *retp = std::get_if<int>(&retInit);
590 if (retp) {
591 ALOGE("Unable to initialize camera helper");
592 return false;
593 }
594
595 if (!cameraHelper.isCameraReady()) {
596 ALOGW("Camera is not ready after successful initialization. It's either due to camera "
597 "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
598 "camera on board.");
599 return true;
600 }
601
602 for (int i = 0; i < pictureCount; i++) {
603 ret = cameraHelper.takePicture();
604 if (ret < 0) {
605 ALOGE("Unable to take picture");
606 return false;
607 }
608 }
609
610 // Sleep until all capture finished
611 for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
612 usleep(kCaptureWaitUs);
613 if (testCase.getAcquiredImageCount() == pictureCount) {
614 ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
615 pictureCount);
616 break;
617 }
618 }
619 return testCase.getAcquiredImageCount() == pictureCount &&
620 cameraHelper.checkCallbacks(pictureCount);
621 }
622
testTakePicturesNative(const char * id)623 bool testTakePicturesNative(const char* id) {
624 for (auto& readerUsage :
625 {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
626 for (auto& readerMaxImages : {1, 4, 8}) {
627 for (auto& readerAsync : {true, false}) {
628 for (auto& pictureCount : {1, 4, 8}) {
629 if (!takePictures(id, readerUsage, readerMaxImages,
630 readerAsync, pictureCount)) {
631 ALOGE("Test takePictures failed for test case usage=%" PRIu64
632 ", maxImages=%d, async=%d, pictureCount=%d",
633 readerUsage, readerMaxImages, readerAsync, pictureCount);
634 return false;
635 }
636 }
637 }
638 }
639 }
640 return true;
641 }
642
643 // Camera manager
644 ACameraManager* mCameraManager = nullptr;
645 ACameraIdList* mCameraIdList = nullptr;
646
isCapabilitySupported(ACameraMetadata * staticInfo,acamera_metadata_enum_android_request_available_capabilities_t cap)647 bool isCapabilitySupported(ACameraMetadata* staticInfo,
648 acamera_metadata_enum_android_request_available_capabilities_t cap) {
649 ACameraMetadata_const_entry entry;
650 ACameraMetadata_getConstEntry(
651 staticInfo, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
652 for (uint32_t i = 0; i < entry.count; i++) {
653 if (entry.data.u8[i] == cap) {
654 return true;
655 }
656 }
657 return false;
658 }
659
isSizeSupportedForFormat(ACameraMetadata * staticInfo,int32_t format,int32_t width,int32_t height)660 bool isSizeSupportedForFormat(ACameraMetadata* staticInfo,
661 int32_t format, int32_t width, int32_t height) {
662 ACameraMetadata_const_entry entry;
663 ACameraMetadata_getConstEntry(staticInfo,
664 ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
665 for (uint32_t i = 0; i < entry.count; i += 4) {
666 if (entry.data.i32[i] == format &&
667 entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
668 entry.data.i32[i+1] == width &&
669 entry.data.i32[i+2] == height) {
670 return true;
671 }
672 }
673 return false;
674 }
675
findCandidateLogicalCamera(const char ** cameraId,ACameraMetadata ** staticMetadata,std::vector<const char * > * candidatePhysicalIds)676 void findCandidateLogicalCamera(const char **cameraId,
677 ACameraMetadata** staticMetadata,
678 std::vector<const char*>* candidatePhysicalIds) {
679 // Find first available logical camera
680 for (int i = 0; i < mCameraIdList->numCameras; i++) {
681 camera_status_t ret;
682 ret = ACameraManager_getCameraCharacteristics(
683 mCameraManager, mCameraIdList->cameraIds[i], staticMetadata);
684 ASSERT_EQ(ret, ACAMERA_OK);
685 ASSERT_NE(*staticMetadata, nullptr);
686
687 if (!isCapabilitySupported(*staticMetadata,
688 ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)) {
689 ACameraMetadata_free(*staticMetadata);
690 *staticMetadata = nullptr;
691 continue;
692 }
693
694 // Check returned physical camera Ids are valid
695 size_t physicalCameraIdCnt = 0;
696 const char*const* physicalCameraIds = nullptr;
697 bool isLogicalCamera = ACameraMetadata_isLogicalMultiCamera(*staticMetadata,
698 &physicalCameraIdCnt, &physicalCameraIds);
699 ASSERT_TRUE(isLogicalCamera);
700 ASSERT_GE(physicalCameraIdCnt, 2);
701 ACameraMetadata* physicalCameraMetadata = nullptr;
702 candidatePhysicalIds->clear();
703 for (size_t j = 0; j < physicalCameraIdCnt && candidatePhysicalIds->size() < 2; j++) {
704 ASSERT_GT(strlen(physicalCameraIds[j]), 0);
705 ret = ACameraManager_getCameraCharacteristics(
706 mCameraManager, physicalCameraIds[j], &physicalCameraMetadata);
707 ASSERT_EQ(ret, ACAMERA_OK);
708 ASSERT_NE(physicalCameraMetadata, nullptr);
709
710 if (isSizeSupportedForFormat(physicalCameraMetadata, kTestImageFormat,
711 kTestImageWidth, kTestImageHeight)) {
712 candidatePhysicalIds->push_back(physicalCameraIds[j]);
713 }
714 ACameraMetadata_free(physicalCameraMetadata);
715 }
716 if (candidatePhysicalIds->size() == 2) {
717 *cameraId = mCameraIdList->cameraIds[i];
718 return;
719 } else {
720 ACameraMetadata_free(*staticMetadata);
721 *staticMetadata = nullptr;
722 }
723 }
724 *cameraId = nullptr;
725 return;
726 }
727
testLogicalCameraPhysicalStream(bool usePhysicalSettings)728 void testLogicalCameraPhysicalStream(bool usePhysicalSettings) {
729 const char* cameraId = nullptr;
730 ACameraMetadata* staticMetadata = nullptr;
731 std::vector<const char*> physicalCameraIds;
732
733 findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
734 if (cameraId == nullptr) {
735 // Couldn't find logical camera to test
736 return;
737 }
738
739 // Test streaming the logical multi-camera
740 uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
741 int32_t readerMaxImages = 8;
742 bool readerAsync = false;
743 const int pictureCount = 6;
744 std::vector<ImageReaderTestCase*> testCases;
745 for (size_t i = 0; i < 3; i++) {
746 ImageReaderTestCase* testCase = new ImageReaderTestCase(
747 kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage,
748 readerMaxImages, readerAsync);
749 ASSERT_EQ(testCase->initImageReader(), 0);
750 testCases.push_back(testCase);
751 }
752
753 CameraHelper cameraHelper(cameraId, mCameraManager);
754 std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
755 physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
756 physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
757
758 std::variant<int, ConfiguredWindows> retInit =
759 cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo,
760 usePhysicalSettings);
761 int *retp = std::get_if<int>(&retInit);
762 ASSERT_EQ(retp, nullptr);
763 ConfiguredWindows *configuredWindowsp = std::get_if<ConfiguredWindows>(&retInit);
764 ASSERT_NE(configuredWindowsp, nullptr);
765 ASSERT_LE(configuredWindowsp->size(), testCases.size());
766 int ret = 0;
767 if (!cameraHelper.isCameraReady()) {
768 ALOGW("Camera is not ready after successful initialization. It's either due to camera "
769 "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
770 "camera on board.");
771 return;
772 }
773
774 for (int i = 0; i < pictureCount; i++) {
775 ret = cameraHelper.takeLogicalCameraPicture();
776 ASSERT_EQ(ret, 0);
777 }
778
779 // Sleep until all capture finished
780 for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
781 usleep(kCaptureWaitUs);
782 if (testCases[0]->getAcquiredImageCount() == pictureCount) {
783 ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
784 pictureCount);
785 break;
786 }
787 }
788 for(auto &testCase : testCases) {
789 auto it = configuredWindowsp->find(testCase->getNativeWindow());
790 if (it == configuredWindowsp->end()) {
791 continue;
792 }
793 ALOGI("Testing window %p", testCase->getNativeWindow());
794 ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
795 }
796
797 ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
798
799 ACameraMetadata_free(staticMetadata);
800 }
801 };
802
TEST_F(AImageReaderVendorTest,CreateWindowNativeHandle)803 TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) {
804 // We always use the first camera.
805 const char* cameraId = mCameraIdList->cameraIds[0];
806 ASSERT_TRUE(cameraId != nullptr);
807
808 ACameraMetadata* staticMetadata = nullptr;
809 camera_status_t ret = ACameraManager_getCameraCharacteristics(
810 mCameraManager, cameraId, &staticMetadata);
811 ASSERT_EQ(ret, ACAMERA_OK);
812 ASSERT_NE(staticMetadata, nullptr);
813
814 bool isBC = isCapabilitySupported(staticMetadata,
815 ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
816
817 uint32_t namedTag = 0;
818 // Test that ACameraMetadata_getTagFromName works as expected for public tag
819 // names
820 camera_status_t status = ACameraManager_getTagFromName(mCameraManager, cameraId,
821 "android.control.aeMode", &namedTag);
822
823 ASSERT_EQ(status, ACAMERA_OK);
824 ASSERT_EQ(namedTag, ACAMERA_CONTROL_AE_MODE);
825
826 ACameraMetadata_free(staticMetadata);
827
828 if (!isBC) {
829 ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
830 return;
831 }
832
833 EXPECT_TRUE(testTakePicturesNative(cameraId));
834 }
835
TEST_F(AImageReaderVendorTest,LogicalCameraPhysicalStream)836 TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
837 testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/);
838 testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/);
839 }
840
841 } // namespace
842