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 <hidl/ServiceManagement.h>
39 #include <media/NdkImage.h>
40 #include <media/NdkImageReader.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<ANativeWindow*>;
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 ANativeWindow* anw;
64 };
65
66 // Retaining the error code in case the caller needs to analyze it.
initCamera(ANativeWindow * imgReaderAnw,const std::vector<PhysicalImgReaderInfo> & physicalImgReaders,bool usePhysicalSettings,bool prepareWindows=false)67 std::variant<int, ConfiguredWindows> initCamera(ANativeWindow* imgReaderAnw,
68 const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
69 bool usePhysicalSettings, bool prepareWindows = false) {
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<ANativeWindow*> 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 if (prepareWindows) {
146 // Set window prepared callback
147 ACameraCaptureSession_setWindowPreparedCallback(mSession, /*context*/this,
148 mPreparedCb);
149 // Prepare windows
150 for (auto &window : configuredWindows) {
151 ret = ACameraCaptureSession_prepareWindow(mSession, window);
152 if (ret != ACAMERA_OK) {
153 ALOGE("%s: ACameraCaptureSession_prepareWindow failed", __FUNCTION__);
154 return ret;
155 }
156 incPendingPrepared(window);
157 }
158 // Some time for the on-PreparedCallbacks
159 usleep(configuredWindows.size() * 100000);
160 // Check that callbacks were received
161 if (!gotAllPreparedCallbacks()) {
162 return -1;
163 }
164 }
165 // Create capture request
166 if (usePhysicalSettings) {
167 ret = ACameraDevice_createCaptureRequest_withPhysicalIds(mDevice,
168 TEMPLATE_STILL_CAPTURE, &cameraIdList, &mStillRequest);
169 } else {
170 ret = ACameraDevice_createCaptureRequest(mDevice,
171 TEMPLATE_STILL_CAPTURE, &mStillRequest);
172 }
173 if (ret != AMEDIA_OK) {
174 ALOGE("ACameraDevice_createCaptureRequest failed, ret=%d", ret);
175 return ret;
176 }
177 ret = ACameraOutputTarget_create(mImgReaderAnw, &mReqImgReaderOutput);
178 if (ret != AMEDIA_OK) {
179 ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
180 return ret;
181 }
182 ret = ACaptureRequest_addTarget(mStillRequest, mReqImgReaderOutput);
183 if (ret != AMEDIA_OK) {
184 ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
185 return ret;
186 }
187
188 for (auto& physicalStream : physicalImgReaders) {
189 if (physicalStreamMap.find(physicalStream.anw) == physicalStreamMap.end()) {
190 ALOGI("Skipping physicalStream anw=%p", physicalStream.anw);
191 continue;
192 }
193 ACameraOutputTarget* outputTarget = nullptr;
194 ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
195 if (ret != AMEDIA_OK) {
196 ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
197 return ret;
198 }
199 ret = ACaptureRequest_addTarget(mStillRequest, outputTarget);
200 if (ret != AMEDIA_OK) {
201 ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
202 return ret;
203 }
204 mReqPhysicalOutputs.push_back(outputTarget);
205 }
206
207 mIsCameraReady = true;
208 return configuredWindows;
209 }
210
211
isCameraReady()212 bool isCameraReady() { return mIsCameraReady; }
213
closeCamera()214 void closeCamera() {
215 // Destroy capture request
216 if (mReqImgReaderOutput) {
217 ACameraOutputTarget_free(mReqImgReaderOutput);
218 mReqImgReaderOutput = nullptr;
219 }
220 for (auto& outputTarget : mReqPhysicalOutputs) {
221 ACameraOutputTarget_free(outputTarget);
222 }
223 mReqPhysicalOutputs.clear();
224 if (mStillRequest) {
225 ACaptureRequest_free(mStillRequest);
226 mStillRequest = nullptr;
227 }
228 // Destroy capture session
229 if (mSession != nullptr) {
230 ACameraCaptureSession_close(mSession);
231 mSession = nullptr;
232 }
233 if (mImgReaderOutput) {
234 ACaptureSessionOutput_free(mImgReaderOutput);
235 mImgReaderOutput = nullptr;
236 }
237 for (auto& extraOutput : mSessionPhysicalOutputs) {
238 ACaptureSessionOutput_free(extraOutput);
239 }
240 mSessionPhysicalOutputs.clear();
241 if (mOutputs) {
242 ACaptureSessionOutputContainer_free(mOutputs);
243 mOutputs = nullptr;
244 }
245 // Destroy camera device
246 if (mDevice) {
247 ACameraDevice_close(mDevice);
248 mDevice = nullptr;
249 }
250 mIsCameraReady = false;
251 }
252
takePicture()253 int takePicture() {
254 int seqId;
255 return ACameraCaptureSession_capture(mSession, &mCaptureCallbacks, 1, &mStillRequest,
256 &seqId);
257 }
takePicture2()258 int takePicture2() {
259 int seqId;
260 return ACameraCaptureSession_captureV2(mSession, &mCaptureCallbacksV2, 1,
261 &mStillRequest, &seqId);
262 }
263
takeLogicalCameraPicture()264 int takeLogicalCameraPicture() {
265 int seqId;
266 return ACameraCaptureSession_logicalCamera_capture(mSession, &mLogicalCaptureCallbacks,
267 1, &mStillRequest, &seqId);
268 }
269
takeLogicalCameraPicture2()270 int takeLogicalCameraPicture2() {
271 int seqId;
272 return ACameraCaptureSession_logicalCamera_captureV2(mSession,
273 &mLogicalCaptureCallbacksV2, 1, &mStillRequest, &seqId);
274 }
275
checkCallbacks(int pictureCount,bool printLog=false)276 bool checkCallbacks(int pictureCount, bool printLog = false) {
277 std::lock_guard<std::mutex> lock(mMutex);
278 if (mCompletedCaptureCallbackCount != pictureCount) {
279 ALOGE_IF(printLog,
280 "Completed capture callback count not as expected. expected %d actual %d",
281 pictureCount, mCompletedCaptureCallbackCount);
282 return false;
283 }
284 return true;
285 }
checkCallbacksV2(int pictureCount,bool printLog=false)286 bool checkCallbacksV2(int pictureCount, bool printLog = false) {
287 std::lock_guard<std::mutex> lock(mMutex);
288 if (mCaptureStartedCallbackCount != pictureCount) {
289 ALOGE_IF(printLog,
290 "Capture started callback count not as expected. expected %d actual %d",
291 pictureCount, mCaptureStartedCallbackCount);
292 return false;
293 }
294 return true;
295 }
296
297
298 private:
onPreparedCb(void * obj,ANativeWindow * anw,ACameraCaptureSession * session)299 static void onPreparedCb(void* obj, ANativeWindow *anw, ACameraCaptureSession *session) {
300 CameraHelper* thiz = reinterpret_cast<CameraHelper*>(obj);
301 thiz->handlePrepared(anw, session);
302 }
gotAllPreparedCallbacks()303 bool gotAllPreparedCallbacks() {
304 std::lock_guard<std::mutex> lock(mMutex);
305 bool ret = (mPendingPreparedCbs.size() == 0);
306 if (!ret) {
307 ALOGE("%s: mPendingPreparedCbs has the following expected callbacks", __FUNCTION__);
308 for (auto pair : mPendingPreparedCbs) {
309 ALOGE("%s: ANW: %p : pending callbacks %d", __FUNCTION__, pair.first, pair.second);
310 }
311 }
312 return ret;
313 }
314
handlePrepared(ANativeWindow * anw,ACameraCaptureSession * session)315 void handlePrepared(ANativeWindow *anw, ACameraCaptureSession *session) {
316 // Reduce the pending prepared count of anw by 1. If count is 0, remove the key.
317 std::lock_guard<std::mutex> lock(mMutex);
318 if (session != mSession) {
319 ALOGE("%s: Received callback for incorrect session ? mSession %p, session %p",
320 __FUNCTION__, mSession, session);
321 return;
322 }
323 if(mPendingPreparedCbs.find(anw) == mPendingPreparedCbs.end()) {
324 ALOGE("%s: ANW %p was not being prepared at all ?", __FUNCTION__, anw);
325 return;
326 }
327 mPendingPreparedCbs[anw]--;
328 if (mPendingPreparedCbs[anw] == 0) {
329 mPendingPreparedCbs.erase(anw);
330 }
331 }
incPendingPrepared(ANativeWindow * anw)332 void incPendingPrepared(ANativeWindow *anw) {
333 std::lock_guard<std::mutex> lock(mMutex);
334 if ((mPendingPreparedCbs.find(anw) == mPendingPreparedCbs.end())) {
335 mPendingPreparedCbs[anw] = 1;
336 return;
337 }
338 mPendingPreparedCbs[anw]++;
339 }
340
341 // ANW -> pending prepared callbacks
342 std::unordered_map<ANativeWindow*, int> mPendingPreparedCbs;
343 ACameraDevice_StateCallbacks mDeviceCb{this, nullptr, nullptr};
344 ACameraCaptureSession_stateCallbacks mSessionCb{ this, nullptr, nullptr, nullptr};
345
346 ACameraCaptureSession_prepareCallback mPreparedCb = &onPreparedCb;
347
348 ANativeWindow* mImgReaderAnw = nullptr; // not owned by us.
349
350 // Camera device
351 ACameraDevice* mDevice = nullptr;
352 // Capture session
353 ACaptureSessionOutputContainer* mOutputs = nullptr;
354 ACaptureSessionOutput* mImgReaderOutput = nullptr;
355 std::vector<ACaptureSessionOutput*> mSessionPhysicalOutputs;
356
357 ACameraCaptureSession* mSession = nullptr;
358 // Capture request
359 ACaptureRequest* mStillRequest = nullptr;
360 ACameraOutputTarget* mReqImgReaderOutput = nullptr;
361 std::vector<ACameraOutputTarget*> mReqPhysicalOutputs;
362
363 bool mIsCameraReady = false;
364 const char* mCameraId;
365 ACameraManager* mCameraManager;
366 int mCompletedCaptureCallbackCount = 0;
367 int mCaptureStartedCallbackCount = 0;
368 std::mutex mMutex;
369 ACameraCaptureSession_captureCallbacks mCaptureCallbacks = {
370 // TODO: Add tests for other callbacks
371 this, // context
372 nullptr, // onCaptureStarted
373 nullptr, // onCaptureProgressed
374 [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
__anon511359ea0202() 375 const ACameraMetadata *) {
376 CameraHelper *ch = static_cast<CameraHelper *>(ctx);
377 std::lock_guard<std::mutex> lock(ch->mMutex);
378 ch->mCompletedCaptureCallbackCount++;
379 },
380 nullptr, // onCaptureFailed
381 nullptr, // onCaptureSequenceCompleted
382 nullptr, // onCaptureSequenceAborted
383 nullptr, // onCaptureBufferLost
384 };
385 ACameraCaptureSession_captureCallbacksV2 mCaptureCallbacksV2 = {
386 this, // context
387 [](void* ctx , ACameraCaptureSession *,const ACaptureRequest *, int64_t,
__anon511359ea0302() 388 int64_t frameNumber ) {
389 CameraHelper *ch = static_cast<CameraHelper *>(ctx);
390 ASSERT_TRUE(frameNumber >= 0);
391 std::lock_guard<std::mutex> lock(ch->mMutex);
392 ch->mCaptureStartedCallbackCount++;
393 },
394 nullptr, // onCaptureProgressed
395 nullptr, // onCaptureCompleted
396 nullptr, // onCaptureFailed
397 nullptr, // onCaptureSequenceCompleted
398 nullptr, // onCaptureSequenceAborted
399 nullptr, // onCaptureBufferLost
400 };
401
402 std::vector<std::string> mPhysicalCameraIds;
403
404 ACameraCaptureSession_logicalCamera_captureCallbacks mLogicalCaptureCallbacks = {
405 // TODO: Add tests for other callbacks
406 this, // context
407 nullptr, // onCaptureStarted
408 nullptr, // onCaptureProgressed
409 [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
410 const ACameraMetadata *, size_t physicalResultCount,
__anon511359ea0402() 411 const char** physicalCameraIds, const ACameraMetadata** physicalResults) {
412 CameraHelper *ch = static_cast<CameraHelper *>(ctx);
413 std::lock_guard<std::mutex> lock(ch->mMutex);
414 ASSERT_EQ(physicalResultCount, ch->mPhysicalCameraIds.size());
415 for (size_t i = 0; i < physicalResultCount; i++) {
416 ASSERT_TRUE(physicalCameraIds[i] != nullptr);
417 ASSERT_TRUE(physicalResults[i] != nullptr);
418 ASSERT_NE(std::find(ch->mPhysicalCameraIds.begin(),
419 ch->mPhysicalCameraIds.end(), physicalCameraIds[i]),
420 ch->mPhysicalCameraIds.end());
421
422 // Verify frameNumber and sensorTimestamp exist in physical
423 // result metadata
424 ACameraMetadata_const_entry entry;
425 ACameraMetadata_getConstEntry(
426 physicalResults[i], ACAMERA_SYNC_FRAME_NUMBER, &entry);
427 ASSERT_EQ(entry.count, 1);
428 ACameraMetadata_getConstEntry(
429 physicalResults[i], ACAMERA_SENSOR_TIMESTAMP, &entry);
430 ASSERT_EQ(entry.count, 1);
431 }
432 ch->mCompletedCaptureCallbackCount++;
433 },
434 [] (void * /*ctx*/, ACameraCaptureSession* /*session*/, ACaptureRequest* /*request*/,
__anon511359ea0502() 435 ALogicalCameraCaptureFailure* failure) {
436 if (failure->physicalCameraId) {
437 ALOGD("%s: Physical camera id: %s result failure", __FUNCTION__,
438 failure->physicalCameraId);
439 }
440 },
441 nullptr, // onCaptureSequenceCompleted
442 nullptr, // onCaptureSequenceAborted
443 nullptr, // onCaptureBufferLost
444 };
445 ACameraCaptureSession_logicalCamera_captureCallbacksV2 mLogicalCaptureCallbacksV2 = {
446 this, // context
447 [](void* ctx , ACameraCaptureSession *,const ACaptureRequest *, int64_t,
__anon511359ea0602() 448 int64_t frameNumber) {
449 CameraHelper *ch = static_cast<CameraHelper *>(ctx);
450 ASSERT_TRUE(frameNumber >= 0);
451 std::lock_guard<std::mutex> lock(ch->mMutex);
452 ch->mCaptureStartedCallbackCount++;
453 },
454 nullptr, // onCaptureProgressed
455 nullptr, //onLogicalCaptureCompleted
456 nullptr, //onLogicalCpatureFailed
457 nullptr, // onCaptureSequenceCompleted
458 nullptr, // onCaptureSequenceAborted
459 nullptr, // onCaptureBufferLost
460 };
461
462 };
463
464 class ImageReaderTestCase {
465 public:
ImageReaderTestCase(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,bool async)466 ImageReaderTestCase(int32_t width,
467 int32_t height,
468 int32_t format,
469 uint64_t usage,
470 int32_t maxImages,
471 bool async)
472 : mWidth(width),
473 mHeight(height),
474 mFormat(format),
475 mUsage(usage),
476 mMaxImages(maxImages),
477 mAsync(async) {}
478
~ImageReaderTestCase()479 ~ImageReaderTestCase() {
480 if (mImgReaderAnw) {
481 AImageReader_delete(mImgReader);
482 // No need to call AImageReader_release(mImgReaderAnw).
483 }
484 }
485
initImageReader()486 int initImageReader() {
487 if (mImgReader != nullptr || mImgReaderAnw != nullptr) {
488 ALOGE("Cannot re-initalize image reader, mImgReader=%p, mImgReaderAnw=%p", mImgReader,
489 mImgReaderAnw);
490 return -1;
491 }
492
493 media_status_t ret = AImageReader_newWithUsage(
494 mWidth, mHeight, mFormat, mUsage, mMaxImages, &mImgReader);
495 if (ret != AMEDIA_OK || mImgReader == nullptr) {
496 ALOGE("Failed to create new AImageReader, ret=%d, mImgReader=%p", ret, mImgReader);
497 return -1;
498 }
499
500 ret = AImageReader_setImageListener(mImgReader, &mReaderAvailableCb);
501 if (ret != AMEDIA_OK) {
502 ALOGE("Failed to set image available listener, ret=%d.", ret);
503 return ret;
504 }
505
506 ret = AImageReader_setBufferRemovedListener(mImgReader, &mReaderDetachedCb);
507 if (ret != AMEDIA_OK) {
508 ALOGE("Failed to set buffer detaching listener, ret=%d.", ret);
509 return ret;
510 }
511
512
513 ret = AImageReader_getWindow(mImgReader, &mImgReaderAnw);
514 if (ret != AMEDIA_OK || mImgReaderAnw == nullptr) {
515 ALOGE("Failed to get ANativeWindow* from AImageReader, ret=%d, mImgReader=%p.", ret,
516 mImgReader);
517 return -1;
518 }
519
520 return 0;
521 }
522
getNativeWindow()523 ANativeWindow* getNativeWindow() { return mImgReaderAnw; }
524
getAcquiredImageCount()525 int getAcquiredImageCount() {
526 std::lock_guard<std::mutex> lock(mMutex);
527 return mAcquiredImageCount;
528 }
529
HandleImageAvailable(AImageReader * reader)530 void HandleImageAvailable(AImageReader* reader) {
531 std::lock_guard<std::mutex> lock(mMutex);
532
533 AImage* outImage = nullptr;
534 media_status_t ret;
535
536 // Make sure AImage will be deleted automatically when it goes out of
537 // scope.
538 auto imageDeleter = [this](AImage* img) {
539 if (mAsync) {
540 AImage_deleteAsync(img, kDummyFenceFd);
541 } else {
542 AImage_delete(img);
543 }
544 };
545 std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter);
546
547 if (mAsync) {
548 int outFenceFd = 0;
549 // Verity that outFenceFd's value will be changed by
550 // AImageReader_acquireNextImageAsync.
551 ret = AImageReader_acquireNextImageAsync(reader, &outImage, &outFenceFd);
552 if (ret != AMEDIA_OK || outImage == nullptr || outFenceFd == 0) {
553 ALOGE("Failed to acquire image, ret=%d, outIamge=%p, outFenceFd=%d.", ret, outImage,
554 outFenceFd);
555 return;
556 }
557 img.reset(outImage);
558 } else {
559 ret = AImageReader_acquireNextImage(reader, &outImage);
560 if (ret != AMEDIA_OK || outImage == nullptr) {
561 ALOGE("Failed to acquire image, ret=%d, outIamge=%p.", ret, outImage);
562 return;
563 }
564 img.reset(outImage);
565 }
566
567 AHardwareBuffer* outBuffer = nullptr;
568 ret = AImage_getHardwareBuffer(img.get(), &outBuffer);
569 if (ret != AMEDIA_OK || outBuffer == nullptr) {
570 ALOGE("Faild to get hardware buffer, ret=%d, outBuffer=%p.", ret, outBuffer);
571 return;
572 }
573
574 // No need to release AHardwareBuffer, since we don't acquire additional
575 // reference to it.
576 AHardwareBuffer_Desc outDesc;
577 AHardwareBuffer_describe(outBuffer, &outDesc);
578 int32_t imageWidth = 0;
579 int32_t imageHeight = 0;
580 int32_t bufferWidth = static_cast<int32_t>(outDesc.width);
581 int32_t bufferHeight = static_cast<int32_t>(outDesc.height);
582
583 AImage_getWidth(outImage, &imageWidth);
584 AImage_getHeight(outImage, &imageHeight);
585 if (imageWidth != mWidth || imageHeight != mHeight) {
586 ALOGE("Mismatched output image dimension: expected=%dx%d, actual=%dx%d", mWidth,
587 mHeight, imageWidth, imageHeight);
588 return;
589 }
590
591 if (mFormat == AIMAGE_FORMAT_RGBA_8888 ||
592 mFormat == AIMAGE_FORMAT_RGBX_8888 ||
593 mFormat == AIMAGE_FORMAT_RGB_888 ||
594 mFormat == AIMAGE_FORMAT_RGB_565 ||
595 mFormat == AIMAGE_FORMAT_RGBA_FP16 ||
596 mFormat == AIMAGE_FORMAT_YUV_420_888 ||
597 mFormat == AIMAGE_FORMAT_Y8) {
598 // Check output buffer dimension for certain formats. Don't do this for blob based
599 // formats.
600 if (bufferWidth != mWidth || bufferHeight != mHeight) {
601 ALOGE("Mismatched output buffer dimension: expected=%dx%d, actual=%dx%d", mWidth,
602 mHeight, bufferWidth, bufferHeight);
603 return;
604 }
605 }
606
607 if ((outDesc.usage & mUsage) != mUsage) {
608 ALOGE("Mismatched output buffer usage: actual (%" PRIu64 "), expected (%" PRIu64 ")",
609 outDesc.usage, mUsage);
610 return;
611 }
612
613 uint8_t* data = nullptr;
614 int dataLength = 0;
615 ret = AImage_getPlaneData(img.get(), 0, &data, &dataLength);
616 if (mUsage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN) {
617 // When we have CPU_READ_OFTEN usage bits, we can lock the image.
618 if (ret != AMEDIA_OK || data == nullptr || dataLength < 0) {
619 ALOGE("Failed to access CPU data, ret=%d, data=%p, dataLength=%d", ret, data,
620 dataLength);
621 return;
622 }
623 } else {
624 if (ret != AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE || data != nullptr || dataLength != 0) {
625 ALOGE("Shouldn't be able to access CPU data, ret=%d, data=%p, dataLength=%d", ret,
626 data, dataLength);
627 return;
628 }
629 }
630 // Only increase mAcquiredImageCount if all checks pass.
631 mAcquiredImageCount++;
632 }
633
onImageAvailable(void * obj,AImageReader * reader)634 static void onImageAvailable(void* obj, AImageReader* reader) {
635 ImageReaderTestCase* thiz = reinterpret_cast<ImageReaderTestCase*>(obj);
636 thiz->HandleImageAvailable(reader);
637 }
638
639 static void
onBufferRemoved(void *,AImageReader *,AHardwareBuffer *)640 onBufferRemoved(void* /*obj*/, AImageReader* /*reader*/, AHardwareBuffer* /*buffer*/) {
641 // No-op, just to check the listener can be set properly.
642 }
643
644 private:
645 int32_t mWidth;
646 int32_t mHeight;
647 int32_t mFormat;
648 uint64_t mUsage;
649 int32_t mMaxImages;
650 bool mAsync;
651
652 std::mutex mMutex;
653 int mAcquiredImageCount{0};
654
655 AImageReader* mImgReader = nullptr;
656 ANativeWindow* mImgReaderAnw = nullptr;
657
658 AImageReader_ImageListener mReaderAvailableCb{this, onImageAvailable};
659 AImageReader_BufferRemovedListener mReaderDetachedCb{this, onBufferRemoved};
660 };
661
662
663 class AImageReaderVendorTest : public ::testing::Test {
664 public:
SetUp()665 void SetUp() override {
666 mCameraManager = ACameraManager_create();
667 if (mCameraManager == nullptr) {
668 ALOGE("Failed to create ACameraManager.");
669 return;
670 }
671
672 camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
673 if (ret != ACAMERA_OK) {
674 ALOGE("Failed to get cameraIdList: ret=%d", ret);
675 return;
676 }
677 // TODO: Add more rigorous tests for vendor tags
678 ASSERT_NE(VendorTagDescriptorCache::getGlobalVendorTagCache(), nullptr);
679 if (mCameraIdList->numCameras < 1) {
680 ALOGW("Device has no camera on board.");
681 return;
682 }
683 }
TearDown()684 void TearDown() override {
685 // Destroy camera manager
686 if (mCameraIdList) {
687 ACameraManager_deleteCameraIdList(mCameraIdList);
688 mCameraIdList = nullptr;
689 }
690 if (mCameraManager) {
691 ACameraManager_delete(mCameraManager);
692 mCameraManager = nullptr;
693 }
694 }
695
takePictures(const char * id,uint64_t readerUsage,int readerMaxImages,bool readerAsync,int pictureCount,bool v2=false,bool prepareSurfaces=false)696 bool takePictures(const char* id, uint64_t readerUsage, int readerMaxImages,
697 bool readerAsync, int pictureCount, bool v2 = false, bool prepareSurfaces = false) {
698 int ret = 0;
699
700 ImageReaderTestCase testCase(
701 kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
702 readerAsync);
703 ret = testCase.initImageReader();
704 if (ret < 0) {
705 ALOGE("Unable to initialize ImageReader");
706 return false;
707 }
708
709 CameraHelper cameraHelper(id, mCameraManager);
710 std::variant<int, ConfiguredWindows> retInit =
711 cameraHelper.initCamera(testCase.getNativeWindow(), {}/*physicalImageReaders*/,
712 false/*usePhysicalSettings*/, prepareSurfaces);
713 int *retp = std::get_if<int>(&retInit);
714 if (retp) {
715 ALOGE("Unable to initialize camera helper");
716 return false;
717 }
718
719 if (!cameraHelper.isCameraReady()) {
720 ALOGW("Camera is not ready after successful initialization. It's either due to camera "
721 "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
722 "camera on board.");
723 return true;
724 }
725
726 for (int i = 0; i < pictureCount; i++) {
727 if (v2) {
728 ret = cameraHelper.takePicture2();
729 } else {
730 ret = cameraHelper.takePicture();
731 }
732 if (ret < 0) {
733 ALOGE("Unable to take picture");
734 return false;
735 }
736 }
737
738 // Sleep until all capture finished
739 for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
740 usleep(kCaptureWaitUs);
741 bool receivedAllCallbacks = v2 ? cameraHelper.checkCallbacksV2(pictureCount)
742 : cameraHelper.checkCallbacks(pictureCount);
743
744 bool acquiredAllImages = testCase.getAcquiredImageCount() == pictureCount;
745 if (acquiredAllImages) {
746 ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
747 pictureCount);
748 }
749 // Wait for all images to be acquired and all callbacks to be processed
750 if (acquiredAllImages && receivedAllCallbacks) {
751 break;
752 }
753 }
754 return testCase.getAcquiredImageCount() == pictureCount &&
755 v2 ? cameraHelper.checkCallbacksV2(pictureCount, /* printLog= */true) :
756 cameraHelper.checkCallbacks(pictureCount, /* printLog= */true);
757 }
758
testTakePicturesNative(const char * id,bool prepareSurfaces)759 bool testTakePicturesNative(const char* id, bool prepareSurfaces) {
760 for (auto& readerUsage :
761 {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
762 for (auto& readerMaxImages : {1, 4, 8}) {
763 for (auto& readerAsync : {true, false}) {
764 for (auto& pictureCount : {1, 4, 8}) {
765 for ( auto & v2 : {true, false}) {
766 if (!takePictures(id, readerUsage, readerMaxImages,
767 readerAsync, pictureCount, v2, prepareSurfaces)) {
768 ALOGE("Test takePictures failed for test case usage=%" PRIu64
769 ", maxImages=%d, async=%d, pictureCount=%d",
770 readerUsage, readerMaxImages, readerAsync, pictureCount);
771 return false;
772 }
773 }
774 }
775 }
776 }
777 }
778 return true;
779 }
780
781 // Camera manager
782 ACameraManager* mCameraManager = nullptr;
783 ACameraIdList* mCameraIdList = nullptr;
784
isCapabilitySupported(ACameraMetadata * staticInfo,acamera_metadata_enum_android_request_available_capabilities_t cap)785 bool isCapabilitySupported(ACameraMetadata* staticInfo,
786 acamera_metadata_enum_android_request_available_capabilities_t cap) {
787 ACameraMetadata_const_entry entry;
788 ACameraMetadata_getConstEntry(
789 staticInfo, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
790 for (uint32_t i = 0; i < entry.count; i++) {
791 if (entry.data.u8[i] == cap) {
792 return true;
793 }
794 }
795 return false;
796 }
797
isSizeSupportedForFormat(ACameraMetadata * staticInfo,int32_t format,int32_t width,int32_t height)798 bool isSizeSupportedForFormat(ACameraMetadata* staticInfo,
799 int32_t format, int32_t width, int32_t height) {
800 ACameraMetadata_const_entry entry;
801 ACameraMetadata_getConstEntry(staticInfo,
802 ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
803 for (uint32_t i = 0; i < entry.count; i += 4) {
804 if (entry.data.i32[i] == format &&
805 entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
806 entry.data.i32[i+1] == width &&
807 entry.data.i32[i+2] == height) {
808 return true;
809 }
810 }
811 return false;
812 }
813
findCandidateLogicalCamera(const char ** cameraId,ACameraMetadata ** staticMetadata,std::vector<const char * > * candidatePhysicalIds)814 void findCandidateLogicalCamera(const char **cameraId,
815 ACameraMetadata** staticMetadata,
816 std::vector<const char*>* candidatePhysicalIds) {
817 // Find first available logical camera
818 for (int i = 0; i < mCameraIdList->numCameras; i++) {
819 camera_status_t ret;
820 ret = ACameraManager_getCameraCharacteristics(
821 mCameraManager, mCameraIdList->cameraIds[i], staticMetadata);
822 ASSERT_EQ(ret, ACAMERA_OK);
823 ASSERT_NE(*staticMetadata, nullptr);
824
825 if (!isCapabilitySupported(*staticMetadata,
826 ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)) {
827 ACameraMetadata_free(*staticMetadata);
828 *staticMetadata = nullptr;
829 continue;
830 }
831
832 // Check returned physical camera Ids are valid
833 size_t physicalCameraIdCnt = 0;
834 const char*const* physicalCameraIds = nullptr;
835 bool isLogicalCamera = ACameraMetadata_isLogicalMultiCamera(*staticMetadata,
836 &physicalCameraIdCnt, &physicalCameraIds);
837 ASSERT_TRUE(isLogicalCamera);
838 ASSERT_GE(physicalCameraIdCnt, 2);
839 ACameraMetadata* physicalCameraMetadata = nullptr;
840 candidatePhysicalIds->clear();
841 for (size_t j = 0; j < physicalCameraIdCnt && candidatePhysicalIds->size() < 2; j++) {
842 ASSERT_GT(strlen(physicalCameraIds[j]), 0);
843 ret = ACameraManager_getCameraCharacteristics(
844 mCameraManager, physicalCameraIds[j], &physicalCameraMetadata);
845 ASSERT_EQ(ret, ACAMERA_OK);
846 ASSERT_NE(physicalCameraMetadata, nullptr);
847
848 if (isSizeSupportedForFormat(physicalCameraMetadata, kTestImageFormat,
849 kTestImageWidth, kTestImageHeight)) {
850 candidatePhysicalIds->push_back(physicalCameraIds[j]);
851 }
852 ACameraMetadata_free(physicalCameraMetadata);
853 }
854 if (candidatePhysicalIds->size() == 2) {
855 *cameraId = mCameraIdList->cameraIds[i];
856 return;
857 } else {
858 ACameraMetadata_free(*staticMetadata);
859 *staticMetadata = nullptr;
860 }
861 }
862 *cameraId = nullptr;
863 return;
864 }
865
testLogicalCameraPhysicalStream(bool usePhysicalSettings,bool v2)866 void testLogicalCameraPhysicalStream(bool usePhysicalSettings, bool v2) {
867 const char* cameraId = nullptr;
868 ACameraMetadata* staticMetadata = nullptr;
869 std::vector<const char*> physicalCameraIds;
870
871 findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
872 if (cameraId == nullptr) {
873 // Couldn't find logical camera to test
874 return;
875 }
876
877 // Test streaming the logical multi-camera
878 uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
879 int32_t readerMaxImages = 8;
880 bool readerAsync = false;
881 const int pictureCount = 6;
882 std::vector<ImageReaderTestCase*> testCases;
883 for (size_t i = 0; i < 3; i++) {
884 ImageReaderTestCase* testCase = new ImageReaderTestCase(
885 kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage,
886 readerMaxImages, readerAsync);
887 ASSERT_EQ(testCase->initImageReader(), 0);
888 testCases.push_back(testCase);
889 }
890
891 CameraHelper cameraHelper(cameraId, mCameraManager);
892 std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
893 physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
894 physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
895
896 std::variant<int, ConfiguredWindows> retInit =
897 cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo,
898 usePhysicalSettings);
899 int *retp = std::get_if<int>(&retInit);
900 ASSERT_EQ(retp, nullptr);
901 ConfiguredWindows *configuredWindowsp = std::get_if<ConfiguredWindows>(&retInit);
902 ASSERT_NE(configuredWindowsp, nullptr);
903 ASSERT_LE(configuredWindowsp->size(), testCases.size());
904 int ret = 0;
905 if (!cameraHelper.isCameraReady()) {
906 ALOGW("Camera is not ready after successful initialization. It's either due to camera "
907 "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
908 "camera on board.");
909 return;
910 }
911
912 for (int i = 0; i < pictureCount; i++) {
913 if (v2) {
914 ret = cameraHelper.takeLogicalCameraPicture2();
915 }
916 else {
917 ret = cameraHelper.takeLogicalCameraPicture();
918 }
919 ASSERT_EQ(ret, 0);
920 }
921
922 // Sleep until all capture finished
923 for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
924 usleep(kCaptureWaitUs);
925 if (testCases[0]->getAcquiredImageCount() == pictureCount) {
926 ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
927 pictureCount);
928 break;
929 }
930 }
931 for(auto &testCase : testCases) {
932 auto it = configuredWindowsp->find(testCase->getNativeWindow());
933 if (it == configuredWindowsp->end()) {
934 continue;
935 }
936 ALOGI("Testing window %p", testCase->getNativeWindow());
937 ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
938 }
939 if (v2) {
940 ASSERT_TRUE(cameraHelper.checkCallbacksV2(pictureCount));
941 } else {
942 ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
943 }
944
945 ACameraMetadata_free(staticMetadata);
946 }
947
testBasicTakePictures(bool prepareSurfaces)948 void testBasicTakePictures(bool prepareSurfaces) {
949 // We always use the first camera.
950 const char* cameraId = mCameraIdList->cameraIds[0];
951 ASSERT_TRUE(cameraId != nullptr);
952
953 ACameraMetadata* staticMetadata = nullptr;
954 camera_status_t ret = ACameraManager_getCameraCharacteristics(
955 mCameraManager, cameraId, &staticMetadata);
956 ASSERT_EQ(ret, ACAMERA_OK);
957 ASSERT_NE(staticMetadata, nullptr);
958
959 bool isBC = isCapabilitySupported(staticMetadata,
960 ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
961
962 uint32_t namedTag = 0;
963 // Test that ACameraMetadata_getTagFromName works as expected for public tag
964 // names
965 camera_status_t status = ACameraManager_getTagFromName(mCameraManager, cameraId,
966 "android.control.aeMode", &namedTag);
967
968 ASSERT_EQ(status, ACAMERA_OK);
969 ASSERT_EQ(namedTag, ACAMERA_CONTROL_AE_MODE);
970
971 ACameraMetadata_free(staticMetadata);
972
973 if (!isBC) {
974 ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
975 return;
976 }
977
978 EXPECT_TRUE(testTakePicturesNative(cameraId, prepareSurfaces));
979 }
980 };
981
982
983
TEST_F(AImageReaderVendorTest,CreateANativeWindow)984 TEST_F(AImageReaderVendorTest, CreateANativeWindow) {
985 testBasicTakePictures(/*prepareSurfaces*/ false);
986 testBasicTakePictures(/*prepareSurfaces*/ true);
987 }
988
TEST_F(AImageReaderVendorTest,LogicalCameraPhysicalStream)989 TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
990 for (auto & v2 : {true, false}) {
991 testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/, v2);
992 testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/, v2);
993 }
994 }
995
996 } // namespace
997