Merge "Remove NdkJavaVMHelper.h from NDK directory"
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 15c295e..4745ee8 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -50,6 +50,15 @@
     mBuffer = clone_camera_metadata(other.mBuffer);
 }
 
+CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL),  mLocked(false) {
+    acquire(other);
+}
+
+CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
+    acquire(other);
+    return *this;
+}
+
 CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
         mBuffer(NULL), mLocked(false) {
     acquire(buffer);
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
index 1d8e8c4..9cbfdb0 100644
--- a/camera/CaptureResult.cpp
+++ b/camera/CaptureResult.cpp
@@ -117,6 +117,12 @@
         mMetadata(), mResultExtras() {
 }
 
+CaptureResult::CaptureResult(CaptureResult &&otherResult) {
+    mMetadata = std::move(otherResult.mMetadata);
+    mResultExtras = otherResult.mResultExtras;
+    mPhysicalMetadatas = std::move(otherResult.mPhysicalMetadatas);
+}
+
 CaptureResult::CaptureResult(const CaptureResult &otherResult) {
     mResultExtras = otherResult.mResultExtras;
     mMetadata = otherResult.mMetadata;
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index 844bb80..9d1b5c7 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -40,6 +40,11 @@
      * dataCapacity extra storage */
     CameraMetadata(size_t entryCapacity, size_t dataCapacity = 10);
 
+    /**
+     * Move constructor, acquires other's metadata buffer
+     */
+    CameraMetadata(CameraMetadata &&other);
+
     ~CameraMetadata();
 
     /** Takes ownership of passed-in buffer */
@@ -54,6 +59,11 @@
     CameraMetadata &operator=(const camera_metadata_t *buffer);
 
     /**
+     * Move assignment operator, acquires other's metadata buffer
+     */
+    CameraMetadata &operator=(CameraMetadata &&other);
+
+    /**
      * Get reference to the underlying metadata buffer. Ownership remains with
      * the CameraMetadata object, but non-const CameraMetadata methods will not
      * work until unlock() is called. Note that the lock has nothing to do with
diff --git a/camera/include/camera/CaptureResult.h b/camera/include/camera/CaptureResult.h
index ef830b5..dc3d282 100644
--- a/camera/include/camera/CaptureResult.h
+++ b/camera/include/camera/CaptureResult.h
@@ -135,6 +135,8 @@
 
     CaptureResult(const CaptureResult& otherResult);
 
+    CaptureResult(CaptureResult &&captureResult);
+
     status_t                readFromParcel(android::Parcel* parcel);
     status_t                writeToParcel(android::Parcel* parcel) const;
 };
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index fd71837..f427834 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -26,11 +26,13 @@
     shared_libs: [
         "libmedia",
         "libmediametrics",
+        "libcutils",
         "libutils",
         "liblog",
         "libbinder",
         "libdl",
         "libselinux",
+        "libstagefright_foundation",
     ],
 
     static_libs: ["libdrmframeworkcommon"],
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 38dc052..9a32cc5 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -16,9 +16,10 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DrmManager(Native)"
-#include "utils/Log.h"
 
+#include <cutils/properties.h>
 #include <utils/String8.h>
+#include <utils/Log.h>
 
 #include <binder/IPCThreadState.h>
 #include <drm/DrmInfo.h>
@@ -37,12 +38,30 @@
 #include "DrmManager.h"
 #include "ReadWriteUtils.h"
 
+#include <algorithm>
+
 #define DECRYPT_FILE_ERROR (-1)
 
 using namespace android;
 
 const String8 DrmManager::EMPTY_STRING("");
 
+const std::map<const char*, size_t> DrmManager::kMethodIdMap {
+    {"getConstraints"     , DrmManagerMethodId::GET_CONSTRAINTS       },
+    {"getMetadata"        , DrmManagerMethodId::GET_METADATA          },
+    {"canHandle"          , DrmManagerMethodId::CAN_HANDLE            },
+    {"processDrmInfo"     , DrmManagerMethodId::PROCESS_DRM_INFO      },
+    {"acquireDrmInfo"     , DrmManagerMethodId::ACQUIRE_DRM_INFO      },
+    {"saveRights"         , DrmManagerMethodId::SAVE_RIGHTS           },
+    {"getOriginalMimeType", DrmManagerMethodId::GET_ORIGINAL_MIME_TYPE},
+    {"getDrmObjectType"   , DrmManagerMethodId::GET_DRM_OBJECT_TYPE   },
+    {"checkRightsStatus"  , DrmManagerMethodId::CHECK_RIGHTS_STATUS   },
+    {"removeRights"       , DrmManagerMethodId::REMOVE_RIGHTS         },
+    {"removeAllRights"    , DrmManagerMethodId::REMOVE_ALL_RIGHTS     },
+    {"openConvertSession" , DrmManagerMethodId::OPEN_CONVERT_SESSION  },
+    {"openDecryptSession" , DrmManagerMethodId::OPEN_DECRYPT_SESSION  }
+};
+
 DrmManager::DrmManager() :
     mDecryptSessionId(0),
     mConvertId(0) {
@@ -51,42 +70,106 @@
 }
 
 DrmManager::~DrmManager() {
-
+    if (mMetricsLooper != NULL) {
+        mMetricsLooper->stop();
+    }
+    flushEngineMetrics();
 }
 
-void DrmManager::reportEngineMetrics(
-        const char func[], const String8& plugInId, const String8& mimeType) {
-    IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId);
+void DrmManager::initMetricsLooper() {
+    if (mMetricsLooper != NULL) {
+        return;
+    }
+    mMetricsLooper = new ALooper;
+    mMetricsLooper->setName("DrmManagerMetricsLooper");
+    mMetricsLooper->start();
+    mMetricsLooper->registerHandler(this);
 
-    std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
-    item->setUid(IPCThreadState::self()->getCallingUid());
-    item->setCString("function_name", func);
-    item->setCString("plugin_id", plugInId.getPathLeaf().getBasePath().c_str());
+    sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
+    msg->post(getMetricsFlushPeriodUs());
+}
 
+void DrmManager::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatFlushMetrics:
+        {
+            flushEngineMetrics();
+            msg->post(getMetricsFlushPeriodUs());
+            break;
+        }
+        default:
+        {
+            ALOGW("Unrecognized message type: %zd", msg->what());
+        }
+    }
+}
+
+int64_t DrmManager::getMetricsFlushPeriodUs() {
+    return 1000 * 1000 * std::max(1ll, property_get_int64("drmmanager.metrics.period", 86400));
+}
+
+void DrmManager::recordEngineMetrics(
+        const char func[], const String8& plugInId8, const String8& mimeType) {
+    IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId8);
     std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
-    if (NULL != info) {
-        item->setCString("description", info->getDescription().c_str());
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
+    ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
+
+    Mutex::Autolock _l(mMetricsLock);
+    auto& metrics = mPluginMetrics[std::make_pair(callingUid, plugInId)];
+    if (metrics.mPluginId.empty()) {
+        metrics.mPluginId = plugInId;
+        metrics.mCallingUid = callingUid;
+        if (NULL != info) {
+            metrics.mDescription = info->getDescription().c_str();
+        }
     }
 
     if (!mimeType.isEmpty()) {
-        item->setCString("mime_types", mimeType.c_str());
+        metrics.mMimeTypes.insert(mimeType.c_str());
     } else if (NULL != info) {
         DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
-        String8 mimes;
         while (mimeIter.hasNext()) {
-            mimes += mimeIter.next();
-            if (mimeIter.hasNext()) {
-                mimes += ",";
-            }
+            metrics.mMimeTypes.insert(mimeIter.next().c_str());
         }
-        item->setCString("mime_types", mimes.c_str());
     }
 
-    if (!item->selfrecord()) {
-        ALOGE("Failed to record metrics");
+    size_t methodId = kMethodIdMap.at(func);
+    if (methodId < metrics.mMethodCounts.size()) {
+        metrics.mMethodCounts[methodId]++;
     }
 }
 
+void DrmManager::flushEngineMetrics() {
+    using namespace std::string_literals;
+    Mutex::Autolock _l(mMetricsLock);
+    for (auto kv : mPluginMetrics) {
+        DrmManagerMetrics& metrics = kv.second;
+        std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
+        item->setUid(metrics.mCallingUid);
+        item->setCString("plugin_id", metrics.mPluginId.c_str());
+        item->setCString("description", metrics.mDescription.c_str());
+
+        std::vector<std::string> mimeTypes(metrics.mMimeTypes.begin(), metrics.mMimeTypes.end());
+        std::string mimeTypesStr(mimeTypes.empty() ? "" : mimeTypes[0]);
+        for (size_t i = 1; i < mimeTypes.size() ; i++) {
+            mimeTypesStr.append(",").append(mimeTypes[i]);
+        }
+        item->setCString("mime_types", mimeTypesStr.c_str());
+
+        for (size_t i = 0; i < metrics.mMethodCounts.size() ; i++) {
+            item->setInt64(("method"s + std::to_string(i)).c_str(), metrics.mMethodCounts[i]);
+        }
+
+        if (!item->selfrecord()) {
+            ALOGE("Failed to record metrics");
+        }
+    }
+    mPluginMetrics.clear();
+}
+
 int DrmManager::addUniqueId(bool isNative) {
     Mutex::Autolock _l(mLock);
 
@@ -184,7 +267,6 @@
     for (size_t index = 0; index < plugInIdList.size(); index++) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
         rDrmEngine.terminate(uniqueId);
-        reportEngineMetrics(__func__, plugInIdList[index]);
     }
 }
 
@@ -197,7 +279,7 @@
         constraints = rDrmEngine.getConstraints(uniqueId, path, action);
     }
     if (NULL != constraints) {
-        reportEngineMetrics(__func__, plugInId);
+        recordEngineMetrics(__func__, plugInId);
     }
     return constraints;
 }
@@ -211,7 +293,7 @@
         meta = rDrmEngine.getMetadata(uniqueId, path);
     }
     if (NULL != meta) {
-        reportEngineMetrics(__func__, plugInId);
+        recordEngineMetrics(__func__, plugInId);
     }
     return meta;
 }
@@ -222,7 +304,7 @@
     bool result = (EMPTY_STRING != plugInId) ? true : false;
 
     if (result) {
-        reportEngineMetrics(__func__, plugInId, mimeType);
+        recordEngineMetrics(__func__, plugInId, mimeType);
     }
 
     if (0 < path.length()) {
@@ -249,7 +331,7 @@
         infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
     }
     if (NULL != infoStatus) {
-        reportEngineMetrics(__func__, plugInId, mimeType);
+        recordEngineMetrics(__func__, plugInId, mimeType);
     }
     return infoStatus;
 }
@@ -263,7 +345,7 @@
         result = rDrmEngine.canHandle(uniqueId, path);
 
         if (result) {
-            reportEngineMetrics(__func__, plugInPathList[i]);
+            recordEngineMetrics(__func__, plugInPathList[i]);
             break;
         }
     }
@@ -280,7 +362,7 @@
         info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
     }
     if (NULL != info) {
-        reportEngineMetrics(__func__, plugInId, mimeType);
+        recordEngineMetrics(__func__, plugInId, mimeType);
     }
     return info;
 }
@@ -296,7 +378,7 @@
         result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
     }
     if (DRM_NO_ERROR == result) {
-        reportEngineMetrics(__func__, plugInId, mimeType);
+        recordEngineMetrics(__func__, plugInId, mimeType);
     }
     return result;
 }
@@ -310,7 +392,7 @@
         mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
     }
     if (!mimeType.isEmpty()) {
-        reportEngineMetrics(__func__, plugInId, mimeType);
+        recordEngineMetrics(__func__, plugInId, mimeType);
     }
     return mimeType;
 }
@@ -324,7 +406,7 @@
         type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
     }
     if (DrmObjectType::UNKNOWN != type) {
-        reportEngineMetrics(__func__, plugInId, mimeType);
+        recordEngineMetrics(__func__, plugInId, mimeType);
     }
     return type;
 }
@@ -338,7 +420,7 @@
         rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
     }
     if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
-        reportEngineMetrics(__func__, plugInId);
+        recordEngineMetrics(__func__, plugInId);
     }
     return rightsStatus;
 }
@@ -385,7 +467,7 @@
         result = rDrmEngine.removeRights(uniqueId, path);
     }
     if (DRM_NO_ERROR == result) {
-        reportEngineMetrics(__func__, plugInId);
+        recordEngineMetrics(__func__, plugInId);
     }
     return result;
 }
@@ -399,7 +481,7 @@
         if (DRM_NO_ERROR != result) {
             break;
         }
-        reportEngineMetrics(__func__, plugInIdList[index]);
+        recordEngineMetrics(__func__, plugInIdList[index]);
     }
     return result;
 }
@@ -416,7 +498,7 @@
             ++mConvertId;
             convertId = mConvertId;
             mConvertSessionMap.add(convertId, &rDrmEngine);
-            reportEngineMetrics(__func__, plugInId, mimeType);
+            recordEngineMetrics(__func__, plugInId, mimeType);
         }
     }
     return convertId;
@@ -497,7 +579,7 @@
             if (DRM_NO_ERROR == result) {
                 ++mDecryptSessionId;
                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
-                reportEngineMetrics(__func__, plugInId, String8(mime));
+                recordEngineMetrics(__func__, plugInId, String8(mime));
                 break;
             }
         }
@@ -526,7 +608,7 @@
             if (DRM_NO_ERROR == result) {
                 ++mDecryptSessionId;
                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
-                reportEngineMetrics(__func__, plugInId, String8(mime));
+                recordEngineMetrics(__func__, plugInId, String8(mime));
                 break;
             }
         }
@@ -556,7 +638,7 @@
             if (DRM_NO_ERROR == result) {
                 ++mDecryptSessionId;
                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
-                reportEngineMetrics(__func__, plugInId, mimeType);
+                recordEngineMetrics(__func__, plugInId, mimeType);
                 break;
             }
         }
diff --git a/drm/drmserver/DrmManager.h b/drm/drmserver/DrmManager.h
index 75fc1a8..350fcf4 100644
--- a/drm/drmserver/DrmManager.h
+++ b/drm/drmserver/DrmManager.h
@@ -17,13 +17,26 @@
 #ifndef __DRM_MANAGER_H__
 #define __DRM_MANAGER_H__
 
+#include <drm/drm_framework_common.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <sys/types.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
-#include <drm/drm_framework_common.h>
+
 #include "IDrmEngine.h"
 #include "PlugInManager.h"
 #include "IDrmServiceListener.h"
 
+#include <array>
+#include <cstddef>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
 namespace android {
 
 class IDrmManager;
@@ -40,6 +53,31 @@
 class DrmSupportInfo;
 class ActionDescription;
 
+enum DrmManagerMethodId {
+  GET_CONSTRAINTS,
+  GET_METADATA,
+  CAN_HANDLE,
+  PROCESS_DRM_INFO,
+  ACQUIRE_DRM_INFO,
+  SAVE_RIGHTS,
+  GET_ORIGINAL_MIME_TYPE,
+  GET_DRM_OBJECT_TYPE,
+  CHECK_RIGHTS_STATUS,
+  REMOVE_RIGHTS,
+  REMOVE_ALL_RIGHTS,
+  OPEN_CONVERT_SESSION,
+  OPEN_DECRYPT_SESSION,
+  NUM_METHODS,
+};
+
+struct DrmManagerMetrics {
+    std::string mPluginId;
+    std::string mDescription;
+    std::set<std::string> mMimeTypes;
+    std::array<int64_t, DrmManagerMethodId::NUM_METHODS> mMethodCounts{};
+    uid_t mCallingUid;
+};
+
 /**
  * This is implementation class for DRM Manager. This class delegates the
  * functionality to corresponding DRM Engine.
@@ -47,7 +85,7 @@
  * The DrmManagerService class creates an instance of this class.
  *
  */
-class DrmManager : public IDrmEngine::OnInfoListener {
+class DrmManager : public AHandler, public IDrmEngine::OnInfoListener {
 public:
     DrmManager();
     virtual ~DrmManager();
@@ -134,6 +172,8 @@
 
     void onInfo(const DrmInfoEvent& event);
 
+    void initMetricsLooper();
+
 private:
     String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
 
@@ -143,16 +183,24 @@
 
     bool canHandle(int uniqueId, const String8& path);
 
-    void reportEngineMetrics(const char func[],
+    void onMessageReceived(const sp<AMessage> &msg);
+
+    int64_t getMetricsFlushPeriodUs();
+
+    void recordEngineMetrics(const char func[],
             const String8& plugInId, const String8& mimeType = String8(""));
 
+    void flushEngineMetrics();
+
 private:
     enum {
         kMaxNumUniqueIds = 0x1000,
+        kWhatFlushMetrics = 'metr',
     };
 
     bool mUniqueIdArray[kMaxNumUniqueIds];
     static const String8 EMPTY_STRING;
+    static const std::map<const char*, size_t> kMethodIdMap;
 
     int mDecryptSessionId;
     int mConvertId;
@@ -160,11 +208,15 @@
     Mutex mListenerLock;
     Mutex mDecryptLock;
     Mutex mConvertLock;
+    Mutex mMetricsLock;
     TPlugInManager<IDrmEngine> mPlugInManager;
     KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
     KeyedVector< int, IDrmEngine*> mConvertSessionMap;
     KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
     KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
+
+    std::map<std::pair<uid_t, std::string>, DrmManagerMetrics> mPluginMetrics;
+    sp<ALooper> mMetricsLooper;
 };
 
 };
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 2600a2c..4b8b3f6 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -130,13 +130,14 @@
         mDrmManager(NULL) {
     ALOGV("created");
     mDrmManager = new DrmManager();
+    mDrmManager->initMetricsLooper();
     mDrmManager->loadPlugIns();
 }
 
 DrmManagerService::~DrmManagerService() {
     ALOGV("Destroyed");
     mDrmManager->unloadPlugIns();
-    delete mDrmManager; mDrmManager = NULL;
+    mDrmManager = NULL;
 }
 
 int DrmManagerService::addUniqueId(bool isNative) {
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index 2e27a3c..f9b8bef 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -142,7 +142,7 @@
     virtual status_t dump(int fd, const Vector<String16>& args);
 
 private:
-    DrmManager* mDrmManager;
+    sp<DrmManager> mDrmManager;
 };
 
 };
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 5b32a04..f218041 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -713,7 +713,8 @@
     } while (retry);
 
     if (err == OK) {
-        std::shared_ptr<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
+        std::shared_ptr<DrmSessionClient> client =
+                ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
         DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
                 std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
         mOpenSessions.push_back(client);
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 3568f7b..f39620e 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -40,6 +40,8 @@
 #define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM  0  /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS (0.25) /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
 // names of properties that can be used to override the default DRC settings
@@ -190,6 +192,24 @@
                 })
                 .withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps)
                 .build());
+
+        addParameter(
+                DefineParam(mDrcAlbumMode, C2_PARAMKEY_DRC_ALBUM_MODE)
+                .withDefault(new C2StreamDrcAlbumModeTuning::input(0u, C2Config::DRC_ALBUM_MODE_OFF))
+                .withFields({
+                    C2F(mDrcAlbumMode, value).oneOf({
+                            C2Config::DRC_ALBUM_MODE_OFF,
+                            C2Config::DRC_ALBUM_MODE_ON})
+                })
+                .withSetter(Setter<decltype(*mDrcAlbumMode)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcOutputLoudness, C2_PARAMKEY_DRC_OUTPUT_LOUDNESS)
+                .withDefault(new C2StreamDrcOutputLoudnessTuning::output(0u, DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS))
+                .withFields({C2F(mDrcOutputLoudness, value).inRange(-57.75, 0.25)})
+                .withSetter(Setter<decltype(*mDrcOutputLoudness)>::StrictValueWithNoDeps)
+                .build());
     }
 
     bool isAdts() const { return mAacFormat->value == C2Config::AAC_PACKAGING_ADTS; }
@@ -204,6 +224,8 @@
     int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; }
     int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; }
     int32_t getDrcEffectType() const { return mDrcEffectType->value; }
+    int32_t getDrcAlbumMode() const { return mDrcAlbumMode->value; }
+    int32_t getDrcOutputLoudness() const { return (mDrcOutputLoudness->value <= 0 ? -mDrcOutputLoudness->value * 4. + 0.5 : -1); }
 
 private:
     std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
@@ -218,6 +240,8 @@
     std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor;
     std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor;
     std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType;
+    std::shared_ptr<C2StreamDrcAlbumModeTuning::input> mDrcAlbumMode;
+    std::shared_ptr<C2StreamDrcOutputLoudnessTuning::output> mDrcOutputLoudness;
     // TODO Add : C2StreamAacSbrModeTuning
 };
 
@@ -324,7 +348,7 @@
 
     //  DRC_PRES_MODE_WRAP_DESIRED_HEAVY
     int32_t compressMode = mIntf->getDrcCompressMode();
-    ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+    ALOGV("AAC decoder using desired DRC heavy compression switch of %d", compressMode);
     mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
 
     // DRC_PRES_MODE_WRAP_ENCODER_TARGET
@@ -337,6 +361,11 @@
     ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
     aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
 
+    // AAC_UNIDRC_ALBUM_MODE
+    int32_t albumMode = mIntf->getDrcAlbumMode();
+    ALOGV("AAC decoder using MPEG-D DRC album mode %d", albumMode);
+    aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
+
     // By default, the decoder creates a 5.1 channel downmix signal.
     // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
     aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
@@ -632,6 +661,7 @@
 
         INT prevSampleRate = mStreamInfo->sampleRate;
         INT prevNumChannels = mStreamInfo->numChannels;
+        INT prevOutLoudness = mStreamInfo->outputLoudness;
 
         aacDecoder_Fill(mAACDecoder,
                         inBuffer,
@@ -640,6 +670,43 @@
 
         // run DRC check
         mDrcWrap.submitStreamData(mStreamInfo);
+
+        // apply runtime updates
+        //  DRC_PRES_MODE_WRAP_DESIRED_TARGET
+        int32_t targetRefLevel = mIntf->getDrcTargetRefLevel();
+        ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel);
+
+        //  DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
+        int32_t attenuationFactor = mIntf->getDrcAttenuationFactor();
+        ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor);
+
+        //  DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
+        int32_t boostFactor = mIntf->getDrcBoostFactor();
+        ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor);
+
+        //  DRC_PRES_MODE_WRAP_DESIRED_HEAVY
+        int32_t compressMode = mIntf->getDrcCompressMode();
+        ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
+
+        // DRC_PRES_MODE_WRAP_ENCODER_TARGET
+        int32_t encTargetLevel = mIntf->getDrcEncTargetLevel();
+        ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel);
+
+        // AAC_UNIDRC_SET_EFFECT
+        int32_t effectType = mIntf->getDrcEffectType();
+        ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
+        aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+
+        // AAC_UNIDRC_ALBUM_MODE
+        int32_t albumMode = mIntf->getDrcAlbumMode();
+        ALOGV("AAC decoder using MPEG-D DRC album mode %d", albumMode);
+        aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
+
         mDrcWrap.update();
 
         UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
@@ -763,6 +830,23 @@
                 }
             }
             ALOGV("size = %zu", size);
+
+            if (mStreamInfo->outputLoudness != prevOutLoudness) {
+                C2StreamDrcOutputLoudnessTuning::output
+                        drcOutLoudness(0u, (float) (mStreamInfo->outputLoudness*-0.25));
+
+                std::vector<std::unique_ptr<C2SettingResult>> failures;
+                c2_status_t err = mIntf->config(
+                                    { &drcOutLoudness },
+                                    C2_MAY_BLOCK,
+                                    &failures);
+                if (err == OK) {
+                    work->worklets.front()->output.configUpdate.push_back(
+                        C2Param::Copy(drcOutLoudness));
+                } else {
+                    ALOGE("Getting output loudness failed");
+                }
+            }
         } while (decoderErr == AAC_DEC_OK);
     }
 
diff --git a/media/codec2/components/aac/DrcPresModeWrap.cpp b/media/codec2/components/aac/DrcPresModeWrap.cpp
index 5b9aebc..bee969b 100644
--- a/media/codec2/components/aac/DrcPresModeWrap.cpp
+++ b/media/codec2/components/aac/DrcPresModeWrap.cpp
@@ -47,10 +47,9 @@
     mEncoderTarget = -1;
 
     /* Values from last time. */
-    /* Initialized to the same values as the desired values */
-    mLastTarget = -1;
-    mLastAttFactor = 0;
-    mLastBoostFactor = 0;
+    mLastTarget = -2;
+    mLastAttFactor = -1;
+    mLastBoostFactor = -1;
     mLastHeavy = 0;
 }
 
@@ -163,7 +162,7 @@
 
     if (mDataUpdate) {
         // sanity check
-        if (mDesTarget < MAX_TARGET_LEVEL){
+        if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){
             mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -10 dB or below
             newTarget = MAX_TARGET_LEVEL;
         }
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index f9eb2fa..74fdc8b 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -58,6 +58,8 @@
     enum bitrate_mode_t : uint32_t;         ///< bitrate control mode
     enum drc_compression_mode_t : int32_t;  ///< DRC compression mode
     enum drc_effect_type_t : int32_t;       ///< DRC effect type
+    enum drc_album_mode_t : int32_t;        ///< DRC album mode
+    enum drc_output_loudness : int32_t;     ///< DRC output loudness
     enum intra_refresh_mode_t : uint32_t;   ///< intra refresh modes
     enum level_t : uint32_t;                ///< coding level
     enum ordinal_key_t : uint32_t;          ///< work ordering keys
@@ -218,6 +220,8 @@
     kParamIndexDrcBoostFactor, // drc, float (0-1)
     kParamIndexDrcAttenuationFactor, // drc, float (0-1)
     kParamIndexDrcEffectType, // drc, enum
+    kParamIndexDrcOutputLoudness, // drc, float (dBFS)
+    kParamIndexDrcAlbumMode, // drc, enum
 
     /* ============================== platform-defined parameters ============================== */
 
@@ -1941,6 +1945,24 @@
         C2StreamDrcEffectTypeTuning;
 constexpr char C2_PARAMKEY_DRC_EFFECT_TYPE[] = "coding.drc.effect-type";
 
+/**
+ * DRC album mode. Used during decoding.
+ */
+C2ENUM(C2Config::drc_album_mode_t, int32_t,
+    DRC_ALBUM_MODE_OFF = 0,
+    DRC_ALBUM_MODE_ON = 1
+)
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::drc_album_mode_t>, kParamIndexDrcAlbumMode>
+        C2StreamDrcAlbumModeTuning;
+constexpr char C2_PARAMKEY_DRC_ALBUM_MODE[] = "coding.drc.album-mode";
+
+/**
+ * DRC output loudness in dBFS. Retrieved during decoding
+ */
+ typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
+        C2StreamDrcOutputLoudnessTuning;
+ constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+
 /* --------------------------------------- AAC components --------------------------------------- */
 
 /**
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index d2f5ea7..b019d0d 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -34,6 +34,8 @@
 #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0   /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS -1 /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 // names of properties that can be used to override the default DRC settings
 #define PROP_DRC_OVERRIDE_REF_LEVEL  "aac_drc_reference_level"
@@ -700,63 +702,101 @@
 
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
-            if (!v.get(&value) || value < 0) {
+            if (!v.get(&value) || value < -1) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_REF_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL);
             }
             return float(-0.25 * c2_min(value, 127));
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+                return (int32_t) (-4. * value);
+            }
+            return C2Value();
         }));
 
     // convert to 0-1 (%) and add default
     add(ConfigMapper(KEY_AAC_DRC_ATTENUATION_FACTOR, C2_PARAMKEY_DRC_ATTENUATION_FACTOR, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_CUT, DRC_DEFAULT_MOBILE_DRC_CUT);
             }
             return float(c2_min(value, 127) / 127.);
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+              return (int32_t) (value * 127. + 0.5);
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to 0-1 (%) and add default
     add(ConfigMapper(KEY_AAC_DRC_BOOST_FACTOR, C2_PARAMKEY_DRC_BOOST_FACTOR, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_BOOST, DRC_DEFAULT_MOBILE_DRC_BOOST);
             }
             return float(c2_min(value, 127) / 127.);
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+              return (int32_t) (value * 127. + 0.5);
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to compression type and add default
     add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
             }
             return value == 1 ? C2Config::DRC_COMPRESSION_HEAVY : C2Config::DRC_COMPRESSION_LIGHT;
+        },[](C2Value v) -> C2Value {
+            int32_t value;
+            if (v.get(&value)) {
+              return value;
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_ENCODED_TARGET_LEVEL, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_ENC_LEVEL, DRC_DEFAULT_MOBILE_ENC_LEVEL);
             }
             return float(-0.25 * c2_min(value, 127));
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+              return (int32_t) (-4. * value);
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to effect type (these map to SDK values) and add default
     add(ConfigMapper(KEY_AAC_DRC_EFFECT_TYPE, C2_PARAMKEY_DRC_EFFECT_TYPE, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < -1 || value > 8) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_EFFECT, DRC_DEFAULT_MOBILE_DRC_EFFECT);
@@ -766,13 +806,60 @@
                 }
             }
             return value;
+        },[](C2Value v) -> C2Value {
+            int32_t value;
+            if (v.get(&value)) {
+              return  value;
+            }
+            else {
+              return C2Value();
+            }
+        }));
+
+    // convert to album mode and add default
+    add(ConfigMapper(KEY_AAC_DRC_ALBUM_MODE, C2_PARAMKEY_DRC_ALBUM_MODE, "value")
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
+            int32_t value;
+            if (!v.get(&value) || value < 0 || value > 1) {
+                value = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+                // ensure value is within range
+                if (value < 0 || value > 1) {
+                    value = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+                }
+            }
+            return value;
+        },[](C2Value v) -> C2Value {
+            int32_t value;
+            if (v.get(&value)) {
+              return value;
+            }
+            else {
+              return C2Value();
+            }
+        }));
+
+    add(ConfigMapper(KEY_AAC_DRC_OUTPUT_LOUDNESS, C2_PARAMKEY_DRC_OUTPUT_LOUDNESS, "value")
+        .limitTo(D::OUTPUT & D::DECODER & D::READ)
+        .withMappers([](C2Value v) -> C2Value {
+            int32_t value;
+            if (!v.get(&value) || value < -1) {
+                value = DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS;
+            }
+            return float(-0.25 * c2_min(value, 127));
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+                return (int32_t) (-4. * value);
+            }
+            return C2Value();
         }));
 
     add(ConfigMapper(KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT, C2_PARAMKEY_MAX_CHANNEL_COUNT, "value")
-        .limitTo(D::AUDIO));
+        .limitTo(D::AUDIO & (D::CONFIG | D::PARAM | D::READ)));
 
     add(ConfigMapper(KEY_AAC_SBR_MODE, C2_PARAMKEY_AAC_SBR_MODE, "value")
-        .limitTo(D::AUDIO & D::ENCODER & D::CONFIG)
+        .limitTo(D::AUDIO & D::ENCODER & (D::CONFIG | D::PARAM | D::READ))
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index 91d2eff..abc3239 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -72,7 +72,7 @@
 
 // Implement FixedBlockProcessor
 int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
-    int32_t numFrames = numBytes / getBytesPerDeviceFrame();
+    int32_t numFrames = numBytes / mBlockAdapterBytesPerFrame;
     return (int32_t) callDataCallbackFrames(buffer, numFrames);
 }
 
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 8e78554..da9205f 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -133,6 +133,7 @@
     MonotonicCounter           mTimestampPosition;
 
     FixedBlockAdapter         *mBlockAdapter = nullptr;
+    int32_t                    mBlockAdapterBytesPerFrame = 0;
     aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
     int32_t                    mCallbackBufferSize = 0;
     const android::sp<StreamDeviceCallback>   mDeviceCallback;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 2ed82d2..904edd1 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -213,7 +213,10 @@
 
     // We may need to pass the data through a block size adapter to guarantee constant size.
     if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
-        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+        // The block adapter runs before the format conversion.
+        // So we need to use the device frame size.
+        mBlockAdapterBytesPerFrame = getBytesPerDeviceFrame();
+        int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
         mFixedBlockWriter.open(callbackSizeBytes);
         mBlockAdapter = &mFixedBlockWriter;
     } else {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 00963d6..d54d043 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -196,7 +196,10 @@
 
     // We may need to pass the data through a block size adapter to guarantee constant size.
     if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
-        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+        // This may need to change if we add format conversion before
+        // the block size adaptation.
+        mBlockAdapterBytesPerFrame = getBytesPerFrame();
+        int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
         mFixedBlockReader.open(callbackSizeBytes);
         mBlockAdapter = &mFixedBlockReader;
     } else {
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1769062..2f67a18 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -842,13 +842,13 @@
     return aps->handleDeviceConfigChange(device, address, name, encodedFormat);
 }
 
-status_t AudioSystem::setPhoneState(audio_mode_t state)
+status_t AudioSystem::setPhoneState(audio_mode_t state, uid_t uid)
 {
     if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    return aps->setPhoneState(state);
+    return aps->setPhoneState(state, uid);
 }
 
 status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
@@ -879,6 +879,7 @@
                                         audio_stream_type_t *stream,
                                         pid_t pid,
                                         uid_t uid,
+                                        const String16& opPackageName,
                                         const audio_config_t *config,
                                         audio_output_flags_t flags,
                                         audio_port_handle_t *selectedDeviceId,
@@ -888,7 +889,7 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return NO_INIT;
     return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
-                                 config,
+                                 opPackageName, config,
                                  flags, selectedDeviceId, portId, secondaryOutputs);
 }
 
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index cc78ec1..cccb131 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -170,11 +170,12 @@
         return static_cast <status_t> (reply.readInt32());
     }
 
-    virtual status_t setPhoneState(audio_mode_t state)
+    virtual status_t setPhoneState(audio_mode_t state, uid_t uid)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(state);
+        data.writeInt32(uid);
         remote()->transact(SET_PHONE_STATE, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
@@ -213,6 +214,7 @@
                               audio_stream_type_t *stream,
                               pid_t pid,
                               uid_t uid,
+                              const String16& opPackageName,
                               const audio_config_t *config,
                               audio_output_flags_t flags,
                               audio_port_handle_t *selectedDeviceId,
@@ -251,6 +253,7 @@
             }
             data.writeInt32(pid);
             data.writeInt32(uid);
+            data.writeString16(opPackageName);
             data.write(config, sizeof(audio_config_t));
             data.writeInt32(static_cast <uint32_t>(flags));
             data.writeInt32(*selectedDeviceId);
@@ -1596,7 +1599,8 @@
         case SET_PHONE_STATE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             reply->writeInt32(static_cast <uint32_t>(setPhoneState(
-                    (audio_mode_t) data.readInt32())));
+                    (audio_mode_t) data.readInt32(),
+                    (uid_t) data.readInt32())));
             return NO_ERROR;
         } break;
 
@@ -1643,6 +1647,11 @@
             }
             pid_t pid = (pid_t)data.readInt32();
             uid_t uid = (uid_t)data.readInt32();
+            String16 opPackageName;
+            status = data.readString16(&opPackageName);
+            if (status != NO_ERROR) {
+                return status;
+            }
             audio_config_t config;
             memset(&config, 0, sizeof(audio_config_t));
             data.read(&config, sizeof(audio_config_t));
@@ -1654,7 +1663,7 @@
             std::vector<audio_io_handle_t> secondaryOutputs;
             status = getOutputForAttr(&attr,
                     &output, session, &stream, pid, uid,
-                    &config,
+                    opPackageName, &config,
                     flags, &selectedDeviceId, &portId, &secondaryOutputs);
             reply->writeInt32(status);
             status = reply->write(&attr, sizeof(audio_attributes_t));
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 9d3f8b6..07a2292 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -230,7 +230,7 @@
                                              const char *device_address,
                                              const char *device_name,
                                              audio_format_t encodedFormat);
-    static status_t setPhoneState(audio_mode_t state);
+    static status_t setPhoneState(audio_mode_t state, uid_t uid);
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
 
@@ -240,6 +240,7 @@
                                      audio_stream_type_t *stream,
                                      pid_t pid,
                                      uid_t uid,
+                                     const String16& opPackageName,
                                      const audio_config_t *config,
                                      audio_output_flags_t flags,
                                      audio_port_handle_t *selectedDeviceId,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 8bc1d83..8658cfa 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -70,6 +70,7 @@
             if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
                 return DEAD_OBJECT;
             }
+            opPackageName = parcel->readString16();
             if (parcel->readInt32() != 0) {
                 // TODO: Using unsecurePointer() has some associated security
                 //       pitfalls (see declaration for details).
@@ -97,6 +98,7 @@
             (void)parcel->write(&attr, sizeof(audio_attributes_t));
             (void)parcel->write(&config, sizeof(audio_config_t));
             (void)clientInfo.writeToParcel(parcel);
+            (void)parcel->writeString16(opPackageName);
             if (sharedBuffer != 0) {
                 (void)parcel->writeInt32(1);
                 (void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
@@ -119,6 +121,7 @@
         audio_attributes_t attr;
         audio_config_t config;
         AudioClient clientInfo;
+        String16 opPackageName;
         sp<IMemory> sharedBuffer;
         uint32_t notificationsPerBuffer;
         float speed;
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index caa1d13..779ca43 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -53,7 +53,7 @@
                                               const char *device_address,
                                               const char *device_name,
                                               audio_format_t encodedFormat) = 0;
-    virtual status_t setPhoneState(audio_mode_t state) = 0;
+    virtual status_t setPhoneState(audio_mode_t state, uid_t uid) = 0;
     virtual status_t setForceUse(audio_policy_force_use_t usage,
                                     audio_policy_forced_cfg_t config) = 0;
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
@@ -64,6 +64,7 @@
                                       audio_stream_type_t *stream,
                                       pid_t pid,
                                       uid_t uid,
+                                      const String16& opPackageName,
                                       const audio_config_t *config,
                                       audio_output_flags_t flags,
                                       audio_port_handle_t *selectedDeviceId,
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 1a6a5a2..39b0ceb 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -19,6 +19,25 @@
         // uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
         // "-DUSE_NEON=false",
     ],
+
+    arch: {
+        x86: {
+            avx2: {
+                cflags: [
+                    "-mavx2",
+                    "-mfma",
+                ],
+            },
+        },
+        x86_64: {
+            avx2: {
+                cflags: [
+                    "-mavx2",
+                    "-mfma",
+                ],
+            },
+        },
+    },
 }
 
 cc_library_shared {
diff --git a/media/libaudioprocessing/AudioResamplerFirOps.h b/media/libaudioprocessing/AudioResamplerFirOps.h
index 2e4cee3..a3f5ff5 100644
--- a/media/libaudioprocessing/AudioResamplerFirOps.h
+++ b/media/libaudioprocessing/AudioResamplerFirOps.h
@@ -36,13 +36,20 @@
 #include <arm_neon.h>
 #endif
 
-#if defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#if defined(__AVX2__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_AVX2 (true)  // Inference AVX2/FMA Intrinsics
 #define USE_SSE (true)
+#include <immintrin.h>
+#elif defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_SSE (true)  // Inference SSE Intrinsics
+#define USE_AVX2 (false)
 #include <tmmintrin.h>
 #else
 #define USE_SSE (false)
+#define USE_AVX2(false)
 #endif
 
+
 template<typename T, typename U>
 struct is_same
 {
diff --git a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
index 30233b5..1c16bc4 100644
--- a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
+++ b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
@@ -80,11 +80,16 @@
             posCoef1 = _mm_sub_ps(posCoef1, posCoef);
             negCoef = _mm_sub_ps(negCoef, negCoef1);
 
+
+            #if USE_AVX2
+            posCoef = _mm_fmadd_ps(posCoef1, interp, posCoef);
+            negCoef = _mm_fmadd_ps(negCoef, interp, negCoef1);
+            #else
             posCoef1 = _mm_mul_ps(posCoef1, interp);
             negCoef = _mm_mul_ps(negCoef, interp);
-
             posCoef = _mm_add_ps(posCoef1, posCoef);
             negCoef = _mm_add_ps(negCoef, negCoef1);
+            #endif //USE_AVX2
         }
         switch (CHANNELS) {
         case 1: {
@@ -94,11 +99,17 @@
             sN += 4;
 
             posSamp = _mm_shuffle_ps(posSamp, posSamp, 0x1B);
+
+            #if USE_AVX2
+            accL = _mm_fmadd_ps(posSamp, posCoef, accL);
+            accL = _mm_fmadd_ps(negSamp, negCoef, accL);
+            #else
             posSamp = _mm_mul_ps(posSamp, posCoef);
             negSamp = _mm_mul_ps(negSamp, negCoef);
-
             accL = _mm_add_ps(accL, posSamp);
             accL = _mm_add_ps(accL, negSamp);
+            #endif
+
         } break;
         case 2: {
             __m128 posSamp0 = _mm_loadu_ps(sP);
@@ -114,15 +125,23 @@
             __m128 negSampL = _mm_shuffle_ps(negSamp0, negSamp1, 0x88);
             __m128 negSampR = _mm_shuffle_ps(negSamp0, negSamp1, 0xDD);
 
-            posSampL = _mm_mul_ps(posSampL, posCoef);
-            posSampR = _mm_mul_ps(posSampR, posCoef);
-            negSampL = _mm_mul_ps(negSampL, negCoef);
-            negSampR = _mm_mul_ps(negSampR, negCoef);
+           #if USE_AVX2
+           accL = _mm_fmadd_ps(posSampL, posCoef, accL);
+           accR = _mm_fmadd_ps(posSampR, posCoef, accR);
+           accL = _mm_fmadd_ps(negSampL, negCoef, accL);
+           accR = _mm_fmadd_ps(negSampR, negCoef, accR);
+           #else
+           posSampL = _mm_mul_ps(posSampL, posCoef);
+           posSampR = _mm_mul_ps(posSampR, posCoef);
+           negSampL = _mm_mul_ps(negSampL, negCoef);
+           negSampR = _mm_mul_ps(negSampR, negCoef);
 
-            accL = _mm_add_ps(accL, posSampL);
-            accR = _mm_add_ps(accR, posSampR);
-            accL = _mm_add_ps(accL, negSampL);
-            accR = _mm_add_ps(accR, negSampR);
+           accL = _mm_add_ps(accL, posSampL);
+           accR = _mm_add_ps(accR, posSampR);
+           accL = _mm_add_ps(accL, negSampL);
+           accR = _mm_add_ps(accR, negSampR);
+           #endif
+
         } break;
         }
     } while (count -= 4);
@@ -144,9 +163,13 @@
         outAccum = _mm_hadd_ps(accL, accR);
         outAccum = _mm_hadd_ps(outAccum, outAccum);
     }
-
+    #if USE_AVX2
+    outSamp = _mm_fmadd_ps(outAccum, vLR,outSamp);
+    #else
     outAccum = _mm_mul_ps(outAccum, vLR);
     outSamp = _mm_add_ps(outSamp, outAccum);
+    #endif
+
     _mm_storel_pi(reinterpret_cast<__m64*>(out), outSamp);
 }
 
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index cc9643d..53feae8 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -115,8 +115,7 @@
      * Setup the high pass filter
      */
     LoadConst_Float(0,                                          /* Clear the history, value 0 */
-                   (LVM_FLOAT *)&pInstance->pData->HPFTaps,     /* Destination Cast to void: \
-                                                                  no dereferencing in function*/
+                   (LVM_FLOAT *)&pInstance->pData->HPFTaps,     /* Destination */
                     sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
     BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
                                     &pInstance->pData->HPFTaps,
@@ -126,8 +125,7 @@
      * Setup the band pass filter
      */
     LoadConst_Float(0,                                           /* Clear the history, value 0 */
-                 (LVM_FLOAT *)&pInstance->pData->BPFTaps,        /* Destination Cast to void: \
-                                                                    no dereferencing in function*/
+                 (LVM_FLOAT *)&pInstance->pData->BPFTaps,        /* Destination */
                  sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT));   /* Number of words */
     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,    /* Initialise the filter */
                                     &pInstance->pData->BPFTaps,
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 86a4ca2..1f0d39b 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -83,8 +83,7 @@
         FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
                                          &pPrivate->pFastData->HPTaps, &Coeffs);
         LoadConst_Float(0,
-                (LVM_FLOAT *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: \
-                                                                 no dereferencing in function*/
+                (LVM_FLOAT *)&pPrivate->pFastData->HPTaps,
                         sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
     }
 
@@ -116,8 +115,7 @@
         FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
                                          &pPrivate->pFastData->LPTaps, &Coeffs);
         LoadConst_Float(0,
-                (LVM_FLOAT *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: \
-                                                                 no dereferencing in function*/
+                (LVM_FLOAT *)&pPrivate->pFastData->LPTaps,
                         sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
     }
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 8b38a16..586539f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -60,12 +60,10 @@
      */
 
     LoadConst_Float(0,
-        (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: \
-                                                         no dereferencing in function*/
+        (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps,
         2);
     LoadConst_Float(0,
-        (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: \
-                                                         no dereferencing in function*/
+        (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps,
         2);
     if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
     {
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index ecf949d..431b7e3 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -91,8 +91,7 @@
         Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
 
         LoadConst_Float((LVM_INT16)0,                                         /* Value */
-                        (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination Cast to void:\
-                                                                  no dereferencing in function*/
+                        (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination */
                         /* Number of words */
                         (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
 
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index 68a7120..d0e6e09 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -109,8 +109,7 @@
         Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
 
         LoadConst_Float(0,                                 /* Value */
-                        (LVM_FLOAT *)&pData->ReverbBiquadTaps,  /* Destination Cast to void:
-                                                             no dereferencing in function*/
+                        (LVM_FLOAT *)&pData->ReverbBiquadTaps, /* Destination */
                         /* Number of words */
                         (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
 
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index 9cfc9a0..7fd8444 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -87,8 +87,7 @@
 
         /* Clear the taps */
         LoadConst_Float(0,                                  /* Value */
-                        (LVM_FLOAT *)&pData->SEBiquadTapsMid,    /* Destination Cast to void:\
-                                                              no dereferencing in function*/
+                        (LVM_FLOAT *)&pData->SEBiquadTapsMid,    /* Destination */
                         /* Number of words */
                         (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
 
@@ -115,8 +114,7 @@
 
         /* Clear the taps */
         LoadConst_Float(0,                                /* Value */
-                        (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination Cast to void:\
-                                                             no dereferencing in function*/
+                        (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination */
                         /* Number of words */
                         (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
         /* Callbacks */
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 960120f..73d3a0b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2181,12 +2181,20 @@
             }
             if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
                 // value is unknown
-                drc.targetRefLevel = -1;
+                drc.targetRefLevel = -2;
             }
             if (!msg->findInt32("aac-drc-effect-type", &drc.effectType)) {
                 // value is unknown
                 drc.effectType = -2; // valid values are -1 and over
             }
+            if (!msg->findInt32("aac-drc-album-mode", &drc.albumMode)) {
+                // value is unknown
+                drc.albumMode = -1; // valid values are 0 and 1
+            }
+            if (!msg->findInt32("aac-drc-output-loudness", &drc.outputLoudness)) {
+                // value is unknown
+                drc.outputLoudness = -1;
+            }
 
             err = setupAACCodec(
                     encoder, numChannels, sampleRate, bitrate, aacProfile,
@@ -2876,6 +2884,8 @@
     presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
     presentation.nPCMLimiterEnable = pcmLimiterEnable;
     presentation.nDrcEffectType = drc.effectType;
+    presentation.nDrcAlbumMode = drc.albumMode;
+    presentation.nDrcOutputLoudness = drc.outputLoudness;
 
     status_t res = mOMXNode->setParameter(
             OMX_IndexParamAudioAac, &profile, sizeof(profile));
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index d75b317..3c4524b 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -647,7 +647,9 @@
                 crop_left, crop_top, crop_right, crop_bottom,
                 mFrame->getFlattenedData(),
                 mFrame->mWidth, mFrame->mHeight, mFrame->mRowBytes,
-                crop_left, crop_top, crop_right, crop_bottom);
+                // since the frame is allocated with top-left adjusted,
+                // the dst rect should start at {0,0} as well.
+                0, 0, mFrame->mWidth - 1, mFrame->mHeight - 1);
         return OK;
     }
 
diff --git a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
index 95d3724..168d140 100644
--- a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
+++ b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
@@ -47,10 +47,9 @@
     mEncoderTarget = -1;
 
     /* Values from last time. */
-    /* Initialized to the same values as the desired values */
-    mLastTarget = -1;
-    mLastAttFactor = 0;
-    mLastBoostFactor = 0;
+    mLastTarget = -2;
+    mLastAttFactor = -1;
+    mLastBoostFactor = -1;
     mLastHeavy = 0;
 }
 
@@ -163,7 +162,7 @@
 
     if (mDataUpdate) {
         // sanity check
-        if (mDesTarget < MAX_TARGET_LEVEL){
+        if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){
             mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -10 dB or below
             newTarget = MAX_TARGET_LEVEL;
         }
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 41bc16c..2aeddd7 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -37,6 +37,7 @@
 #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0  /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
 // names of properties that can be used to override the default DRC settings
@@ -219,6 +220,11 @@
     ALOGV("AAC decoder using MPEG-D DRC effect type %d (default=%d)",
             effectType, DRC_DEFAULT_MOBILE_DRC_EFFECT);
     aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+    // AAC_UNIDRC_ALBUM_MODE
+    int32_t albumMode = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+    ALOGV("AAC decoder using MPEG-D Album mode value %d (default=%d)", albumMode,
+            DRC_DEFAULT_MOBILE_DRC_ALBUM);
+    aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
 
     // By default, the decoder creates a 5.1 channel downmix signal.
     // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
@@ -459,6 +465,11 @@
                 ALOGV("set nDrcEffectType=%d", aacPresParams->nDrcEffectType);
                 aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, aacPresParams->nDrcEffectType);
             }
+            if (aacPresParams->nDrcAlbumMode >= -1) {
+                ALOGV("set nDrcAlbumMode=%d", aacPresParams->nDrcAlbumMode);
+                aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE,
+                        aacPresParams->nDrcAlbumMode);
+            }
             bool updateDrcWrapper = false;
             if (aacPresParams->nDrcBoost >= 0) {
                 ALOGV("set nDrcBoost=%d", aacPresParams->nDrcBoost);
@@ -477,7 +488,7 @@
                         aacPresParams->nHeavyCompression);
                 updateDrcWrapper = true;
             }
-            if (aacPresParams->nTargetReferenceLevel >= 0) {
+            if (aacPresParams->nTargetReferenceLevel >= -1) {
                 ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
                         aacPresParams->nTargetReferenceLevel);
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
new file mode 100644
index 0000000..b9a8117
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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_test {
+    name: "Mpeg4H263EncoderTest",
+    gtest: true,
+
+    srcs : [ "Mpeg4H263EncoderTest.cpp" ],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+    ],
+
+    static_libs: [
+        "libstagefright_m4vh263enc",
+    ],
+
+    cflags: [
+        "-DOSCL_IMPORT_REF=",
+        "-Wall",
+        "-Werror",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "signed-integer-overflow",
+            "unsigned-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
new file mode 100644
index 0000000..5218932
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for MPEG4H263 encoder unit tests">
+    <option name="test-suite-tag" value="Mpeg4H263EncoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
+            value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="Mpeg4H263EncoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
new file mode 100644
index 0000000..78c705a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Mpeg4H263EncoderTest"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "mp4enc_api.h"
+
+#include "Mpeg4H263EncoderTestEnvironment.h"
+
+#define ENCODED_FILE "/data/local/tmp/Mpeg4H263Output"
+
+// assuming a worst case compression of 2X
+constexpr int16_t kCompressionRatio = 2;
+constexpr int8_t kIDRFrameRefreshIntervalInSec = 1;
+
+static Mpeg4H263EncoderTestEnvironment *gEnv = nullptr;
+
+class Mpeg4H263EncoderTest
+    : public ::testing::TestWithParam<tuple<string, bool, int32_t, int32_t, float, int32_t>> {
+  private:
+    void initEncoderParams();
+
+  public:
+    Mpeg4H263EncoderTest()
+        : mInputBuffer(nullptr),
+          mOutputBuffer(nullptr),
+          mFpInput(nullptr),
+          mFpOutput(nullptr),
+          mEncodeHandle(nullptr),
+          mEncodeControl(nullptr) {}
+
+    ~Mpeg4H263EncoderTest() {
+        if(mFpInput) {
+            fclose(mFpInput);
+        }
+        if(mFpOutput) {
+            fclose(mFpOutput);
+        }
+        if(mInputBuffer) free(mInputBuffer);
+        if(mOutputBuffer) free(mOutputBuffer);
+        if(mEncodeHandle) free(mEncodeHandle);
+        if(mEncodeControl) free(mEncodeControl);
+    }
+
+    void SetUp() override {
+        tuple<string /* fileName */, bool /* isMpeg4 */, int32_t /* frameWidth */,
+          int32_t /* frameHeight */, float /* frameRate */, int32_t /* bitRate */>
+            params = GetParam();
+        mFileName = gEnv->getRes() + get<0>(params);
+        mIsMpeg4 = get<1>(params);
+        mFrameWidth = get<2>(params);
+        mFrameHeight = get<3>(params);
+        mFrameRate = get<4>(params);
+        mBitRate = get<5>(params);
+
+        ASSERT_TRUE(mFrameWidth % 16 == 0) << "Frame Width should be multiple of 16";
+        ASSERT_TRUE(mFrameHeight % 16 == 0) << "Frame Height should be multiple of 16";
+        ASSERT_LE(mFrameWidth, (mIsMpeg4 ? 720 : 352))
+                << "Frame Width <= 720 for Mpeg4 and <= 352 for H263";
+        ASSERT_LE(mFrameHeight, (mIsMpeg4 ? 480 : 288))
+                << "Frame Height <= 480 for Mpeg4 and <= 288 for H263";
+        ASSERT_LE(mFrameRate, 30) << "Frame rate less than or equal to 30";
+        ASSERT_LE(mBitRate, 2048) << "Bit rate less than or equal to 2048 kbps";
+
+        mOutputBufferSize = ( mFrameWidth * mFrameHeight * 3/2 ) / kCompressionRatio;
+        mEncodeHandle = new VideoEncOptions;
+        ASSERT_NE(mEncodeHandle, nullptr) << "Failed to get Video Encoding options object";
+        memset(mEncodeHandle, 0, sizeof(VideoEncOptions));
+        mEncodeControl = new VideoEncControls;
+        ASSERT_NE(mEncodeControl, nullptr) << "Failed to get Video Encoding control object";
+        memset(mEncodeControl, 0, sizeof(VideoEncControls));
+        ASSERT_NO_FATAL_FAILURE(initEncoderParams())
+                << "Failed to get the default Encoding parameters!";
+    }
+
+    int64_t getTotalFrames();
+    void processEncoder(int32_t);
+    bool mIsMpeg4;
+    int32_t mFrameWidth, mFrameHeight, mBitRate;
+    int64_t mOutputBufferSize;
+    float mFrameRate;
+    string mFileName;
+    uint8_t *mInputBuffer, *mOutputBuffer;
+    FILE *mFpInput, *mFpOutput;
+    VideoEncOptions *mEncodeHandle;
+    VideoEncControls *mEncodeControl;
+};
+
+void Mpeg4H263EncoderTest::initEncoderParams() {
+    bool status = PVGetDefaultEncOption(mEncodeHandle, 0);
+    ASSERT_TRUE(status);
+
+    mEncodeHandle->rcType = VBR_1;
+    mEncodeHandle->vbvDelay = 5.0f;
+    mEncodeHandle->profile_level = CORE_PROFILE_LEVEL2;
+    mEncodeHandle->packetSize = 32;
+    mEncodeHandle->rvlcEnable = PV_OFF;
+    mEncodeHandle->numLayers = 1;
+    mEncodeHandle->timeIncRes = 1000;
+    mEncodeHandle->iQuant[0] = 15;
+    mEncodeHandle->pQuant[0] = 12;
+    mEncodeHandle->quantType[0] = 0;
+    mEncodeHandle->noFrameSkipped = PV_OFF;
+    mEncodeHandle->numIntraMB = 0;
+    mEncodeHandle->sceneDetect = PV_ON;
+    mEncodeHandle->searchRange = 16;
+    mEncodeHandle->mv8x8Enable = PV_OFF;
+    mEncodeHandle->gobHeaderInterval = 0;
+    mEncodeHandle->useACPred = PV_ON;
+    mEncodeHandle->intraDCVlcTh = 0;
+    if(!mIsMpeg4) {
+        mEncodeHandle->encMode = H263_MODE;
+    } else {
+        mEncodeHandle->encMode = COMBINE_MODE_WITH_ERR_RES;
+    }
+    mEncodeHandle->encWidth[0] = mFrameWidth;
+    mEncodeHandle->encHeight[0] = mFrameHeight;
+    mEncodeHandle->encFrameRate[0] = mFrameRate;
+    mEncodeHandle->bitRate[0] = mBitRate * 1024;
+    mEncodeHandle->tickPerSrc = mEncodeHandle->timeIncRes / mFrameRate;
+    if (kIDRFrameRefreshIntervalInSec == 0) {
+        // All I frames.
+        mEncodeHandle->intraPeriod = 1;
+    } else {
+        mEncodeHandle->intraPeriod = (kIDRFrameRefreshIntervalInSec * mFrameRate);
+    }
+}
+
+int64_t Mpeg4H263EncoderTest::getTotalFrames() {
+    int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+    struct stat buf;
+    stat(mFileName.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int64_t totalFrames = (int64_t)(fileSize/frameSize);
+    return totalFrames;
+}
+
+void Mpeg4H263EncoderTest::processEncoder(int32_t numFramesToEncode) {
+    bool status;
+    int64_t numEncodedFrames = 0;
+    int32_t bytesRead;
+    int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+    while(numFramesToEncode != 0) {
+        bytesRead = fread(mInputBuffer, 1, frameSize, mFpInput);
+        // End of file.
+        if (bytesRead != frameSize) {
+            break;
+        }
+
+        VideoEncFrameIO videoIn, videoOut;
+        videoIn.height = mFrameHeight;
+        videoIn.pitch = mFrameWidth;
+        videoIn.timestamp = (numEncodedFrames * 1000) / mFrameRate;  // in ms.
+        videoIn.yChan = mInputBuffer;
+        videoIn.uChan = videoIn.yChan + videoIn.height * videoIn.pitch;
+        videoIn.vChan = videoIn.uChan + ((videoIn.height * videoIn.pitch) >> 2);
+        uint32_t modTimeMs = 0;
+        int32_t dataLength = mOutputBufferSize;
+        int32_t nLayer = 0;
+        status = PVEncodeVideoFrame(mEncodeControl, &videoIn, &videoOut, &modTimeMs, mOutputBuffer,
+                                    &dataLength, &nLayer);
+        ASSERT_TRUE(status) << "Failed to Encode: " << mFileName;
+
+        MP4HintTrack hintTrack;
+        status = PVGetHintTrack(mEncodeControl, &hintTrack);
+        ASSERT_TRUE(status) << "Failed to get hint track!";
+        UChar *overrunBuffer = PVGetOverrunBuffer(mEncodeControl);
+        ASSERT_EQ(overrunBuffer, nullptr) << "Overrun of buffer!";
+
+        int64_t numBytes = fwrite(mOutputBuffer, 1, dataLength, mFpOutput);
+        ASSERT_EQ(numBytes, dataLength) << "Failed to write to the output file!";
+        numEncodedFrames++;
+        numFramesToEncode--;
+    }
+}
+
+TEST_P(Mpeg4H263EncoderTest, EncodeTest) {
+    mInputBuffer = (uint8_t *)malloc((mFrameWidth * mFrameWidth * 3) / 2);
+    ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate the input buffer!";
+
+    mOutputBuffer = (uint8_t *)malloc(mOutputBufferSize);
+    ASSERT_NE(mOutputBuffer, nullptr) << "Failed to allocate the output buffer!";
+
+    mFpInput = fopen(mFileName.c_str(), "rb");
+    ASSERT_NE(mFpInput, nullptr) << "Failed to open the input file: " << mFileName;
+
+    mFpOutput = fopen(ENCODED_FILE, "wb");
+    ASSERT_NE(mFpOutput, nullptr) << "Failed to open the output file:" << ENCODED_FILE;
+
+    bool status = PVInitVideoEncoder(mEncodeControl, mEncodeHandle);
+    ASSERT_TRUE(status) << "Failed to initialize the encoder!";
+
+    // Get VOL header.
+    int32_t size = mOutputBufferSize;
+    status = PVGetVolHeader(mEncodeControl, mOutputBuffer, &size, 0);
+    ASSERT_TRUE(status) << "Failed to get the VOL header!";
+
+    // Write the VOL header on the first frame.
+    int32_t numBytes = fwrite(mOutputBuffer, 1, size, mFpOutput);
+    ASSERT_EQ(numBytes, size) << "Failed to write the VOL header!";
+
+    int64_t totalFrames = getTotalFrames();
+    ASSERT_NO_FATAL_FAILURE(processEncoder(totalFrames)) << "Failed to Encode: " << mFileName;
+    status = PVCleanUpVideoEncoder(mEncodeControl);
+    ASSERT_TRUE(status) << "Failed to clean up the encoder resources!";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        EncodeTest, Mpeg4H263EncoderTest,
+        ::testing::Values(
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 352, 288, 25, 1024),
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 352, 288, 25, 1024),
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 176, 144, 25, 1024),
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 176, 144, 25, 1024),
+                make_tuple("football_qvga.yuv", false, 352, 288, 25, 1024),
+                make_tuple("football_qvga.yuv", true, 352, 288, 25, 1024),
+                make_tuple("football_qvga.yuv", false, 176, 144, 30, 1024),
+                make_tuple("football_qvga.yuv", true, 176, 144, 30, 1024)));
+
+int32_t main(int argc, char **argv) {
+    gEnv = new Mpeg4H263EncoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    uint8_t status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGI("Encoder Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
new file mode 100644
index 0000000..7ee36e0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+#define __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mpeg4H263EncoderTestEnvironment : public::testing::Environment {
+  public:
+    Mpeg4H263EncoderTestEnvironment() : res("/data/local/tmp/Mpeg4H263EncoderTest/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int Mpeg4H263EncoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/README.md b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
new file mode 100644
index 0000000..25de878
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
@@ -0,0 +1,38 @@
+## Media Testing ##
+---
+
+#### Mpeg4H263Encoder :
+The Mpeg4H263Encoder Test Suite validates the Mpeg4 and H263 encoder available in libstagefright.
+Run the following steps to build the test suite:
+```
+m Mpeg4H263EncoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip ) Download, unzip and push these files into device for testing.
+
+```
+adb push Mpeg4H263Encoder/. /data/local/tmp/
+```
+
+usage: Mpeg4H263EncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mpeg4H263EncoderTest -P /data/local/tmp/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg4H263EncoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/libstagefright/flac/dec/test/Android.bp
new file mode 100644
index 0000000..70ca80a
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/Android.bp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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_test {
+    name: "FlacDecoderTest",
+    gtest: true,
+
+    srcs: [
+        "FlacDecoderTest.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    static_libs: [
+        "libstagefright_flacdec",
+        "libFLAC",
+    ],
+
+    header_libs: [
+        "libstagefright_foundation_headers",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/flac/dec/test/AndroidTest.xml b/media/libstagefright/flac/dec/test/AndroidTest.xml
new file mode 100644
index 0000000..bebba8e
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for flac decoder unit tests">
+    <option name="test-suite-tag" value="FlacDecoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
+            value="/data/local/tmp/FlacDecoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="FlacDecoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
new file mode 100644
index 0000000..34f12db
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "FlacDecoderTest"
+
+#include <utils/Log.h>
+#include <fstream>
+
+#include "FLACDecoder.h"
+
+#include "FlacDecoderTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/FlacDecoderOutput.raw"
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCount = 10;
+constexpr int32_t kMaxBlockSize = 4096;
+
+using namespace android;
+
+struct FrameInfo {
+    int32_t bytesCount;
+    uint32_t flags;
+    int64_t timestamp;
+};
+
+static FlacDecoderTestEnvironment *gEnv = nullptr;
+
+class FLACDecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {
+  public:
+    FLACDecoderTest() : mFLACDecoder(nullptr), mHasStreamInfo(false), mInputBufferCount(0) {}
+
+    ~FLACDecoderTest() {
+        if (mEleStream.is_open()) mEleStream.close();
+        if (mFLACDecoder) delete mFLACDecoder;
+        mFLACDecoder = nullptr;
+    }
+
+    virtual void SetUp() override {
+        mFLACDecoder = FLACDecoder::Create();
+        ASSERT_NE(mFLACDecoder, nullptr) << "initDecoder: failed to create FLACDecoder";
+    }
+
+    int32_t processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+                               bool outputFloat, ofstream &ostrm);
+
+    FLACDecoder *mFLACDecoder;
+    FLAC__StreamMetadata_StreamInfo mStreamInfo;
+
+    bool mHasStreamInfo;
+    int32_t mInputBufferCount;
+    ifstream mEleStream;
+};
+
+void getInfo(string infoFileName, vector<FrameInfo> &Info) {
+    ifstream eleInfo;
+    eleInfo.open(infoFileName);
+    ASSERT_EQ(eleInfo.is_open(), true);
+    int32_t bytesCount = 0;
+    uint32_t flags = 0;
+    uint32_t timestamp = 0;
+    while (1) {
+        if (!(eleInfo >> bytesCount)) break;
+        eleInfo >> flags;
+        eleInfo >> timestamp;
+        Info.push_back({bytesCount, flags, timestamp});
+    }
+    if (eleInfo.is_open()) eleInfo.close();
+}
+
+int32_t FLACDecoderTest::processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+                                            bool outputFloat, ofstream &ostrm) {
+    memset(&mStreamInfo, 0, sizeof(mStreamInfo));
+
+    int32_t frameID = offset;
+    if (range + offset > Info.size() || range < 0 || offset > Info.size() - 1 || offset < 0) {
+        ALOGE("Invalid offset or range or both passed for decoding");
+        ALOGE("offset = %d \t range = %d  \t Info.size() = %zu", offset, range, Info.size());
+        return -1;
+    }
+
+    while (1) {
+        if (frameID == Info.size() || frameID == (offset + range)) break;
+        int64_t flags = (Info)[frameID].flags;
+        int32_t size = (Info)[frameID].bytesCount;
+        if (size < 0) {
+            ALOGE("Size for the memory allocation is negative");
+            return -1;
+        }
+        char *data = (char *)malloc(size);
+        if (!data) {
+            ALOGE("Insufficient memory to read frame");
+            return -1;
+        }
+
+        mEleStream.read(data, size);
+        if (mEleStream.gcount() != size) {
+            if (data) {
+                free(data);
+                data = nullptr;
+            }
+            ALOGE("Invalid size read, requested: %d and read: %zu", size, mEleStream.gcount());
+            return -1;
+        }
+
+        if (flags == CODEC_CONFIG_FLAG && mInputBufferCount == 0) {
+            status_t decoderErr = mFLACDecoder->parseMetadata((uint8_t *)data, size);
+            if (decoderErr == WOULD_BLOCK) {
+                ALOGV("process: parseMetadata is Blocking, Continue %d", decoderErr);
+            } else if (decoderErr == OK) {
+                mStreamInfo = mFLACDecoder->getStreamInfo();
+                if (mStreamInfo.sample_rate && mStreamInfo.max_blocksize && mStreamInfo.channels) {
+                    mHasStreamInfo = true;
+                }
+                ALOGV("decoder configuration : %d Hz, %d channels, %d samples,"
+                      " %d block size",
+                      mStreamInfo.sample_rate, mStreamInfo.channels,
+                      (int32_t)mStreamInfo.total_samples, mStreamInfo.max_blocksize);
+            } else {
+                ALOGE("FLACDecoder parseMetaData returns error %d", decoderErr);
+                if (data) {
+                    free(data);
+                    data = nullptr;
+                }
+                return decoderErr;
+            }
+        } else {
+            const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+            size_t outSize = mHasStreamInfo
+                                     ? mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+                                     : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
+
+            void *out_buf = malloc(outSize);
+            if (!out_buf) {
+                if (data) {
+                    free(data);
+                    data = nullptr;
+                }
+                ALOGE("Output buffer allocation failed");
+                return -1;
+            }
+            status_t decoderErr = mFLACDecoder->decodeOneFrame((uint8_t *)data, size, out_buf,
+                                                               &outSize, outputFloat);
+            if (decoderErr != OK) {
+                ALOGE("decodeOneFrame returns error %d", decoderErr);
+                if (data) {
+                    free(data);
+                    data = nullptr;
+                }
+                if (out_buf) {
+                    free(out_buf);
+                    out_buf = nullptr;
+                }
+                return decoderErr;
+            }
+            ostrm.write(reinterpret_cast<char *>(out_buf), outSize);
+            free(out_buf);
+            out_buf = nullptr;
+        }
+        mInputBufferCount++;
+        frameID++;
+        free(data);
+        data = nullptr;
+    }
+    ALOGV("frameID=%d", frameID);
+    return 0;
+}
+
+TEST_F(FLACDecoderTest, CreateDeleteTest) {
+    if (mFLACDecoder) delete mFLACDecoder;
+    mFLACDecoder = nullptr;
+
+    for (int32_t i = 0; i < kMaxCount; i++) {
+        mFLACDecoder = FLACDecoder::Create();
+        ASSERT_NE(mFLACDecoder, nullptr) << "FLACDecoder Creation Failed";
+        if (mFLACDecoder) delete mFLACDecoder;
+        mFLACDecoder = nullptr;
+    }
+}
+
+TEST_P(FLACDecoderTest, FlushTest) {
+    tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+            GetParam();
+
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    string infoFileName = gEnv->getRes() + get<1>(params);
+    bool outputFloat = get<2>(params);
+
+    vector<FrameInfo> Info;
+    getInfo(infoFileName, Info);
+
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true);
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+    ASSERT_EQ(ostrm.is_open(), true);
+
+    int32_t status = processFlacDecoder(Info, 0, Info.size() / 3, outputFloat, ostrm);
+    ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+    mFLACDecoder->flush();
+    mHasStreamInfo = false;
+    status = processFlacDecoder(Info, (Info.size() / 3), Info.size() - (Info.size() / 3),
+                                outputFloat, ostrm);
+    ostrm.close();
+    Info.clear();
+    ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+TEST_P(FLACDecoderTest, DecodeTest) {
+    tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+            GetParam();
+
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    string infoFileName = gEnv->getRes() + get<1>(params);
+    bool outputFloat = get<2>(params);
+
+    vector<FrameInfo> Info;
+    getInfo(infoFileName, Info);
+
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true);
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+    ASSERT_EQ(ostrm.is_open(), true);
+
+    int32_t status = processFlacDecoder(Info, 0, Info.size(), outputFloat, ostrm);
+    ostrm.close();
+    Info.clear();
+    ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+// TODO: Add remaining tests
+INSTANTIATE_TEST_SUITE_P(
+        FLACDecoderTestAll, FLACDecoderTest,
+        ::testing::Values(make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+                                     "bbb_flac_stereo_680kbps_48000hz.info", true),
+                          make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+                                     "bbb_flac_stereo_680kbps_48000hz.info", false),
+                          make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+                                     "bbb_flac_stereo_600kbps_44100hz.info", true),
+                          make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+                                     "bbb_flac_stereo_600kbps_44100hz.info", false)));
+
+int main(int argc, char **argv) {
+    gEnv = new FlacDecoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Flac Decoder Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
new file mode 100644
index 0000000..1334bba
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef __FLAC_DECODER_TEST_ENVIRONMENT_H__
+#define __FLAC_DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class FlacDecoderTestEnvironment : public ::testing::Environment {
+  public:
+    FlacDecoderTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int FlacDecoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __FLAC_DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/flac/dec/test/README.md b/media/libstagefright/flac/dec/test/README.md
new file mode 100644
index 0000000..4d194cd
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/README.md
@@ -0,0 +1,40 @@
+## Media Testing ##
+---
+#### FlacDecoder :
+The FlacDecoder Test Suite validates the FlacDecoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m FlacDecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip).
+Download, unzip and push these files into device for testing.
+
+```
+adb push FlacDecoder /data/local/tmp/
+```
+
+usage: FlacDecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/FlacDecoderTest -P /data/local/tmp/FlacDecoder/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest FlacDecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index d56ec4f..83e92b9 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -476,6 +476,8 @@
         int32_t targetRefLevel;
         int32_t encodedTargetLevel;
         int32_t effectType;
+        int32_t albumMode;
+        int32_t outputLoudness;
     } drcParams_t;
 
     status_t setupAACCodec(
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index eb7e5f7..bfdc9e7 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -733,10 +733,12 @@
 constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
 constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
 
+constexpr char KEY_AAC_DRC_ALBUM_MODE[] = "aac-drc-album-mode";
 constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
 constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
 constexpr char KEY_AAC_DRC_EFFECT_TYPE[] = "aac-drc-effect-type";
 constexpr char KEY_AAC_DRC_HEAVY_COMPRESSION[] = "aac-drc-heavy-compression";
+constexpr char KEY_AAC_DRC_OUTPUT_LOUDNESS[] = "aac-drc-output-loudness";
 constexpr char KEY_AAC_DRC_TARGET_REFERENCE_LEVEL[] = "aac-target-ref-level";
 constexpr char KEY_AAC_ENCODED_TARGET_LEVEL[] = "aac-encoded-target-level";
 constexpr char KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT[] = "aac-max-output-channel_count";
diff --git a/media/libstagefright/webm/tests/Android.bp b/media/libstagefright/webm/tests/Android.bp
new file mode 100644
index 0000000..5183a49
--- /dev/null
+++ b/media/libstagefright/webm/tests/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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_test {
+    name: "WebmFrameThreadUnitTest",
+    gtest: true,
+
+    srcs: [
+        "WebmFrameThreadUnitTest.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright",
+    ],
+
+    static_libs: [
+        "libdatasource",
+        "libstagefright",
+        "libstagefright_webm",
+        "libstagefright_foundation",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/webm/tests/README.md b/media/libstagefright/webm/tests/README.md
new file mode 100644
index 0000000..2e74f34
--- /dev/null
+++ b/media/libstagefright/webm/tests/README.md
@@ -0,0 +1,26 @@
+## Media Testing ##
+---
+#### Webm Writer Utility Tests :
+The Webm Writer Utility Test Suite validates the APIs being used by the WebmWriter.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/webm/tests/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+#### WebmFrameThread
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/WebmFrameThreadUnitTest/WebmFrameThreadUnitTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/WebmFrameThreadUnitTest/WebmFrameThreadUnitTest /data/local/tmp/
+
+```
+adb shell /data/local/tmp/WebmFrameThreadUnitTest
+```
diff --git a/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp b/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp
new file mode 100644
index 0000000..89cd2ca
--- /dev/null
+++ b/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WebmFrameThreadUnitTest"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/MediaAdapter.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/OpusHeader.h>
+
+#include "webm/EbmlUtil.h"
+#include "webm/WebmConstants.h"
+#include "webm/WebmFrameThread.h"
+
+using namespace android;
+using namespace webm;
+
+static constexpr int32_t kVideoIdx = 0;
+static constexpr int32_t kAudioIdx = 1;
+static constexpr int32_t kMaxStreamCount = 2;
+
+static constexpr int32_t kCsdSize = 32;
+static constexpr int32_t kFrameSize = 128;
+
+static constexpr int32_t kMaxLoopCount = 20;
+static constexpr int32_t kNumFramesToWrite = 32;
+static constexpr int32_t kSyncFrameInterval = 10;
+static constexpr uint64_t kDefaultTimeCodeScaleUs = 1000000; /* 1sec */
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/webmFrameThreadOutput.webm"
+
+// LookUpTable of clips and metadata for component testing
+static const struct InputData {
+    const char *mime;
+    int32_t firstParam;
+    int32_t secondParam;
+    bool isAudio;
+} kInputData[] = {
+        {MEDIA_MIMETYPE_AUDIO_OPUS, 48000, 6, true},
+        {MEDIA_MIMETYPE_AUDIO_VORBIS, 44100, 1, true},
+        {MEDIA_MIMETYPE_VIDEO_VP9, 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_VP8, 1920, 1080, false},
+};
+
+class WebmFrameThreadUnitTest : public ::testing::TestWithParam<std::pair<int32_t, int32_t>> {
+  public:
+    WebmFrameThreadUnitTest()
+        : mSinkThread(nullptr), mAudioThread(nullptr), mVideoThread(nullptr), mSource{} {}
+
+    ~WebmFrameThreadUnitTest() {
+        if (mSinkThread) mSinkThread.clear();
+        if (mAudioThread) mAudioThread.clear();
+        if (mVideoThread) mVideoThread.clear();
+    }
+
+    virtual void SetUp() override {
+        mSegmentDataStart = 0;
+        mFd = open(OUTPUT_FILE_NAME, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+        ASSERT_GE(mFd, 0) << "Failed to open output file " << OUTPUT_FILE_NAME;
+    }
+
+    virtual void TearDown() override {
+        if (mFd >= 0) close(mFd);
+        for (int32_t idx = 0; idx < kMaxStreamCount; idx++) {
+            if (mSource[idx] != nullptr) {
+                mSource[idx].clear();
+            }
+        }
+        mVSink.clear();
+        mASink.clear();
+        mCuePoints.clear();
+    }
+
+    void addTrack(bool isAudio, int32_t index);
+    void writeFileData(int32_t inputFrameId, int32_t range);
+
+    void createWebmThreads(std::initializer_list<int32_t> indexList);
+    void startWebmFrameThreads();
+    void stopWebmFrameThreads();
+
+    int32_t mFd;
+    uint64_t mSegmentDataStart;
+
+    sp<WebmFrameSinkThread> mSinkThread;
+    sp<WebmFrameSourceThread> mAudioThread;
+    sp<WebmFrameSourceThread> mVideoThread;
+
+    List<sp<WebmElement>> mCuePoints;
+    sp<MediaAdapter> mSource[kMaxStreamCount];
+    LinkedBlockingQueue<const sp<WebmFrame>> mVSink;
+    LinkedBlockingQueue<const sp<WebmFrame>> mASink;
+};
+
+void writeAudioHeaderData(const sp<AMessage> &format, const char *mimeType) {
+    if (strncasecmp(mimeType, MEDIA_MIMETYPE_AUDIO_OPUS, strlen(MEDIA_MIMETYPE_AUDIO_OPUS) + 1) &&
+        strncasecmp(mimeType, MEDIA_MIMETYPE_AUDIO_VORBIS,
+                    strlen(MEDIA_MIMETYPE_AUDIO_VORBIS) + 1)) {
+        ASSERT_TRUE(false) << "Unsupported mime type";
+    }
+
+    // Dummy CSD buffers for Opus and Vorbis
+    char csdBuffer[kCsdSize];
+    memset(csdBuffer, 0xFF, sizeof(csdBuffer));
+
+    sp<ABuffer> csdBuffer0 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+    ASSERT_NE(csdBuffer0.get(), nullptr) << "Unable to allocate buffer for CSD0 data";
+    ASSERT_NE(csdBuffer0->base(), nullptr) << "ABuffer base is null for CSD0";
+
+    sp<ABuffer> csdBuffer1 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+    ASSERT_NE(csdBuffer1.get(), nullptr) << "Unable to allocate buffer for CSD1 data";
+    ASSERT_NE(csdBuffer1->base(), nullptr) << "ABuffer base is null for CSD1";
+
+    sp<ABuffer> csdBuffer2 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+    ASSERT_NE(csdBuffer2.get(), nullptr) << "Unable to allocate buffer for CSD2 data";
+    ASSERT_NE(csdBuffer2->base(), nullptr) << "ABuffer base is null for CSD2";
+
+    format->setBuffer("csd-0", csdBuffer0);
+    format->setBuffer("csd-1", csdBuffer1);
+    format->setBuffer("csd-2", csdBuffer2);
+}
+
+void WebmFrameThreadUnitTest::addTrack(bool isAudio, int32_t index) {
+    ASSERT_LT(index, sizeof(kInputData) / sizeof(kInputData[0]))
+            << "Invalid index for loopup table";
+
+    sp<AMessage> format = new AMessage;
+    format->setString("mime", kInputData[index].mime);
+    if (!isAudio) {
+        format->setInt32("width", kInputData[index].firstParam);
+        format->setInt32("height", kInputData[index].secondParam);
+    } else {
+        format->setInt32("sample-rate", kInputData[index].firstParam);
+        format->setInt32("channel-count", kInputData[index].secondParam);
+        ASSERT_NO_FATAL_FAILURE(writeAudioHeaderData(format, kInputData[index].mime));
+    }
+
+    sp<MetaData> trackMeta = new MetaData;
+    convertMessageToMetaData(format, trackMeta);
+
+    if (!isAudio) {
+        mSource[kVideoIdx] = new MediaAdapter(trackMeta);
+        ASSERT_NE(mSource[kVideoIdx], nullptr) << "Unable to create source";
+    } else {
+        mSource[kAudioIdx] = new MediaAdapter(trackMeta);
+        ASSERT_NE(mSource[kAudioIdx], nullptr) << "Unable to create source";
+    }
+}
+
+void WebmFrameThreadUnitTest::createWebmThreads(std::initializer_list<int32_t> indexList) {
+    mSinkThread = new WebmFrameSinkThread(mFd, mSegmentDataStart, mVSink, mASink, mCuePoints);
+    ASSERT_NE(mSinkThread, nullptr) << "Failed to create Sink Thread";
+
+    bool isAudio;
+    // MultiTrack input
+    for (int32_t index : indexList) {
+        isAudio = kInputData[index].isAudio;
+        ASSERT_NO_FATAL_FAILURE(addTrack(isAudio, index));
+        if (!isAudio) {
+            mVideoThread = new WebmFrameMediaSourceThread(mSource[kVideoIdx], kVideoType, mVSink,
+                                                          kDefaultTimeCodeScaleUs, 0, 0, 1, 0);
+        } else {
+            mAudioThread = new WebmFrameMediaSourceThread(mSource[kAudioIdx], kAudioType, mASink,
+                                                          kDefaultTimeCodeScaleUs, 0, 0, 1, 0);
+        }
+    }
+    // To handle single track file
+    if (!mVideoThread) {
+        mVideoThread = new WebmFrameEmptySourceThread(kVideoType, mVSink);
+    } else if (!mAudioThread) {
+        mAudioThread = new WebmFrameEmptySourceThread(kAudioType, mASink);
+    }
+    ASSERT_NE(mVideoThread, nullptr) << "Failed to create Video Thread";
+    ASSERT_NE(mAudioThread, nullptr) << "Failed to create Audio Thread";
+}
+
+void WebmFrameThreadUnitTest::startWebmFrameThreads() {
+    status_t status = mAudioThread->start();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Audio Thread";
+    status = mVideoThread->start();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Video Thread";
+    status = mSinkThread->start();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Sink Thread";
+}
+
+void WebmFrameThreadUnitTest::stopWebmFrameThreads() {
+    status_t status = mAudioThread->stop();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Audio Thread";
+    status = mVideoThread->stop();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Video Thread";
+    status = mSinkThread->stop();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Sink Thread";
+}
+
+// Write dummy data to a file
+void WebmFrameThreadUnitTest::writeFileData(int32_t inputFrameId, int32_t range) {
+    char data[kFrameSize];
+    memset(data, 0xFF, sizeof(data));
+    int32_t status = OK;
+    do {
+        // Queue frames for both A/V tracks
+        for (int32_t idx = kVideoIdx; idx < kMaxStreamCount; idx++) {
+            sp<ABuffer> buffer = new ABuffer((void *)data, kFrameSize);
+            ASSERT_NE(buffer.get(), nullptr) << "ABuffer returned nullptr";
+
+            // Released in MediaAdapter::signalBufferReturned().
+            MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+            ASSERT_NE(mediaBuffer, nullptr) << "MediaBuffer returned nullptr";
+
+            mediaBuffer->add_ref();
+            mediaBuffer->set_range(buffer->offset(), buffer->size());
+
+            MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+            sampleMetaData.setInt64(kKeyTime, inputFrameId * kDefaultTimeCodeScaleUs);
+
+            // For audio codecs, treat all frame as sync frame
+            if ((idx == kAudioIdx) || (inputFrameId % kSyncFrameInterval == 0)) {
+                sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+            }
+
+            // This pushBuffer will wait until the mediaBuffer is consumed.
+            if (mSource[idx] != nullptr) {
+                status = mSource[idx]->pushBuffer(mediaBuffer);
+            }
+            ASSERT_EQ(status, OK);
+        }
+        inputFrameId++;
+    } while (inputFrameId < range);
+}
+
+TEST_P(WebmFrameThreadUnitTest, WriteTest) {
+    int32_t index1 = GetParam().first;
+    int32_t index2 = GetParam().second;
+    ASSERT_NO_FATAL_FAILURE(createWebmThreads({index1, index2}));
+
+    ASSERT_NO_FATAL_FAILURE(startWebmFrameThreads());
+
+    ASSERT_NO_FATAL_FAILURE(writeFileData(0, kNumFramesToWrite));
+
+    if (mSource[kAudioIdx]) mSource[kAudioIdx]->stop();
+    if (mSource[kVideoIdx]) mSource[kVideoIdx]->stop();
+
+    ASSERT_NO_FATAL_FAILURE(stopWebmFrameThreads());
+}
+
+TEST_P(WebmFrameThreadUnitTest, PauseTest) {
+    int32_t index1 = GetParam().first;
+    int32_t index2 = GetParam().second;
+    ASSERT_NO_FATAL_FAILURE(createWebmThreads({index1, index2}));
+
+    ASSERT_NO_FATAL_FAILURE(startWebmFrameThreads());
+
+    int32_t offset = 0;
+    ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+    offset += kNumFramesToWrite;
+
+    for (int idx = 0; idx < kMaxLoopCount; idx++) {
+        // pause the threads
+        status_t status = mAudioThread->pause();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to pause Audio Thread";
+        status = mVideoThread->pause();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to pause Video Thread";
+
+        // Under pause state, no write should happen
+        ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+        offset += kNumFramesToWrite;
+
+        status = mAudioThread->resume();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to resume Audio Thread";
+        status = mVideoThread->resume();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to resume Video Thread";
+
+        ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+        offset += kNumFramesToWrite;
+    }
+
+    if (mSource[kAudioIdx]) mSource[kAudioIdx]->stop();
+    if (mSource[kVideoIdx]) mSource[kVideoIdx]->stop();
+    ASSERT_NO_FATAL_FAILURE(stopWebmFrameThreads());
+}
+
+INSTANTIATE_TEST_SUITE_P(WebmFrameThreadUnitTestAll, WebmFrameThreadUnitTest,
+                         ::testing::Values(std::make_pair(0, 1), std::make_pair(0, 2),
+                                           std::make_pair(0, 3), std::make_pair(1, 0),
+                                           std::make_pair(1, 2), std::make_pair(1, 3),
+                                           std::make_pair(2, 3)));
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGV("Test result = %d\n", status);
+    return status;
+}
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index fdf51b1..8677b90 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -969,7 +969,7 @@
         modifiedTime = 0;
 
     if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0) ||
-        (strcmp(name, "/") == 0) || (strcmp(basename(name), name) != 0)) {
+        (strchr(name, '/') != NULL)) {
         char errMsg[80];
 
         snprintf(errMsg, sizeof(errMsg), "Invalid name: %s", (const char *) name);
@@ -981,7 +981,7 @@
     }
     if (path[path.size() - 1] != '/')
         path.append("/");
-    path.append(basename(name));
+    path.append(name);
 
     // check space first
     if (mSendObjectFileSize > storage->getFreeSpace())
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..7fd4d0a 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -223,6 +223,25 @@
     return ok;
 }
 
+bool accessCallAudioAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
+    static const String16 sAccessCallAudio("android.permission.ACCESS_CALL_AUDIO");
+    PermissionController permissionController;
+    const String16 resolvedOpPackageName = resolveCallingPackage(
+         permissionController, opPackageName, uid);
+    if (resolvedOpPackageName.size() == 0) {
+        ALOGE("accessCallAudioAllowed - FAIL - package not found.");
+        return false;
+    }
+    AppOpsManager appOps;
+    const int32_t op = appOps.permissionToOpCode(sAccessCallAudio);
+    const int32_t opResult = appOps.noteOp(op, uid, resolvedOpPackageName);
+    if (opResult == PermissionController::MODE_DEFAULT) {
+        // Only allow in case this is a system app with the proper privilege permission
+        return PermissionCache::checkPermission(sAccessCallAudio, pid, uid);
+    }
+    return opResult == PermissionController::MODE_ALLOWED;
+}
+
 // privileged behavior needed by Dialer, Settings, SetupWizard and CellBroadcastReceiver
 bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid) {
     static const String16 sWriteSecureSettings("android.permission.WRITE_SECURE_SETTINGS");
@@ -259,28 +278,29 @@
     return NO_ERROR;
 }
 
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+void MediaPackageManager::loadPackageManager() {
+    if (mPackageManager != nullptr) {
+        return;
+    }
     const sp<IServiceManager> sm = defaultServiceManager();
     if (sm == nullptr) {
         ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
-        return nullptr;
+        return;
     }
     sp<IBinder> packageManager = sm->checkService(String16(nativePackageManagerName));
     if (packageManager == nullptr) {
         ALOGW("%s: failed to retrieve native package manager", __func__);
-        return nullptr;
+        return;
     }
-    return interface_cast<content::pm::IPackageManagerNative>(packageManager);
+    mPackageManager = interface_cast<content::pm::IPackageManagerNative>(packageManager);
 }
 
 std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
+    /** Can not fetch package manager at construction it may not yet be registered. */
+    loadPackageManager();
     if (mPackageManager == nullptr) {
-        /** Can not fetch package manager at construction it may not yet be registered. */
-        mPackageManager = retreivePackageManager();
-        if (mPackageManager == nullptr) {
-            ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
-            return std::nullopt;
-        }
+        ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
+        return std::nullopt;
     }
 
     std::vector<std::string> packageNames;
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..060e849 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -93,6 +93,7 @@
 bool dumpAllowed();
 bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
 bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);
+bool accessCallAudioAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
 
 status_t checkIMemory(const sp<IMemory>& iMemory);
 
@@ -110,7 +111,7 @@
 private:
     static constexpr const char* nativePackageManagerName = "package_native";
     std::optional<bool> doIsAllowed(uid_t uid);
-    sp<content::pm::IPackageManagerNative> retreivePackageManager();
+    void loadPackageManager();
     sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
     uint_t mPackageManagerErrors = 0;
     struct Package {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5c5c5bb..e5a6e27 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -326,7 +326,7 @@
         ret = AudioSystem::getOutputForAttr(&localAttr, &io,
                                             actualSessionId,
                                             &streamType, client.clientPid, client.clientUid,
-                                            &fullConfig,
+                                            client.packageName, &fullConfig,
                                             (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
                                                     AUDIO_OUTPUT_FLAG_DIRECT),
                                             deviceId, &portId, &secondaryOutputs);
@@ -766,8 +766,9 @@
     output.outputId = AUDIO_IO_HANDLE_NONE;
     output.selectedDeviceId = input.selectedDeviceId;
     lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
-                                            clientPid, clientUid, &input.config, input.flags,
-                                            &output.selectedDeviceId, &portId, &secondaryOutputs);
+                                            clientPid, clientUid, input.opPackageName,
+                                            &input.config, input.flags, &output.selectedDeviceId,
+                                            &portId, &secondaryOutputs);
 
     if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
         ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3726b9a..2833525 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1872,7 +1872,7 @@
     // and the mute set to false).
     mMasterVolume = audioFlinger->masterVolume_l();
     mMasterMute = audioFlinger->masterMute_l();
-    if (mOutput && mOutput->audioHwDev) {
+    if (mOutput->audioHwDev) {
         if (mOutput->audioHwDev->canSetMasterVolume()) {
             mMasterVolume = 1.0;
         }
@@ -2832,7 +2832,7 @@
             this/* srcThread */, this/* dstThread */);
     }
 
-    audio_output_flags_t flags = mOutput != nullptr ? mOutput->flags : AUDIO_OUTPUT_FLAG_NONE;
+    audio_output_flags_t flags = mOutput->flags;
     mediametrics::LogItem item(mMetricsId);
     item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
         .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
@@ -8731,6 +8731,7 @@
                                             &stream,
                                             client.clientPid,
                                             client.clientUid,
+                                            client.packageName,
                                             &config,
                                             flags,
                                             &deviceId,
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 2044863..5f551d5 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -135,8 +135,10 @@
         }
         DeviceVector deviceList =
             mSupportedDevices.getDevicesFromTypes(deviceTypes);
-        if (!deviceList.empty()) {
-            return deviceList.itemAt(0)->hasCurrentEncodedFormat();
+        for (const auto& device : deviceList) {
+            if (device->hasCurrentEncodedFormat()) {
+                return true;
+            }
         }
         return false;
     }
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index ba3d4ff..38801ec 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -121,7 +121,7 @@
                                                          device_name, encodedFormat);
 }
 
-status_t AudioPolicyService::setPhoneState(audio_mode_t state)
+status_t AudioPolicyService::setPhoneState(audio_mode_t state, uid_t uid)
 {
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
@@ -145,6 +145,7 @@
     AutoCallerClear acc;
     mAudioPolicyManager->setPhoneState(state);
     mPhoneState = state;
+    mPhoneStateOwnerUid = uid;
     return NO_ERROR;
 }
 
@@ -210,6 +211,7 @@
                                               audio_stream_type_t *stream,
                                               pid_t pid,
                                               uid_t uid,
+                                              const String16& opPackageName,
                                               const audio_config_t *config,
                                               audio_output_flags_t flags,
                                               audio_port_handle_t *selectedDeviceId,
@@ -256,7 +258,8 @@
         case AudioPolicyInterface::API_OUTPUT_LEGACY:
             break;
         case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
-            if (!modifyPhoneStateAllowed(pid, uid)) {
+          if (!modifyPhoneStateAllowed(pid, uid) &&
+              !accessCallAudioAllowed(opPackageName, pid, uid)) {
                 ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
                     __func__, uid);
                 result = PERMISSION_DENIED;
@@ -453,15 +456,22 @@
     }
 
     bool canCaptureOutput = captureAudioOutputAllowed(pid, uid);
-    if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
-        inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
-        inputSource == AUDIO_SOURCE_VOICE_CALL ||
-        inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
-        inputSource == AUDIO_SOURCE_FM_TUNER) &&
+    bool canCaptureTelephonyOutput = canCaptureOutput
+        || accessCallAudioAllowed(opPackageName, pid, uid);
+
+    if ((attr->source == AUDIO_SOURCE_ECHO_REFERENCE ||
+         attr->source == AUDIO_SOURCE_FM_TUNER) &&
         !canCaptureOutput) {
         return PERMISSION_DENIED;
     }
 
+    if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
+        attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
+        attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+        !canCaptureTelephonyOutput) {
+        return PERMISSION_DENIED;
+    }
+
     bool canCaptureHotword = captureHotwordAllowed(opPackageName, pid, uid);
     if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
         return BAD_VALUE;
@@ -493,6 +503,11 @@
                 break;
             case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
                 // FIXME: use the same permission as for remote submix for now.
+                if (!canCaptureTelephonyOutput) {
+                    ALOGE("getInputForAttr() permission denied: call capture not allowed");
+                    status = PERMISSION_DENIED;
+                }
+                break;
             case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
                 if (!canCaptureOutput) {
                     ALOGE("getInputForAttr() permission denied: capture not allowed");
@@ -520,9 +535,13 @@
             return status;
         }
 
+        bool allowAudioCapture = canCaptureOutput ||
+            (inputType == AudioPolicyInterface::API_INPUT_TELEPHONY_RX &&
+             canCaptureTelephonyOutput);
+
         sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session, *portId,
                                                              *selectedDeviceId, opPackageName,
-                                                             canCaptureOutput, canCaptureHotword);
+                                                             allowAudioCapture, canCaptureHotword);
         mAudioRecordClients.add(*portId, client);
     }
 
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e5c36ea..99cec5a 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -534,8 +534,8 @@
         //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
         bool allowCapture = !isAssistantOnTop
                 && ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
-                && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
-                && !(isInCall && !current->canCaptureOutput);
+                && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureCallOrOutput))
+                && !(isInCall && !current->canCaptureCallOrOutput);
 
         if (isVirtualSource(source)) {
             // Allow capture for virtual (remote submix, call audio TX or RX...) sources
@@ -555,7 +555,7 @@
             } else {
                 if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
                         source == AUDIO_SOURCE_HOTWORD) &&
-                        (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+                        (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
                     allowCapture = true;
                 }
             }
@@ -567,7 +567,7 @@
             //     OR
             //         Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
             if (!isAssistantOnTop
-                    && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+                    && (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
                 allowCapture = true;
             }
             if (isA11yOnTop) {
@@ -580,7 +580,7 @@
             //     All active clients are using HOTWORD source
             //     AND no call is active
             //         OR client has CAPTURE_AUDIO_OUTPUT privileged permission
-            if (onlyHotwordActive && !(isInCall && !current->canCaptureOutput)) {
+            if (onlyHotwordActive && !(isInCall && !current->canCaptureCallOrOutput)) {
                 allowCapture = true;
             }
         }
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index e297f34..c3c87f1 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -72,7 +72,7 @@
                                               const char *device_address,
                                               const char *device_name,
                                               audio_format_t encodedFormat);
-    virtual status_t setPhoneState(audio_mode_t state);
+    virtual status_t setPhoneState(audio_mode_t state, uid_t uid);
     virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
     virtual audio_io_handle_t getOutput(audio_stream_type_t stream);
@@ -82,6 +82,7 @@
                               audio_stream_type_t *stream,
                               pid_t pid,
                               uid_t uid,
+                              const String16& opPackageName,
                               const audio_config_t *config,
                               audio_output_flags_t flags,
                               audio_port_handle_t *selectedDeviceId,
@@ -807,15 +808,16 @@
                           const audio_io_handle_t io, uid_t uid, pid_t pid,
                           const audio_session_t session, audio_port_handle_t portId,
                           const audio_port_handle_t deviceId, const String16& opPackageName,
-                          bool canCaptureOutput, bool canCaptureHotword) :
+                          bool canCaptureCallOrOutput, bool canCaptureHotword) :
                     AudioClient(attributes, io, uid, pid, session, portId, deviceId),
                     opPackageName(opPackageName), startTimeNs(0),
-                    canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
+                    canCaptureCallOrOutput(canCaptureCallOrOutput),
+                    canCaptureHotword(canCaptureHotword) {}
                 ~AudioRecordClient() override = default;
 
         const String16 opPackageName;        // client package name
         nsecs_t startTimeNs;
-        const bool canCaptureOutput;
+        const bool canCaptureCallOrOutput;
         const bool canCaptureHotword;
     };
 
@@ -880,6 +882,7 @@
     // those can call back into AudioPolicyService methods and try to acquire the mutex
     sp<AudioPolicyEffects> mAudioPolicyEffects;
     audio_mode_t mPhoneState;
+    uid_t mPhoneStateOwnerUid;
 
     sp<UidPolicy> mUidPolicy;
     sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index b20774a..2c97a38 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1352,29 +1352,9 @@
 
     // Get list of concurrent streaming camera device combinations
     if (mMinorVersion >= 6) {
-        hardware::Return<void> ret = interface2_6->getConcurrentStreamingCameraIds([&status, this](
-                Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
-                const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
-                        cameraDeviceIdCombinations) {
-            status = concurrentIdStatus;
-            if (status == Status::OK) {
-                for (auto& combination : cameraDeviceIdCombinations) {
-                    std::unordered_set<std::string> deviceIds;
-                    for (auto &cameraDeviceId : combination) {
-                        deviceIds.insert(cameraDeviceId.c_str());
-                    }
-                    mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
-                }
-            } });
-        if (!ret.isOk()) {
-            ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
-                    __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
-            return DEAD_OBJECT;
-        }
-        if (status != Status::OK) {
-            ALOGE("%s: Unable to query for camera devices from provider '%s'",
-                    __FUNCTION__, mProviderName.c_str());
-            return mapToStatusT(status);
+        res = getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+        if (res != OK) {
+            return res;
         }
     }
 
@@ -1626,6 +1606,75 @@
     return OK;
 }
 
+status_t CameraProviderManager::ProviderInfo::getConcurrentStreamingCameraIdsInternalLocked(
+        sp<provider::V2_6::ICameraProvider> &interface2_6) {
+    if (interface2_6 == nullptr) {
+        ALOGE("%s: null interface provided", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    Status status = Status::OK;
+    hardware::Return<void> ret =
+            interface2_6->getConcurrentStreamingCameraIds([&status, this](
+            Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+            const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+                        cameraDeviceIdCombinations) {
+            status = concurrentIdStatus;
+            if (status == Status::OK) {
+                mConcurrentCameraIdCombinations.clear();
+                for (auto& combination : cameraDeviceIdCombinations) {
+                    std::unordered_set<std::string> deviceIds;
+                    for (auto &cameraDeviceId : combination) {
+                        deviceIds.insert(cameraDeviceId.c_str());
+                    }
+                    mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+                }
+            } });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+            return DEAD_OBJECT;
+    }
+    if (status != Status::OK) {
+        ALOGE("%s: Unable to query for camera devices from provider '%s'",
+                    __FUNCTION__, mProviderName.c_str());
+        return mapToStatusT(status);
+    }
+    return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+    if (mMinorVersion < 6) {
+      // Unsupported operation, nothing to do here
+      return OK;
+    }
+    // Check if the provider is currently active - not going to start it up for this notification
+    auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+    if (interface == nullptr) {
+        ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+                mProviderName.c_str());
+        return INVALID_OPERATION;
+    }
+    auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+
+    if (castResult.isOk()) {
+        sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
+        if (interface2_6 != nullptr) {
+            return getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+        } else {
+            // This should not happen since mMinorVersion >= 6
+            ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
+            return UNKNOWN_ERROR;
+        }
+    }
+    return OK;
+}
+
+std::vector<std::unordered_set<std::string>>
+CameraProviderManager::ProviderInfo::getConcurrentCameraIdCombinations() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mConcurrentCameraIdCombinations;
+}
+
 hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         CameraDeviceStatus newStatus) {
@@ -1659,6 +1708,10 @@
         }
         listener = mManager->getStatusListener();
         initialized = mInitialized;
+        if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+            ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+                      __FUNCTION__, mProviderName.c_str());
+        }
     }
     // Call without lock held to allow reentrancy into provider manager
     // Don't send the callback if providerInfo hasn't been initialized.
@@ -2747,7 +2800,7 @@
     std::vector<std::unordered_set<std::string>> deviceIdCombinations;
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     for (auto &provider : mProviders) {
-        for (auto &combinations : provider->mConcurrentCameraIdCombinations) {
+        for (auto &combinations : provider->getConcurrentCameraIdCombinations()) {
             deviceIdCombinations.push_back(combinations);
         }
     }
@@ -2831,7 +2884,7 @@
     // TODO: we should also do a findDeviceInfoLocked here ?
     for (auto &provider : mProviders) {
         if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
-                provider->mConcurrentCameraIdCombinations)) {
+                provider->getConcurrentCameraIdCombinations())) {
             // For each camera device in cameraIdsAndSessionConfigs collect
             // the streamConfigs and create the HAL
             // CameraIdAndStreamCombination, exit early if needed
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 42da227..1a02980 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -417,6 +417,9 @@
         status_t notifyDeviceStateChange(
                 hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
                     newDeviceState);
+
+        std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
+
         /**
          * Query the camera provider for concurrent stream configuration support
          */
@@ -510,8 +513,6 @@
         // physical camera IDs.
         std::vector<std::string> mProviderPublicCameraIds;
 
-        std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
-
         // HALv1-specific camera fields, including the actual device interface
         struct DeviceInfo1 : public DeviceInfo {
             typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
@@ -600,6 +601,8 @@
 
         bool mInitialized = false;
 
+        std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
+
         // Templated method to instantiate the right kind of DeviceInfo and call the
         // right CameraProvider getCameraDeviceInterface_* method.
         template<class DeviceInfoT>
@@ -623,6 +626,12 @@
         static metadata_vendor_id_t generateVendorTagId(const std::string &name);
 
         void removeDevice(std::string id);
+
+        // Expects to have mLock locked
+        status_t reCacheConcurrentStreamingCameraIdsLocked();
+        // Expects to have mLock locked
+        status_t getConcurrentStreamingCameraIdsInternalLocked(
+                sp<hardware::camera::provider::V2_6::ICameraProvider> &interface2_6);
     };
 
     // Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 90d21a2..f29431c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -364,100 +364,103 @@
 
 status_t Camera3Device::disconnectImpl() {
     ATRACE_CALL();
-    Mutex::Autolock il(mInterfaceLock);
-
     ALOGI("%s: E", __FUNCTION__);
 
     status_t res = OK;
     std::vector<wp<Camera3StreamInterface>> streams;
-    nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
     {
-        Mutex::Autolock l(mLock);
-        if (mStatus == STATUS_UNINITIALIZED) return res;
+        Mutex::Autolock il(mInterfaceLock);
+        nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+        {
+            Mutex::Autolock l(mLock);
+            if (mStatus == STATUS_UNINITIALIZED) return res;
 
-        if (mStatus == STATUS_ACTIVE ||
-                (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
-            res = mRequestThread->clearRepeatingRequests();
-            if (res != OK) {
-                SET_ERR_L("Can't stop streaming");
-                // Continue to close device even in case of error
-            } else {
-                res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+            if (mStatus == STATUS_ACTIVE ||
+                    (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
+                res = mRequestThread->clearRepeatingRequests();
                 if (res != OK) {
-                    SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
-                            maxExpectedDuration);
+                    SET_ERR_L("Can't stop streaming");
                     // Continue to close device even in case of error
+                } else {
+                    res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+                    if (res != OK) {
+                        SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
+                                maxExpectedDuration);
+                        // Continue to close device even in case of error
+                    }
                 }
             }
-        }
 
-        if (mStatus == STATUS_ERROR) {
-            CLOGE("Shutting down in an error state");
-        }
+            if (mStatus == STATUS_ERROR) {
+                CLOGE("Shutting down in an error state");
+            }
 
-        if (mStatusTracker != NULL) {
-            mStatusTracker->requestExit();
-        }
+            if (mStatusTracker != NULL) {
+                mStatusTracker->requestExit();
+            }
 
-        if (mRequestThread != NULL) {
-            mRequestThread->requestExit();
-        }
+            if (mRequestThread != NULL) {
+                mRequestThread->requestExit();
+            }
 
-        streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
-        for (size_t i = 0; i < mOutputStreams.size(); i++) {
-            streams.push_back(mOutputStreams[i]);
-        }
-        if (mInputStream != nullptr) {
-            streams.push_back(mInputStream);
+            streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
+            for (size_t i = 0; i < mOutputStreams.size(); i++) {
+                streams.push_back(mOutputStreams[i]);
+            }
+            if (mInputStream != nullptr) {
+                streams.push_back(mInputStream);
+            }
         }
     }
-
-    // Joining done without holding mLock, otherwise deadlocks may ensue
-    // as the threads try to access parent state
+    // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
+    // as the threads try to access parent state (b/143513518)
     if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
         // HAL may be in a bad state, so waiting for request thread
         // (which may be stuck in the HAL processCaptureRequest call)
         // could be dangerous.
+        // give up mInterfaceLock here and then lock it again. Could this lead
+        // to other deadlocks
         mRequestThread->join();
     }
-
-    if (mStatusTracker != NULL) {
-        mStatusTracker->join();
-    }
-
-    HalInterface* interface;
     {
-        Mutex::Autolock l(mLock);
-        mRequestThread.clear();
-        Mutex::Autolock stLock(mTrackerLock);
-        mStatusTracker.clear();
-        interface = mInterface.get();
-    }
+        Mutex::Autolock il(mInterfaceLock);
+        if (mStatusTracker != NULL) {
+            mStatusTracker->join();
+        }
 
-    // Call close without internal mutex held, as the HAL close may need to
-    // wait on assorted callbacks,etc, to complete before it can return.
-    interface->close();
+        HalInterface* interface;
+        {
+            Mutex::Autolock l(mLock);
+            mRequestThread.clear();
+            Mutex::Autolock stLock(mTrackerLock);
+            mStatusTracker.clear();
+            interface = mInterface.get();
+        }
 
-    flushInflightRequests();
+        // Call close without internal mutex held, as the HAL close may need to
+        // wait on assorted callbacks,etc, to complete before it can return.
+        interface->close();
 
-    {
-        Mutex::Autolock l(mLock);
-        mInterface->clear();
-        mOutputStreams.clear();
-        mInputStream.clear();
-        mDeletedStreams.clear();
-        mBufferManager.clear();
-        internalUpdateStatusLocked(STATUS_UNINITIALIZED);
-    }
+        flushInflightRequests();
 
-    for (auto& weakStream : streams) {
-        sp<Camera3StreamInterface> stream = weakStream.promote();
-        if (stream != nullptr) {
-            ALOGE("%s: Stream %d leaked! strong reference (%d)!",
-                    __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+        {
+            Mutex::Autolock l(mLock);
+            mInterface->clear();
+            mOutputStreams.clear();
+            mInputStream.clear();
+            mDeletedStreams.clear();
+            mBufferManager.clear();
+            internalUpdateStatusLocked(STATUS_UNINITIALIZED);
+        }
+
+        for (auto& weakStream : streams) {
+              sp<Camera3StreamInterface> stream = weakStream.promote();
+            if (stream != nullptr) {
+                ALOGE("%s: Stream %d leaked! strong reference (%d)!",
+                        __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+            }
         }
     }
-
     ALOGI("%s: X", __FUNCTION__);
     return res;
 }
@@ -1768,9 +1771,7 @@
 }
 
 void Camera3Device::pauseStateNotify(bool enable) {
-    // We must not hold mInterfaceLock here since this function is called from
-    // RequestThread::threadLoop and holding mInterfaceLock could lead to
-    // deadlocks (http://b/143513518)
+    Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
     mPauseStateNotify = enable;
@@ -2340,9 +2341,7 @@
     ATRACE_CALL();
     bool ret = false;
 
-    // We must not hold mInterfaceLock here since this function is called from
-    // RequestThread::threadLoop and holding mInterfaceLock could lead to
-    // deadlocks (http://b/143513518)
+    Mutex::Autolock il(mInterfaceLock);
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
 
     Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e13e45f..0069fb3 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -278,7 +278,6 @@
 
     // A lock to enforce serialization on the input/configure side
     // of the public interface.
-    // Only locked by public methods inherited from CameraDeviceBase.
     // Not locked by methods guarded by mOutputLock, since they may act
     // concurrently to the input/configure side of the interface.
     // Must be locked before mLock if both will be locked by a method
@@ -1102,7 +1101,7 @@
     uint32_t               mNextReprocessShutterFrameNumber;
     // the minimal frame number of the next ZSL still capture shutter
     uint32_t               mNextZslStillShutterFrameNumber;
-    List<CaptureResult>    mResultQueue;
+    std::list<CaptureResult>    mResultQueue;
     std::condition_variable  mResultSignal;
     wp<NotificationListener> mListener;
 
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 27043d2..208f70d 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -212,7 +212,7 @@
     const uint32_t mNumPartialResults;
 
     std::mutex mOutputLock;
-    List<CaptureResult> mResultQueue;
+    std::list<CaptureResult> mResultQueue;
     std::condition_variable mResultSignal;
     // the minimal frame number of the next non-reprocess result
     uint32_t mNextResultFrameNumber;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 39b7db4..238356e 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -153,9 +153,9 @@
     }
 
     // Valid result, insert into queue
-    List<CaptureResult>::iterator queuedResult =
+    std::list<CaptureResult>::iterator queuedResult =
             states.resultQueue.insert(states.resultQueue.end(), CaptureResult(*result));
-    ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
+    ALOGV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
            ", burstId = %" PRId32, __FUNCTION__,
            queuedResult->mResultExtras.requestId,
            queuedResult->mResultExtras.frameNumber,
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 300df5b..fbb47f8 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -62,7 +62,7 @@
         std::mutex& inflightLock;
         InFlightRequestMap& inflightMap; // end of inflightLock scope
         std::mutex& outputLock;
-        List<CaptureResult>& resultQueue;
+        std::list<CaptureResult>& resultQueue;
         std::condition_variable& resultSignal;
         uint32_t& nextShutterFrameNum;
         uint32_t& nextReprocShutterFrameNum;
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index f825373..0441cfa 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -13,10 +13,11 @@
         "libcodec2-hidl-defaults",
     ],
     shared_libs: [
-        "android.hardware.media.c2@1.0",
-        "android.hardware.media.c2@1.1",
         "libbase",
-        "libcodec2_hidl@1.1",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libhidlbase",
+        "libutils",
     ],
 
     // Codecs
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 450af79..83d233e 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -22,10 +22,9 @@
 
 #include <C2Component.h>
 #include <C2PlatformSupport.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
 #include <codec2/hidl/1.1/ComponentStore.h>
-#include <codec2/hidl/1.0/Configurable.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
 #include <hidl/HidlSupport.h>
 #include <media/CodecServiceRegistrant.h>
 
@@ -36,8 +35,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
+using namespace ::android::hardware::media::c2::V1_1;
+using namespace ::android::hardware::media::c2::V1_1::utils;
 
 constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
 
@@ -400,11 +399,10 @@
 } // unnamed namespace
 
 extern "C" void RegisterCodecServices() {
-    using ComponentStore_Latest = ::android::hardware::media::c2::V1_1::
-            utils::ComponentStore;
+    using namespace ::android::hardware::media::c2::V1_1;
     LOG(INFO) << "Creating software Codec2 service...";
-    sp<ComponentStore_Latest> store =
-        new ComponentStore_Latest(::android::GetCodec2PlatformComponentStore());
+    sp<ComponentStore> store =
+        new ComponentStore(::android::GetCodec2PlatformComponentStore());
     if (store == nullptr) {
         LOG(ERROR) <<
                 "Cannot create software Codec2 service.";