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