Camera: Support vendor tags from multiple providers

Different vendors could have different vendor tags.
A global vendor tag cache will store all available
vendor tag descriptors from different providers.
The cache will then be shared with each camera client.
Camera metadata will use specific vendor ids stored
in the metadata buffer to identify the correct vendor
tag provider.

Bug: 34275821
Test: adb shell /data/nativetest/cameraservice_test/cameraservice_test
--gtest_filter=CameraProviderManagerTest.MultipleVendorTagTest
Complete Camera/Camera2 CTS tests
Change-Id: I2262128f21a0167504f018230624e2a89786c467
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 373b94e..e143e05 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -170,7 +170,7 @@
 }
 
 status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
-    int tagType = get_camera_metadata_tag_type(tag);
+    int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
     if ( CC_UNLIKELY(tagType == -1)) {
         ALOGE("Update metadata entry: Unknown tag %d", tag);
         return INVALID_OPERATION;
@@ -178,7 +178,7 @@
     if ( CC_UNLIKELY(tagType != expectedType) ) {
         ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
                 "got type %s data instead ",
-                get_camera_metadata_tag_name(tag), tag,
+                get_local_camera_metadata_tag_name(tag, mBuffer), tag,
                 camera_metadata_type_names[tagType],
                 camera_metadata_type_names[expectedType]);
         return INVALID_OPERATION;
@@ -297,7 +297,7 @@
         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
         return INVALID_OPERATION;
     }
-    int type = get_camera_metadata_tag_type(tag);
+    int type = get_local_camera_metadata_tag_type(tag, mBuffer);
     if (type == -1) {
         ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
         return BAD_VALUE;
@@ -332,8 +332,9 @@
 
     if (res != OK) {
         ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
-                __FUNCTION__, get_camera_metadata_section_name(tag),
-                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+                __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
+                get_local_camera_metadata_tag_name(tag, mBuffer), tag,
+                strerror(-res), res);
     }
 
     IF_ALOGV() {
@@ -392,16 +393,18 @@
     } else if (res != OK) {
         ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
                 __FUNCTION__,
-                get_camera_metadata_section_name(tag),
-                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+                get_local_camera_metadata_section_name(tag, mBuffer),
+                get_local_camera_metadata_tag_name(tag, mBuffer),
+                tag, strerror(-res), res);
         return res;
     }
     res = delete_camera_metadata_entry(mBuffer, entry.index);
     if (res != OK) {
         ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
                 __FUNCTION__,
-                get_camera_metadata_section_name(tag),
-                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+                get_local_camera_metadata_section_name(tag, mBuffer),
+                get_local_camera_metadata_tag_name(tag, mBuffer),
+                tag, strerror(-res), res);
     }
     return res;
 }
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index ed09b60..4c28789 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -29,6 +29,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <inttypes.h>
 
 namespace android {
 
@@ -40,11 +41,22 @@
 static const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* v, uint32_t tag);
 static int vendor_tag_descriptor_get_tag_type(const vendor_tag_ops_t* v, uint32_t tag);
 
+static int vendor_tag_descriptor_cache_get_tag_count(metadata_vendor_id_t id);
+static void vendor_tag_descriptor_cache_get_all_tags(uint32_t* tagArray,
+        metadata_vendor_id_t id);
+static const char* vendor_tag_descriptor_cache_get_section_name(uint32_t tag,
+        metadata_vendor_id_t id);
+static const char* vendor_tag_descriptor_cache_get_tag_name(uint32_t tag,
+        metadata_vendor_id_t id);
+static int vendor_tag_descriptor_cache_get_tag_type(uint32_t tag,
+        metadata_vendor_id_t id);
+
 } /* extern "C" */
 
 
 static Mutex sLock;
 static sp<VendorTagDescriptor> sGlobalVendorTagDescriptor;
+static sp<VendorTagDescriptorCache> sGlobalVendorTagDescriptorCache;
 
 namespace hardware {
 namespace camera2 {
@@ -333,11 +345,166 @@
 
 }
 
+status_t VendorTagDescriptorCache::writeToParcel(Parcel* parcel) const {
+    status_t res = OK;
+    if (parcel == NULL) {
+        ALOGE("%s: parcel argument was NULL.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    if ((res = parcel->writeInt32(mVendorMap.size())) != OK) {
+        return res;
+    }
+
+    for (const auto &iter : mVendorMap) {
+        if ((res = parcel->writeUint64(iter.first)) != OK) break;
+        if ((res = parcel->writeParcelable(*iter.second)) != OK) break;
+    }
+
+    return res;
+}
+
+
+status_t VendorTagDescriptorCache::readFromParcel(const Parcel* parcel) {
+    status_t res = OK;
+    if (parcel == NULL) {
+        ALOGE("%s: parcel argument was NULL.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    int32_t vendorCount = 0;
+    if ((res = parcel->readInt32(&vendorCount)) != OK) {
+        ALOGE("%s: could not read vendor count from parcel", __FUNCTION__);
+        return res;
+    }
+
+    if (vendorCount < 0 || vendorCount > INT32_MAX) {
+        ALOGE("%s: vendor count %d from is invalid.", __FUNCTION__, vendorCount);
+        return BAD_VALUE;
+    }
+
+    metadata_vendor_id_t id;
+    for (int32_t i = 0; i < vendorCount; i++) {
+        if ((res = parcel->readUint64(&id)) != OK) {
+            ALOGE("%s: could not read vendor id from parcel for index %d",
+                  __FUNCTION__, i);
+            break;
+        }
+        sp<android::VendorTagDescriptor> desc = new android::VendorTagDescriptor();
+        if ((res = parcel->readParcelable(desc.get())) != OK) {
+            ALOGE("%s: could not read vendor tag descriptor from parcel for index %d rc = %d",
+                  __FUNCTION__, i, res);
+            break;
+        }
+
+        if ((res = addVendorDescriptor(id, desc)) != OK) {
+            ALOGE("%s: failed to add vendor tag descriptor for index: %d ",
+                  __FUNCTION__, i);
+            break;
+        }
+    }
+
+    return res;
+}
+
+int VendorTagDescriptorCache::getTagCount(metadata_vendor_id_t id) const {
+    int ret = 0;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getTagCount();
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+void VendorTagDescriptorCache::getTagArray(uint32_t* tagArray,
+        metadata_vendor_id_t id) const {
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        desc->second->getTagArray(tagArray);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+}
+
+const char* VendorTagDescriptorCache::getSectionName(uint32_t tag,
+        metadata_vendor_id_t id) const {
+    const char *ret = nullptr;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getSectionName(tag);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+const char* VendorTagDescriptorCache::getTagName(uint32_t tag,
+        metadata_vendor_id_t id) const {
+    const char *ret = nullptr;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getTagName(tag);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+int VendorTagDescriptorCache::getTagType(uint32_t tag,
+        metadata_vendor_id_t id) const {
+    int ret = 0;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getTagType(tag);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+void VendorTagDescriptorCache::dump(int fd, int verbosity,
+        int indentation) const {
+    for (const auto &desc : mVendorMap) {
+        dprintf(fd, "%*sDumping vendor tag descriptors for vendor with"
+                " id %" PRIu64 " \n", indentation, "", desc.first);
+        desc.second->dump(fd, verbosity, indentation);
+    }
+}
+
+int32_t VendorTagDescriptorCache::addVendorDescriptor(metadata_vendor_id_t id,
+        sp<android::VendorTagDescriptor> desc) {
+    auto entry = mVendorMap.find(id);
+    if (entry != mVendorMap.end()) {
+        ALOGE("%s: Vendor descriptor with same id already present!", __func__);
+        return BAD_VALUE;
+    }
+
+    mVendorMap.emplace(id, desc);
+    return NO_ERROR;
+}
+
+int32_t VendorTagDescriptorCache::getVendorTagDescriptor(
+        metadata_vendor_id_t id, sp<android::VendorTagDescriptor> *desc /*out*/) {
+    auto entry = mVendorMap.find(id);
+    if (entry == mVendorMap.end()) {
+        return NAME_NOT_FOUND;
+    }
+
+    *desc = entry->second;
+
+    return NO_ERROR;
+}
+
 } // namespace params
 } // namespace camera2
 } // namespace hardware
 
-
 status_t VendorTagDescriptor::createDescriptorFromOps(const vendor_tag_ops_t* vOps,
             /*out*/
             sp<VendorTagDescriptor>& descriptor) {
@@ -451,6 +618,39 @@
     return sGlobalVendorTagDescriptor;
 }
 
+status_t VendorTagDescriptorCache::setAsGlobalVendorTagCache(
+        const sp<VendorTagDescriptorCache>& cache) {
+    status_t res = OK;
+    Mutex::Autolock al(sLock);
+    sGlobalVendorTagDescriptorCache = cache;
+
+    struct vendor_tag_cache_ops* opsPtr = NULL;
+    if (cache != NULL) {
+        opsPtr = &(cache->mVendorCacheOps);
+        opsPtr->get_tag_count = vendor_tag_descriptor_cache_get_tag_count;
+        opsPtr->get_all_tags = vendor_tag_descriptor_cache_get_all_tags;
+        opsPtr->get_section_name = vendor_tag_descriptor_cache_get_section_name;
+        opsPtr->get_tag_name = vendor_tag_descriptor_cache_get_tag_name;
+        opsPtr->get_tag_type = vendor_tag_descriptor_cache_get_tag_type;
+    }
+    if((res = set_camera_metadata_vendor_cache_ops(opsPtr)) != OK) {
+        ALOGE("%s: Could not set vendor tag cache, received error %s (%d)."
+                , __FUNCTION__, strerror(-res), res);
+    }
+    return res;
+}
+
+void VendorTagDescriptorCache::clearGlobalVendorTagCache() {
+    Mutex::Autolock al(sLock);
+    set_camera_metadata_vendor_cache_ops(NULL);
+    sGlobalVendorTagDescriptorCache.clear();
+}
+
+sp<VendorTagDescriptorCache> VendorTagDescriptorCache::getGlobalVendorTagCache() {
+    Mutex::Autolock al(sLock);
+    return sGlobalVendorTagDescriptorCache;
+}
+
 extern "C" {
 
 int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* /*v*/) {
@@ -498,5 +698,53 @@
     return sGlobalVendorTagDescriptor->getTagType(tag);
 }
 
+int vendor_tag_descriptor_cache_get_tag_count(metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_TAG_COUNT_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getTagCount(id);
+}
+
+void vendor_tag_descriptor_cache_get_all_tags(uint32_t* tagArray,
+        metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+    }
+    sGlobalVendorTagDescriptorCache->getTagArray(tagArray, id);
+}
+
+const char* vendor_tag_descriptor_cache_get_section_name(uint32_t tag,
+        metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_SECTION_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getSectionName(tag, id);
+}
+
+const char* vendor_tag_descriptor_cache_get_tag_name(uint32_t tag,
+        metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_TAG_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getTagName(tag, id);
+}
+
+int vendor_tag_descriptor_cache_get_tag_type(uint32_t tag,
+        metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_TAG_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getTagType(tag, id);
+}
+
 } /* extern "C" */
 } /* namespace android */
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 99c479c..9c0f28b 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -21,6 +21,7 @@
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.params.VendorTagDescriptor;
+import android.hardware.camera2.params.VendorTagDescriptorCache;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.ICameraServiceListener;
 import android.hardware.CameraInfo;
@@ -130,6 +131,14 @@
     VendorTagDescriptor getCameraVendorTagDescriptor();
 
     /**
+     * Retrieve the vendor tag descriptor cache which can have multiple vendor
+     * providers.
+     * Intended to be used by the native code of CameraMetadataNative to correctly
+     * interpret camera metadata with vendor tags.
+     */
+    VendorTagDescriptorCache getCameraVendorTagCache();
+
+    /**
      * Read the legacy camera1 parameters into a String
      */
     String getLegacyParameters(int cameraId);
diff --git a/camera/aidl/android/hardware/camera2/params/VendorTagDescriptorCache.aidl b/camera/aidl/android/hardware/camera2/params/VendorTagDescriptorCache.aidl
new file mode 100644
index 0000000..d212207
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/params/VendorTagDescriptorCache.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+/** @hide */
+parcelable VendorTagDescriptorCache cpp_header "camera/VendorTagDescriptor.h";
diff --git a/camera/include/camera/VendorTagDescriptor.h b/camera/include/camera/VendorTagDescriptor.h
index adfc8c7..904fba2 100644
--- a/camera/include/camera/VendorTagDescriptor.h
+++ b/camera/include/camera/VendorTagDescriptor.h
@@ -22,7 +22,7 @@
 #include <utils/String8.h>
 #include <utils/RefBase.h>
 #include <system/camera_vendor_tags.h>
-
+#include <unordered_map>
 #include <stdint.h>
 
 namespace android {
@@ -166,8 +166,84 @@
 
 };
 
-} /* namespace android */
+namespace hardware {
+namespace camera2 {
+namespace params {
 
+class VendorTagDescriptorCache : public Parcelable {
+  public:
+
+    VendorTagDescriptorCache() {};
+
+    int32_t addVendorDescriptor(metadata_vendor_id_t id,
+            sp<android::VendorTagDescriptor> desc);
+
+    int32_t getVendorTagDescriptor(
+            metadata_vendor_id_t id,
+            sp<android::VendorTagDescriptor> *desc /*out*/);
+
+    // Parcelable interface
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    // Returns the number of vendor tags defined.
+    int getTagCount(metadata_vendor_id_t id) const;
+
+    // Returns an array containing the id's of vendor tags defined.
+    void getTagArray(uint32_t* tagArray, metadata_vendor_id_t id) const;
+
+    // Returns the section name string for a given vendor tag id.
+    const char* getSectionName(uint32_t tag, metadata_vendor_id_t id) const;
+
+    // Returns the tag name string for a given vendor tag id.
+    const char* getTagName(uint32_t tag, metadata_vendor_id_t id) const;
+
+    // Returns the tag type for a given vendor tag id.
+    int getTagType(uint32_t tag, metadata_vendor_id_t id) const;
+
+    /**
+     * Dump the currently configured vendor tags to a file descriptor.
+     */
+    void dump(int fd, int verbosity, int indentation) const;
+
+  protected:
+    std::unordered_map<metadata_vendor_id_t, sp<android::VendorTagDescriptor>> mVendorMap;
+    struct vendor_tag_cache_ops mVendorCacheOps;
+};
+
+} /* namespace params */
+} /* namespace camera2 */
+} /* namespace hardware */
+
+class VendorTagDescriptorCache :
+        public ::android::hardware::camera2::params::VendorTagDescriptorCache,
+        public LightRefBase<VendorTagDescriptorCache> {
+  public:
+
+    /**
+     * Sets the global vendor tag descriptor cache to use for this process.
+     * Camera metadata operations that access vendor tags will use the
+     * vendor tag definitions set this way.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t setAsGlobalVendorTagCache(
+            const sp<VendorTagDescriptorCache>& cache);
+
+    /**
+     * Returns the global vendor tag cache used by this process.
+     * This will contain NULL if no vendor tags are defined.
+     */
+    static sp<VendorTagDescriptorCache> getGlobalVendorTagCache();
+
+    /**
+     * Clears the global vendor tag cache used by this process.
+     */
+    static void clearGlobalVendorTagCache();
+
+};
+
+} /* namespace android */
 
 #define VENDOR_TAG_DESCRIPTOR_H
 #endif /* VENDOR_TAG_DESCRIPTOR_H */
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index ba2100c..3f64bcc 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -131,10 +131,36 @@
         binder::Status ret = mCameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
 
         if (ret.isOk()) {
-            status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
-            if (err != OK) {
-                ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
-                        __FUNCTION__, strerror(-err), err);
+            if (0 < desc->getTagCount()) {
+                status_t err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
+                if (err != OK) {
+                    ALOGE("%s: Failed to set vendor tag descriptors, received error %s (%d)",
+                            __FUNCTION__, strerror(-err), err);
+                }
+            } else {
+                sp<VendorTagDescriptorCache> cache =
+                        new VendorTagDescriptorCache();
+                binder::Status res =
+                        mCameraService->getCameraVendorTagCache(
+                                /*out*/cache.get());
+                if (res.serviceSpecificErrorCode() ==
+                        hardware::ICameraService::ERROR_DISCONNECTED) {
+                    // No camera module available, not an error on devices with no cameras
+                    VendorTagDescriptorCache::clearGlobalVendorTagCache();
+                } else if (res.isOk()) {
+                    status_t err =
+                            VendorTagDescriptorCache::setAsGlobalVendorTagCache(
+                                    cache);
+                    if (err != OK) {
+                        ALOGE("%s: Failed to set vendor tag cache,"
+                                "received error %s (%d)", __FUNCTION__,
+                                strerror(-err), err);
+                    }
+                } else {
+                    VendorTagDescriptorCache::clearGlobalVendorTagCache();
+                    ALOGE("%s: Failed to setup vendor tag cache: %s",
+                            __FUNCTION__, res.toString8().string());
+                }
             }
         } else if (ret.serviceSpecificErrorCode() ==
                 hardware::ICameraService::ERROR_DEPRECATED_HAL) {