From 9401b553496fa0a6be0513fd6b26758c672151e7 Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Mon, 7 Jan 2019 16:20:28 -0800 Subject: [PATCH] camera2 vndk: Set up vendor tags in CameraManager Bug: 122477622 Test: AImageReaderVendorTest Change-Id: I3957d8ee5d1b03c263584e1cd79e937a2f8782ac Signed-off-by: Jayant Chowdhary --- camera/ndk/Android.bp | 4 + camera/ndk/ndk_vendor/impl/ACameraManager.cpp | 140 +++++++++++++++++- camera/ndk/ndk_vendor/impl/ACameraManager.h | 2 + .../tests/AImageReaderVendorTest.cpp | 11 +- 4 files changed, 148 insertions(+), 9 deletions(-) diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp index 60c9f851b8..d96f4039e9 100644 --- a/camera/ndk/Android.bp +++ b/camera/ndk/Android.bp @@ -137,6 +137,7 @@ cc_test { shared_libs: [ "libhwbinder", "libcamera2ndk_vendor", + "libcamera_metadata", "libmediandk", "libnativewindow", "libutils", @@ -144,6 +145,9 @@ cc_test { "libcutils", "liblog", ], + static_libs: [ + "android.hardware.camera.common@1.0-helper", + ], cflags: [ "-D__ANDROID_VNDK__", ], diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp index f395b443ee..575ee9dd6f 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp +++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp @@ -34,7 +34,10 @@ using namespace android::acam; namespace android { namespace acam { -using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId; +using frameworks::cameraservice::service::V2_0::CameraStatusAndId; +using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections; +using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor; +using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache; // Static member definitions const char* CameraManagerGlobal::kCameraIdKey = "CameraId"; @@ -43,6 +46,104 @@ const char* CameraManagerGlobal::kContextKey = "CallbackContext"; Mutex CameraManagerGlobal::sLock; CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr; +/** + * The vendor tag descriptor class that takes HIDL vendor tag information as + * input. Not part of vendor available VendorTagDescriptor class because that class is used by + * default HAL implementation code as well. + */ +class HidlVendorTagDescriptor : public VendorTagDescriptor { +public: + /** + * Create a VendorTagDescriptor object from the HIDL VendorTagSection + * vector. + * + * Returns OK on success, or a negative error code. + */ + static status_t createDescriptorFromHidl(const hidl_vec& vts, + /*out*/ sp *descriptor); +}; + +status_t HidlVendorTagDescriptor::createDescriptorFromHidl(const hidl_vec &vts, + sp *descriptor) { + int tagCount = 0; + + for (size_t s = 0; s < vts.size(); s++) { + tagCount += vts[s].tags.size(); + } + + if (tagCount < 0 || tagCount > INT32_MAX) { + ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount); + return BAD_VALUE; + } + + Vector tagArray; + LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount, + "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount); + + sp desc = new HidlVendorTagDescriptor(); + desc->mTagCount = tagCount; + + KeyedVector tagToSectionMap; + + int idx = 0; + for (size_t s = 0; s < vts.size(); s++) { + const VendorTagSection& section = vts[s]; + const char *sectionName = section.sectionName.c_str(); + if (sectionName == NULL) { + ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s); + return BAD_VALUE; + } + String8 sectionString(sectionName); + desc->mSections.add(sectionString); + + for (size_t j = 0; j < section.tags.size(); j++) { + uint32_t tag = section.tags[j].tagId; + if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) { + ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag); + return BAD_VALUE; + } + + tagArray.editItemAt(idx++) = section.tags[j].tagId; + + const char *tagName = section.tags[j].tagName.c_str(); + if (tagName == NULL) { + ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag); + return BAD_VALUE; + } + desc->mTagToNameMap.add(tag, String8(tagName)); + tagToSectionMap.add(tag, sectionString); + + int tagType = (int) section.tags[j].tagType; + if (tagType < 0 || tagType >= NUM_TYPES) { + ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType); + return BAD_VALUE; + } + desc->mTagToTypeMap.emplace(tag, tagType); + } + } + + for (size_t i = 0; i < tagArray.size(); ++i) { + uint32_t tag = tagArray[i]; + String8 sectionString = tagToSectionMap.valueFor(tag); + + // Set up tag to section index map + ssize_t index = desc->mSections.indexOf(sectionString); + LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index); + desc->mTagToSectionMap.add(tag, static_cast(index)); + + // Set up reverse mapping + ssize_t reverseIndex = -1; + if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) { + KeyedVector* nameMapper = new KeyedVector(); + reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper); + } + desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag); + } + + *descriptor = std::move(desc); + return OK; +} + CameraManagerGlobal& CameraManagerGlobal::getInstance() { Mutex::Autolock _l(sLock); @@ -80,8 +181,34 @@ static bool isCameraServiceDisabled() { return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0); } -// TODO: Add back when vendor tags are supported for libcamera2ndk_vendor when -// the HIDL interface supports querying by vendor id. +bool CameraManagerGlobal::setupVendorTags() { + sp tagCache = new VendorTagDescriptorCache(); + Status status = Status::NO_ERROR; + std::vector providerIdsAndVts; + auto remoteRet = mCameraService->getCameraVendorTagSections([&status, &providerIdsAndVts] + (Status s, + auto &IdsAndVts) { + status = s; + providerIdsAndVts = IdsAndVts; }); + + if (!remoteRet.isOk() || status != Status::NO_ERROR) { + ALOGE("Failed to retrieve VendorTagSections %s", remoteRet.description().c_str()); + return false; + } + // Convert each providers VendorTagSections into a VendorTagDescriptor and + // add it to the cache + for (auto &providerIdAndVts : providerIdsAndVts) { + sp vendorTagDescriptor; + if (HidlVendorTagDescriptor::createDescriptorFromHidl(providerIdAndVts.vendorTagSections, + &vendorTagDescriptor) != OK) { + ALOGE("Failed to convert from Hidl: VendorTagDescriptor"); + return false; + } + tagCache->addVendorDescriptor(providerIdAndVts.providerId, vendorTagDescriptor); + } + VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache); + return true; +} sp CameraManagerGlobal::getCameraService() { Mutex::Autolock _l(mLock); @@ -140,6 +267,13 @@ sp CameraManagerGlobal::getCameraService() { if (!remoteRet.isOk() || status != Status::NO_ERROR) { ALOGE("Failed to add listener to camera service %s", remoteRet.description().c_str()); } + + // Setup vendor tags + if (!setupVendorTags()) { + ALOGE("Unable to set up vendor tags"); + return nullptr; + } + for (auto& c : cameraStatuses) { onStatusChangedLocked(c); } diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h index c8d640ffe7..6b1365a8c1 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraManager.h +++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h @@ -142,6 +142,8 @@ class CameraManagerGlobal final : public RefBase { void onStatusChanged(const CameraStatusAndId &statusAndId); void onStatusChangedLocked(const CameraStatusAndId &statusAndId); + bool setupVendorTags(); + // Utils for status static bool validStatus(CameraDeviceStatus status); static bool isStatusAvailable(CameraDeviceStatus status); diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp index f9bb3acefe..93108b0995 100644 --- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp +++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp @@ -37,12 +37,7 @@ #include #include #include - -//#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) -//#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +#include namespace { @@ -53,6 +48,8 @@ static constexpr int kTestImageWidth = 640; static constexpr int kTestImageHeight = 480; static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888; +using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache; + class CameraHelper { public: CameraHelper(const char* id, ACameraManager *manager) : @@ -527,6 +524,8 @@ class AImageReaderVendorTest : public ::testing::Test { ALOGE("Failed to get cameraIdList: ret=%d", ret); return; } + // TODO: Add more rigorous tests for vendor tags + ASSERT_NE(VendorTagDescriptorCache::getGlobalVendorTagCache(), nullptr); if (mCameraIdList->numCameras < 1) { ALOGW("Device has no camera on board."); return;