camera2 vndk: Set up vendor tags in CameraManager

Bug: 122477622

Test: AImageReaderVendorTest

Change-Id: I3957d8ee5d1b03c263584e1cd79e937a2f8782ac
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 60c9f85..d96f403 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -137,6 +137,7 @@
     shared_libs: [
         "libhwbinder",
         "libcamera2ndk_vendor",
+        "libcamera_metadata",
         "libmediandk",
         "libnativewindow",
         "libutils",
@@ -144,6 +145,9 @@
         "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 f395b44..575ee9d 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -34,7 +34,10 @@
 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 @@
 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<VendorTagSection>& vts,
+                                             /*out*/ sp<VendorTagDescriptor> *descriptor);
+};
+
+status_t HidlVendorTagDescriptor::createDescriptorFromHidl(const hidl_vec<VendorTagSection> &vts,
+                                                           sp<VendorTagDescriptor> *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<uint32_t> tagArray;
+    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+    sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+    desc->mTagCount = tagCount;
+
+    KeyedVector<uint32_t, String8> 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<uint32_t>(index));
+
+        // Set up reverse mapping
+        ssize_t reverseIndex = -1;
+        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+            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 @@
     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<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
+    Status status = Status::NO_ERROR;
+    std::vector<ProviderIdAndVendorTagSections> 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> 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<ICameraService> CameraManagerGlobal::getCameraService() {
     Mutex::Autolock _l(mLock);
@@ -140,6 +267,13 @@
         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 c8d640f..6b1365a 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -142,6 +142,8 @@
 
     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 f9bb3ac..93108b0 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -37,12 +37,7 @@
 #include <media/NdkImage.h>
 #include <media/NdkImageReader.h>
 #include <cutils/native_handle.h>
-
-//#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 <VendorTagDescriptor.h>
 
 namespace {
 
@@ -53,6 +48,8 @@
 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 @@
             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;