Merge "Camera: Don't advertize zoom in case max digital zoom is 1" into oc-dev
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) {
diff --git a/drm/libmediadrm/CasImpl.cpp b/drm/libmediadrm/CasImpl.cpp
index de15244..fcedd6b 100644
--- a/drm/libmediadrm/CasImpl.cpp
+++ b/drm/libmediadrm/CasImpl.cpp
@@ -49,13 +49,24 @@
     return result;
 }
 
+struct CasImpl::PluginHolder : public RefBase {
+public:
+    explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
+    ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
+    CasPlugin* get() { return mPlugin; }
+
+private:
+    CasPlugin *mPlugin;
+    DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
+};
+
 CasImpl::CasImpl(const sp<ICasListener> &listener)
-    : mPlugin(NULL), mListener(listener) {
-    ALOGV("CTOR: mPlugin=%p", mPlugin);
+    : mPluginHolder(NULL), mListener(listener) {
+    ALOGV("CTOR");
 }
 
 CasImpl::~CasImpl() {
-    ALOGV("DTOR: mPlugin=%p", mPlugin);
+    ALOGV("DTOR");
     release();
 }
 
@@ -76,7 +87,7 @@
 
 void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
     mLibrary = library;
-    mPlugin = plugin;
+    mPluginHolder = new PluginHolder(plugin);
 }
 
 void CasImpl::onEvent(
@@ -95,13 +106,20 @@
 
 Status CasImpl::setPrivateData(const CasData& pvtData) {
     ALOGV("setPrivateData");
-    return getBinderStatus(mPlugin->setPrivateData(pvtData));
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
+    return getBinderStatus(holder->get()->setPrivateData(pvtData));
 }
 
 Status CasImpl::openSession(int32_t program_number, CasSessionId* sessionId) {
     ALOGV("openSession: program_number=%d", program_number);
-
-    status_t err = mPlugin->openSession(program_number, sessionId);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
+    status_t err = holder->get()->openSession(program_number, sessionId);
 
     ALOGV("openSession: session opened for program_number=%d, sessionId=%s",
             program_number, sessionIdToString(*sessionId).string());
@@ -115,8 +133,11 @@
         CasSessionId* sessionId) {
     ALOGV("openSession: program_number=%d, elementary_PID=%d",
             program_number, elementary_PID);
-
-    status_t err = mPlugin->openSession(
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
+    status_t err = holder->get()->openSession(
             program_number, elementary_PID, sessionId);
 
     ALOGV("openSession: session opened for "
@@ -131,69 +152,92 @@
         const CasSessionId &sessionId, const CasData& pvtData) {
     ALOGV("setSessionPrivateData: sessionId=%s",
             sessionIdToString(sessionId).string());
-
-    return getBinderStatus(mPlugin->setSessionPrivateData(sessionId, pvtData));
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
+    return getBinderStatus(holder->get()->setSessionPrivateData(sessionId, pvtData));
 }
 
 Status CasImpl::closeSession(const CasSessionId &sessionId) {
     ALOGV("closeSession: sessionId=%s",
             sessionIdToString(sessionId).string());
-
-    return getBinderStatus(mPlugin->closeSession(sessionId));
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
+    return getBinderStatus(holder->get()->closeSession(sessionId));
 }
 
 Status CasImpl::processEcm(const CasSessionId &sessionId, const ParcelableCasData& ecm) {
     ALOGV("processEcm: sessionId=%s",
             sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
 
-    return getBinderStatus(mPlugin->processEcm(sessionId, ecm));
+    return getBinderStatus(holder->get()->processEcm(sessionId, ecm));
 }
 
 Status CasImpl::processEmm(const ParcelableCasData& emm) {
     ALOGV("processEmm");
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
 
-    return getBinderStatus(mPlugin->processEmm(emm));
+    return getBinderStatus(holder->get()->processEmm(emm));
 }
 
 Status CasImpl::sendEvent(
         int32_t event, int32_t arg, const ::std::unique_ptr<CasData> &eventData) {
     ALOGV("sendEvent");
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
 
     status_t err;
     if (eventData == nullptr) {
-        err = mPlugin->sendEvent(event, arg, CasData());
+        err = holder->get()->sendEvent(event, arg, CasData());
     } else {
-        err = mPlugin->sendEvent(event, arg, *eventData);
+        err = holder->get()->sendEvent(event, arg, *eventData);
     }
     return getBinderStatus(err);
 }
 
 Status CasImpl::provision(const String16& provisionString) {
     ALOGV("provision: provisionString=%s", String8(provisionString).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
 
-    return getBinderStatus(mPlugin->provision(String8(provisionString)));
+    return getBinderStatus(holder->get()->provision(String8(provisionString)));
 }
 
 Status CasImpl::refreshEntitlements(
         int32_t refreshType, const ::std::unique_ptr<CasData> &refreshData) {
     ALOGV("refreshEntitlements");
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return getBinderStatus(INVALID_OPERATION);
+    }
 
     status_t err;
     if (refreshData == nullptr) {
-        err = mPlugin->refreshEntitlements(refreshType, CasData());
+        err = holder->get()->refreshEntitlements(refreshType, CasData());
     } else {
-        err = mPlugin->refreshEntitlements(refreshType, *refreshData);
+        err = holder->get()->refreshEntitlements(refreshType, *refreshData);
     }
     return getBinderStatus(err);
 }
 
 Status CasImpl::release() {
-    ALOGV("release: mPlugin=%p", mPlugin);
-
-    if (mPlugin != NULL) {
-        delete mPlugin;
-        mPlugin = NULL;
-    }
+    ALOGV("release: plugin=%p",
+            mPluginHolder == NULL ? mPluginHolder->get() : NULL);
+    mPluginHolder.clear();
     return Status::ok();
 }
 
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index 221b74b..f4c3577 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -84,7 +84,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 ClearKeyCasPlugin::ClearKeyCasPlugin(
         uint64_t appData, CasPluginCallback callback)
-    : mAppData(appData), mCallback(callback) {
+    : mCallback(callback), mAppData(appData) {
     ALOGV("CTOR");
 }
 
@@ -93,7 +93,7 @@
     ClearKeySessionLibrary::get()->destroyPlugin(this);
 }
 
-status_t ClearKeyCasPlugin::setPrivateData(const CasData &data) {
+status_t ClearKeyCasPlugin::setPrivateData(const CasData &/*data*/) {
     ALOGV("setPrivateData");
 
     return OK;
@@ -142,7 +142,7 @@
 }
 
 status_t ClearKeyCasPlugin::setSessionPrivateData(
-        const CasSessionId &sessionId, const CasData &data) {
+        const CasSessionId &sessionId, const CasData & /*data*/) {
     ALOGV("setSessionPrivateData: sessionId=%s",
             sessionIdToString(sessionId).string());
     sp<ClearKeyCasSession> session =
@@ -167,7 +167,7 @@
     return session->updateECM(mKeyFetcher.get(), (void*)ecm.data(), ecm.size());
 }
 
-status_t ClearKeyCasPlugin::processEmm(const CasEmm& emm) {
+status_t ClearKeyCasPlugin::processEmm(const CasEmm& /*emm*/) {
     ALOGV("processEmm");
     Mutex::Autolock lock(mKeyFetcherLock);
 
@@ -212,8 +212,8 @@
 }
 
 status_t ClearKeyCasPlugin::refreshEntitlements(
-        int32_t refreshType, const CasData &refreshData) {
-    ALOGV("refreshEntitlements");
+        int32_t refreshType, const CasData &/*refreshData*/) {
+    ALOGV("refreshEntitlements: refreshType=%d", refreshType);
     Mutex::Autolock lock(mKeyFetcherLock);
 
     return OK;
@@ -344,7 +344,7 @@
                 AES_BLOCK_SIZE * 8, &mKeyInfo[keyIndex].contentKey);
         mKeyInfo[keyIndex].valid = (result == 0);
         if (!mKeyInfo[keyIndex].valid) {
-            ALOGE("updateECM: failed to set key %d, key_id=%d",
+            ALOGE("updateECM: failed to set key %zu, key_id=%d",
                     keyIndex, keys[keyIndex].key_id);
         }
     }
@@ -356,6 +356,10 @@
         bool secure, DescramblerPlugin::ScramblingControl scramblingControl,
         size_t numSubSamples, const DescramblerPlugin::SubSample *subSamples,
         const void *srcPtr, void *dstPtr, AString * /* errorDetailMsg */) {
+    if (secure) {
+        return ERROR_DRM_CANNOT_HANDLE;
+    }
+
     AES_KEY contentKey;
 
     if (scramblingControl != DescramblerPlugin::kScrambling_Unscrambled) {
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
index 210bab3..cb69f91 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "ClearKeyFetcher"
 
 #include <algorithm>
+#include <inttypes.h>
 #include <string>
 
 #include "ClearKeyFetcher.h"
@@ -70,7 +71,7 @@
         bool same_parity = (((container.descriptor(0).id() & 0x01) ^
                 (container.descriptor(1).id() & 0x01)) == 0);
         if (same_parity) {
-            ALOGW("asset_id=%llu: malformed Ecm, "
+            ALOGW("asset_id=%" PRIu64 ": malformed Ecm, "
                     "content keys have same parity, id0=%d, id1=%d",
                     container.descriptor(0).ecm().asset_id(),
                     container.descriptor(0).id(),
@@ -88,7 +89,7 @@
     // asset_id change. If it sends an EcmContainer with 2 Ecms with different
     // asset_ids (old and new) then it might be best to prefetch the Emm.
     if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
-        ALOGW("Asset_id change from %llu to %llu", asset_.id(), *asset_id);
+        ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
         asset_.Clear();
     }
 
diff --git a/drm/mediacas/plugins/clearkey/ecm_generator.cpp b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
index f1aa973..7d29659 100644
--- a/drm/mediacas/plugins/clearkey/ecm_generator.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
@@ -80,7 +80,7 @@
     CHECK(default_fields);
 
     if (ecm->size() < kTotalEcmSize) {
-        ALOGE("Short ECM: expected_length=%zu, actual_length=%zu",
+        ALOGE("Short ECM: expected_length=%d, actual_length=%zu",
                 kTotalEcmSize, ecm->size());
         return BAD_VALUE;
     }
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index d5a47ca..58421b9 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -63,22 +63,28 @@
             Vector<uint8_t>& keySetId);
 
     virtual status_t removeKeys(const Vector<uint8_t>& sessionId) {
-        UNUSED(sessionId);
+        if (sessionId.size() == 0) {
+            return android::BAD_VALUE;
+        }
+
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
     virtual status_t restoreKeys(
             const Vector<uint8_t>& sessionId,
             const Vector<uint8_t>& keySetId) {
-        UNUSED(sessionId);
-        UNUSED(keySetId);
+        if (sessionId.size() == 0 || keySetId.size() == 0) {
+            return android::BAD_VALUE;
+        }
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
     virtual status_t queryKeyStatus(
             const Vector<uint8_t>& sessionId,
             KeyedVector<String8, String8>& infoMap) const {
-        UNUSED(sessionId);
+        if (sessionId.size() == 0) {
+            return android::BAD_VALUE;
+        }
         UNUSED(infoMap);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
@@ -179,10 +185,10 @@
             const Vector<uint8_t>& input,
             const Vector<uint8_t>& iv,
             Vector<uint8_t>& output) {
-        UNUSED(sessionId);
-        UNUSED(keyId);
-        UNUSED(input);
-        UNUSED(iv);
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                input.size() == 0 || iv.size() == 0) {
+            return android::BAD_VALUE;
+        }
         UNUSED(output);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
@@ -193,10 +199,10 @@
             const Vector<uint8_t>& input,
             const Vector<uint8_t>& iv,
             Vector<uint8_t>& output) {
-        UNUSED(sessionId);
-        UNUSED(keyId);
-        UNUSED(input);
-        UNUSED(iv);
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                input.size() == 0 || iv.size() == 0) {
+            return android::BAD_VALUE;
+        }
         UNUSED(output);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
@@ -206,9 +212,10 @@
             const Vector<uint8_t>& keyId,
             const Vector<uint8_t>& message,
             Vector<uint8_t>& signature) {
-        UNUSED(sessionId);
-        UNUSED(keyId);
-        UNUSED(message);
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                message.size() == 0) {
+            return android::BAD_VALUE;
+        }
         UNUSED(signature);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
@@ -218,10 +225,10 @@
             const Vector<uint8_t>& keyId,
             const Vector<uint8_t>& message,
             const Vector<uint8_t>& signature, bool& match) {
-        UNUSED(sessionId);
-        UNUSED(keyId);
-        UNUSED(message);
-        UNUSED(signature);
+        if (sessionId.size() == 0 || keyId.size() == 0 ||
+                message.size() == 0 || signature.size() == 0) {
+            return android::BAD_VALUE;
+        }
         UNUSED(match);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
@@ -232,10 +239,10 @@
             const Vector<uint8_t>& message,
             const Vector<uint8_t>& wrappedKey,
             Vector<uint8_t>& signature) {
-        UNUSED(sessionId);
-        UNUSED(algorithm);
-        UNUSED(message);
-        UNUSED(wrappedKey);
+        if (sessionId.size() == 0 || algorithm.size() == 0 ||
+                message.size() == 0 || wrappedKey.size() == 0) {
+            return android::BAD_VALUE;
+        }
         UNUSED(signature);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
diff --git a/include/media/CasImpl.h b/include/media/CasImpl.h
index 80c901e..3c07092 100644
--- a/include/media/CasImpl.h
+++ b/include/media/CasImpl.h
@@ -84,8 +84,9 @@
     virtual Status release() override;
 
 private:
+    struct PluginHolder;
     sp<SharedLibrary> mLibrary;
-    CasPlugin *mPlugin;
+    sp<PluginHolder> mPluginHolder;
     sp<ICasListener> mListener;
 
     DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
diff --git a/include/media/IMediaAnalyticsService.h b/include/media/IMediaAnalyticsService.h
index 97915e4..a596d60 120000
--- a/include/media/IMediaAnalyticsService.h
+++ b/include/media/IMediaAnalyticsService.h
@@ -1 +1 @@
-../../media/libmedia/include/IMediaAnalyticsService.h
\ No newline at end of file
+../../media/libmediametrics/include/IMediaAnalyticsService.h
\ No newline at end of file
diff --git a/include/media/MediaAnalyticsItem.h b/include/media/MediaAnalyticsItem.h
index 71957a5..e8124e0 120000
--- a/include/media/MediaAnalyticsItem.h
+++ b/include/media/MediaAnalyticsItem.h
@@ -1 +1 @@
-../../media/libmedia/include/MediaAnalyticsItem.h
\ No newline at end of file
+../../media/libmediametrics/include/MediaAnalyticsItem.h
\ No newline at end of file
diff --git a/include/ndk/NdkMediaDrm.h b/include/ndk/NdkMediaDrm.h
index 9dd6283..cba4380 100644
--- a/include/ndk/NdkMediaDrm.h
+++ b/include/ndk/NdkMediaDrm.h
@@ -159,8 +159,7 @@
  * to obtain or release keys used to decrypt encrypted content.
  * AMediaDrm_getKeyRequest is used to obtain an opaque key request byte array that
  * is delivered to the license server.  The opaque key request byte array is
- * returned in KeyRequest.data.  The recommended URL to deliver the key request to
- * is returned in KeyRequest.defaultUrl.
+ * returned in KeyRequest.data.
  *
  * After the app has received the key request response from the server,
  * it should deliver to the response to the DRM engine plugin using the method
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 921248a..551dcc9 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -15,7 +15,16 @@
  */
 
 /**
- * This is the 'C' ABI for AAudio.
+ * @addtogroup Audio
+ * @{
+ */
+
+/**
+ * @file AAudio.h
+ */
+
+/**
+ * This is the 'C' API for AAudio.
  */
 #ifndef AAUDIO_AAUDIO_H
 #define AAUDIO_AAUDIO_H
@@ -525,3 +534,5 @@
 #endif
 
 #endif //AAUDIO_AAUDIO_H
+
+/** @} */
diff --git a/media/libaaudio/include/aaudio/AAudioDefinitions.h b/media/libaaudio/include/aaudio/AAudioDefinitions.h
index 846318c..fbd284c 100644
--- a/media/libaaudio/include/aaudio/AAudioDefinitions.h
+++ b/media/libaaudio/include/aaudio/AAudioDefinitions.h
@@ -14,6 +14,15 @@
  * limitations under the License.
  */
 
+/**
+ * @addtogroup Audio
+ * @{
+ */
+
+/**
+ * @file AAudioDefinitions.h
+ */
+
 #ifndef AAUDIO_AAUDIODEFINITIONS_H
 #define AAUDIO_AAUDIODEFINITIONS_H
 
@@ -117,3 +126,5 @@
 #endif
 
 #endif // AAUDIO_AAUDIODEFINITIONS_H
+
+/** @} */
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index 554c14d..523b6e1 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -48,6 +48,7 @@
 static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
                           // was not modified since last call to EffectQueryNumberEffects()
 
+static list_elem_t *gLibraryFailedList;  //list of lib_failed_entry_t: libraries failed to load
 
 /////////////////////////////////////////////////
 //      Local functions prototypes
@@ -584,6 +585,17 @@
     if (hdl != NULL) {
         dlclose(hdl);
     }
+    //add entry for library errors in gLibraryFailedList
+    lib_failed_entry_t *fl = malloc(sizeof(lib_failed_entry_t));
+    fl->name = strndup(name, PATH_MAX);
+    fl->path = strndup(path, PATH_MAX);
+
+    list_elem_t *fe = malloc(sizeof(list_elem_t));
+    fe->object = fl;
+    fe->next = gLibraryFailedList;
+    gLibraryFailedList = fe;
+    ALOGV("getLibrary() linked error in library %p for path %s", fl, path);
+
     return -EINVAL;
 }
 
@@ -986,16 +998,31 @@
 
 int EffectDumpEffects(int fd) {
     char s[512];
+
+    list_elem_t *fe = gLibraryFailedList;
+    lib_failed_entry_t *fl = NULL;
+
+    dprintf(fd, "Libraries NOT loaded:\n");
+
+    while (fe) {
+        fl = (lib_failed_entry_t *)fe->object;
+        dprintf(fd, " Library %s\n", fl->name);
+        dprintf(fd, "  path: %s\n", fl->path);
+        fe = fe->next;
+    }
+
     list_elem_t *e = gLibraryList;
     lib_entry_t *l = NULL;
     effect_descriptor_t *d = NULL;
     int found = 0;
     int ret = 0;
 
+    dprintf(fd, "Libraries loaded:\n");
     while (e) {
         l = (lib_entry_t *)e->object;
         list_elem_t *efx = l->effects;
-        dprintf(fd, "Library %s\n", l->name);
+        dprintf(fd, " Library %s\n", l->name);
+        dprintf(fd, "  path: %s\n", l->path);
         if (!efx) {
             dprintf(fd, "  (no effects)\n");
         }
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
index b7936e0..72e0931 100644
--- a/media/libeffects/factory/EffectsFactory.h
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -58,6 +58,11 @@
     lib_entry_t *lib;
 } effect_entry_t;
 
+typedef struct lib_failed_entry_s {
+    char *name;
+    char *path;
+} lib_failed_entry_t;
+
 // Structure used to store the lib entry
 // and the descriptor of the sub effects.
 // The library entry is to be stored in case of
@@ -69,6 +74,7 @@
 } sub_effect_entry_t;
 
 
+
 ////////////////////////////////////////////////////////////////////////////////
 //
 //    Function:       EffectGetSubEffects
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 8a1ce22..b0bd22e 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -26,7 +26,6 @@
     IMediaPlayer.cpp \
     IMediaRecorder.cpp \
     IMediaSource.cpp \
-    IMediaAnalyticsService.cpp \
     IRemoteDisplay.cpp \
     IRemoteDisplayClient.cpp \
     IResourceManagerClient.cpp \
@@ -35,7 +34,6 @@
     MediaCodecBuffer.cpp \
     MediaCodecInfo.cpp \
     MediaDefs.cpp \
-    MediaAnalyticsItem.cpp \
     MediaUtils.cpp \
     Metadata.cpp \
     mediarecorder.cpp \
@@ -66,6 +64,7 @@
         libcamera_client libstagefright_foundation \
         libgui libdl libaudioutils libaudioclient \
         libmedia_helper libmediadrm \
+        libmediametrics \
         libbase \
         libhidlbase \
         libhidltransport \
diff --git a/media/libmedia/include/mediaplayer.h b/media/libmedia/include/mediaplayer.h
index 18d69a7..623c374 100644
--- a/media/libmedia/include/mediaplayer.h
+++ b/media/libmedia/include/mediaplayer.h
@@ -133,6 +133,10 @@
     MEDIA_INFO_NOT_SEEKABLE = 801,
     // New media metadata is available.
     MEDIA_INFO_METADATA_UPDATE = 802,
+    // Audio can not be played.
+    MEDIA_INFO_PLAY_AUDIO_ERROR = 804,
+    // Video can not be played.
+    MEDIA_INFO_PLAY_VIDEO_ERROR = 805,
 
     //9xx
     MEDIA_INFO_TIMED_TEXT_ERROR = 900,
diff --git a/media/libmedia/omx/1.0/WOmxNode.cpp b/media/libmedia/omx/1.0/WOmxNode.cpp
index b5186b5..6c92b52 100644
--- a/media/libmedia/omx/1.0/WOmxNode.cpp
+++ b/media/libmedia/omx/1.0/WOmxNode.cpp
@@ -411,7 +411,7 @@
         getExtensionIndex_cb _hidl_cb) {
     OMX_INDEXTYPE index;
     Status status = toStatus(mBase->getExtensionIndex(
-            parameterName, &index));
+            parameterName.c_str(), &index));
     _hidl_cb(status, toRawIndexType(index));
     return Void();
 }
diff --git a/media/libmediametrics/Android.mk b/media/libmediametrics/Android.mk
new file mode 100644
index 0000000..f8c4bb3
--- /dev/null
+++ b/media/libmediametrics/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES += \
+    IMediaAnalyticsService.cpp \
+    MediaAnalyticsItem.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+        liblog libcutils libutils libbinder \
+        libstagefright_foundation \
+        libbase \
+
+LOCAL_MODULE:= libmediametrics
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_C_INCLUDES := \
+    $(TOP)/system/libhidl/base/include \
+    $(TOP)/frameworks/native/include/media/openmax \
+    $(TOP)/frameworks/av/include/media/ \
+    $(TOP)/frameworks/av/media/libmedia/aidl \
+    $(TOP)/frameworks/av/include \
+    $(TOP)/frameworks/native/include \
+    $(call include-path-for, audio-utils)
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    frameworks/av/include/media \
+
+LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
+LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow cfi
+LOCAL_SANITIZE_DIAG := cfi
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/IMediaAnalyticsService.cpp b/media/libmediametrics/IMediaAnalyticsService.cpp
similarity index 94%
rename from media/libmedia/IMediaAnalyticsService.cpp
rename to media/libmediametrics/IMediaAnalyticsService.cpp
index 340cf19..68bafe1 100644
--- a/media/libmedia/IMediaAnalyticsService.cpp
+++ b/media/libmediametrics/IMediaAnalyticsService.cpp
@@ -23,15 +23,6 @@
 #include <binder/Parcel.h>
 #include <binder/IMemory.h>
 #include <binder/IPCThreadState.h>
-#include <media/IHDCP.h>
-#include <media/IMediaCodecList.h>
-#include <media/IMediaHTTPService.h>
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaRecorder.h>
-#include <media/IOMX.h>
-#include <media/IRemoteDisplay.h>
-#include <media/IRemoteDisplayClient.h>
-#include <media/IStreamSource.h>
 
 #include <utils/Errors.h>  // for status_t
 #include <utils/List.h>
diff --git a/media/libmedia/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
similarity index 100%
rename from media/libmedia/MediaAnalyticsItem.cpp
rename to media/libmediametrics/MediaAnalyticsItem.cpp
diff --git a/media/libmedia/include/IMediaAnalyticsService.h b/media/libmediametrics/include/IMediaAnalyticsService.h
similarity index 100%
rename from media/libmedia/include/IMediaAnalyticsService.h
rename to media/libmediametrics/include/IMediaAnalyticsService.h
diff --git a/media/libmedia/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h
similarity index 100%
rename from media/libmedia/include/MediaAnalyticsItem.h
rename to media/libmediametrics/include/MediaAnalyticsItem.h
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index f7e1ff5..7af7031 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -27,6 +27,7 @@
     libgui                      \
     libaudioclient              \
     libmedia                    \
+    libmediametrics             \
     libmediadrm                 \
     libmediautils               \
     libmemunreachable           \
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 510794c..d9a5c26 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -197,6 +197,8 @@
       mPrepared(false),
       mResetting(false),
       mSourceStarted(false),
+      mAudioDecoderError(false),
+      mVideoDecoderError(false),
       mPaused(false),
       mPausedByClient(true),
       mPausedForBuffering(false),
@@ -1093,12 +1095,14 @@
                 ALOGV("%s shutdown completed", audio ? "audio" : "video");
                 if (audio) {
                     mAudioDecoder.clear();
+                    mAudioDecoderError = false;
                     ++mAudioDecoderGeneration;
 
                     CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
                     mFlushingAudio = SHUT_DOWN;
                 } else {
                     mVideoDecoder.clear();
+                    mVideoDecoderError = false;
                     ++mVideoDecoderGeneration;
 
                     CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
@@ -1153,7 +1157,29 @@
                         finishFlushIfPossible();  // Should not occur.
                         break;                    // Finish anyways.
                 }
-                notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+                if (mSource != nullptr) {
+                    if (audio) {
+                        if (mVideoDecoderError || mSource->getFormat(false /* audio */) == NULL) {
+                            // When both audio and video have error, or this stream has only audio
+                            // which has error, notify client of error.
+                            notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+                        } else {
+                            // Only audio track has error. Video track could be still good to play.
+                            notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
+                        }
+                        mAudioDecoderError = true;
+                    } else {
+                        if (mAudioDecoderError || mSource->getFormat(true /* audio */) == NULL) {
+                            // When both audio and video have error, or this stream has only video
+                            // which has error, notify client of error.
+                            notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+                        } else {
+                            // Only video track has error. Audio track could be still good to play.
+                            notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
+                        }
+                        mVideoDecoderError = true;
+                    }
+                }
             } else {
                 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
                       what,
@@ -1617,7 +1643,8 @@
     // is possible; otherwise the decoders call the renderer openAudioSink directly.
 
     status_t err = mRenderer->openAudioSink(
-            format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio);
+            format, true /* offloadOnly */, hasVideo,
+            AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mSource->isStreaming());
     if (err != OK) {
         // Any failure we turn off mOffloadAudio.
         mOffloadAudio = false;
@@ -1635,6 +1662,7 @@
     if (mAudioDecoder != NULL) {
         mAudioDecoder->pause();
         mAudioDecoder.clear();
+        mAudioDecoderError = false;
         ++mAudioDecoderGeneration;
     }
     if (mFlushingAudio == FLUSHING_DECODER) {
@@ -1772,6 +1800,7 @@
             *decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer);
             ALOGV("instantiateDecoder audio Decoder");
         }
+        mAudioDecoderError = false;
     } else {
         sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
         ++mVideoDecoderGeneration;
@@ -1779,6 +1808,7 @@
 
         *decoder = new Decoder(
                 notify, mSource, mPID, mUID, mRenderer, mSurface, mCCDecoder);
+        mVideoDecoderError = false;
 
         // enable FRC if high-quality AV sync is requested, even if not
         // directly queuing to display, as this will even improve textureview
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index d3cb7c1..d542749 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -218,6 +218,8 @@
     bool mPrepared;
     bool mResetting;
     bool mSourceStarted;
+    bool mAudioDecoderError;
+    bool mVideoDecoderError;
 
     // Actual pause state, either as requested by client or due to buffering.
     bool mPaused;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 9a2224e..9e579f9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -762,8 +762,7 @@
         int64_t durationUs;
         bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
         if (getAudioDeepBufferSetting() // override regardless of source duration
-                || (!hasVideo
-                        && mSource->getDuration(&durationUs) == OK
+                || (mSource->getDuration(&durationUs) == OK
                         && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
             flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
         } else {
@@ -773,7 +772,8 @@
         sp<AMessage> reply = new AMessage(kWhatAudioOutputFormatChanged, this);
         reply->setInt32("generation", mBufferGeneration);
         mRenderer->changeAudioFormat(
-                format, false /* offloadOnly */, hasVideo, flags, reply);
+                format, false /* offloadOnly */, hasVideo,
+                flags, mSource->isStreaming(), reply);
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index 9a4bc8c..6b05b53 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -76,7 +76,7 @@
     // format is different.
     status_t err = mRenderer->openAudioSink(
             format, true /* offloadOnly */, hasVideo,
-            AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */);
+            AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */, mSource->isStreaming());
     if (err != OK) {
         handleError(err);
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 9350440..9fe61703 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -397,12 +397,14 @@
         bool offloadOnly,
         bool hasVideo,
         uint32_t flags,
-        bool *isOffloaded) {
+        bool *isOffloaded,
+        bool isStreaming) {
     sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
     msg->setMessage("format", format);
     msg->setInt32("offload-only", offloadOnly);
     msg->setInt32("has-video", hasVideo);
     msg->setInt32("flags", flags);
+    msg->setInt32("isStreaming", isStreaming);
 
     sp<AMessage> response;
     status_t postStatus = msg->postAndAwaitResponse(&response);
@@ -430,12 +432,14 @@
         bool offloadOnly,
         bool hasVideo,
         uint32_t flags,
+        bool isStreaming,
         const sp<AMessage> &notify) {
     sp<AMessage> meta = new AMessage;
     meta->setMessage("format", format);
     meta->setInt32("offload-only", offloadOnly);
     meta->setInt32("has-video", hasVideo);
     meta->setInt32("flags", flags);
+    meta->setInt32("isStreaming", isStreaming);
 
     sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
     msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
@@ -460,7 +464,10 @@
             uint32_t flags;
             CHECK(msg->findInt32("flags", (int32_t *)&flags));
 
-            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
+            uint32_t isStreaming;
+            CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
+
+            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
 
             sp<AMessage> response = new AMessage;
             response->setInt32("err", err);
@@ -1838,7 +1845,8 @@
         const sp<AMessage> &format,
         bool offloadOnly,
         bool hasVideo,
-        uint32_t flags) {
+        uint32_t flags,
+        bool isStreaming) {
     ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
             offloadOnly, offloadingAudio());
     bool audioSinkChanged = false;
@@ -1891,7 +1899,7 @@
             offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
             offloadInfo.bit_rate = avgBitRate;
             offloadInfo.has_video = hasVideo;
-            offloadInfo.is_streaming = true;
+            offloadInfo.is_streaming = isStreaming;
 
             if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
                 ALOGV("openAudioSink: no change in offload mode");
@@ -2043,7 +2051,10 @@
     uint32_t flags;
     CHECK(meta->findInt32("flags", (int32_t *)&flags));
 
-    status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
+    uint32_t isStreaming;
+    CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
+
+    status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
 
     if (err != OK) {
         notify->setInt32("err", err);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 385bb06..e6850b5 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -76,7 +76,8 @@
             bool offloadOnly,
             bool hasVideo,
             uint32_t flags,
-            bool *isOffloaded);
+            bool *isOffloaded,
+            bool isStreaming);
     void closeAudioSink();
 
     // re-open audio sink after all pending audio buffers played.
@@ -85,6 +86,7 @@
             bool offloadOnly,
             bool hasVideo,
             uint32_t flags,
+            bool isStreaming,
             const sp<AMessage> &notify);
 
     enum {
@@ -267,7 +269,8 @@
             const sp<AMessage> &format,
             bool offloadOnly,
             bool hasVideo,
-            uint32_t flags);
+            uint32_t flags,
+            bool isStreaming);
     void onCloseAudioSink();
     void onChangeAudioFormat(const sp<AMessage> &meta, const sp<AMessage> &notify);
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 37e1546..72645ab 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -549,6 +549,7 @@
       mTimePerFrameUs(-1ll),
       mTimePerCaptureUs(-1ll),
       mCreateInputBuffersSuspended(false),
+      mLatency(0),
       mTunneled(false),
       mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
       mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
@@ -1211,7 +1212,7 @@
             break;
         }
 
-        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
+        sp<GraphicBuffer> graphicBuffer(GraphicBuffer::from(buf));
         BufferInfo info;
         info.mStatus = BufferInfo::OWNED_BY_US;
         info.mFenceFd = fenceFd;
@@ -1515,7 +1516,7 @@
     CHECK(storingMetadataInDecodedBuffers());
 
     // discard buffer in LRU info and replace with new buffer
-    oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
+    oldest->mGraphicBuffer = GraphicBuffer::from(buf);
     oldest->mNewGraphicBuffer = true;
     oldest->mStatus = BufferInfo::OWNED_BY_US;
     oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
@@ -2281,6 +2282,30 @@
     return err;
 }
 
+status_t ACodec::setLatency(uint32_t latency) {
+    OMX_PARAM_U32TYPE config;
+    InitOMXParams(&config);
+    config.nPortIndex = kPortIndexInput;
+    config.nU32 = (OMX_U32)latency;
+    status_t err = mOMXNode->setConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
+            &config, sizeof(config));
+    return err;
+}
+
+status_t ACodec::getLatency(uint32_t *latency) {
+    OMX_PARAM_U32TYPE config;
+    InitOMXParams(&config);
+    config.nPortIndex = kPortIndexInput;
+    status_t err = mOMXNode->getConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigLatency,
+            &config, sizeof(config));
+    if (err == OK) {
+        *latency = config.nU32;
+    }
+    return err;
+}
+
 status_t ACodec::setPriority(int32_t priority) {
     if (priority < 0) {
         return BAD_VALUE;
@@ -3798,6 +3823,8 @@
         }
     }
 
+    configureEncoderLatency(msg);
+
     switch (compressionFormat) {
         case OMX_VIDEO_CodingMPEG4:
             err = setupMPEG4EncoderParameters(msg);
@@ -4257,7 +4284,7 @@
         h264type.nSliceHeaderSpacing = 0;
         h264type.bUseHadamard = OMX_TRUE;
         h264type.nRefFrames = 2;
-        h264type.nBFrames = 1;
+        h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1);
         h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
         h264type.nAllowedPictureTypes =
             OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
@@ -4528,6 +4555,29 @@
             OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
 }
 
+void ACodec::configureEncoderLatency(const sp<AMessage> &msg) {
+    if (!mIsEncoder || !mIsVideo) {
+        return;
+    }
+
+    int32_t latency = 0, bitrateMode;
+    if (msg->findInt32("latency", &latency) && latency > 0) {
+        status_t err = setLatency(latency);
+        if (err != OK) {
+            ALOGW("[%s] failed setLatency. Failure is fine since this key is optional",
+                    mComponentName.c_str());
+            err = OK;
+        } else {
+            mLatency = latency;
+        }
+    } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) &&
+            bitrateMode == OMX_Video_ControlRateConstant)) {
+        // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode
+        // is CBR.
+        mLatency = 1;
+    }
+}
+
 status_t ACodec::setupErrorCorrectionParameters() {
     OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
     InitOMXParams(&errorCorrectionType);
@@ -4786,6 +4836,10 @@
                         if (mConfigFormat->contains("hdr-static-info")) {
                             (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify);
                         }
+                        uint32_t latency = 0;
+                        if (mIsEncoder && getLatency(&latency) == OK && latency > 0) {
+                            notify->setInt32("latency", latency);
+                        }
                     }
 
                     break;
@@ -5728,8 +5782,7 @@
                 case IOMX::kPortModeDynamicANWBuffer:
                     if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
                         VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
-                        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
-                                vnmd->pBuffer, false /* keepOwnership */);
+                        sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(vnmd->pBuffer);
                         err2 = mCodec->mOMXNode->emptyBuffer(
                             bufferID, graphicBuffer, flags, timeUs, info->mFenceFd);
                     }
@@ -7183,6 +7236,16 @@
         }
     }
 
+    int32_t latency = 0;
+    if (params->findInt32("latency", &latency) && latency > 0) {
+        status_t err = setLatency(latency);
+        if (err != OK) {
+            ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
+                    mComponentName.c_str());
+            err = OK;
+        }
+    }
+
     status_t err = configureTemporalLayers(params, false /* inConfigure */, mOutputFormat);
     if (err != OK) {
         err = OK; // ignore failure
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 18cfc0e..bdc37a5 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -86,6 +86,7 @@
         liblog \
         libmedia \
         libaudioclient \
+        libmediametrics \
         libmediautils \
         libnetd_client \
         libsonivox \
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index a017737..f2a4d06 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -3914,7 +3914,8 @@
 
                 while (true) {
                     if (mDataSource->readAt(*offset, hdr, 8) < 8) {
-                        return ERROR_END_OF_STREAM;
+                        // no more box to the end of file.
+                        break;
                     }
                     chunk_size = ntohl(hdr[0]);
                     chunk_type = ntohl(hdr[1]);
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 82e959e..b6b315d 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -176,7 +176,7 @@
             break;
         }
 
-        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+        sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
 
         // Fill the buffer with the a 1x1 checkerboard pattern ;)
         uint32_t *img = NULL;
diff --git a/media/libstagefright/include/ACodec.h b/media/libstagefright/include/ACodec.h
index c57005d..6c1a5c6 100644
--- a/media/libstagefright/include/ACodec.h
+++ b/media/libstagefright/include/ACodec.h
@@ -296,6 +296,7 @@
     int64_t mTimePerFrameUs;
     int64_t mTimePerCaptureUs;
     bool mCreateInputBuffersSuspended;
+    uint32_t mLatency;
 
     bool mTunneled;
 
@@ -483,6 +484,8 @@
             AudioEncoding encoding = kAudioEncodingPcm16bit);
 
     status_t setPriority(int32_t priority);
+    status_t setLatency(uint32_t latency);
+    status_t getLatency(uint32_t *latency);
     status_t setOperatingRate(float rateFloat, bool isVideo);
     status_t getIntraRefreshPeriod(uint32_t *intraRefreshPeriod);
     status_t setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure);
@@ -505,6 +508,7 @@
 
     status_t configureBitrate(
             int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode);
+    void configureEncoderLatency(const sp<AMessage> &msg);
 
     status_t setupErrorCorrectionParameters();
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index b933002..6bac1db 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -577,7 +577,7 @@
     // fill in CryptoInfo fields for AnotherPacketSource::read()
     // MediaCas doesn't use cryptoMode, but set to non-zero value here.
     scrambledAccessUnit->meta()->setInt32(
-            "cryptoMode", CryptoPlugin::kMode_AES_CBC);
+            "cryptoMode", CryptoPlugin::kMode_AES_CTR);
     scrambledAccessUnit->meta()->setInt32("cryptoKey", keyId);
     scrambledAccessUnit->meta()->setBuffer("clearBytes", clearSizes);
     scrambledAccessUnit->meta()->setBuffer("encBytes", encSizes);
diff --git a/media/libstagefright/omx/1.0/Omx.cpp b/media/libstagefright/omx/1.0/Omx.cpp
index 134c661..e5b89da 100644
--- a/media/libstagefright/omx/1.0/Omx.cpp
+++ b/media/libstagefright/omx/1.0/Omx.cpp
@@ -95,11 +95,11 @@
     }
 
     sp<OMXNodeInstance> instance = new OMXNodeInstance(
-            this, new LWOmxObserver(observer), name);
+            this, new LWOmxObserver(observer), name.c_str());
 
     OMX_COMPONENTTYPE *handle;
     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
-            name, &OMXNodeInstance::kCallbacks,
+            name.c_str(), &OMXNodeInstance::kCallbacks,
             instance.get(), &handle);
 
     if (err != OMX_ErrorNone) {
diff --git a/media/libstagefright/omx/1.0/WOmxNode.cpp b/media/libstagefright/omx/1.0/WOmxNode.cpp
index dc5c8e1..ea9fb35 100644
--- a/media/libstagefright/omx/1.0/WOmxNode.cpp
+++ b/media/libstagefright/omx/1.0/WOmxNode.cpp
@@ -414,7 +414,7 @@
         getExtensionIndex_cb _hidl_cb) {
     OMX_INDEXTYPE index;
     Status status = toStatus(mBase->getExtensionIndex(
-            parameterName, &index));
+            parameterName.c_str(), &index));
     _hidl_cb(status, toRawIndexType(index));
     return Void();
 }
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 39ed759..807c2ea 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -902,6 +902,9 @@
                         ? kMetadataBufferTypeGrallocSource : requestedType;
             err = OMX_SetParameter(mHandle, index, &params);
         }
+        if (err == OMX_ErrorBadParameter) {
+            err = OMX_ErrorUnsupportedIndex;
+        }
     }
 
     // don't log loud error if component does not support metadata mode on the output
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index ea58343..7c464ff 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -510,7 +510,7 @@
 
     // Fill the buffer with the a checkerboard pattern
     uint8_t* img = NULL;
-    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
     buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
     SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride());
     buf->unlock();
@@ -527,7 +527,7 @@
     ASSERT_TRUE(anb != NULL);
 
     // We do not fill the buffer in. Just queue it back.
-    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
     ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
             -1));
 }
diff --git a/media/mtp/AsyncIO.cpp b/media/mtp/AsyncIO.cpp
index e77ad38..bfb07dc 100644
--- a/media/mtp/AsyncIO.cpp
+++ b/media/mtp/AsyncIO.cpp
@@ -96,6 +96,10 @@
 
 } // end anonymous namespace
 
+aiocb::~aiocb() {
+    CHECK(!thread.joinable());
+}
+
 void aio_pool_init(void(f)(int)) {
     CHECK(done == 1);
     done = 0;
diff --git a/media/mtp/AsyncIO.h b/media/mtp/AsyncIO.h
index f7515a2..ed80828 100644
--- a/media/mtp/AsyncIO.h
+++ b/media/mtp/AsyncIO.h
@@ -48,6 +48,8 @@
     std::thread thread;
     ssize_t ret;
     int error;
+
+    ~aiocb();
 };
 
 // Submit a request for IO to be completed
@@ -58,9 +60,13 @@
 
 // Suspend current thread until given IO is complete, at which point
 // its return value and any errors can be accessed
+// All submitted requests must have a corresponding suspend.
+// aiocb->aio_buf must refer to valid memory until after the suspend call
 int aio_suspend(struct aiocb *[], int, const struct timespec *);
 int aio_error(const struct aiocb *);
 ssize_t aio_return(struct aiocb *);
+
+// (Currently unimplemented)
 int aio_cancel(int, struct aiocb *);
 
 // Initialize a threadpool to perform IO. Only one pool can be
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 35dd10f..565a2fe 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -490,7 +490,11 @@
 
 int MtpFfsHandle::configure(bool usePtp) {
     // Wait till previous server invocation has closed
-    std::lock_guard<std::mutex> lk(mLock);
+    if (!mLock.try_lock_for(std::chrono::milliseconds(1000))) {
+        LOG(ERROR) << "MtpServer was unable to get configure lock";
+        return -1;
+    }
+    int ret = 0;
 
     // If ptp is changed, the configuration must be rewritten
     if (mPtp != usePtp) {
@@ -500,10 +504,10 @@
     mPtp = usePtp;
 
     if (!initFunctionfs()) {
-        return -1;
+        ret = -1;
     }
-
-    return 0;
+    mLock.unlock();
+    return ret;
 }
 
 void MtpFfsHandle::close() {
@@ -537,14 +541,12 @@
         if (file_length > 0) {
             length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
 
-            // Read data from USB
-            if ((ret = readHandle(mBulkOut, data, length)) == -1) {
-                return -1;
-            }
+            // Read data from USB, handle errors after waiting for write thread.
+            ret = readHandle(mBulkOut, data, length);
 
             if (file_length != MAX_MTP_FILE_SIZE && ret < static_cast<int>(length)) {
+                ret = -1;
                 errno = EIO;
-                return -1;
             }
             read = true;
         }
@@ -565,6 +567,11 @@
             write = false;
         }
 
+        // If there was an error reading above
+        if (ret == -1) {
+            return -1;
+        }
+
         if (read) {
             // Enqueue a new write request
             aio.aio_buf = data;
@@ -622,6 +629,7 @@
     aio.aio_fildes = mfr.fd;
     struct aiocb *aiol[] = {&aio};
     int ret, length;
+    int error = 0;
     bool read = false;
     bool write = false;
 
@@ -665,6 +673,10 @@
             write = true;
         }
 
+        if (error == -1) {
+            return -1;
+        }
+
         if (file_length > 0) {
             length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
             // Queue up another read
@@ -676,8 +688,9 @@
         }
 
         if (write) {
-            if (writeHandle(mBulkIn, data2, ret) == -1)
-                return -1;
+            if (writeHandle(mBulkIn, data2, ret) == -1) {
+                error = -1;
+            }
             write = false;
         }
     }
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index b4d5a97..7491a1b 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -36,7 +36,7 @@
 
     bool mPtp;
 
-    std::mutex mLock;
+    std::timed_mutex mLock;
 
     android::base::unique_fd mControl;
     // "in" from the host's perspective => sink for mtp server
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
new file mode 100644
index 0000000..72917dd
--- /dev/null
+++ b/media/utils/Android.bp
@@ -0,0 +1,41 @@
+// Copyright 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.
+
+cc_library_shared {
+    name: "libmediautils",
+
+    srcs: [
+        "BatteryNotifier.cpp",
+        "ISchedulingPolicyService.cpp",
+        "MemoryLeakTrackUtil.cpp",
+        "ProcessInfo.cpp",
+        "SchedulingPolicyService.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libmemunreachable",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+}
diff --git a/media/utils/Android.mk b/media/utils/Android.mk
deleted file mode 100644
index 21d1b5b..0000000
--- a/media/utils/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2015 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-  BatteryNotifier.cpp \
-  ISchedulingPolicyService.cpp \
-  MemoryLeakTrackUtil.cpp \
-  ProcessInfo.cpp \
-  SchedulingPolicyService.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-  libbinder \
-  libcutils \
-  liblog \
-  libutils \
-  libmemunreachable \
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-
-LOCAL_CFLAGS += \
-  -Wall \
-  -Wextra \
-  -Werror \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_MODULE := libmediautils
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 8a7bb86..2be9362 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -57,9 +57,6 @@
     utils/AutoConditionLock.cpp \
     utils/TagMonitor.cpp
 
-LOCAL_STATIC_LIBRARIES:= \
-    libgrallocusage
-
 LOCAL_SHARED_LIBRARIES:= \
     libui \
     liblog \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 4318a11..39351e7 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -661,6 +661,22 @@
     return Status::ok();
 }
 
+Status CameraService::getCameraVendorTagCache(
+        /*out*/ hardware::camera2::params::VendorTagDescriptorCache* cache) {
+    ATRACE_CALL();
+    if (!mInitialized) {
+        ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+        return STATUS_ERROR(ERROR_DISCONNECTED,
+                "Camera subsystem not available");
+    }
+    sp<VendorTagDescriptorCache> globalCache =
+            VendorTagDescriptorCache::getGlobalVendorTagCache();
+    if (globalCache != nullptr) {
+        *cache = *(globalCache.get());
+    }
+    return Status::ok();
+}
+
 int CameraService::getDeviceVersion(const String8& cameraId, int* facing) {
     ATRACE_CALL();
 
@@ -2859,7 +2875,13 @@
 
     sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
     if (desc == NULL) {
-        dprintf(fd, "No vendor tags.\n");
+        sp<VendorTagDescriptorCache> cache =
+                VendorTagDescriptorCache::getGlobalVendorTagCache();
+        if (cache == NULL) {
+            dprintf(fd, "No vendor tags.\n");
+        } else {
+            cache->dump(fd, /*verbosity*/2, /*indentation*/2);
+        }
     } else {
         desc->dump(fd, /*verbosity*/2, /*indentation*/2);
     }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c7acdc9..e49fe62 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -112,6 +112,9 @@
     virtual binder::Status     getCameraVendorTagDescriptor(
             /*out*/
             hardware::camera2::params::VendorTagDescriptor* desc);
+    virtual binder::Status     getCameraVendorTagCache(
+            /*out*/
+            hardware::camera2::params::VendorTagDescriptorCache* cache);
 
     virtual binder::Status     connect(const sp<hardware::ICameraClient>& cameraClient,
             int32_t cameraId, const String16& clientPackageName,
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
index 394eb4c..733a78e 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
@@ -367,9 +367,12 @@
 
     entry = result.find(tag);
     if (entry.count == 0) {
+        const camera_metadata *metaBuffer = result.getAndLock();
         ALOGV("%s: Camera %d: No %s provided by HAL for frame %d in this result!",
                 __FUNCTION__, cameraId,
-                get_camera_metadata_tag_name(tag), frameNumber);
+                get_local_camera_metadata_tag_name(tag, metaBuffer),
+                frameNumber);
+        result.unlock(metaBuffer);
         return false;
     } else {
         switch(sizeof(Src)){
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index f4c447d..b2686bf 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -798,16 +798,38 @@
             exposureCompensationStep.data.r[0].denominator);
 
     autoExposureLock = false;
-    params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
-            CameraParameters::FALSE);
-    params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
-            CameraParameters::TRUE);
+    autoExposureLockAvailable = false;
+    camera_metadata_ro_entry_t exposureLockAvailable =
+        staticInfo(ANDROID_CONTROL_AE_LOCK_AVAILABLE, 1, 1);
+    if ((0 < exposureLockAvailable.count) &&
+            (ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE ==
+                    exposureLockAvailable.data.u8[0])) {
+        params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
+                CameraParameters::FALSE);
+        params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
+                   CameraParameters::TRUE);
+        autoExposureLockAvailable = true;
+    } else {
+        params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
+                   CameraParameters::FALSE);
+    }
 
     autoWhiteBalanceLock = false;
-    params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
-            CameraParameters::FALSE);
-    params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
-            CameraParameters::TRUE);
+    autoWhiteBalanceLockAvailable = false;
+    camera_metadata_ro_entry_t whitebalanceLockAvailable =
+        staticInfo(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, 1, 1);
+    if ((0 < whitebalanceLockAvailable.count) &&
+            (ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE ==
+                    whitebalanceLockAvailable.data.u8[0])) {
+        params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
+                CameraParameters::FALSE);
+        params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
+                CameraParameters::TRUE);
+        autoWhiteBalanceLockAvailable = true;
+    } else {
+        params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
+                CameraParameters::FALSE);
+    }
 
     meteringAreas.add(Parameters::Area(0, 0, 0, 0, 0));
     params.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS,
@@ -1205,11 +1227,14 @@
 camera_metadata_ro_entry_t Parameters::staticInfo(uint32_t tag,
         size_t minCount, size_t maxCount, bool required) const {
     camera_metadata_ro_entry_t entry = info->find(tag);
+    const camera_metadata_t *metaBuffer = info->getAndLock();
 
     if (CC_UNLIKELY( entry.count == 0 ) && required) {
-        const char* tagSection = get_camera_metadata_section_name(tag);
+        const char* tagSection = get_local_camera_metadata_section_name(tag,
+                metaBuffer);
         if (tagSection == NULL) tagSection = "<unknown>";
-        const char* tagName = get_camera_metadata_tag_name(tag);
+        const char* tagName = get_local_camera_metadata_tag_name(tag,
+                metaBuffer);
         if (tagName == NULL) tagName = "<unknown>";
 
         ALOGE("Error finding static metadata entry '%s.%s' (%x)",
@@ -1217,14 +1242,17 @@
     } else if (CC_UNLIKELY(
             (minCount != 0 && entry.count < minCount) ||
             (maxCount != 0 && entry.count > maxCount) ) ) {
-        const char* tagSection = get_camera_metadata_section_name(tag);
+        const char* tagSection = get_local_camera_metadata_section_name(tag,
+                metaBuffer);
         if (tagSection == NULL) tagSection = "<unknown>";
-        const char* tagName = get_camera_metadata_tag_name(tag);
+        const char* tagName = get_local_camera_metadata_tag_name(tag,
+                metaBuffer);
         if (tagName == NULL) tagName = "<unknown>";
         ALOGE("Malformed static metadata entry '%s.%s' (%x):"
                 "Expected between %zu and %zu values, but got %zu values",
                 tagSection, tagName, tag, minCount, maxCount, entry.count);
     }
+    info->unlock(metaBuffer);
 
     return entry;
 }
@@ -1837,13 +1865,25 @@
         return BAD_VALUE;
     }
 
-    // AUTO_EXPOSURE_LOCK (always supported)
-    validatedParams.autoExposureLock = boolFromString(
-        newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
+    if (autoExposureLockAvailable) {
+        validatedParams.autoExposureLock = boolFromString(
+            newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
+    } else if (nullptr !=
+            newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK)){
+        ALOGE("%s: Requested auto exposure lock is not supported",
+              __FUNCTION__);
+        return BAD_VALUE;
+    }
 
-    // AUTO_WHITEBALANCE_LOCK (always supported)
-    validatedParams.autoWhiteBalanceLock = boolFromString(
-        newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
+    if (autoWhiteBalanceLockAvailable) {
+        validatedParams.autoWhiteBalanceLock = boolFromString(
+                newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
+    } else if (nullptr !=
+           newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) {
+        ALOGE("%s: Requested auto whitebalance lock is not supported",
+              __FUNCTION__);
+        return BAD_VALUE;
+    }
 
     // METERING_AREAS
     size_t maxAeRegions = (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS,
@@ -1991,10 +2031,12 @@
     }
     if (res != OK) return res;
 
-    uint8_t reqWbLock = autoWhiteBalanceLock ?
-            ANDROID_CONTROL_AWB_LOCK_ON : ANDROID_CONTROL_AWB_LOCK_OFF;
-    res = request->update(ANDROID_CONTROL_AWB_LOCK,
-            &reqWbLock, 1);
+    if (autoWhiteBalanceLockAvailable) {
+        uint8_t reqWbLock = autoWhiteBalanceLock ?
+                ANDROID_CONTROL_AWB_LOCK_ON : ANDROID_CONTROL_AWB_LOCK_OFF;
+        res = request->update(ANDROID_CONTROL_AWB_LOCK,
+                &reqWbLock, 1);
+    }
 
     res = request->update(ANDROID_CONTROL_EFFECT_MODE,
             &effectMode, 1);
@@ -2052,11 +2094,13 @@
             &reqAeMode, 1);
     if (res != OK) return res;
 
-    uint8_t reqAeLock = autoExposureLock ?
-            ANDROID_CONTROL_AE_LOCK_ON : ANDROID_CONTROL_AE_LOCK_OFF;
-    res = request->update(ANDROID_CONTROL_AE_LOCK,
-            &reqAeLock, 1);
-    if (res != OK) return res;
+    if (autoExposureLockAvailable) {
+        uint8_t reqAeLock = autoExposureLock ?
+                ANDROID_CONTROL_AE_LOCK_ON : ANDROID_CONTROL_AE_LOCK_OFF;
+        res = request->update(ANDROID_CONTROL_AE_LOCK,
+                &reqAeLock, 1);
+        if (res != OK) return res;
+    }
 
     res = request->update(ANDROID_CONTROL_AWB_MODE,
             &wbMode, 1);
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 3c3e854..507de75 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -122,7 +122,9 @@
 
     int32_t exposureCompensation;
     bool autoExposureLock;
+    bool autoExposureLockAvailable;
     bool autoWhiteBalanceLock;
+    bool autoWhiteBalanceLockAvailable;
 
     // 3A region types, for use with ANDROID_CONTROL_MAX_REGIONS
     enum region_t {
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index bfae9e9..e03ec66 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -304,7 +304,7 @@
         sp<IGraphicBufferProducer> producer;
         sp<IGraphicBufferConsumer> consumer;
         BufferQueue::createBufferQueue(&producer, &consumer);
-        mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_READ,
+        mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL,
             mBufferQueueDepth);
         mProducer->setName(String8("Camera2-ZslRingBufferConsumer"));
         sp<Surface> outSurface = new Surface(producer);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index bbeeca6..56ba5b6 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -23,6 +23,8 @@
 #include <chrono>
 #include <inttypes.h>
 #include <hidl/ServiceManagement.h>
+#include <functional>
+#include <camera_metadata_hidden.h>
 
 namespace android {
 
@@ -221,7 +223,9 @@
 }
 
 status_t CameraProviderManager::setUpVendorTags() {
-    // TODO (b/34275821): support aggregating vendor tags for more than one provider
+    sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
+
+    VendorTagDescriptorCache::clearGlobalVendorTagCache();
     for (auto& provider : mProviders) {
         hardware::hidl_vec<VendorTagSection> vts;
         Status status;
@@ -242,8 +246,6 @@
             return mapToStatusT(status);
         }
 
-        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-
         // Read all vendor tag definitions into a descriptor
         sp<VendorTagDescriptor> desc;
         status_t res;
@@ -255,9 +257,11 @@
             return res;
         }
 
-        // Set the global descriptor to use with camera metadata
-        VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
+        tagCache->addVendorDescriptor(provider->mProviderTagid, desc);
     }
+
+    VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache);
+
     return OK;
 }
 
@@ -350,6 +354,24 @@
     return nullptr;
 }
 
+metadata_vendor_id_t CameraProviderManager::getProviderTagIdLocked(
+        const std::string& id, hardware::hidl_version minVersion,
+        hardware::hidl_version maxVersion) const {
+    metadata_vendor_id_t ret = CAMERA_METADATA_INVALID_VENDOR_ID;
+
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    for (auto& provider : mProviders) {
+        for (auto& deviceInfo : provider->mDevices) {
+            if (deviceInfo->mId == id &&
+                    minVersion <= deviceInfo->mVersion &&
+                    maxVersion >= deviceInfo->mVersion) {
+                return provider->mProviderTagid;
+            }
+        }
+    }
+
+    return ret;
+}
 
 status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
     for (const auto& providerInfo : mProviders) {
@@ -430,6 +452,7 @@
         CameraProviderManager *manager) :
         mProviderName(providerName),
         mInterface(interface),
+        mProviderTagid(generateVendorTagId(providerName)),
         mManager(manager) {
     (void) mManager;
 }
@@ -542,10 +565,12 @@
     std::unique_ptr<DeviceInfo> deviceInfo;
     switch (major) {
         case 1:
-            deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, id, minor);
+            deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, mProviderTagid,
+                    id, minor);
             break;
         case 3:
-            deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, id, minor);
+            deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
+                    id, minor);
             break;
         default:
             ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
@@ -691,7 +716,7 @@
 template<class DeviceInfoT>
 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
     CameraProviderManager::ProviderInfo::initializeDeviceInfo(
-        const std::string &name,
+        const std::string &name, const metadata_vendor_id_t tagId,
         const std::string &id, uint16_t minorVersion) const {
     Status status;
 
@@ -711,7 +736,8 @@
         return nullptr;
     }
     return std::unique_ptr<DeviceInfo>(
-        new DeviceInfoT(name, id, minorVersion, resourceCost, cameraInterface));
+        new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
+                cameraInterface));
 }
 
 template<class InterfaceT>
@@ -782,11 +808,12 @@
 }
 
 CameraProviderManager::ProviderInfo::DeviceInfo1::DeviceInfo1(const std::string& name,
-        const std::string &id,
+        const metadata_vendor_id_t tagId, const std::string &id,
         uint16_t minorVersion,
         const CameraResourceCost& resourceCost,
         sp<InterfaceT> interface) :
-        DeviceInfo(name, id, hardware::hidl_version{1, minorVersion}, resourceCost),
+        DeviceInfo(name, tagId, id, hardware::hidl_version{1, minorVersion},
+                   resourceCost),
         mInterface(interface) {
     // Get default parameters and initialize flash unit availability
     // Requires powering on the camera device
@@ -869,11 +896,12 @@
 }
 
 CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& name,
-        const std::string &id,
+        const metadata_vendor_id_t tagId, const std::string &id,
         uint16_t minorVersion,
         const CameraResourceCost& resourceCost,
         sp<InterfaceT> interface) :
-        DeviceInfo(name, id, hardware::hidl_version{3, minorVersion}, resourceCost),
+        DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
+                   resourceCost),
         mInterface(interface) {
     // Get camera characteristics and initialize flash unit availability
     Status status;
@@ -884,6 +912,7 @@
                 if (s == Status::OK) {
                     camera_metadata_t *buffer =
                             reinterpret_cast<camera_metadata_t*>(metadata.data());
+                    set_camera_metadata_vendor_id(buffer, mProviderTagid);
                     mCameraCharacteristics = buffer;
                 }
             });
@@ -1004,6 +1033,17 @@
     return OK;
 }
 
+metadata_vendor_id_t CameraProviderManager::ProviderInfo::generateVendorTagId(
+        const std::string &name) {
+    metadata_vendor_id_t ret = std::hash<std::string> {} (name);
+    // CAMERA_METADATA_INVALID_VENDOR_ID is not a valid hash value
+    if (CAMERA_METADATA_INVALID_VENDOR_ID == ret) {
+        ret = 0;
+    }
+
+    return ret;
+}
+
 status_t CameraProviderManager::ProviderInfo::parseDeviceName(const std::string& name,
         uint16_t *major, uint16_t *minor, std::string *type, std::string *id) {
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index a388db5..2df4fd5 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -224,6 +224,13 @@
     static status_t mapToStatusT(const hardware::camera::common::V1_0::Status& s);
     static const char* statusToString(const hardware::camera::common::V1_0::Status& s);
 
+    /*
+     * Return provider type for a specific device.
+     */
+    metadata_vendor_id_t getProviderTagIdLocked(const std::string& id,
+            hardware::hidl_version minVersion = hardware::hidl_version{0,0},
+            hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;
+
 private:
     // All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
     mutable std::mutex mInterfaceMutex;
@@ -241,6 +248,7 @@
     {
         const std::string mProviderName;
         const sp<hardware::camera::provider::V2_4::ICameraProvider> mInterface;
+        const metadata_vendor_id_t mProviderTagid;
 
         ProviderInfo(const std::string &providerName,
                 sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
@@ -274,6 +282,7 @@
             const std::string mName;  // Full instance name
             const std::string mId;    // ID section of full name
             const hardware::hidl_version mVersion;
+            const metadata_vendor_id_t mProviderTagid;
 
             const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
 
@@ -287,10 +296,11 @@
                 return INVALID_OPERATION;
             }
 
-            DeviceInfo(const std::string& name, const std::string &id,
-                    const hardware::hidl_version& version,
+            DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
+                    const std::string &id, const hardware::hidl_version& version,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
-                    mName(name), mId(id), mVersion(version), mResourceCost(resourceCost),
+                    mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
+                    mResourceCost(resourceCost),
                     mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
                     mHasFlashUnit(false) {}
             virtual ~DeviceInfo();
@@ -312,8 +322,8 @@
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
 
-            DeviceInfo1(const std::string& name, const std::string &id,
-                    uint16_t minorVersion,
+            DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId,
+                    const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
                     sp<InterfaceT> interface);
             virtual ~DeviceInfo1();
@@ -331,8 +341,8 @@
             virtual status_t getCameraCharacteristics(
                     CameraMetadata *characteristics) const override;
 
-            DeviceInfo3(const std::string& name, const std::string &id,
-                    uint16_t minorVersion,
+            DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
+                    const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
                     sp<InterfaceT> interface);
             virtual ~DeviceInfo3();
@@ -352,7 +362,8 @@
         // right CameraProvider getCameraDeviceInterface_* method.
         template<class DeviceInfoT>
         std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &name,
-                const std::string &id, uint16_t minorVersion) const;
+                const metadata_vendor_id_t tagId, const std::string &id,
+                uint16_t minorVersion) const;
 
         // Helper for initializeDeviceInfo to use the right CameraProvider get method.
         template<class InterfaceT>
@@ -365,6 +376,9 @@
         // Parse device instance name for device version, type, and id.
         static status_t parseDeviceName(const std::string& name,
                 uint16_t *major, uint16_t *minor, std::string *type, std::string *id);
+
+        // Generate vendor tag id
+        static metadata_vendor_id_t generateVendorTagId(const std::string &name);
     };
 
     // Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 0b57c50..9c058bc 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -17,8 +17,6 @@
 //#define LOG_NDEBUG 0
 
 #include <inttypes.h>
-#include <grallocusage/GrallocUsageConversion.h>
-
 #include "CameraHardwareInterface.h"
 
 namespace android {
@@ -397,14 +395,14 @@
 }
 
 hardware::Return<Status>
-CameraHardwareInterface::setUsage(hardware::camera::device::V1_0::ProducerUsageFlags usage) {
+CameraHardwareInterface::setUsage(hardware::graphics::allocator::V2_0::ProducerUsage usage) {
     Status s = Status::INTERNAL_ERROR;
     ANativeWindow *a = mPreviewWindow.get();
     if (a == nullptr) {
         ALOGE("%s: preview window is null", __FUNCTION__);
         return s;
     }
-    mPreviewUsage = ::android_convertGralloc1To0Usage(usage, /*consumerUsage*/ 0);
+    mPreviewUsage = (int) usage;
     int rc = native_window_set_usage(a, mPreviewUsage);
     if (rc == OK) {
         cleanupCirculatingBuffers();
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index caeacef..c2b0e9c 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -461,7 +461,7 @@
     hardware::Return<hardware::camera::common::V1_0::Status>
             setCrop(int32_t left, int32_t top, int32_t right, int32_t bottom) override;
     hardware::Return<hardware::camera::common::V1_0::Status>
-            setUsage(hardware::camera::device::V1_0::ProducerUsageFlags usage) override;
+            setUsage(hardware::graphics::allocator::V2_0::ProducerUsage usage) override;
     hardware::Return<hardware::camera::common::V1_0::Status>
             setSwapInterval(int32_t interval) override;
     hardware::Return<void> getMinUndequeuedBufferCount(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 980ba39..c35dab6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -44,8 +44,6 @@
 #include <utils/Timers.h>
 #include <cutils/properties.h>
 
-#include <grallocusage/GrallocUsageConversion.h>
-
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 
 #include "utils/CameraTraces.h"
@@ -76,7 +74,8 @@
         mNextReprocessResultFrameNumber(0),
         mNextShutterFrameNumber(0),
         mNextReprocessShutterFrameNumber(0),
-        mListener(NULL)
+        mListener(NULL),
+        mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
 {
     ATRACE_CALL();
     camera3_callback_ops::notify = &sNotify;
@@ -204,6 +203,8 @@
     //       for now use 3_4 to keep legacy devices working
     mDeviceVersion = CAMERA_DEVICE_API_VERSION_3_4;
     mInterface = std::make_unique<HalInterface>(session);
+    std::string providerType;
+    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
 
     return initializeCommonLocked();
 }
@@ -227,6 +228,8 @@
     /** Create buffer manager */
     mBufferManager = new Camera3BufferManager();
 
+    mTagMonitor.initialize(mVendorTagId);
+
     bool aeLockAvailable = false;
     camera_metadata_entry aeLockAvailableEntry = mDeviceInfo.find(
             ANDROID_CONTROL_AE_LOCK_AVAILABLE);
@@ -497,6 +500,11 @@
     return dataSpace;
 }
 
+ConsumerUsageFlags Camera3Device::mapToConsumerUsage(
+        uint32_t usage) {
+    return usage;
+}
+
 StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
     switch (rotation) {
         case CAMERA3_STREAM_ROTATION_0:
@@ -546,6 +554,16 @@
     return static_cast<uint32_t>(pixelFormat);
 }
 
+uint32_t Camera3Device::mapConsumerToFrameworkUsage(
+        ConsumerUsageFlags usage) {
+    return usage;
+}
+
+uint32_t Camera3Device::mapProducerToFrameworkUsage(
+        ProducerUsageFlags usage) {
+    return usage;
+}
+
 ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
     // Get max jpeg size (area-wise).
     Size maxJpegResolution = getMaxJpegResolution();
@@ -1574,6 +1592,7 @@
         return res;
     }
 
+    set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
     mRequestTemplateCache[templateId].acquire(rawRequest);
 
     // Derive some new keys for backward compatibility
@@ -2524,6 +2543,11 @@
             const AeTriggerCancelOverride_t &aeTriggerCancelOverride) {
     if (result == nullptr) return;
 
+    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
+            result->mMetadata.getAndLock());
+    set_camera_metadata_vendor_id(meta, mVendorTagId);
+    result->mMetadata.unlock(meta);
+
     if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
             (int32_t*)&frameNumber, 1) != OK) {
         SET_ERR("Failed to set frame number %d in metadata", frameNumber);
@@ -3143,9 +3167,7 @@
             dst.width = src->width;
             dst.height = src->height;
             dst.format = mapToPixelFormat(src->format);
-            uint64_t consumerUsage, producerUsage;
-            ::android_convertGralloc0To1Usage(src->usage, &producerUsage, &consumerUsage);
-            dst.usage = consumerUsage;
+            dst.usage = mapToConsumerUsage(src->usage);
             dst.dataSpace = mapToHidlDataspace(src->data_space);
             dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
 
@@ -3227,6 +3249,7 @@
                             __FUNCTION__, streamId);
                     return INVALID_OPERATION;
                 }
+                dst->usage = mapConsumerToFrameworkUsage(src.consumerUsage);
             } else {
                 // OUTPUT
                 if (src.consumerUsage != 0) {
@@ -3234,8 +3257,8 @@
                             __FUNCTION__, streamId);
                     return INVALID_OPERATION;
                 }
+                dst->usage = mapProducerToFrameworkUsage(src.producerUsage);
             }
-            dst->usage = ::android_convertGralloc1To0Usage(src.producerUsage, src.consumerUsage);
             dst->max_buffers = src.maxBuffers;
         }
     }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d4b92cf..5d731ed 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -39,6 +39,7 @@
 #include "device3/StatusTracker.h"
 #include "device3/Camera3BufferManager.h"
 #include "utils/TagMonitor.h"
+#include <camera_metadata_hidden.h>
 
 /**
  * Function pointer types with C calling convention to
@@ -597,6 +598,7 @@
     static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
     static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
             android_dataspace dataSpace);
+    static hardware::camera::device::V3_2::ConsumerUsageFlags mapToConsumerUsage(uint32_t usage);
     static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
             camera3_stream_rotation_t rotation);
     // Returns a negative error code if the passed-in operation mode is not valid.
@@ -604,6 +606,10 @@
             /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
     static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
     static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
+    static uint32_t mapConsumerToFrameworkUsage(
+            hardware::camera::device::V3_2::ConsumerUsageFlags usage);
+    static uint32_t mapProducerToFrameworkUsage(
+            hardware::camera::device::V3_2::ProducerUsageFlags usage);
 
     struct RequestTrigger {
         // Metadata tag number, e.g. android.control.aePrecaptureTrigger
@@ -1059,6 +1065,8 @@
     void monitorMetadata(TagMonitor::eventSource source, int64_t frameNumber,
             nsecs_t timestamp, const CameraMetadata& metadata);
 
+    metadata_vendor_id_t mVendorTagId;
+
     /**
      * Static callback forwarding methods from HAL to instance
      */
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index c60a68c..e46d55e 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -634,7 +634,7 @@
             NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
 
     // If an opaque output stream's endpoint is ImageReader, add
-    // GRALLOC_USAGE_HW_CAMERA_READ to the usage so HAL knows it will be used
+    // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
     // for the ZSL use case.
     // Assume it's for ImageReader if the consumer usage doesn't have any of these bits set:
     //     1. GRALLOC_USAGE_HW_TEXTURE
@@ -644,7 +644,7 @@
     if (camera3_stream::format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
             (u & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
             GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_VIDEO_ENCODER)) == 0) {
-        u |= GRALLOC_USAGE_HW_CAMERA_READ;
+        u |= GRALLOC_USAGE_HW_CAMERA_ZSL;
     }
 
     *usage = u;
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index 179643b..37a05c2 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -22,6 +22,9 @@
     libcameraservice \
     libhidlbase \
     liblog \
+    libhidltransport \
+    libcamera_client \
+    libcamera_metadata \
     libutils \
     android.hardware.camera.common@1.0 \
     android.hardware.camera.provider@2.4 \
@@ -29,6 +32,7 @@
     android.hardware.camera.device@3.2
 
 LOCAL_C_INCLUDES += \
+    system/media/private/camera/include \
 
 LOCAL_CFLAGS += -Wall -Wextra -Werror
 
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index eb934ba..b18df5f 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -20,38 +20,104 @@
 #include "../common/CameraProviderManager.h"
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <android/hidl/manager/1.0/IServiceNotification.h>
-
+#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
+#include <camera_metadata_hidden.h>
 #include <gtest/gtest.h>
 
 using namespace android;
 using namespace android::hardware::camera;
 using android::hardware::camera::common::V1_0::Status;
+using android::hardware::camera::common::V1_0::VendorTag;
+using android::hardware::camera::common::V1_0::VendorTagSection;
+using android::hardware::camera::common::V1_0::CameraMetadataType;
+using android::hardware::camera::device::V3_2::ICameraDeviceCallback;
+using android::hardware::camera::device::V3_2::ICameraDeviceSession;
+
+/**
+ * Basic test implementation of a camera ver. 3.2 device interface
+ */
+struct TestDeviceInterface : public device::V3_2::ICameraDevice {
+    std::vector<hardware::hidl_string> mDeviceNames;
+    TestDeviceInterface(std::vector<hardware::hidl_string> deviceNames) :
+        mDeviceNames(deviceNames) {}
+    using getResourceCost_cb = std::function<void(
+            hardware::camera::common::V1_0::Status status,
+            const hardware::camera::common::V1_0::CameraResourceCost& resourceCost)>;
+    virtual ::android::hardware::Return<void> getResourceCost(
+            getResourceCost_cb _hidl_cb) override {
+        hardware::camera::common::V1_0::CameraResourceCost resourceCost = {100,
+                mDeviceNames};
+        _hidl_cb(Status::OK, resourceCost);
+        return hardware::Void();
+    }
+
+    using getCameraCharacteristics_cb = std::function<void(
+            hardware::camera::common::V1_0::Status status,
+            const hardware::hidl_vec<uint8_t>& cameraCharacteristics)>;
+    hardware::Return<void> getCameraCharacteristics(
+            getCameraCharacteristics_cb _hidl_cb) override {
+        hardware::hidl_vec<uint8_t> cameraCharacteristics;
+        _hidl_cb(Status::OK, cameraCharacteristics);
+        return hardware::Void();
+    }
+
+    hardware::Return<hardware::camera::common::V1_0::Status> setTorchMode(
+            ::android::hardware::camera::common::V1_0::TorchMode) override {
+        return Status::OK;
+    }
+
+    using open_cb = std::function<void(
+            ::android::hardware::camera::common::V1_0::Status status,
+             const ::android::sp<ICameraDeviceSession>& session)>;
+    hardware::Return<void> open(
+            const ::android::sp<ICameraDeviceCallback>&,
+            open_cb _hidl_cb) override {
+        sp<ICameraDeviceSession> deviceSession = nullptr;
+        _hidl_cb(Status::OK, deviceSession);
+        return hardware::Void();
+    }
+
+    hardware::Return<void> dumpState(
+            const ::android::hardware::hidl_handle&) override {
+        return hardware::Void();
+    }
+};
 
 /**
  * Basic test implementation of a camera provider
  */
 struct TestICameraProvider : virtual public provider::V2_4::ICameraProvider {
-    sp<provider::V2_4::ICameraProviderCallbacks> mCallbacks;
-
+    sp<provider::V2_4::ICameraProviderCallback> mCallbacks;
     std::vector<hardware::hidl_string> mDeviceNames;
+    sp<device::V3_2::ICameraDevice> mDeviceInterface;
+    hardware::hidl_vec<common::V1_0::VendorTagSection> mVendorTagSections;
 
-    TestICameraProvider() {
-        mDeviceNames.push_back("device@3.2/test/0");
-        mDeviceNames.push_back("device@1.0/test/0");
-        mDeviceNames.push_back("device@3.2/test/1");
-    }
+    TestICameraProvider(const std::vector<hardware::hidl_string> &devices,
+            const hardware::hidl_vec<common::V1_0::VendorTagSection> &vendorSection) :
+        mDeviceNames(devices),
+        mDeviceInterface(new TestDeviceInterface(devices)),
+        mVendorTagSections (vendorSection) {}
 
-    virtual hardware::Return<Status> setCallbacks(
-            const sp<provider::V2_4::ICameraProviderCallbacks>& callbacks) override {
+    virtual hardware::Return<Status> setCallback(
+            const sp<provider::V2_4::ICameraProviderCallback>& callbacks) override {
         mCallbacks = callbacks;
         return hardware::Return<Status>(Status::OK);
     }
 
     using getVendorTags_cb = std::function<void(Status status,
             const hardware::hidl_vec<common::V1_0::VendorTagSection>& sections)>;
-    virtual hardware::Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override {
-        hardware::hidl_vec<common::V1_0::VendorTagSection> sections;
-        _hidl_cb(Status::OK, sections);
+    hardware::Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override {
+        _hidl_cb(Status::OK, mVendorTagSections);
+        return hardware::Void();
+    }
+
+    using isSetTorchModeSupported_cb = std::function<void(
+            ::android::hardware::camera::common::V1_0::Status status,
+             bool support)>;
+    virtual ::hardware::Return<void> isSetTorchModeSupported(
+            isSetTorchModeSupported_cb _hidl_cb) override {
+        _hidl_cb(Status::OK, false);
         return hardware::Void();
     }
 
@@ -68,17 +134,17 @@
             const hardware::hidl_string& cameraDeviceName,
             getCameraDeviceInterface_V1_x_cb _hidl_cb) override {
         (void) cameraDeviceName;
-        _hidl_cb(Status::OK, nullptr);
+        _hidl_cb(Status::OK, nullptr); //TODO: impl. of ver. 1.0 device interface
+                                       //      otherwise enumeration will fail.
         return hardware::Void();
     }
 
     using getCameraDeviceInterface_V3_x_cb = std::function<void(Status status,
             const sp<device::V3_2::ICameraDevice>& device)>;
     virtual hardware::Return<void> getCameraDeviceInterface_V3_x(
-            const hardware::hidl_string& cameraDeviceName,
+            const hardware::hidl_string&,
             getCameraDeviceInterface_V3_x_cb _hidl_cb) override {
-        (void) cameraDeviceName;
-        _hidl_cb(Status::OK, nullptr);
+        _hidl_cb(Status::OK, mDeviceInterface);
         return hardware::Void();
     }
 
@@ -90,12 +156,13 @@
  */
 struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionProxy {
     sp<hidl::manager::V1_0::IServiceNotification> mManagerNotificationInterface;
-    const sp<TestICameraProvider> mTestCameraProvider;
+    sp<TestICameraProvider> mTestCameraProvider;
 
-    TestInteractionProxy() :
-            mTestCameraProvider(new TestICameraProvider()) {
-
+    TestInteractionProxy() {}
+    void setProvider(sp<TestICameraProvider> provider) {
+        mTestCameraProvider = provider;
     }
+
     std::string mLastRequestedServiceName;
 
     virtual ~TestInteractionProxy() {}
@@ -116,13 +183,30 @@
 
 };
 
-TEST(CameraProviderManagerTest, InitializeTest) {
+struct TestStatusListener : public CameraProviderManager::StatusListener {
+    ~TestStatusListener() {}
 
+    void onDeviceStatusChanged(const String8 &,
+            hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+    void onTorchStatusChanged(const String8 &,
+            hardware::camera::common::V1_0::TorchModeStatus) override {}
+};
+
+TEST(CameraProviderManagerTest, InitializeTest) {
+    std::vector<hardware::hidl_string> deviceNames;
+    deviceNames.push_back("device@3.2/test/0");
+    deviceNames.push_back("device@1.0/test/0");
+    deviceNames.push_back("device@3.2/test/1");
+    hardware::hidl_vec<common::V1_0::VendorTagSection> vendorSection;
     status_t res;
     sp<CameraProviderManager> providerManager = new CameraProviderManager();
-    TestInteractionProxy serviceProxy{};
+    sp<TestStatusListener> statusListener = new TestStatusListener();
+    TestInteractionProxy serviceProxy;
+    sp<TestICameraProvider> provider =  new TestICameraProvider(deviceNames,
+            vendorSection);
+    serviceProxy.setProvider(provider);
 
-    res = providerManager->initialize(&serviceProxy);
+    res = providerManager->initialize(statusListener, &serviceProxy);
     ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
 
     hardware::hidl_string legacyInstanceName = "legacy/0";
@@ -139,3 +223,145 @@
     ASSERT_EQ(serviceProxy.mLastRequestedServiceName, testProviderInstanceName) <<
             "Incorrect instance requested from service manager";
 }
+
+TEST(CameraProviderManagerTest, MultipleVendorTagTest) {
+    hardware::hidl_string sectionName = "VendorTestSection";
+    hardware::hidl_string tagName = "VendorTestTag";
+    uint32_t tagId = VENDOR_SECTION << 16;
+    hardware::hidl_vec<common::V1_0::VendorTagSection> vendorSection;
+    CameraMetadataType tagType = CameraMetadataType::BYTE;
+    vendorSection.resize(1);
+    vendorSection[0].sectionName = sectionName;
+    vendorSection[0].tags.resize(1);
+    vendorSection[0].tags[0].tagId = tagId;
+    vendorSection[0].tags[0].tagName = tagName;
+    vendorSection[0].tags[0].tagType = tagType;
+    std::vector<hardware::hidl_string> deviceNames = {"device@3.2/test/0"};
+
+    sp<CameraProviderManager> providerManager = new CameraProviderManager();
+    sp<TestStatusListener> statusListener = new TestStatusListener();
+    TestInteractionProxy serviceProxy;
+
+    sp<TestICameraProvider> provider =  new TestICameraProvider(deviceNames,
+            vendorSection);
+    serviceProxy.setProvider(provider);
+
+    auto res = providerManager->initialize(statusListener, &serviceProxy);
+    ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+
+    hardware::hidl_string testProviderInstanceName = "test/0";
+    hardware::hidl_string testProviderFqInterfaceName =
+            "android.hardware.camera.provider@2.4::ICameraProvider";
+    serviceProxy.mManagerNotificationInterface->onRegistration(
+            testProviderFqInterfaceName, testProviderInstanceName, false);
+    ASSERT_EQ(serviceProxy.mLastRequestedServiceName, testProviderInstanceName) <<
+            "Incorrect instance requested from service manager";
+
+    hardware::hidl_string sectionNameSecond = "SecondVendorTestSection";
+    hardware::hidl_string secondTagName = "SecondVendorTestTag";
+    CameraMetadataType secondTagType = CameraMetadataType::DOUBLE;
+    vendorSection[0].sectionName = sectionNameSecond;
+    vendorSection[0].tags[0].tagId = tagId;
+    vendorSection[0].tags[0].tagName = secondTagName;
+    vendorSection[0].tags[0].tagType = secondTagType;
+    deviceNames = {"device@3.2/test2/1"};
+
+    sp<TestICameraProvider> secondProvider =  new TestICameraProvider(
+            deviceNames, vendorSection);
+    serviceProxy.setProvider(secondProvider);
+    hardware::hidl_string testProviderSecondInstanceName = "test2/0";
+    serviceProxy.mManagerNotificationInterface->onRegistration(
+            testProviderFqInterfaceName, testProviderSecondInstanceName, false);
+    ASSERT_EQ(serviceProxy.mLastRequestedServiceName,
+              testProviderSecondInstanceName) <<
+            "Incorrect instance requested from service manager";
+
+    ASSERT_EQ(NO_ERROR , providerManager->setUpVendorTags());
+    sp<VendorTagDescriptorCache> vendorCache =
+            VendorTagDescriptorCache::getGlobalVendorTagCache();
+    ASSERT_NE(nullptr, vendorCache.get());
+
+    metadata_vendor_id_t vendorId = std::hash<std::string> {} (
+            testProviderInstanceName.c_str());
+    metadata_vendor_id_t vendorIdSecond = std::hash<std::string> {} (
+            testProviderSecondInstanceName.c_str());
+
+    hardware::hidl_string resultTag = vendorCache->getTagName(tagId, vendorId);
+    ASSERT_EQ(resultTag, tagName);
+
+    resultTag = vendorCache->getTagName(tagId, vendorIdSecond);
+    ASSERT_EQ(resultTag, secondTagName);
+
+    // Check whether we can create two separate CameraMetadata instances
+    // using different tag vendor vendors.
+    camera_metadata *metaBuffer = allocate_camera_metadata(10, 20);
+    ASSERT_NE(nullptr, metaBuffer);
+    set_camera_metadata_vendor_id(metaBuffer, vendorId);
+    CameraMetadata metadata(metaBuffer);
+
+    uint8_t byteVal = 10;
+    ASSERT_TRUE(metadata.isEmpty());
+    ASSERT_EQ(OK, metadata.update(tagId, &byteVal, 1));
+    ASSERT_FALSE(metadata.isEmpty());
+    ASSERT_TRUE(metadata.exists(tagId));
+
+    metaBuffer = allocate_camera_metadata(10, 20);
+    ASSERT_NE(nullptr, metaBuffer);
+    set_camera_metadata_vendor_id(metaBuffer, vendorIdSecond);
+    CameraMetadata secondMetadata(metaBuffer);
+
+    ASSERT_TRUE(secondMetadata.isEmpty());
+    double doubleVal = 1.0f;
+    ASSERT_EQ(OK, secondMetadata.update(tagId, &doubleVal, 1));
+    ASSERT_FALSE(secondMetadata.isEmpty());
+    ASSERT_TRUE(secondMetadata.exists(tagId));
+
+    // Check whether CameraMetadata copying works as expected
+    CameraMetadata metadataCopy(metadata);
+    ASSERT_FALSE(metadataCopy.isEmpty());
+    ASSERT_TRUE(metadataCopy.exists(tagId));
+    ASSERT_EQ(OK, metadataCopy.update(tagId, &byteVal, 1));
+    ASSERT_TRUE(metadataCopy.exists(tagId));
+
+    // Check whether values are as expected
+    camera_metadata_entry_t entry = metadata.find(tagId);
+    ASSERT_EQ(1u, entry.count);
+    ASSERT_EQ(byteVal, entry.data.u8[0]);
+    entry = secondMetadata.find(tagId);
+    ASSERT_EQ(1u, entry.count);
+    ASSERT_EQ(doubleVal, entry.data.d[0]);
+
+    // Swap and erase
+    secondMetadata.swap(metadataCopy);
+    ASSERT_TRUE(metadataCopy.exists(tagId));
+    ASSERT_TRUE(secondMetadata.exists(tagId));
+    ASSERT_EQ(OK, secondMetadata.erase(tagId));
+    ASSERT_TRUE(secondMetadata.isEmpty());
+    doubleVal = 0.0f;
+    ASSERT_EQ(OK, metadataCopy.update(tagId, &doubleVal, 1));
+    entry = metadataCopy.find(tagId);
+    ASSERT_EQ(1u, entry.count);
+    ASSERT_EQ(doubleVal, entry.data.d[0]);
+
+    // Append
+    uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_ACTION;
+    secondMetadata.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
+    // Append from two different vendor tag providers is not supported!
+    ASSERT_NE(OK, metadataCopy.append(secondMetadata));
+    ASSERT_EQ(OK, metadataCopy.erase(tagId));
+    metadataCopy.update(ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
+    // However appending from same vendor tag provider should be fine
+    ASSERT_EQ(OK, metadata.append(secondMetadata));
+    // Append from a metadata without vendor tag provider should not be supported
+    CameraMetadata regularMetadata(10, 20);
+    uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
+    regularMetadata.update(ANDROID_CONTROL_MODE, &controlMode, 1);
+    ASSERT_NE(OK, secondMetadata.append(regularMetadata));
+    ASSERT_EQ(1u, secondMetadata.entryCount());
+    ASSERT_EQ(2u, metadata.entryCount());
+
+    // Dump
+    metadata.dump(1, 2);
+    metadataCopy.dump(1, 2);
+    secondMetadata.dump(1, 2);
+}
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index f1b65bd..dec97d7 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -23,12 +23,14 @@
 #include <inttypes.h>
 #include <utils/Log.h>
 #include <camera/VendorTagDescriptor.h>
+#include <camera_metadata_hidden.h>
 
 namespace android {
 
 TagMonitor::TagMonitor():
         mMonitoringEnabled(false),
-        mMonitoringEvents(kMaxMonitorEvents)
+        mMonitoringEvents(kMaxMonitorEvents),
+        mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
 {}
 
 const char* TagMonitor::k3aTags =
@@ -55,6 +57,13 @@
 
     sp<VendorTagDescriptor> vTags =
             VendorTagDescriptor::getGlobalVendorTagDescriptor();
+    if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
+        sp<VendorTagDescriptorCache> cache =
+                VendorTagDescriptorCache::getGlobalVendorTagCache();
+        if (cache.get()) {
+            cache->getVendorTagDescriptor(mVendorTagId, &vTags);
+        }
+    }
 
     bool gotTag = false;
 
@@ -104,6 +113,15 @@
         camera_metadata_ro_entry entry = metadata.find(tag);
         CameraMetadata &lastValues = (source == REQUEST) ?
                 mLastMonitoredRequestValues : mLastMonitoredResultValues;
+        if (lastValues.isEmpty()) {
+            lastValues = CameraMetadata(mMonitoredTagList.size());
+            const camera_metadata_t *metaBuffer =
+                    lastValues.getAndLock();
+            set_camera_metadata_vendor_id(
+                    const_cast<camera_metadata_t *> (metaBuffer), mVendorTagId);
+            lastValues.unlock(metaBuffer);
+        }
+
         camera_metadata_entry lastEntry = lastValues.find(tag);
 
         if (entry.count > 0) {
@@ -129,16 +147,21 @@
             }
 
             if (isDifferent) {
-                ALOGV("%s: Tag %s changed", __FUNCTION__, get_camera_metadata_tag_name(tag));
+                ALOGV("%s: Tag %s changed", __FUNCTION__,
+                      get_local_camera_metadata_tag_name_vendor_id(
+                              tag, mVendorTagId));
                 lastValues.update(entry);
                 mMonitoringEvents.emplace(source, frameNumber, timestamp, entry);
             }
         } else if (lastEntry.count > 0) {
             // Value has been removed
-            ALOGV("%s: Tag %s removed", __FUNCTION__, get_camera_metadata_tag_name(tag));
+            ALOGV("%s: Tag %s removed", __FUNCTION__,
+                  get_local_camera_metadata_tag_name_vendor_id(
+                          tag, mVendorTagId));
             lastValues.erase(tag);
             entry.tag = tag;
-            entry.type = get_camera_metadata_tag_type(tag);
+            entry.type = get_local_camera_metadata_tag_type_vendor_id(tag,
+                    mVendorTagId);
             entry.count = 0;
             mMonitoringEvents.emplace(source, frameNumber, timestamp, entry);
         }
@@ -152,8 +175,10 @@
         dprintf(fd, "     Tag monitoring enabled for tags:\n");
         for (uint32_t tag : mMonitoredTagList) {
             dprintf(fd, "        %s.%s\n",
-                    get_camera_metadata_section_name(tag),
-                    get_camera_metadata_tag_name(tag));
+                    get_local_camera_metadata_section_name_vendor_id(tag,
+                            mVendorTagId),
+                    get_local_camera_metadata_tag_name_vendor_id(tag,
+                            mVendorTagId));
         }
     } else {
         dprintf(fd, "     Tag monitoring disabled (enable with -m <name1,..,nameN>)\n");
@@ -166,8 +191,10 @@
                     event.frameNumber, event.timestamp,
                     indentation,
                     event.source == REQUEST ? "REQ:" : "RES:",
-                    get_camera_metadata_section_name(event.tag),
-                    get_camera_metadata_tag_name(event.tag));
+                    get_local_camera_metadata_section_name_vendor_id(event.tag,
+                            mVendorTagId),
+                    get_local_camera_metadata_tag_name_vendor_id(event.tag,
+                            mVendorTagId));
             if (event.newData.size() == 0) {
                 dprintf(fd, " (Removed)\n");
             } else {
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index d7aa419..7155314 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -27,6 +27,7 @@
 
 #include <media/RingBuffer.h>
 #include <system/camera_metadata.h>
+#include <system/camera_vendor_tags.h>
 #include <camera/CameraMetadata.h>
 
 namespace android {
@@ -44,6 +45,8 @@
 
     TagMonitor();
 
+    void initialize(metadata_vendor_id_t id) { mVendorTagId = id; }
+
     // Parse tag name list (comma-separated) and if valid, enable monitoring
     // If invalid, do nothing.
     // Recognizes "3a" as a shortcut for enabling tracking 3A state, mode, and
@@ -100,6 +103,7 @@
 
     // 3A fields to use with the "3a" option
     static const char *k3aTags;
+    metadata_vendor_id_t mVendorTagId;
 };
 
 } // namespace android
diff --git a/services/mediaanalytics/Android.mk b/services/mediaanalytics/Android.mk
index ef49df4..f7197af 100644
--- a/services/mediaanalytics/Android.mk
+++ b/services/mediaanalytics/Android.mk
@@ -18,6 +18,7 @@
     libgui                      \
     libmedia                    \
     libmediautils               \
+    libmediametrics             \
     libstagefright_foundation   \
     libutils