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