Merge "Add meta data extensions to support APE playback"
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 477c371..376d3e4 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-apex {
+apex_test {
     name: "test_com.android.media",
     manifest: "test_manifest.json",
     file_contexts: ":com.android.media-file_contexts",
@@ -20,7 +20,7 @@
     installable: false,
 }
 
-apex {
+apex_test {
     name: "test_com.android.media.swcodec",
     manifest: "test_manifest_codec.json",
     file_contexts: ":com.android.media.swcodec-file_contexts",
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 22e9578..dc7f88a 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -48,6 +48,6 @@
     init_rc: ["cameraserver.rc"],
 
     vintf_fragments: [
-        "manifest_android.frameworks.cameraservice.service@2.0.xml",
+        "manifest_android.frameworks.cameraservice.service@2.1.xml",
     ],
 }
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml
similarity index 90%
rename from camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml
rename to camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml
index 601c717..5a15b35 100644
--- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml
@@ -2,7 +2,7 @@
     <hal>
         <name>android.frameworks.cameraservice.service</name>
         <transport>hwbinder</transport>
-        <version>2.0</version>
+        <version>2.1</version>
         <interface>
             <name>ICameraService</name>
             <instance>default</instance>
diff --git a/camera/include/camera/VendorTagDescriptor.h b/camera/include/camera/VendorTagDescriptor.h
index 6f55890..b2fbf3a 100644
--- a/camera/include/camera/VendorTagDescriptor.h
+++ b/camera/include/camera/VendorTagDescriptor.h
@@ -188,8 +188,8 @@
             sp<android::VendorTagDescriptor> *desc /*out*/);
 
     // Parcelable interface
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
+    status_t writeToParcel(android::Parcel* parcel) const override;
+    status_t readFromParcel(const android::Parcel* parcel) override;
 
     // Returns the number of vendor tags defined.
     int getTagCount(metadata_vendor_id_t id) const;
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 56f209c..7ba82c1 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -123,6 +123,7 @@
         "android.frameworks.cameraservice.device@2.0",
         "android.frameworks.cameraservice.common@2.0",
         "android.frameworks.cameraservice.service@2.0",
+        "android.frameworks.cameraservice.service@2.1",
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
@@ -140,9 +141,12 @@
 }
 
 cc_test {
-    name: "AImageReaderVendorTest",
+    name: "ACameraNdkVendorTest",
     vendor: true,
-    srcs: ["ndk_vendor/tests/AImageReaderVendorTest.cpp"],
+    srcs: [
+        "ndk_vendor/tests/AImageReaderVendorTest.cpp",
+        "ndk_vendor/tests/ACameraManagerTest.cpp",
+    ],
     shared_libs: [
         "libcamera2ndk_vendor",
         "libcamera_metadata",
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 4870265..f408b6a 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -130,6 +130,11 @@
         mCameraService->addListener(mCameraServiceListener, &cameraStatuses);
         for (auto& c : cameraStatuses) {
             onStatusChangedLocked(c.status, c.cameraId);
+
+            for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) {
+                onStatusChangedLocked(hardware::ICameraServiceListener::STATUS_NOT_PRESENT,
+                        c.cameraId, unavailablePhysicalId);
+            }
         }
 
         // setup vendor tags
@@ -200,9 +205,7 @@
 
 void CameraManagerGlobal::registerExtendedAvailabilityCallback(
         const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
-    Mutex::Autolock _l(mLock);
-    Callback cb(callback);
-    mCallbacks.insert(cb);
+    return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
 }
 
 void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
@@ -214,6 +217,18 @@
 
 void CameraManagerGlobal::registerAvailabilityCallback(
         const ACameraManager_AvailabilityCallbacks *callback) {
+    return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
+}
+
+void CameraManagerGlobal::unregisterAvailabilityCallback(
+        const ACameraManager_AvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+    Callback cb(callback);
+    mCallbacks.erase(cb);
+}
+
+template<class T>
+void CameraManagerGlobal::registerAvailCallback(const T *callback) {
     Mutex::Autolock _l(mLock);
     Callback cb(callback);
     auto pair = mCallbacks.insert(cb);
@@ -227,24 +242,33 @@
             if (!pair.second.supportsHAL3) {
                 continue;
             }
+
+            // Camera available/unavailable callback
             sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
-            ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
-                    callback->onCameraAvailable : callback->onCameraUnavailable;
-            msg->setPointer(kCallbackFpKey, (void *) cb);
-            msg->setPointer(kContextKey, callback->context);
+            ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+            msg->setPointer(kContextKey, cb.mContext);
             msg->setString(kCameraIdKey, AString(cameraId));
             msg->post();
+
+            // Physical camera unavailable callback
+            std::set<String8> unavailablePhysicalCameras =
+                    pair.second.getUnavailablePhysicalIds();
+            for (const auto& physicalCameraId : unavailablePhysicalCameras) {
+                sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+                ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
+                        cb.mPhysicalCamUnavailable;
+                msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+                msg->setPointer(kContextKey, cb.mContext);
+                msg->setString(kCameraIdKey, AString(cameraId));
+                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+                msg->post();
+            }
         }
     }
 }
 
-void CameraManagerGlobal::unregisterAvailabilityCallback(
-        const ACameraManager_AvailabilityCallbacks *callback) {
-    Mutex::Autolock _l(mLock);
-    Callback cb(callback);
-    mCallbacks.erase(cb);
-}
-
 bool CameraManagerGlobal::supportsCamera2ApiLocked(const String8 &cameraId) {
     bool camera2Support = false;
     auto cs = getCameraServiceLocked();
@@ -550,6 +574,11 @@
     return count > 0;
 }
 
+std::set<String8> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return unavailablePhysicalIds;
+}
+
 } // namespace acam
 } // namespace android
 
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 98cd934..836e037 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -70,6 +70,9 @@
     const char*                  kCameraServiceName      = "media.camera";
     Mutex                        mLock;
 
+    template<class T>
+    void registerAvailCallback(const T *callback);
+
     class DeathNotifier : public IBinder::DeathRecipient {
       public:
         explicit DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
@@ -222,6 +225,7 @@
         bool removeUnavailablePhysicalId(const String8& physicalCameraId);
         int32_t getStatus();
         void updateStatus(int32_t newStatus);
+        std::set<String8> getUnavailablePhysicalIds();
     };
 
     // Map camera_id -> status
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index 70c887a..a95fe2a 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -36,13 +36,13 @@
 namespace android {
 namespace acam {
 
-using frameworks::cameraservice::service::V2_0::CameraStatusAndId;
 using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections;
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
 
 // Static member definitions
 const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
+const char* CameraManagerGlobal::kPhysicalCameraIdKey   = "PhysicalCameraId";
 const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
 const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
 Mutex                CameraManagerGlobal::sLock;
@@ -258,9 +258,9 @@
         if (mCameraServiceListener == nullptr) {
             mCameraServiceListener = new CameraServiceListener(this);
         }
-        hidl_vec<CameraStatusAndId> cameraStatuses{};
+        hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> cameraStatuses{};
         Status status = Status::NO_ERROR;
-        auto remoteRet = mCameraService->addListener(mCameraServiceListener,
+        auto remoteRet = mCameraService->addListener_2_1(mCameraServiceListener,
                                                      [&status, &cameraStatuses](Status s,
                                                                                 auto &retStatuses) {
                                                          status = s;
@@ -277,7 +277,15 @@
         }
 
         for (auto& c : cameraStatuses) {
-            onStatusChangedLocked(c);
+            onStatusChangedLocked(c.v2_0);
+
+            for (auto& unavailablePhysicalId : c.unavailPhysicalCameraIds) {
+                PhysicalCameraStatusAndId statusAndId;
+                statusAndId.deviceStatus = CameraDeviceStatus::STATUS_NOT_PRESENT;
+                statusAndId.cameraId = c.v2_0.cameraId;
+                statusAndId.physicalCameraId = unavailablePhysicalId;
+                onStatusChangedLocked(statusAndId);
+            }
         }
     }
     return mCameraService;
@@ -293,7 +301,7 @@
         for (auto& pair : cm->mDeviceStatusMap) {
             CameraStatusAndId cameraStatusAndId;
             cameraStatusAndId.cameraId = pair.first;
-            cameraStatusAndId.deviceStatus = pair.second;
+            cameraStatusAndId.deviceStatus = pair.second.getStatus();
             cm->onStatusChangedLocked(cameraStatusAndId);
         }
         cm->mCameraService.clear();
@@ -303,24 +311,7 @@
 
 void CameraManagerGlobal::registerAvailabilityCallback(
         const ACameraManager_AvailabilityCallbacks *callback) {
-    Mutex::Autolock _l(mLock);
-    Callback cb(callback);
-    auto pair = mCallbacks.insert(cb);
-    // Send initial callbacks if callback is newly registered
-    if (pair.second) {
-        for (auto& pair : mDeviceStatusMap) {
-            const hidl_string& cameraId = pair.first;
-            CameraDeviceStatus status = pair.second;
-
-            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
-            ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
-                    callback->onCameraAvailable : callback->onCameraUnavailable;
-            msg->setPointer(kCallbackFpKey, (void *) cb);
-            msg->setPointer(kContextKey, callback->context);
-            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
-            msg->post();
-        }
-    }
+    return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
 }
 
 void CameraManagerGlobal::unregisterAvailabilityCallback(
@@ -330,14 +321,63 @@
     mCallbacks.erase(cb);
 }
 
+void CameraManagerGlobal::registerExtendedAvailabilityCallback(
+        const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+    return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
+}
+
+void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
+        const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+    Callback cb(callback);
+    mCallbacks.erase(cb);
+}
+
+template <class T>
+void CameraManagerGlobal::registerAvailCallback(const T *callback) {
+    Mutex::Autolock _l(mLock);
+    Callback cb(callback);
+    auto pair = mCallbacks.insert(cb);
+    // Send initial callbacks if callback is newly registered
+    if (pair.second) {
+        for (auto& pair : mDeviceStatusMap) {
+            const hidl_string& cameraId = pair.first;
+            CameraDeviceStatus status = pair.second.getStatus();
+
+            // Camera available/unavailable callback
+            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+            ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+            msg->post();
+
+            // Physical camera unavailable callback
+            std::set<hidl_string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
+            for (const auto& physicalCameraId : unavailPhysicalIds) {
+                sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+                ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
+                        cb.mPhysicalCamUnavailable;
+                msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+                msg->setPointer(kContextKey, cb.mContext);
+                msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+                msg->post();
+            }
+        }
+    }
+}
+
 void CameraManagerGlobal::getCameraIdList(std::vector<hidl_string>* cameraIds) {
     // Ensure that we have initialized/refreshed the list of available devices
     auto cs = getCameraService();
     Mutex::Autolock _l(mLock);
 
     for(auto& deviceStatus : mDeviceStatusMap) {
-        if (deviceStatus.second == CameraDeviceStatus::STATUS_NOT_PRESENT ||
-                deviceStatus.second == CameraDeviceStatus::STATUS_ENUMERATING) {
+        CameraDeviceStatus status = deviceStatus.second.getStatus();
+        if (status == CameraDeviceStatus::STATUS_NOT_PRESENT ||
+                status == CameraDeviceStatus::STATUS_ENUMERATING) {
             continue;
         }
         cameraIds->push_back(deviceStatus.first);
@@ -391,6 +431,35 @@
             (*cb)(context, cameraId.c_str());
             break;
         }
+        case kWhatSendSinglePhysicalCameraCallback:
+        {
+            ACameraManager_PhysicalCameraAvailabilityCallback cb;
+            void* context;
+            AString cameraId;
+            AString physicalCameraId;
+            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+            if (!found) {
+                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+                return;
+            }
+            found = msg->findPointer(kContextKey, &context);
+            if (!found) {
+                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+                return;
+            }
+            found = msg->findString(kCameraIdKey, &cameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
+                return;
+            }
+            found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
+                return;
+            }
+            (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
+            break;
+        }
         default:
             ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
             break;
@@ -426,7 +495,7 @@
     bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
     CameraDeviceStatus oldStatus = firstStatus ?
             status : // first status
-            mDeviceStatusMap[cameraId];
+            mDeviceStatusMap[cameraId].getStatus();
 
     if (!firstStatus &&
             isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
@@ -435,7 +504,7 @@
     }
 
     // Iterate through all registered callbacks
-    mDeviceStatusMap[cameraId] = status;
+    mDeviceStatusMap[cameraId].updateStatus(status);
     for (auto cb : mCallbacks) {
         sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
         ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
@@ -450,6 +519,98 @@
     }
 }
 
+hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
+        const PhysicalCameraStatusAndId &statusAndId) {
+    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+    if (cm != nullptr) {
+        cm->onStatusChanged(statusAndId);
+    } else {
+        ALOGE("Cannot deliver status change. Global camera manager died");
+    }
+    return Void();
+}
+
+void CameraManagerGlobal::onStatusChanged(
+        const PhysicalCameraStatusAndId &statusAndId) {
+    Mutex::Autolock _l(mLock);
+    onStatusChangedLocked(statusAndId);
+}
+
+void CameraManagerGlobal::onStatusChangedLocked(
+        const PhysicalCameraStatusAndId &statusAndId) {
+    hidl_string cameraId = statusAndId.cameraId;
+    hidl_string physicalCameraId = statusAndId.physicalCameraId;
+    CameraDeviceStatus status = statusAndId.deviceStatus;
+    if (!validStatus(status)) {
+        ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+        return;
+    }
+
+    auto logicalStatus = mDeviceStatusMap.find(cameraId);
+    if (logicalStatus == mDeviceStatusMap.end()) {
+        ALOGE("%s: Physical camera id %s status change on a non-present id %s",
+                __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
+        return;
+    }
+    CameraDeviceStatus logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
+    if (logicalCamStatus != CameraDeviceStatus::STATUS_PRESENT &&
+            logicalCamStatus != CameraDeviceStatus::STATUS_NOT_AVAILABLE) {
+        ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
+                __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
+        return;
+    }
+
+    bool updated = false;
+    if (status == CameraDeviceStatus::STATUS_PRESENT) {
+        updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
+    } else {
+        updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
+    }
+
+    // Iterate through all registered callbacks
+    if (updated) {
+        for (auto cb : mCallbacks) {
+            sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+            ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
+                    cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFp);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+            msg->post();
+        }
+    }
+}
+
+CameraDeviceStatus CameraManagerGlobal::CameraStatus::getStatus() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return status;
+}
+
+void CameraManagerGlobal::CameraStatus::updateStatus(CameraDeviceStatus newStatus) {
+    std::lock_guard<std::mutex> lock(mLock);
+    status = newStatus;
+}
+
+bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId(
+        const hidl_string& physicalCameraId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    auto result = unavailablePhysicalIds.insert(physicalCameraId);
+    return result.second;
+}
+
+bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId(
+        const hidl_string& physicalCameraId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    auto count = unavailablePhysicalIds.erase(physicalCameraId);
+    return count > 0;
+}
+
+std::set<hidl_string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return unavailablePhysicalIds;
+}
+
 } // namespace acam
 } // namespace android
 
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 2c62d44..36c8e2b 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -21,6 +21,8 @@
 
 #include <android-base/parseint.h>
 #include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
 
 #include <CameraMetadata.h>
 #include <utils/StrongPointer.h>
@@ -36,9 +38,10 @@
 namespace android {
 namespace acam {
 
-using ICameraService = frameworks::cameraservice::service::V2_0::ICameraService;
+using ICameraService = frameworks::cameraservice::service::V2_1::ICameraService;
 using CameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus;
-using ICameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener;
+using ICameraServiceListener = frameworks::cameraservice::service::V2_1::ICameraServiceListener;
+using PhysicalCameraStatusAndId = frameworks::cameraservice::service::V2_1::PhysicalCameraStatusAndId;
 using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
 using Status = frameworks::cameraservice::common::V2_0::Status;
 using VendorTagSection = frameworks::cameraservice::common::V2_0::VendorTagSection;
@@ -65,9 +68,9 @@
             const ACameraManager_AvailabilityCallbacks *callback);
 
     void registerExtendedAvailabilityCallback(
-            const ACameraManager_ExtendedAvailabilityCallbacks* /*callback*/) {}
+            const ACameraManager_ExtendedAvailabilityCallbacks* callback);
     void unregisterExtendedAvailabilityCallback(
-            const ACameraManager_ExtendedAvailabilityCallbacks* /*callback*/) {}
+            const ACameraManager_ExtendedAvailabilityCallbacks* callback);
 
     /**
      * Return camera IDs that support camera2
@@ -94,6 +97,8 @@
         explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
         android::hardware::Return<void> onStatusChanged(
             const CameraStatusAndId &statusAndId) override;
+        android::hardware::Return<void> onPhysicalCameraStatusChanged(
+            const PhysicalCameraStatusAndId &statusAndId) override;
 
       private:
         const wp<CameraManagerGlobal> mCameraManager;
@@ -105,11 +110,25 @@
         explicit Callback(const ACameraManager_AvailabilityCallbacks *callback) :
             mAvailable(callback->onCameraAvailable),
             mUnavailable(callback->onCameraUnavailable),
+            mAccessPriorityChanged(nullptr),
+            mPhysicalCamAvailable(nullptr),
+            mPhysicalCamUnavailable(nullptr),
             mContext(callback->context) {}
 
+        explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) :
+            mAvailable(callback->availabilityCallbacks.onCameraAvailable),
+            mUnavailable(callback->availabilityCallbacks.onCameraUnavailable),
+            mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged),
+            mPhysicalCamAvailable(callback->onPhysicalCameraAvailable),
+            mPhysicalCamUnavailable(callback->onPhysicalCameraUnavailable),
+            mContext(callback->availabilityCallbacks.context) {}
+
         bool operator == (const Callback& other) const {
             return (mAvailable == other.mAvailable &&
                     mUnavailable == other.mUnavailable &&
+                    mAccessPriorityChanged == other.mAccessPriorityChanged &&
+                    mPhysicalCamAvailable == other.mPhysicalCamAvailable &&
+                    mPhysicalCamUnavailable == other.mPhysicalCamUnavailable &&
                     mContext == other.mContext);
         }
         bool operator != (const Callback& other) const {
@@ -119,6 +138,12 @@
             if (*this == other) return false;
             if (mContext != other.mContext) return mContext < other.mContext;
             if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable;
+            if (mAccessPriorityChanged != other.mAccessPriorityChanged)
+                    return mAccessPriorityChanged < other.mAccessPriorityChanged;
+            if (mPhysicalCamAvailable != other.mPhysicalCamAvailable)
+                    return mPhysicalCamAvailable < other.mPhysicalCamAvailable;
+            if (mPhysicalCamUnavailable != other.mPhysicalCamUnavailable)
+                    return mPhysicalCamUnavailable < other.mPhysicalCamUnavailable;
             return mUnavailable < other.mUnavailable;
         }
         bool operator > (const Callback& other) const {
@@ -126,15 +151,20 @@
         }
         ACameraManager_AvailabilityCallback mAvailable;
         ACameraManager_AvailabilityCallback mUnavailable;
+        ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged;
+        ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamAvailable;
+        ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
         void*                               mContext;
     };
     std::set<Callback> mCallbacks;
 
     // definition of handler and message
     enum {
-        kWhatSendSingleCallback
+        kWhatSendSingleCallback,
+        kWhatSendSinglePhysicalCameraCallback,
     };
     static const char* kCameraIdKey;
+    static const char* kPhysicalCameraIdKey;
     static const char* kCallbackFpKey;
     static const char* kContextKey;
     class CallbackHandler : public AHandler {
@@ -147,6 +177,8 @@
 
     void onStatusChanged(const CameraStatusAndId &statusAndId);
     void onStatusChangedLocked(const CameraStatusAndId &statusAndId);
+    void onStatusChanged(const PhysicalCameraStatusAndId &statusAndId);
+    void onStatusChangedLocked(const PhysicalCameraStatusAndId &statusAndId);
     bool setupVendorTags();
 
     // Utils for status
@@ -174,8 +206,27 @@
         }
     };
 
+    struct CameraStatus {
+      private:
+        CameraDeviceStatus status = CameraDeviceStatus::STATUS_NOT_PRESENT;
+        mutable std::mutex mLock;
+        std::set<hidl_string> unavailablePhysicalIds;
+      public:
+        CameraStatus(CameraDeviceStatus st): status(st) { };
+        CameraStatus() = default;
+
+        bool addUnavailablePhysicalId(const hidl_string& physicalCameraId);
+        bool removeUnavailablePhysicalId(const hidl_string& physicalCameraId);
+        CameraDeviceStatus getStatus();
+        void updateStatus(CameraDeviceStatus newStatus);
+        std::set<hidl_string> getUnavailablePhysicalIds();
+    };
+
+    template <class T>
+    void registerAvailCallback(const T *callback);
+
     // Map camera_id -> status
-    std::map<hidl_string, CameraDeviceStatus, CameraIdComparator> mDeviceStatusMap;
+    std::map<hidl_string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
 
     // For the singleton instance
     static Mutex sLock;
diff --git a/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp b/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp
new file mode 100644
index 0000000..a20a290
--- /dev/null
+++ b/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp
@@ -0,0 +1,238 @@
+/*
+ * 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_TAG "ACameraManagerTest"
+//#define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+
+#include <mutex>
+#include <set>
+#include <string>
+
+#include <utils/Log.h>
+#include <camera/NdkCameraError.h>
+#include <camera/NdkCameraManager.h>
+
+namespace {
+
+class CameraServiceListener {
+  public:
+    typedef std::set<std::pair<std::string, std::string>> StringPairSet;
+
+    static void onAvailable(void* obj, const char* cameraId) {
+        ALOGV("Camera %s onAvailable", cameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mOnAvailableCount++;
+        thiz->mAvailableMap[cameraId] = true;
+        return;
+    }
+
+    static void onUnavailable(void* obj, const char* cameraId) {
+        ALOGV("Camera %s onUnavailable", cameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mOnUnavailableCount++;
+        thiz->mAvailableMap[cameraId] = false;
+        return;
+    }
+
+    static void onCameraAccessPrioritiesChanged(void* /*obj*/) {
+        return;
+    }
+
+    static void onPhysicalCameraAvailable(void* obj, const char* cameraId,
+            const char* physicalCameraId) {
+        ALOGV("Camera %s : %s onAvailable", cameraId, physicalCameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mOnPhysicalCameraAvailableCount++;
+        return;
+    }
+
+    static void onPhysicalCameraUnavailable(void* obj, const char* cameraId,
+            const char* physicalCameraId) {
+        ALOGV("Camera %s : %s onUnavailable", cameraId, physicalCameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mUnavailablePhysicalCameras.emplace(cameraId, physicalCameraId);
+        return;
+    }
+
+    void resetCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mOnAvailableCount = 0;
+        mOnUnavailableCount = 0;
+        mOnPhysicalCameraAvailableCount = 0;
+        mUnavailablePhysicalCameras.clear();
+        return;
+    }
+
+    int getAvailableCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mOnAvailableCount;
+    }
+
+    int getUnavailableCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mOnUnavailableCount;
+    }
+
+    int getPhysicalCameraAvailableCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mOnPhysicalCameraAvailableCount;
+    }
+
+    StringPairSet getUnavailablePhysicalCameras() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mUnavailablePhysicalCameras;
+    }
+
+    bool isAvailable(const char* cameraId) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        if (mAvailableMap.count(cameraId) == 0) {
+            return false;
+        }
+        return mAvailableMap[cameraId];
+    }
+
+  private:
+    std::mutex mMutex;
+    int mOnAvailableCount = 0;
+    int mOnUnavailableCount = 0;
+    int mOnPhysicalCameraAvailableCount = 0;
+    std::map<std::string, bool> mAvailableMap;
+    StringPairSet mUnavailablePhysicalCameras;
+};
+
+class ACameraManagerTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        mCameraManager = ACameraManager_create();
+        if (mCameraManager == nullptr) {
+            ALOGE("Failed to create ACameraManager.");
+            return;
+        }
+
+        camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Failed to get cameraIdList: ret=%d", ret);
+            return;
+        }
+        if (mCameraIdList->numCameras < 1) {
+            ALOGW("Device has no camera on board.");
+            return;
+        }
+    }
+    void TearDown() override {
+        // Destroy camera manager
+        if (mCameraIdList) {
+            ACameraManager_deleteCameraIdList(mCameraIdList);
+            mCameraIdList = nullptr;
+        }
+        if (mCameraManager) {
+            ACameraManager_delete(mCameraManager);
+            mCameraManager = nullptr;
+        }
+    }
+
+    // Camera manager
+    ACameraManager* mCameraManager = nullptr;
+    ACameraIdList* mCameraIdList = nullptr;
+    CameraServiceListener mAvailabilityListener;
+    ACameraManager_ExtendedAvailabilityCallbacks mCbs = {
+        {
+            &mAvailabilityListener,
+                CameraServiceListener::onAvailable,
+                CameraServiceListener::onUnavailable
+        },
+        CameraServiceListener::onCameraAccessPrioritiesChanged,
+        CameraServiceListener::onPhysicalCameraAvailable,
+        CameraServiceListener::onPhysicalCameraUnavailable,
+        {}
+    };
+};
+
+TEST_F(ACameraManagerTest, testCameraManagerExtendedAvailabilityCallbacks) {
+    camera_status_t ret = ACameraManager_registerExtendedAvailabilityCallback(mCameraManager,
+            &mCbs);
+    ASSERT_EQ(ret, ACAMERA_OK);
+
+    sleep(1);
+
+    // Should at least get onAvailable for each camera once
+    ASSERT_EQ(mAvailabilityListener.getAvailableCount(), mCameraIdList->numCameras);
+
+    // Expect no available callbacks for physical cameras
+    int availablePhysicalCamera = mAvailabilityListener.getPhysicalCameraAvailableCount();
+    ASSERT_EQ(availablePhysicalCamera, 0);
+
+    CameraServiceListener::StringPairSet unavailablePhysicalCameras;
+    CameraServiceListener::StringPairSet physicalCameraIdPairs;
+
+    unavailablePhysicalCameras = mAvailabilityListener.getUnavailablePhysicalCameras();
+    for (int i = 0; i < mCameraIdList->numCameras; i++) {
+        const char* cameraId = mCameraIdList->cameraIds[i];
+        ASSERT_NE(cameraId, nullptr);
+        ASSERT_TRUE(mAvailabilityListener.isAvailable(cameraId));
+
+        ACameraMetadata* chars = nullptr;
+        ret = ACameraManager_getCameraCharacteristics(mCameraManager, cameraId, &chars);
+        ASSERT_EQ(ret, ACAMERA_OK);
+        ASSERT_NE(chars, nullptr);
+
+        size_t physicalCameraCnt = 0;
+        const char *const* physicalCameraIds = nullptr;
+        if (!ACameraMetadata_isLogicalMultiCamera(
+                chars, &physicalCameraCnt, &physicalCameraIds)) {
+            ACameraMetadata_free(chars);
+            continue;
+        }
+        for (size_t j = 0; j < physicalCameraCnt; j++) {
+            physicalCameraIdPairs.emplace(cameraId, physicalCameraIds[j]);
+        }
+        ACameraMetadata_free(chars);
+    }
+    for (const auto& unavailIdPair : unavailablePhysicalCameras) {
+        bool validPair = false;
+        for (const auto& idPair : physicalCameraIdPairs) {
+            if (idPair.first == unavailIdPair.first && idPair.second == unavailIdPair.second) {
+                validPair = true;
+                break;
+            }
+        }
+        // Expect valid unavailable physical cameras
+        ASSERT_TRUE(validPair);
+    }
+
+    ret = ACameraManager_unregisterExtendedAvailabilityCallback(mCameraManager, &mCbs);
+    ASSERT_EQ(ret, ACAMERA_OK);
+}
+
+}  // namespace
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 6ba1b9c..1700a95 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -50,6 +50,7 @@
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
+        "android.hardware.drm@1.3",
         "libhidlallocatorutils",
         "libhidlbase",
     ],
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 3549637..51c2e24 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -25,6 +25,8 @@
 #include <android/hardware/drm/1.1/IDrmFactory.h>
 #include <android/hardware/drm/1.2/ICryptoFactory.h>
 #include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.3/ICryptoFactory.h>
+#include <android/hardware/drm/1.3/IDrmFactory.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl/HidlSupport.h>
 
@@ -144,6 +146,7 @@
     MakeHidlFactories<::V1_0::IDrmFactory>(uuid, drmFactories);
     MakeHidlFactories<::V1_1::IDrmFactory>(uuid, drmFactories);
     MakeHidlFactories<::V1_2::IDrmFactory>(uuid, drmFactories);
+    MakeHidlFactories<::V1_3::IDrmFactory>(uuid, drmFactories);
     return drmFactories;
 }
 
@@ -161,6 +164,7 @@
     MakeHidlFactories<::V1_0::ICryptoFactory>(uuid, cryptoFactories);
     MakeHidlFactories<::V1_1::ICryptoFactory>(uuid, cryptoFactories);
     MakeHidlFactories<::V1_2::ICryptoFactory>(uuid, cryptoFactories);
+    MakeHidlFactories<::V1_3::ICryptoFactory>(uuid, cryptoFactories);
     return cryptoFactories;
 }
 
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index e01f452..5a60243 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -1,31 +1,16 @@
 {
-  "presubmit": [
+  "postsubmit": [
     {
-      "name": "GtsMediaTestCases",
-      "options" : [
+      // TODO: move to presubmit once we verify the tests are not flaky
+      "name": "CtsMediaTestCases",
+      "options": [
         {
-	  "include-annotation": "android.platform.test.annotations.Presubmit"
+          "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
         }
       ]
-    },
-    {
-      "name": "GtsExoPlayerTestCases",
-      "options" : [
-        {
-	  "include-annotation": "android.platform.test.annotations.SocPresubmit"
-        },
-        {
-          "include-filter": "com.google.android.exoplayer.gts.DashTest#testWidevine23FpsH264Fixed"
-        }
-      ]
-    }
-  ],
-  "imports": [
-    {
-      "path": "frameworks/av/drm/mediadrm/plugins"
     }
   ]
 }
diff --git a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
index 5cc0d53..5ec88ec 100644
--- a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
@@ -160,12 +160,12 @@
             return false;
         }
         for (int32_t i = 0; i < kBufferCount; ++i) {
-            if (!mSource->onInputBufferAdded(i).isOk()) {
+            if (mSource->onInputBufferAdded(i) != OK) {
                 LOG(WARNING) << "Impl::init: failed to populate GBS slots.";
                 return false;
             }
         }
-        if (!mSource->start().isOk()) {
+        if (mSource->start() != OK) {
             LOG(WARNING) << "Impl::init -- GBS failed to start.";
             return false;
         }
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 94034b5..cb60a45 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -45,7 +45,7 @@
         "libmedia_codeclist",
         "libmedia_omx",
         "libsfplugin_ccodec_utils",
-        "libstagefright_bufferqueue_helper",
+        "libstagefright_bufferqueue_helper_client",
         "libstagefright_codecbase",
         "libstagefright_foundation",
         "libstagefright_omx",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index ae95336..035dca8 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1263,10 +1263,12 @@
         }
 
         if (oStreamFormat.value == C2BufferData::LINEAR) {
-            // WORKAROUND: if we're using early CSD workaround we convert to
-            //             array mode, to appease apps assuming the output
-            //             buffers to be of the same size.
-            output->buffers = output->buffers->toArrayMode(numOutputSlots);
+            if (buffersBoundToCodec) {
+                // WORKAROUND: if we're using early CSD workaround we convert to
+                //             array mode, to appease apps assuming the output
+                //             buffers to be of the same size.
+                output->buffers = output->buffers->toArrayMode(numOutputSlots);
+            }
 
             int32_t channelCount;
             int32_t sampleRate;
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index a1f145b..51d6ffa 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -70,8 +70,6 @@
         "libutils",
     ],
 
-    tidy: false, // b/146435095, clang-tidy segmentation fault
-
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index 59c8200..a00812b 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -652,12 +652,13 @@
     }
 
     mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
-    memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
+
     if (!mSampleTimeEntries) {
         ALOGE("Cannot allocate sample entry table with %llu entries.",
                 (unsigned long long)mNumSampleSizes);
         return;
     }
+    memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
 
     uint32_t sampleIndex = 0;
     uint64_t sampleTime = 0;
diff --git a/media/extractors/tests/AndroidTest.xml b/media/extractors/tests/AndroidTest.xml
new file mode 100644
index 0000000..6bb2c8a
--- /dev/null
+++ b/media/extractors/tests/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 extractor unit tests">
+    <option name="test-suite-tag" value="ExtractorUnitTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="ExtractorUnitTest->/data/local/tmp/ExtractorUnitTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
+            value="/data/local/tmp/ExtractorUnitTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="ExtractorUnitTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/ExtractorUnitTestRes/" />
+    </test>
+</configuration>
diff --git a/media/extractors/tests/README.md b/media/extractors/tests/README.md
index 6e02d3e..69538b6 100644
--- a/media/extractors/tests/README.md
+++ b/media/extractors/tests/README.md
@@ -22,8 +22,8 @@
 adb push ${OUT}/data/nativetest/ExtractorUnitTest/ExtractorUnitTest /data/local/tmp/
 ```
 
-The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/1Z9nCIRB6pGLvb5mPkF8BURa5Nc6cY9pY). Push these files into device for testing.
-Download extractor folder and push all the files in this folder to /data/local/tmp/ on the device.
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip). Download, unzip and push these files into device for testing.
+
 ```
 adb push extractor /data/local/tmp/
 ```
@@ -32,3 +32,8 @@
 ```
 adb shell /data/local/tmp/ExtractorUnitTest -P /data/local/tmp/extractor/
 ```
+Alternatively, the test can also be run using atest command.
+
+```
+atest ExtractorUnitTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 2f43b22..edc09a9 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1030,6 +1030,10 @@
  *
  * After this call, the stream will be in {@link #AAUDIO_STREAM_STATE_CLOSING}
  *
+ * This function is useful if you want to release the audio resources immediately,
+ * but still allow queries to the stream to occur from other threads. This often
+ * happens if you are monitoring stream progress from a UI thread.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
diff --git a/media/libmedia/aidl/android/media/IResourceManagerService.aidl b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
index 3e6f8db..3dd0859 100644
--- a/media/libmedia/aidl/android/media/IResourceManagerService.aidl
+++ b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
@@ -84,4 +84,14 @@
      * @return true if the reclaim was successful and false otherwise.
      */
     boolean reclaimResource(int callingPid, in MediaResourceParcel[] resources);
+
+    /**
+     * Override the pid of original calling process with the pid of the process
+     * who actually use the requested resources.
+     *
+     * @param originalPid pid of the original calling process.
+     * @param newPid pid of the actual process who use the resources.
+     *        remove existing override on originalPid if newPid is -1.
+     */
+    void overridePid(int originalPid, int newPid);
 }
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index e49917f..fb26fae 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -70,14 +70,21 @@
 // Underscores after the AMEDIAMETRICS_PROP_* prefix indicate
 // a "dot" in the property name. For example AMEDIAMETRICS_PROP_VOLUME_LEFT
 // corresponds to "volume.left".
-
+//
+// The property names are camel case, typically a lowercase letter [a-z]
+// followed by one or more characters in the range [a-zA-Z0-9_.].
+// Special symbols such as !@#$%^&*()[]{}<>,:;'"\/?|+-=~ are reserved.
+//
+// A property that ends with a ! will have duplicate values listed instead
+// of suppressed in the Time Machine.
+//
 #define AMEDIAMETRICS_PROP_AUXEFFECTID    "auxEffectId"    // int32 (AudioTrack)
 #define AMEDIAMETRICS_PROP_CHANNELCOUNT   "channelCount"   // int32
 #define AMEDIAMETRICS_PROP_CHANNELMASK    "channelMask"    // int32
 #define AMEDIAMETRICS_PROP_CONTENTTYPE    "contentType"    // string attributes (AudioTrack)
 #define AMEDIAMETRICS_PROP_DURATIONNS     "durationNs"     // int64 duration time span
 #define AMEDIAMETRICS_PROP_ENCODING       "encoding"       // string value of format
-#define AMEDIAMETRICS_PROP_EVENT          "event"          // string value (often func name)
+#define AMEDIAMETRICS_PROP_EVENT          "event!"         // string value (often func name)
 
 // TODO: fix inconsistency in flags: AudioRecord / AudioTrack int32,  AudioThread string
 #define AMEDIAMETRICS_PROP_FLAGS          "flags"
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
index bb4ba75..4d95de5 100644
--- a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
@@ -71,6 +71,9 @@
     Mutex::Autolock autoLock(mLock);
 
     if (mLength >= 0) {
+        if (offset < 0) {
+            return UNKNOWN_ERROR;
+        }
         if (offset >= mLength) {
             return 0;  // read beyond EOF.
         }
diff --git a/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h b/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
new file mode 100644
index 0000000..0e8dcfd
--- /dev/null
+++ b/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
@@ -0,0 +1,216 @@
+/*
+ * 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 ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
+#define ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
+
+#include <utils/Log.h>
+
+#include <functional>
+#include <iostream>
+#include <vector>
+
+namespace android {
+
+/*
+ * AdjustableMaxPriorityQueue is a custom max priority queue that helps managing jobs for
+ * MediaTranscodingService.
+ *
+ * AdjustableMaxPriorityQueue is a wrapper template around the STL's *_heap() functions.
+ * - Internally, it uses a std::vector<T> to store elements in a heap order.
+ * - Support adjusting item's priority while maintaining the heap property.
+ * - Support removing any item in the heap while maintaining the heap property. Note that the
+ *   removal complexity will be O(n) in worst case.
+ * - AdjustableMaxPriorityQueue needs T::operator<() at instantiation time
+ */
+template <class T, class Comparator = std::less<T>>
+class AdjustableMaxPriorityQueue {
+   public:
+    typedef typename std::vector<T>::iterator iterator;
+    typedef typename std::vector<T>::const_iterator const_iterator;
+
+    AdjustableMaxPriorityQueue();
+
+    /* Whether the queue is empty. */
+    bool empty() const;
+
+    /* Number of items in the queue. */
+    int size() const;
+
+    /* Return the top element in the queue. The queue still owns the element. */
+    const T& top() const;
+
+    /* Discards the element with highest value based on the given comparator. */
+    void pop();
+
+    /* Erases all the elements in the queue. */
+    void clear();
+
+    /*
+     * Returns the element with the highest value based on the given comparator. Queue transfer the
+     * ownership of the item to the caller. Client MUST call empty() to check whether there is
+     * element at the top before calling this.
+     */
+    T consume_top();
+
+    /* Adds an element to the heap. The queue will make a deep copy of the element. */
+    bool push(const T& item) { return pushInternal(item); }
+
+    /* Adds an element to the heap. The queue will take ownership of the element. */
+    bool push(T&& item) { return pushInternal(std::move(item)); }
+
+    /* Adds a new element to the AdjustableMaxPriorityQueue. This new element is constructed in
+     * place passing args as the arguments for its constructor. */
+    template <class... Args>
+    bool emplace(Args&&... args);
+
+    /* Remove an element from a AdjustableMaxPriorityQueue. */
+    void erase(iterator pos);
+
+    /*
+     * Rebuild a heap based on the given comparator. This MUST be called after changing the value
+     * of items.
+     */
+    void rebuild();
+
+    /*
+     * Iterators used for accessing and changing the priority.
+     * If you change the value of items through these access iterators BE SURE to call rebuild() to
+     * ensure the integrity of the heap is maintained.
+     * NOTE: The iterator pos will change after calling rebuild().
+     */
+    const iterator begin();
+    const iterator end();
+
+    /*
+     * Iterators used for accessing the priority.
+     */
+    const const_iterator begin() const;
+    const const_iterator end() const;
+
+    /* Return the backbone storage of this PriorityQueue. Mainly used for debugging. */
+    const std::vector<T>& getStorage() const { return mHeap; };
+
+   private:
+    std::vector<T> mHeap;
+
+    /* Implementation shared by both public push() methods. */
+    template <class Arg>
+    bool pushInternal(Arg&& item);
+};
+
+template <class T, class Comparator>
+AdjustableMaxPriorityQueue<T, Comparator>::AdjustableMaxPriorityQueue() {}
+
+template <class T, class Comparator>
+bool AdjustableMaxPriorityQueue<T, Comparator>::empty() const {
+    return mHeap.empty();
+}
+
+template <class T, class Comparator>
+int AdjustableMaxPriorityQueue<T, Comparator>::size() const {
+    return mHeap.size();
+}
+
+template <class T, class Comparator>
+const T& AdjustableMaxPriorityQueue<T, Comparator>::top() const {
+    DCHECK(!mHeap.empty());
+    return mHeap.front();
+}
+
+// Compares elements and potentially swaps (or moves) them until rearranged as a longer heap.
+// Complexity of this: Up to logarithmic in the distance between first and last.
+template <class T, class Comparator>
+template <class Arg>
+bool AdjustableMaxPriorityQueue<T, Comparator>::pushInternal(Arg&& item) {
+    mHeap.push_back(std::forward<Arg>(item));
+    std::push_heap(mHeap.begin(), mHeap.end(), Comparator());
+    return true;
+}
+
+template <class T, class Comparator>
+template <class... Args>
+bool AdjustableMaxPriorityQueue<T, Comparator>::emplace(Args&&... args) {
+    mHeap.emplace_back(std::forward<Args>(args)...);
+    std::push_heap(mHeap.begin(), mHeap.end(), Comparator());
+    return true;
+}
+
+// Compares elements and potentially swaps (or moves) them until rearranged as a shorter heap.
+// Complexity of this: Up to twice logarithmic in the distance between first and last.
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::pop() {
+    DCHECK(!mHeap.empty());
+    std::pop_heap(mHeap.begin(), mHeap.end(), Comparator());
+    mHeap.pop_back();
+}
+
+// Compares elements and potentially swaps (or moves) them until rearranged as a shorter heap.
+// Complexity of this: Up to twice logarithmic in the distance between first and last.
+template <class T, class Comparator>
+T AdjustableMaxPriorityQueue<T, Comparator>::consume_top() {
+    DCHECK(!mHeap.empty());
+    std::pop_heap(mHeap.begin(), mHeap.end(), Comparator());
+    T to_return = std::move(mHeap.back());
+    mHeap.pop_back();
+    return to_return;
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::iterator
+AdjustableMaxPriorityQueue<T, Comparator>::begin() {
+    return mHeap.begin();
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::iterator
+AdjustableMaxPriorityQueue<T, Comparator>::end() {
+    return mHeap.end();
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::const_iterator
+AdjustableMaxPriorityQueue<T, Comparator>::begin() const {
+    return mHeap.begin();
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::const_iterator
+AdjustableMaxPriorityQueue<T, Comparator>::end() const {
+    return mHeap.end();
+}
+
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::clear() {
+    mHeap.erase(mHeap.begin(), mHeap.end());
+}
+
+// Complexity of this: At most 3*std::distance(first, last) comparisons.
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::rebuild() {
+    std::make_heap(mHeap.begin(), mHeap.end(), Comparator());
+}
+
+// Remove a random element from a AdjustableMaxPriorityQueue.
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::erase(iterator pos) {
+    DCHECK(!mHeap.empty());
+    mHeap.erase(pos);
+    rebuild();
+}
+
+}  // namespace android
+#endif  // ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp b/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
new file mode 100644
index 0000000..d58af4e
--- /dev/null
+++ b/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+
+// Unit Test for AdjustableMaxPriorityQueue
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AdjustableMaxPriorityQueueTest"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <media/AdjustableMaxPriorityQueue.h>
+#include <utils/Log.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <list>
+#include <queue>
+#include <unordered_map>
+
+namespace android {
+
+class IntUniquePtrComp {
+   public:
+    bool operator()(const std::unique_ptr<int>& lhs, const std::unique_ptr<int>& rhs) const {
+        return *lhs < *rhs;
+    }
+};
+
+// Test the heap property and make sure it is the same as std::priority_queue.
+TEST(AdjustableMaxPriorityQueueTest, BasicAPIS) {
+    AdjustableMaxPriorityQueue<std::pair<float, char*>> heap;
+    std::priority_queue<std::pair<float, char*>> pq;
+    AdjustableMaxPriorityQueue<std::pair<float, char*>> remove_queue;
+
+    // Push a set of values onto both AdjustableMaxPriorityQueue and priority_queue
+    // Also compute the sum of those values
+    double sum = 0;
+    for (int i = 0; i < 10; ++i) {
+        float value = 2.1 * i;
+        sum += value;
+        heap.push(std::pair<float, char*>(value, nullptr));
+        pq.push(std::pair<float, char*>(value, nullptr));
+        remove_queue.push(std::pair<float, char*>(value, nullptr));
+    }
+
+    // Test the iterator by using it to subtract all values from earlier sum
+    AdjustableMaxPriorityQueue<std::pair<float, char*>>::iterator it;
+    for (it = heap.begin(); it != heap.end(); ++it) {
+        sum -= it->first;
+    }
+    EXPECT_EQ(0, sum);
+
+    // Test the size();
+    EXPECT_EQ(10, heap.size());
+
+    // Testing pop() by popping values from both queues and compare if they are the same.
+    // Also check each pop is smaller than the previous pop max value.
+    float max = 1000;
+    while (!heap.empty()) {
+        float value = heap.top().first;
+        ALOGD("Value is %f ", value);
+        EXPECT_EQ(value, pq.top().first);
+        EXPECT_LE(value, max);
+        max = value;
+        heap.pop();
+        pq.pop();
+    }
+
+    // Test erase() by removing values and ensuring the heap
+    // condition is still met as miscellaneous elements are
+    // removed from the heap.
+    int iteration_mixer = 0;
+    float previous_value = remove_queue.top().first;
+
+    while (!remove_queue.empty()) {
+        int iteration_count = iteration_mixer % remove_queue.size();
+
+        AdjustableMaxPriorityQueue<std::pair<float, char*>>::iterator iterator =
+                remove_queue.begin();
+
+        // Empty loop as we just want to advance the iterator.
+        for (int i = 0; i < iteration_count; ++i, ++iterator) {
+        }
+
+        remove_queue.erase(iterator);
+        float value = remove_queue.top().first;
+        remove_queue.pop();
+
+        EXPECT_GE(previous_value, value);
+
+        ++iteration_mixer;
+        previous_value = value;
+    }
+}
+
+TEST(AdjustableMaxPriorityQueueTest, BasicWithMoveOnly) {
+    AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp> heap;
+
+    auto smaller = std::make_unique<int>(1);
+    EXPECT_TRUE(heap.push(std::move(smaller)));
+    EXPECT_EQ(1, *heap.top());
+    EXPECT_EQ(1, heap.size());
+
+    auto bigger = std::make_unique<int>(2);
+    heap.push(std::move(bigger));
+    EXPECT_EQ(2, *heap.top());
+
+    auto biggest = std::make_unique<int>(3);
+    EXPECT_TRUE(heap.push(std::move(biggest)));
+
+    EXPECT_EQ(3, heap.size());
+    // Biggest should be on top.
+    EXPECT_EQ(3, *heap.top());
+
+    biggest = heap.consume_top();
+    EXPECT_EQ(3, *biggest);
+
+    bigger = heap.consume_top();
+    EXPECT_EQ(2, *bigger);
+
+    smaller = heap.consume_top();
+    EXPECT_EQ(1, *smaller);
+
+    EXPECT_TRUE(heap.empty());
+}
+
+TEST(AdjustableMaxPriorityQueueTest, TestChangingItem) {
+    AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp> heap;
+    using HeapIterator =
+            AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp>::iterator;
+
+    int testValues[] = {1, 2, 3};
+    // Map to save each value's position in the heap.
+    std::unordered_map<int, HeapIterator> itemToIterratorMap;
+
+    // Insert the test values into the heap.
+    for (auto value : testValues) {
+        auto item = std::make_unique<int>(value);
+        EXPECT_TRUE(heap.push(std::move(item)));
+    }
+
+    // Save each value and its pos in the heap into the map.
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // Change the item with value 1 -> 4. And expects the 4 to be the top of the HEAP after that.
+    // After changing, the heap should contain [2,3,4].
+    auto newValue = std::make_unique<int>(4);
+    itemToIterratorMap[1]->swap(newValue);
+    heap.rebuild();
+    EXPECT_EQ(4, *heap.top());
+
+    // Change the item with value 2 -> 5. And expects the 5 to be the top of the HEAP after that.
+    auto newValue2 = std::make_unique<int>(5);
+    itemToIterratorMap[2]->swap(newValue2);
+    heap.rebuild();
+    EXPECT_EQ(5, *heap.top());
+}
+
+TEST(AdjustableMaxPriorityQueueTest, TestErasingItem) {
+    AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp> heap;
+    using HeapIterator =
+            AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp>::iterator;
+
+    int testValues[] = {1, 2, 3};
+    // Map to save each value's position in the heap.
+    std::unordered_map<int, HeapIterator> itemToIterratorMap;
+
+    // Insert the test values into the heap.
+    for (auto value : testValues) {
+        auto item = std::make_unique<int>(value);
+        EXPECT_TRUE(heap.push(std::move(item)));
+    }
+
+    // Save each value and its pos in the heap into the map.
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // The top of the heap must be 3.
+    EXPECT_EQ(3, *heap.top());
+
+    // Remove 3 and the top of the heap should be 2.
+    heap.erase(itemToIterratorMap[3]);
+    EXPECT_EQ(2, *heap.top());
+
+    // Reset the iter pos in the heap.
+    itemToIterratorMap.clear();
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // Remove 2 and the top of the heap should be 1.
+    heap.erase(itemToIterratorMap[2]);
+    EXPECT_EQ(1, *heap.top());
+
+    // Reset the iter pos in the heap as iterator pos changed after
+    itemToIterratorMap.clear();
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // Remove 1 and the heap should be empty.
+    heap.erase(itemToIterratorMap[1]);
+    EXPECT_TRUE(heap.empty());
+}
+
+// Test the heap property and make sure it is the same as std::priority_queue.
+TEST(AdjustableMaxPriorityQueueTest, TranscodingJobTest) {
+    // Test data structure that mimics the Transcoding job.
+    struct TranscodingJob {
+        int32_t priority;
+        int64_t createTimeUs;
+    };
+
+    // The job is arranging according to priority with highest priority comes first.
+    // For the job with the same priority, the job with early createTime will come first.
+    class TranscodingJobComp {
+       public:
+        bool operator()(const std::unique_ptr<TranscodingJob>& lhs,
+                        const std::unique_ptr<TranscodingJob>& rhs) const {
+            if (lhs->priority != rhs->priority) {
+                return lhs->priority < rhs->priority;
+            }
+            return lhs->createTimeUs > rhs->createTimeUs;
+        }
+    };
+
+    // Map to save each value's position in the heap.
+    std::unordered_map<int, TranscodingJob*> jobIdToJobMap;
+
+    TranscodingJob testJobs[] = {
+            {1 /*priority*/, 66 /*createTimeUs*/},  // First job,
+            {2 /*priority*/, 67 /*createTimeUs*/},  // Second job,
+            {2 /*priority*/, 66 /*createTimeUs*/},  // Third job,
+            {3 /*priority*/, 68 /*createTimeUs*/},  // Fourth job.
+    };
+
+    AdjustableMaxPriorityQueue<std::unique_ptr<TranscodingJob>, TranscodingJobComp> jobQueue;
+
+    // Pushes all the jobs into the heap.
+    for (int jobId = 0; jobId < 4; ++jobId) {
+        auto newJob = std::make_unique<TranscodingJob>(testJobs[jobId]);
+        jobIdToJobMap[jobId] = newJob.get();
+        EXPECT_TRUE(jobQueue.push(std::move(newJob)));
+    }
+
+    // Check the job queue size.
+    EXPECT_EQ(4, jobQueue.size());
+
+    // Check the top and it should be Forth job: (3, 68)
+    const std::unique_ptr<TranscodingJob>& topJob = jobQueue.top();
+    EXPECT_EQ(3, topJob->priority);
+    EXPECT_EQ(68, topJob->createTimeUs);
+
+    // Consume the top.
+    std::unique_ptr<TranscodingJob> consumeJob = jobQueue.consume_top();
+
+    // Check the top and it should be Third Job (2, 66)
+    const std::unique_ptr<TranscodingJob>& topJob2 = jobQueue.top();
+    EXPECT_EQ(2, topJob2->priority);
+    EXPECT_EQ(66, topJob2->createTimeUs);
+
+    // Change the Second job's priority to 4 from (2, 67) -> (4, 67). It should becomes top of the
+    // queue.
+    jobIdToJobMap[1]->priority = 4;
+    jobQueue.rebuild();
+    const std::unique_ptr<TranscodingJob>& topJob3 = jobQueue.top();
+    EXPECT_EQ(4, topJob3->priority);
+    EXPECT_EQ(67, topJob3->createTimeUs);
+}
+}  // namespace android
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index f3cc4c5..8191b00 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -35,4 +35,14 @@
     defaults: ["libmediatranscoding_test_defaults"],
 
     srcs: ["TranscodingClientManager_tests.cpp"],
+}
+
+//
+// AdjustableMaxPriorityQueue unit test
+//
+cc_test {
+    name: "AdjustableMaxPriorityQueue_tests",
+    defaults: ["libmediatranscoding_test_defaults"],
+
+    srcs: ["AdjustableMaxPriorityQueue_tests.cpp"],
 }
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
index 9832696..d8e4830 100644
--- a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
+++ b/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
@@ -21,3 +21,6 @@
 
 echo "testing TranscodingClientManager"
 adb shell /data/nativetest64/TranscodingClientManager_tests/TranscodingClientManager_tests
+
+echo "testing AdjustableMaxPriorityQueue"
+adb shell /data/nativetest64/AdjustableMaxPriorityQueue_tests/AdjustableMaxPriorityQueue_tests
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index b29d5f8..dbbdd1b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -625,7 +625,7 @@
 
     CHECK(source.get() != NULL);
 
-    const char *mime;
+    const char *mime = NULL;
     sp<MetaData> meta = source->getFormat();
     meta->findCString(kKeyMIMEType, &mime);
 
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index c1b270c..3c3fff7 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -1,10 +1,14 @@
 {
   "postsubmit": [
     {
+      // TODO: move to presubmit once we verify the tests are not flaky
       "name": "CtsMediaTestCases",
       "options": [
         {
-          "include-annotation": "android.platform.test.annotations.RequiresDevice"
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
         }
       ]
     },
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 6719bab..f4548ff 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -1,9 +1,5 @@
-cc_library_shared {
-    name: "libstagefright_bufferqueue_helper",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
+cc_defaults {
+    name: "libstagefright_bufferqueue-defaults",
     double_loadable: true,
     srcs: [
         "FrameDropper.cpp",
@@ -23,7 +19,7 @@
     ],
 
     shared_libs: [
-        "libbinder",
+        "libbase",
         "libcutils",
         "libhidlbase",
         "libhidlmemory",
@@ -33,24 +29,12 @@
         "libutils",
 
         "android.hardware.graphics.bufferqueue@1.0",
-        // Following libs are from libgui_bufferqueue_static
-        "android.hardware.graphics.bufferqueue@2.0",
-        "android.hidl.token@1.0-utils",
-        "libbase",
-        "libEGL",
-        "libnativewindow",
-        "libvndksupport",
-    ],
-    
-    static_libs: [
-        "libgui_bufferqueue_static"
     ],
 
     export_shared_lib_headers: [
         "libhidlmemory",
         "libstagefright_foundation",
         "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.bufferqueue@2.0",
     ],
 
     cflags: [
@@ -68,3 +52,38 @@
         cfi: true,
     },
 }
+
+cc_library_shared {
+    name: "libstagefright_bufferqueue_helper",
+    defaults: ["libstagefright_bufferqueue-defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    static_libs: [
+        "libgui_bufferqueue_static"
+    ],
+    shared_libs: [
+        "android.hardware.graphics.bufferqueue@2.0",
+        "android.hidl.token@1.0-utils",
+        "libEGL",
+        "libnativewindow",
+        "libvndksupport",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.bufferqueue@2.0",
+    ],
+    cflags: [
+        "-DNO_BINDER",
+    ],
+}
+
+cc_library_shared {
+    name: "libstagefright_bufferqueue_helper_client",
+    defaults: ["libstagefright_bufferqueue-defaults"],
+    vendor_available: false,
+    shared_libs: [
+        "libgui"
+    ],
+}
+
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index de9d12c..cff14ac 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -412,7 +412,7 @@
                     B2HGraphicBufferProducer(getIGraphicBufferProducer());
 }
 
-Status GraphicBufferSource::start() {
+status_t GraphicBufferSource::start() {
     Mutex::Autolock autoLock(mMutex);
     ALOGV("--> start; available=%zu, submittable=%zd",
             mAvailableBuffers.size(), mFreeCodecBuffers.size());
@@ -459,10 +459,10 @@
         }
     }
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::stop() {
+status_t GraphicBufferSource::stop() {
     ALOGV("stop");
 
     Mutex::Autolock autoLock(mMutex);
@@ -472,10 +472,10 @@
         // not loaded->idle.
         mExecuting = false;
     }
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::release(){
+status_t GraphicBufferSource::release(){
     sp<ALooper> looper;
     {
         Mutex::Autolock autoLock(mMutex);
@@ -501,26 +501,26 @@
     if (looper != NULL) {
         looper->stop();
     }
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
+status_t GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting) {
         // This should never happen -- buffers can only be allocated when
         // transitioning from "loaded" to "idle".
         ALOGE("addCodecBuffer: buffer added while executing");
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     ALOGV("addCodecBuffer: bufferId=%u", bufferId);
 
     mFreeCodecBuffers.push_back(bufferId);
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
+status_t GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
     Mutex::Autolock autoLock(mMutex);
     FileDescriptor::Autoclose fence(fenceFd);
 
@@ -528,7 +528,7 @@
     if (cbi < 0) {
         // This should never happen.
         ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId);
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        return BAD_VALUE;
     }
 
     std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi);
@@ -548,13 +548,13 @@
             ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi);
         }
         // No GraphicBuffer to deal with, no additional input or output is expected, so just return.
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        return BAD_VALUE;
     }
 
     if (!mExecuting) {
         // this is fine since this could happen when going from Idle to Loaded
         ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi);
-        return Status::fromServiceSpecificError(OK);
+        return OK;
     }
 
     ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d",
@@ -584,7 +584,7 @@
     }
 
     // releaseReleasableBuffers_l();
-    return Status::ok();
+    return OK;
 }
 
 void GraphicBufferSource::onDataspaceChanged_l(
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
index ed5d7cb..fe6bcce 100644
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
+++ b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
@@ -31,8 +31,6 @@
 
 namespace android {
 
-using ::android::binder::Status;
-
 struct FrameDropper;
 class BufferItem;
 class IGraphicBufferProducer;
@@ -99,26 +97,26 @@
     // This is called when component transitions to running state, which means
     // we can start handing it buffers.  If we already have buffers of data
     // sitting in the BufferQueue, this will send them to the codec.
-    Status start();
+    status_t start();
 
     // This is called when component transitions to stopped, indicating that
     // the codec is meant to return all buffers back to the client for them
     // to be freed. Do NOT submit any more buffers to the component.
-    Status stop();
+    status_t stop();
 
     // This is called when component transitions to released, indicating that
     // we are shutting down.
-    Status release();
+    status_t release();
 
     // A "codec buffer", i.e. a buffer that can be used to pass data into
     // the encoder, has been allocated.  (This call does not call back into
     // component.)
-    Status onInputBufferAdded(int32_t bufferId);
+    status_t onInputBufferAdded(int32_t bufferId);
 
     // Called when encoder is no longer using the buffer.  If we have a BQ
     // buffer available, fill it with a new frame of data; otherwise, just mark
     // it as available.
-    Status onInputBufferEmptied(int32_t bufferId, int fenceFd);
+    status_t onInputBufferEmptied(int32_t bufferId, int fenceFd);
 
     // IGraphicBufferSource interface
     // ------------------------------
diff --git a/media/libstagefright/omx/OmxGraphicBufferSource.cpp b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
index 7b187f9..9484046 100644
--- a/media/libstagefright/omx/OmxGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
@@ -65,15 +65,18 @@
 }  // namespace
 
 Status OmxGraphicBufferSource::onOmxExecuting() {
-    return start();
+    status_t err = start();
+    return (OK == err) ? Status::ok() : Status::fromServiceSpecificError(err);
 }
 
 Status OmxGraphicBufferSource::onOmxIdle() {
-    return stop();
+    status_t err = stop();
+    return (OK == err) ? Status::ok() : Status::fromServiceSpecificError(err);
 }
 
 Status OmxGraphicBufferSource::onOmxLoaded(){
-    return release();
+    status_t err = release();
+    return (OK == err) ? Status::ok() : Status::fromServiceSpecificError(err);
 }
 
 status_t OmxGraphicBufferSource::configure(
diff --git a/media/libstagefright/tests/writer/AndroidTest.xml b/media/libstagefright/tests/writer/AndroidTest.xml
new file mode 100644
index 0000000..d831555
--- /dev/null
+++ b/media/libstagefright/tests/writer/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Test module config for writer tests">
+    <option name="test-suite-tag" value="writerTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="writerTest->/data/local/tmp/writerTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/Writer.zip?unzip=true"
+            value="/data/local/tmp/writerTestRes/" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="writerTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/writerTestRes/" />
+    </test>
+</configuration>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
index 1179d6c..1890661 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -14,6 +14,12 @@
      limitations under the License.
 -->
 <configuration description="Runs Media Benchmark Tests">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark.zip?unzip=true"
+            value="/data/local/tmp/MediaBenchmark/res/" />
+    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
         <option name="cleanup-apks" value="false" />
         <option name="test-file-name" value="MediaBenchmarkTest.apk" />
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
index c41f198..afd70a3 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
@@ -78,7 +78,7 @@
                 {"bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", false},
                 {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", false},
                 {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", false},
-                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", false},
+                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", false},
                 {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4", false},
                 {"bbb_48000hz_2ch_100kbps_opus_30sec.webm", false},
                 // Audio Async Test
@@ -86,7 +86,7 @@
                 {"bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", true},
                 {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", true},
                 {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", true},
-                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", true},
+                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", true},
                 {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4", true},
                 {"bbb_48000hz_2ch_100kbps_opus_30sec.webm", true},
                 // Video Sync Test
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
index 831467a..48e1422 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -19,6 +19,9 @@
 import android.content.Context;
 import android.media.MediaCodec;
 import android.media.MediaFormat;
+
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+
 import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -65,6 +68,7 @@
     private static final int ENCODE_DEFAULT_FRAME_RATE = 25;
     private static final int ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
     private static final int ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+    private static final int ENCODE_DEFAULT_AUDIO_BIT_RATE = 128000 /* 128 Kbps */;
     private String mInputFile;
 
     @Parameterized.Parameters
@@ -98,7 +102,7 @@
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
-    public void sampleEncoderTest() throws Exception {
+    public void testEncoder() throws Exception {
         int status;
         int frameSize;
         //Parameters for video
@@ -107,6 +111,7 @@
         int profile = 0;
         int level = 0;
         int frameRate = 0;
+
         //Parameters for audio
         int bitRate = 0;
         int sampleRate = 0;
@@ -122,6 +127,7 @@
         ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
         ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
         for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+            int colorFormat = COLOR_FormatYUV420Flexible;
             extractor.selectExtractorTrack(currentTrack);
             MediaFormat format = extractor.getFormat(currentTrack);
             // Get samples from extractor
@@ -148,6 +154,7 @@
             status = decoder.decode(inputBuffer, frameInfo, false, format, "");
             assertEquals("Decoder returned error " + status + " for file: " + mInputFile, 0,
                     status);
+            MediaFormat decoderFormat = decoder.getFormat();
             decoder.deInitCodec();
             extractor.unselectExtractorTrack(currentTrack);
             inputBuffer.clear();
@@ -203,10 +210,17 @@
                         if (format.containsKey(MediaFormat.KEY_PROFILE)) {
                             level = format.getInteger(MediaFormat.KEY_LEVEL);
                         }
+                        if (decoderFormat.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
+                            colorFormat = decoderFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+                        }
                     } else {
                         sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                         numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
-                        bitRate = sampleRate * numChannels * 16;
+                        if (decoderFormat.containsKey(MediaFormat.KEY_BIT_RATE)) {
+                            bitRate = decoderFormat.getInteger(MediaFormat.KEY_BIT_RATE);
+                        } else {
+                            bitRate = ENCODE_DEFAULT_AUDIO_BIT_RATE;
+                        }
                     }
                     /*Setup Encode Format*/
                     MediaFormat encodeFormat;
@@ -219,6 +233,7 @@
                         encodeFormat.setInteger(MediaFormat.KEY_LEVEL, level);
                         encodeFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
                         encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, frameSize);
+                        encodeFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
                     } else {
                         encodeFormat = MediaFormat.createAudioFormat(mime, sampleRate, numChannels);
                         encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
@@ -255,7 +270,7 @@
         fileInput.close();
     }
 
-    @Test
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testNativeEncoder() throws Exception {
         File inputFile = new File(mInputFilePath + mInputFile);
         assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
@@ -275,8 +290,8 @@
             // Encoding the decoder's output
             for (String codecName : mediaCodecs) {
                 Native nativeEncoder = new Native();
-                int status = nativeEncoder.Encode(
-                        mInputFilePath, mInputFile, mDecodedFile, mStatsFile, codecName);
+                int status = nativeEncoder
+                        .Encode(mInputFilePath, mInputFile, mDecodedFile, mStatsFile, codecName);
                 assertEquals(
                         codecName + " encoder returned error " + status + " for " + "file:" + " " +
                                 mInputFile, 0, status);
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
index 6b7aad1..4d026c1 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
@@ -70,7 +70,7 @@
                 {"bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0},
                 {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0},
                 {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0},
-                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", 0},
+                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", 0},
                 {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", 0}});
     }
 
@@ -88,7 +88,7 @@
     }
 
     @Test
-    public void sampleExtractTest() throws IOException {
+    public void testExtractor() throws IOException {
         File inputFile = new File(mInputFilePath + mInputFileName);
         assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
                 inputFile.exists());
@@ -107,7 +107,7 @@
     }
 
     @Test
-    public void sampleExtractNativeTest() throws IOException {
+    public void testNativeExtractor() throws IOException {
         Native nativeExtractor = new Native();
         File inputFile = new File(mInputFilePath + mInputFileName);
         assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
index 2efdba2..21ba957 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
@@ -86,7 +86,7 @@
                 {"crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"},
                 {"crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"},
                 {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"},
-                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", "webm"},
+                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", "webm"},
                 {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"},
                 {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"},
                 {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"},
@@ -110,7 +110,7 @@
     }
 
     @Test
-    public void sampleMuxerTest() throws IOException {
+    public void testMuxer() throws IOException {
         File inputFile = new File(mInputFilePath + mInputFileName);
         assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
                 inputFile.exists());
@@ -159,7 +159,7 @@
     }
 
     @Test
-    public void sampleMuxerNativeTest() {
+    public void testNativeMuxer() {
         Native nativeMuxer = new Native();
         File inputFile = new File(mInputFilePath + mInputFileName);
         assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
index 271b852..1277c8b 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
@@ -18,9 +18,9 @@
 #define LOG_TAG "NativeEncoder"
 
 #include <jni.h>
+#include <sys/stat.h>
 #include <fstream>
 #include <iostream>
-#include <sys/stat.h>
 
 #include <android/log.h>
 
@@ -29,6 +29,11 @@
 
 #include <stdio.h>
 
+constexpr int32_t ENCODE_DEFAULT_FRAME_RATE = 25;
+constexpr int32_t ENCODE_DEFAULT_AUDIO_BIT_RATE = 128000 /* 128 Kbps */;
+constexpr int32_t ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+constexpr int32_t ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+
 extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Encode(
         JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jOutFilePath,
         jstring jStatsFile, jstring jCodecName) {
@@ -72,7 +77,7 @@
             ALOGE("Track Format invalid");
             return -1;
         }
-        uint8_t *inputBuffer = (uint8_t *) malloc(fileSize);
+        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
         if (!inputBuffer) {
             ALOGE("Insufficient memory");
             return -1;
@@ -110,6 +115,8 @@
             free(inputBuffer);
             return -1;
         }
+
+        AMediaFormat *decoderFormat = decoder->getFormat();
         AMediaFormat *format = extractor->getFormat();
         if (inputBuffer) {
             free(inputBuffer);
@@ -146,29 +153,34 @@
                 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &encParams.frameRate);
                 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &encParams.bitrate);
                 if (encParams.bitrate <= 0 || encParams.frameRate <= 0) {
-                    encParams.frameRate = 25;
+                    encParams.frameRate = ENCODE_DEFAULT_FRAME_RATE;
                     if (!strcmp(mime, "video/3gpp") || !strcmp(mime, "video/mp4v-es")) {
-                        encParams.bitrate = 600000 /* 600 Kbps */;
+                        encParams.bitrate = ENCODE_MIN_BIT_RATE /* 600 Kbps */;
                     } else {
-                        encParams.bitrate = 8000000 /* 8 Mbps */;
+                        encParams.bitrate = ENCODE_DEFAULT_BIT_RATE /* 8 Mbps */;
                     }
                 }
                 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_PROFILE, &encParams.profile);
                 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_LEVEL, &encParams.level);
+                AMediaFormat_getInt32(decoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT,
+                                      &encParams.colorFormat);
             } else {
                 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &encParams.sampleRate);
                 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
                                       &encParams.numChannels);
-                encParams.bitrate =
-                        encParams.sampleRate * encParams.numChannels * 16 /* bitsPerSample */;
+                encParams.bitrate = ENCODE_DEFAULT_AUDIO_BIT_RATE;
             }
             Encoder *encoder = new Encoder();
             encoder->setupEncoder();
             status = encoder->encode(sCodecName, eleStream, eleSize, asyncMode[i], encParams,
-                                     (char *) mime);
+                                     (char *)mime);
+            if (status != AMEDIA_OK) {
+                ALOGE("Encoder returned error");
+                return -1;
+            }
+            ALOGV("Encoding complete with codec %s for asyncMode = %d", sCodecName.c_str(),
+                  asyncMode[i]);
             encoder->deInitCodec();
-            cout << "codec : " << codecName << endl;
-            ALOGV(" asyncMode = %d \n", asyncMode[i]);
             const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
             encoder->dumpStatistics(sInputReference, extractor->getClipDuration(), sCodecName,
                                     (asyncMode[i] ? "async" : "sync"), statsFile);
@@ -189,6 +201,10 @@
             AMediaFormat_delete(format);
             format = nullptr;
         }
+        if (decoderFormat) {
+            AMediaFormat_delete(decoderFormat);
+            decoderFormat = nullptr;
+        }
         decoder->deInitCodec();
         decoder->resetDecoder();
     }
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
index 3b1eed4..66fee33 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -134,7 +134,6 @@
                     mStats.addOutputTime();
                     onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
                     if (mSawOutputEOS) {
-                        Log.i(TAG, "Saw output EOS");
                         synchronized (mLock) { mLock.notify(); }
                     }
                 }
@@ -211,9 +210,6 @@
                     }
                     onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
                 }
-                if (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
-                    Log.i(TAG, "Saw output EOS");
-                }
             }
         }
         mInputBuffer.clear();
@@ -256,14 +252,21 @@
      */
     public void resetDecoder() { mStats.reset(); }
 
+    /**
+     * Returns the format of the output buffers
+     */
+    public MediaFormat getFormat() {
+        return mCodec.getOutputFormat();
+    }
+
     private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
         if ((inputBufferId >= 0) && !mSawInputEOS) {
             ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
             BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
             inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
             mIndex++;
-            if (bufInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
-                mSawInputEOS = true;
+            mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+            if (mSawInputEOS) {
                 Log.i(TAG, "Saw input EOS");
             }
             mStats.addFrameSize(bufInfo.size);
@@ -301,6 +304,9 @@
             }
         }
         mediaCodec.releaseOutputBuffer(outputBufferId, false);
-        mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+        mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+        if (mSawOutputEOS) {
+            Log.i(TAG, "Saw output EOS");
+        }
     }
 }
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
index 40cf8bd..8df462e 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -260,12 +260,12 @@
         }
         mStats.addFrameSize(outputBuffer.remaining());
         mediaCodec.releaseOutputBuffer(outputBufferId, false);
-        mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+        mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
     }
 
     private void onInputAvailable(MediaCodec mediaCodec, int inputBufferId) throws IOException {
-        if (mSawOutputEOS || inputBufferId < 0) {
-            if (mSawOutputEOS) {
+        if (mSawInputEOS || inputBufferId < 0) {
+            if (mSawInputEOS) {
                 Log.i(TAG, "Saw input EOS");
             }
             return;
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
index 2171589..090f3e1 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -63,8 +63,8 @@
         ssize_t bytesRead = 0;
         uint32_t flag = 0;
         int64_t presentationTimeUs = 0;
-        tie(bytesRead, flag, presentationTimeUs) = readSampleData(
-                mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
+        tie(bytesRead, flag, presentationTimeUs) =
+                readSampleData(mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
         if (flag == AMEDIA_ERROR_MALFORMED) {
             mErrorCode = (media_status_t)flag;
             mSignalledError = true;
@@ -144,6 +144,11 @@
     if (!mFormat) mFormat = mExtractor->getFormat();
 }
 
+AMediaFormat *Decoder::getFormat() {
+    ALOGV("In %s", __func__);
+    return AMediaCodec_getOutputFormat(mCodec);
+}
+
 int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
                         string &codecName, bool asyncMode, FILE *outFp) {
     ALOGV("In %s", __func__);
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
index f3fa6a1..e619cb4 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.h
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -57,6 +57,8 @@
 
     void resetDecoder();
 
+    AMediaFormat *getFormat();
+
     // Async callback APIs
     void onInputAvailable(AMediaCodec *codec, int32_t index) override;
 
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
index 2db612c..8dfe993 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -181,8 +181,8 @@
     mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
 }
 
-int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize,
-                        bool asyncMode, encParameter encParams, char *mime) {
+int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize, bool asyncMode,
+                        encParameter encParams, char *mime) {
     ALOGV("In %s", __func__);
     mEleStream = &eleStream;
     mInputBufferSize = eleSize;
@@ -202,6 +202,7 @@
             AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_PROFILE, mParams.profile);
             AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_LEVEL, mParams.level);
         }
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, mParams.colorFormat);
     } else {
         AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_SAMPLE_RATE, mParams.sampleRate);
         AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mParams.numChannels);
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
index 3d12600..5ad142b 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.h
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -23,9 +23,11 @@
 #include <queue>
 #include <thread>
 
+#include "media/NdkImage.h"
 #include "BenchmarkCommon.h"
 #include "Stats.h"
 
+
 struct encParameter {
     int32_t bitrate = -1;
     int32_t numFrames = -1;
@@ -38,6 +40,7 @@
     int32_t frameRate = -1;
     int32_t profile = 0;
     int32_t level = 0;
+    int32_t colorFormat = AIMAGE_FORMAT_YUV_420_888;
 };
 
 class Encoder : public CallBackHandle {
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
index ecd9759..dedc743 100644
--- a/media/tests/benchmark/tests/C2DecoderTest.cpp
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -157,7 +157,7 @@
                           make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "mp3"),
                           make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
                           make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrnb"),
-                          make_pair("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "vorbis"),
+                          make_pair("bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", "vorbis"),
                           make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
                           make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
 
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 5c6aa5b..9f96d3b 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -101,7 +101,7 @@
                           make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", false),
                           make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
                           make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
-                          make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", false),
+                          make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", "", false),
                           make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", false),
                           make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
 
@@ -111,7 +111,7 @@
                           make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", true),
                           make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
                           make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
-                          make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", true),
+                          make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", "", true),
                           make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", true),
                           make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
 
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
index c2d72ff..ad8f1e6 100644
--- a/media/tests/benchmark/tests/ExtractorTest.cpp
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -69,7 +69,7 @@
                                            make_pair("bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0),
                                            make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0),
                                            make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0),
-                                           make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", 0),
+                                           make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", 0),
                                            make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm",
                                                      0)));
 
diff --git a/media/tests/benchmark/tests/MuxerTest.cpp b/media/tests/benchmark/tests/MuxerTest.cpp
index 7b01732..fa2635d 100644
--- a/media/tests/benchmark/tests/MuxerTest.cpp
+++ b/media/tests/benchmark/tests/MuxerTest.cpp
@@ -136,7 +136,7 @@
                           make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"),
                           make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"),
                           make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"),
-                          make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", "webm"),
+                          make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", "webm"),
                           make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"),
                           make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"),
                           make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"),
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 525e965..46b950c 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -141,15 +141,6 @@
         result = {std::make_unique<engineConfig::Config>(config),
                   static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
     }
-    // Append for internal use only strategies/volume groups (e.g. rerouting/patch)
-    result.parsedConfig->productStrategies.insert(
-                std::end(result.parsedConfig->productStrategies),
-                std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
-
-    result.parsedConfig->volumeGroups.insert(
-                std::end(result.parsedConfig->volumeGroups),
-                std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
-
     ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
 
     engineConfig::VolumeGroup defaultVolumeConfig;
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 3366814..fbce801 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -125,22 +125,15 @@
             AUDIO_FLAG_BEACON, ""}}
          }
      },
-    }
-};
-
-/**
- * For Internal use of respectively audio policy and audioflinger
- * For compatibility reason why apm volume config file, volume group name is the stream type.
- */
-const engineConfig::ProductStrategies gOrderedSystemStrategies = {
-    {"rerouting",
+    },
+    {"STRATEGY_REROUTING",
      {
          {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
      },
     },
-    {"patch",
+    {"STRATEGY_PATCH",
      {
          {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
@@ -148,28 +141,6 @@
      },
     }
 };
-const engineConfig::VolumeGroups gSystemVolumeGroups = {
-    {"AUDIO_STREAM_REROUTING", 0, 1,
-     {
-         {"DEVICE_CATEGORY_SPEAKER", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_HEADSET", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_EARPIECE", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_EXT_MEDIA", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_HEARING_AID", {{0,0}, {100, 0}}},
-
-     }
-    },
-    {"AUDIO_STREAM_PATCH", 0, 1,
-     {
-         {"DEVICE_CATEGORY_SPEAKER", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_HEADSET", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_EARPIECE", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_EXT_MEDIA", {{0,0}, {100, 0}}},
-         {"DEVICE_CATEGORY_HEARING_AID", {{0,0}, {100, 0}}},
-
-     }
-    }
-};
 
 const engineConfig::Config gDefaultEngineConfig = {
     1.0,
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
index f598cf2..337de71 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
@@ -147,6 +147,10 @@
     <ProductStrategy name="notification">
         <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_EVENT"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="system">
@@ -163,5 +167,19 @@
         </AttributesGroup>
     </ProductStrategy>
 
+    <!-- Routing Strategy rerouting may be removed as following media??? -->
+    <ProductStrategy name="rerouting">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
+    <ProductStrategy name="patch">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
index 97a25a8..97e6144 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -189,5 +189,57 @@
         </volume>
     </volumeGroup>
 
+    <volumeGroup>
+        <name>rerouting</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>patch</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
 </volumeGroups>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
index f598cf2..3634313 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
@@ -147,6 +147,10 @@
     <ProductStrategy name="notification">
         <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_EVENT"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="system">
@@ -163,5 +167,18 @@
         </AttributesGroup>
     </ProductStrategy>
 
+    <!-- Routing Strategy rerouting may be removed as following media??? -->
+    <ProductStrategy name="rerouting">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
+    <ProductStrategy name="patch">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
index 97a25a8..97e6144 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
@@ -189,5 +189,57 @@
         </volume>
     </volumeGroup>
 
+    <volumeGroup>
+        <name>rerouting</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>patch</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID">
+            <point>0,0</point>
+            <point>100,0</point>
+        </volume>
+    </volumeGroup>
+
 </volumeGroups>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
index a7388da..b1c0dcf 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -97,5 +97,20 @@
         </AttributesGroup>
     </ProductStrategy>
 
+    <!-- Routing Strategy rerouting may be removed as following media??? -->
+    <ProductStrategy name="STRATEGY_REROUTING">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Default product strategy has empty attributes -->
+    <ProductStrategy name="STRATEGY_PATCH">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
index 8aa71ca..0f9614e 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -215,6 +215,26 @@
         <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
         <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID"  ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
     </volumeGroup>
+    <volumeGroup>
+        <name>rerouting</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
+    </volumeGroup>
 
+    <volumeGroup>
+        <name>patch</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
+    </volumeGroup>
 </volumeGroups>
 
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
index a7388da..b1c0dcf 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -97,5 +97,20 @@
         </AttributesGroup>
     </ProductStrategy>
 
+    <!-- Routing Strategy rerouting may be removed as following media??? -->
+    <ProductStrategy name="STRATEGY_REROUTING">
+        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Default product strategy has empty attributes -->
+    <ProductStrategy name="STRATEGY_PATCH">
+        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+            <Attributes></Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+
 </ProductStrategies>
 
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
index d5c3896..a259950 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -217,5 +217,26 @@
         <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID"  ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
     </volumeGroup>
 
+    <volumeGroup>
+        <name>rerouting</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>patch</name>
+        <indexMin>0</indexMin>
+        <indexMax>1</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
+    </volumeGroup>
 </volumeGroups>
 
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 98fee12..501d922 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -116,6 +116,7 @@
         "libyuv",
         "android.frameworks.cameraservice.common@2.0",
         "android.frameworks.cameraservice.service@2.0",
+        "android.frameworks.cameraservice.service@2.1",
         "android.frameworks.cameraservice.device@2.0",
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.provider@2.4",
@@ -129,6 +130,10 @@
         "android.hardware.camera.device@3.6"
     ],
 
+    static_libs: [
+        "libbinderthreadstateutils",
+    ],
+
     export_shared_lib_headers: [
         "libbinder",
         "libcamera_client",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 5358307..453984e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -43,6 +43,7 @@
 #include <binder/PermissionController.h>
 #include <binder/ProcessInfoService.h>
 #include <binder/IResultReceiver.h>
+#include <binderthreadstate/CallerUtils.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
 #include <cutils/misc.h>
@@ -456,10 +457,14 @@
     }
 
     if (updated) {
-        logDeviceRemoved(id, String8::format("Device %s-%s availability changed from %d to %d",
-                id.string(), physicalId.string(),
-                newStatus != StatusInternal::PRESENT,
-                newStatus == StatusInternal::PRESENT));
+        String8 idCombo = id + " : " + physicalId;
+        if (newStatus == StatusInternal::PRESENT) {
+            logDeviceAdded(idCombo,
+                    String8::format("Device status changed to %d", newStatus));
+        } else {
+            logDeviceRemoved(idCombo,
+                    String8::format("Device status changed to %d", newStatus));
+        }
 
         String16 id16(id), physicalId16(physicalId);
         Mutex::Autolock lock(mStatusListenerLock);
@@ -1179,7 +1184,7 @@
 
     // Only allow clients who are being used by the current foreground device user, unless calling
     // from our own process OR the caller is using the cameraserver's HIDL interface.
-    if (!hardware::IPCThreadState::self()->isServingCall() && callingPid != getpid() &&
+    if (getCurrentServingCall() != BinderCallType::HWBINDER && callingPid != getpid() &&
             (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
         ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
                 "device user %d, currently allowed device users: %s)", callingPid, clientUserId,
@@ -1534,7 +1539,7 @@
         return false;
     }
     // (2)
-    if (!hardware::IPCThreadState::self()->isServingCall() &&
+    if (getCurrentServingCall() != BinderCallType::HWBINDER &&
             systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA) {
         ALOGW("Rejecting access to secure hidden camera %s", cameraId.c_str());
         return true;
@@ -1543,7 +1548,7 @@
     //     getCameraCharacteristics() allows for calls to succeed (albeit after hiding some
     //     characteristics) even if clients don't have android.permission.CAMERA. We do not want the
     //     same behavior for system camera devices.
-    if (!hardware::IPCThreadState::self()->isServingCall() &&
+    if (getCurrentServingCall() != BinderCallType::HWBINDER &&
             systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
             !hasPermissionsForSystemCamera(cPid, cUid)) {
         ALOGW("Rejecting access to system only camera %s, inadequete permissions",
@@ -1569,7 +1574,7 @@
     sp<CameraDeviceClient> client = nullptr;
     String16 clientPackageNameAdj = clientPackageName;
 
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         std::string vendorClient =
                 StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
         clientPackageNameAdj = String16(vendorClient.c_str());
@@ -2778,7 +2783,7 @@
         }
         mClientPackageName = packages[0];
     }
-    if (!hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() != BinderCallType::HWBINDER) {
         mAppOpsManager = std::make_unique<AppOpsManager>();
     }
 }
@@ -3450,7 +3455,7 @@
         const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
         int32_t state) {
 
-    bool isVendorClient = hardware::IPCThreadState::self()->isServingCall();
+    bool isVendorClient = getCurrentServingCall() == BinderCallType::HWBINDER;
     int32_t score_adj = isVendorClient ? kVendorClientScore : score;
     int32_t state_adj = isVendorClient ? kVendorClientState: state;
 
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
index 110ef8e..8e619e1 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
@@ -25,6 +25,7 @@
 namespace implementation {
 
 using hardware::cameraservice::utils::conversion::convertToHidlCameraDeviceStatus;
+typedef frameworks::cameraservice::service::V2_1::ICameraServiceListener HCameraServiceListener2_1;
 
 binder::Status H2BCameraServiceListener::onStatusChanged(
     int32_t status, const ::android::String16& cameraId) {
@@ -40,6 +41,29 @@
   return binder::Status::ok();
 }
 
+binder::Status H2BCameraServiceListener::onPhysicalCameraStatusChanged(
+    int32_t status, const ::android::String16& cameraId,
+    const ::android::String16& physicalCameraId) {
+  auto cast2_1 = HCameraServiceListener2_1::castFrom(mBase);
+  sp<HCameraServiceListener2_1> interface2_1 = nullptr;
+  if (cast2_1.isOk()) {
+    interface2_1 = cast2_1;
+    if (interface2_1 != nullptr) {
+      HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status);
+      V2_1::PhysicalCameraStatusAndId cameraStatusAndId;
+      cameraStatusAndId.deviceStatus = hCameraDeviceStatus;
+      cameraStatusAndId.cameraId = String8(cameraId).string();
+      cameraStatusAndId.physicalCameraId = String8(physicalCameraId).string();
+      auto ret = interface2_1->onPhysicalCameraStatusChanged(cameraStatusAndId);
+      if (!ret.isOk()) {
+        ALOGE("%s OnPhysicalCameraStatusChanged callback failed due to %s",__FUNCTION__,
+            ret.description().c_str());
+      }
+    }
+  }
+  return binder::Status::ok();
+}
+
 ::android::binder::Status H2BCameraServiceListener::onTorchStatusChanged(
     int32_t, const ::android::String16&) {
   // We don't implement onTorchStatusChanged
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 175eb8e..95493a1 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -19,6 +19,7 @@
 
 #include <android/frameworks/cameraservice/common/2.0/types.h>
 #include <android/frameworks/cameraservice/service/2.0/ICameraServiceListener.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
 #include <android/frameworks/cameraservice/device/2.0/types.h>
 #include <android/hardware/BnCameraServiceListener.h>
 #include <android/hardware/BpCameraServiceListener.h>
@@ -47,17 +48,14 @@
 
     virtual ::android::binder::Status onStatusChanged(int32_t status,
             const ::android::String16& cameraId) override;
-    virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
-            const ::android::String16& /*cameraId*/,
-            const ::android::String16& /*physicalCameraId*/) override {
-        // no implementation yet.
-        return binder::Status::ok();
-    }
+    virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
+            const ::android::String16& cameraId,
+            const ::android::String16& physicalCameraId) override;
 
     virtual ::android::binder::Status onTorchStatusChanged(
             int32_t status, const ::android::String16& cameraId) override;
     virtual binder::Status onCameraAccessPrioritiesChanged() {
-        // TODO: no implementation yet. b/148146086
+        // TODO: no implementation yet.
         return binder::Status::ok();
     }
 };
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index 866c3b5..597147b 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -197,6 +197,23 @@
     return;
 }
 
+void convertToHidl(const std::vector<hardware::CameraStatus> &src,
+                   hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId>* dst) {
+    dst->resize(src.size());
+    size_t i = 0;
+    for (const auto &statusAndId : src) {
+        auto &a = (*dst)[i++];
+        a.v2_0.cameraId = statusAndId.cameraId.c_str();
+        a.v2_0.deviceStatus = convertToHidlCameraDeviceStatus(statusAndId.status);
+        size_t numUnvailPhysicalCameras = statusAndId.unavailablePhysicalIds.size();
+        a.unavailPhysicalCameraIds.resize(numUnvailPhysicalCameras);
+        for (size_t j = 0; j < numUnvailPhysicalCameras; j++) {
+            a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j].c_str();
+        }
+    }
+    return;
+}
+
 void convertToHidl(
     const hardware::camera2::utils::SubmitInfo &submitInfo,
     frameworks::cameraservice::device::V2_0::SubmitInfo *hSubmitInfo) {
diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h
index 79683f6..82ffc48 100644
--- a/services/camera/libcameraservice/hidl/Convert.h
+++ b/services/camera/libcameraservice/hidl/Convert.h
@@ -23,6 +23,7 @@
 #include <android/frameworks/cameraservice/device/2.0/ICameraDeviceUser.h>
 #include <android/frameworks/cameraservice/common/2.0/types.h>
 #include <android/frameworks/cameraservice/service/2.0/types.h>
+#include <android/frameworks/cameraservice/service/2.1/types.h>
 #include <android/frameworks/cameraservice/device/2.0/types.h>
 #include <android/hardware/camera/common/1.0/types.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
@@ -79,6 +80,9 @@
 void convertToHidl(const std::vector<hardware::CameraStatus> &src,
                    hidl_vec<HCameraStatusAndId>* dst);
 
+void convertToHidl(const std::vector<hardware::CameraStatus> &src,
+                   hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId>* dst);
+
 void convertToHidl(const hardware::camera2::utils::SubmitInfo &submitInfo,
                    HSubmitInfo *hSubmitInfo);
 
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 97ba9c4..a46133e 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -154,15 +154,50 @@
 
 Return<void> HidlCameraService::addListener(const sp<HCameraServiceListener>& hCsListener,
                                             addListener_cb _hidl_cb) {
-    if (mAidlICameraService == nullptr) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, {});
+    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
+    HStatus status = addListenerInternal<HCameraServiceListener>(
+            hCsListener, &cameraStatusAndIds);
+    if (status != HStatus::NO_ERROR) {
+        _hidl_cb(status, {});
         return Void();
     }
-    if (hCsListener == nullptr) {
-        ALOGE("%s listener must not be NULL", __FUNCTION__);
-        _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {});
+
+    hidl_vec<HCameraStatusAndId> hCameraStatusAndIds;
+    //Convert cameraStatusAndIds to HIDL and call callback
+    convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
+    _hidl_cb(status, hCameraStatusAndIds);
+
+    return Void();
+}
+
+Return<void> HidlCameraService::addListener_2_1(const sp<HCameraServiceListener2_1>& hCsListener,
+                                                addListener_2_1_cb _hidl_cb) {
+    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
+    HStatus status = addListenerInternal<HCameraServiceListener2_1>(
+            hCsListener, &cameraStatusAndIds);
+    if (status != HStatus::NO_ERROR) {
+        _hidl_cb(status, {});
         return Void();
     }
+
+    hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> hCameraStatusAndIds;
+    //Convert cameraStatusAndIds to HIDL and call callback
+    convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
+    _hidl_cb(status, hCameraStatusAndIds);
+
+    return Void();
+}
+
+template<class T>
+HStatus HidlCameraService::addListenerInternal(const sp<T>& hCsListener,
+        std::vector<hardware::CameraStatus>* cameraStatusAndIds) {
+    if (mAidlICameraService == nullptr) {
+        return HStatus::UNKNOWN_ERROR;
+    }
+    if (hCsListener == nullptr || cameraStatusAndIds == nullptr) {
+        ALOGE("%s listener and cameraStatusAndIds must not be NULL", __FUNCTION__);
+        return HStatus::ILLEGAL_ARGUMENT;
+    }
     sp<hardware::ICameraServiceListener> csListener = nullptr;
     // Check the cache for previously registered callbacks
     {
@@ -177,33 +212,27 @@
         } else {
             ALOGE("%s: Trying to add a listener %p already registered",
                   __FUNCTION__, hCsListener.get());
-            _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {});
-            return Void();
+            return HStatus::ILLEGAL_ARGUMENT;
         }
     }
-    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
     binder::Status serviceRet =
-        mAidlICameraService->addListenerHelper(csListener, &cameraStatusAndIds, true);
+            mAidlICameraService->addListenerHelper(csListener, cameraStatusAndIds, true);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
-      ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);
-      status = B2HStatus(serviceRet);
-      _hidl_cb(status, {});
-      return Void();
+        ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);
+        status = B2HStatus(serviceRet);
+        return status;
     }
-    cameraStatusAndIds.erase(std::remove_if(cameraStatusAndIds.begin(), cameraStatusAndIds.end(),
+    cameraStatusAndIds->erase(std::remove_if(cameraStatusAndIds->begin(), cameraStatusAndIds->end(),
             [this](const hardware::CameraStatus& s) {
-              bool supportsHAL3 = false;
-              binder::Status sRet =
+                bool supportsHAL3 = false;
+                binder::Status sRet =
                             mAidlICameraService->supportsCameraApi(String16(s.cameraId),
                                     hardware::ICameraService::API_VERSION_2, &supportsHAL3);
-              return !sRet.isOk() || !supportsHAL3;
-            }), cameraStatusAndIds.end());
-    hidl_vec<HCameraStatusAndId> hCameraStatusAndIds;
-    //Convert cameraStatusAndIds to HIDL and call callback
-    convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
-    _hidl_cb(status, hCameraStatusAndIds);
-    return Void();
+                return !sRet.isOk() || !supportsHAL3;
+            }), cameraStatusAndIds->end());
+
+    return HStatus::NO_ERROR;
 }
 
 Return<HStatus> HidlCameraService::removeListener(const sp<HCameraServiceListener>& hCsListener) {
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.h b/services/camera/libcameraservice/hidl/HidlCameraService.h
index eead0bc..097f4c5 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.h
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.h
@@ -21,7 +21,7 @@
 #include <thread>
 
 #include <android/frameworks/cameraservice/common/2.0/types.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
 #include <android/frameworks/cameraservice/service/2.0/types.h>
 #include <android/frameworks/cameraservice/device/2.0/types.h>
 
@@ -42,8 +42,9 @@
 
 using HCameraDeviceCallback = frameworks::cameraservice::device::V2_0::ICameraDeviceCallback;
 using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata;
-using HCameraService = frameworks::cameraservice::service::V2_0::ICameraService;
+using HCameraService = frameworks::cameraservice::service::V2_1::ICameraService;
 using HCameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener;
+using HCameraServiceListener2_1 = frameworks::cameraservice::service::V2_1::ICameraServiceListener;
 using HStatus = frameworks::cameraservice::common::V2_0::Status;
 using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
 
@@ -66,6 +67,9 @@
 
     Return<void> getCameraVendorTagSections(getCameraVendorTagSections_cb _hidl_cb) override;
 
+    Return<void> addListener_2_1(const sp<HCameraServiceListener2_1>& listener,
+                                 addListener_2_1_cb _hidl_cb) override;
+
     // This method should only be called by the cameraservers main thread to
     // instantiate the hidl cameraserver.
     static sp<HidlCameraService> getInstance(android::CameraService *cs);
@@ -76,6 +80,11 @@
     sp<hardware::ICameraServiceListener> searchListenerCacheLocked(
         sp<HCameraServiceListener> listener, /*removeIfFound*/ bool shouldRemove = false);
 
+
+    template<class T>
+    HStatus addListenerInternal(const sp<T>& listener,
+                                std::vector<hardware::CameraStatus>* cameraStatusAndIds);
+
     void addToListenerCacheLocked(sp<HCameraServiceListener> hListener,
                                   sp<hardware::ICameraServiceListener> csListener);
 
diff --git a/services/camera/libcameraservice/utils/CameraThreadState.cpp b/services/camera/libcameraservice/utils/CameraThreadState.cpp
index b9e344b..2352b80 100644
--- a/services/camera/libcameraservice/utils/CameraThreadState.cpp
+++ b/services/camera/libcameraservice/utils/CameraThreadState.cpp
@@ -17,33 +17,34 @@
 #include "CameraThreadState.h"
 #include <binder/IPCThreadState.h>
 #include <hwbinder/IPCThreadState.h>
+#include <binderthreadstate/CallerUtils.h>
 #include <unistd.h>
 
 namespace android {
 
 int CameraThreadState::getCallingUid() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->getCallingUid();
     }
     return IPCThreadState::self()->getCallingUid();
 }
 
 int CameraThreadState::getCallingPid() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->getCallingPid();
     }
     return IPCThreadState::self()->getCallingPid();
 }
 
 int64_t CameraThreadState::clearCallingIdentity() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->clearCallingIdentity();
     }
     return IPCThreadState::self()->clearCallingIdentity();
 }
 
 void CameraThreadState::restoreCallingIdentity(int64_t token) {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         hardware::IPCThreadState::self()->restoreCallingIdentity(token);
     } else {
         IPCThreadState::self()->restoreCallingIdentity(token);
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index ec6f01c..35d25bf 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -35,7 +35,7 @@
 public:
     /**
      * Choosing to set mIsVendorClient through a parameter instead of calling
-     * hardware::IPCThreadState::self()->isServingCall() to protect against the
+     * getCurrentServingCall() == BinderCallType::HWBINDER to protect against the
      * case where the construction is offloaded to another thread which isn't a
      * hwbinder thread.
      */
@@ -237,7 +237,7 @@
     // We don't use the usual copy constructor here since we want to remember
     // whether a client is a vendor client or not. This could have been wiped
     // off in the incoming priority argument since an AIDL thread might have
-    // called hardware::IPCThreadState::self()->isServingCall() after refreshing
+    // called getCurrentServingCall() == BinderCallType::HWBINDER after refreshing
     // priorities for old clients through ProcessInfoService::getProcessStatesScoresFromPids().
     mPriority.setScore(priority.getScore());
     mPriority.setState(priority.getState());
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index ad03e68..f825373 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -13,7 +13,10 @@
         "libcodec2-hidl-defaults",
     ],
     shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
         "libbase",
+        "libcodec2_hidl@1.1",
     ],
 
     // Codecs
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 58db801e..450af79 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -18,21 +18,412 @@
 #define LOG_TAG "CodecServiceRegistrant"
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 
+#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 <hidl/HidlSupport.h>
 #include <media/CodecServiceRegistrant.h>
 
+namespace /* unnamed */ {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+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;
+
+constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
+
+// Converter from IComponentStore to C2ComponentStore.
+class H2C2ComponentStore : public C2ComponentStore {
+protected:
+    sp<IComponentStore> mStore;
+    sp<IConfigurable> mConfigurable;
+public:
+    explicit H2C2ComponentStore(sp<IComponentStore> const& store)
+          : mStore{store},
+            mConfigurable{[store]() -> sp<IConfigurable>{
+                if (!store) {
+                    return nullptr;
+                }
+                Return<sp<IConfigurable>> transResult =
+                    store->getConfigurable();
+                return transResult.isOk() ?
+                        static_cast<sp<IConfigurable>>(transResult) :
+                        nullptr;
+            }()} {
+        if (!mConfigurable) {
+            LOG(ERROR) << "Preferred store is corrupted.";
+        }
+    }
+
+    virtual ~H2C2ComponentStore() override = default;
+
+    virtual c2_status_t config_sm(
+            std::vector<C2Param*> const &params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        Params hidlParams;
+        if (!createParamsBlob(&hidlParams, params)) {
+            LOG(ERROR) << "config -- bad input.";
+            return C2_TRANSACTION_FAILED;
+        }
+        c2_status_t status{};
+        Return<void> transResult = mConfigurable->config(
+                hidlParams,
+                true,
+                [&status, &params, failures](
+                        Status s,
+                        const hidl_vec<SettingResult> f,
+                        const Params& o) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK && status != C2_BAD_INDEX) {
+                        LOG(DEBUG) << "config -- call failed: "
+                                   << status << ".";
+                    }
+                    size_t i = failures->size();
+                    failures->resize(i + f.size());
+                    for (const SettingResult& sf : f) {
+                        if (!objcpy(&(*failures)[i++], sf)) {
+                            LOG(ERROR) << "config -- "
+                                       << "invalid SettingResult returned.";
+                            return;
+                        }
+                    }
+                    if (!updateParamsFromBlob(params, o)) {
+                        LOG(ERROR) << "config -- "
+                                   << "failed to parse returned params.";
+                        status = C2_CORRUPTED;
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "config -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    };
+
+    virtual c2_status_t copyBuffer(
+            std::shared_ptr<C2GraphicBuffer>,
+            std::shared_ptr<C2GraphicBuffer>) override {
+        LOG(ERROR) << "copyBuffer -- not supported.";
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createComponent(
+            C2String, std::shared_ptr<C2Component> *const component) override {
+        component->reset();
+        LOG(ERROR) << "createComponent -- not supported.";
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createInterface(
+            C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
+        interface->reset();
+        LOG(ERROR) << "createInterface -- not supported.";
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t query_sm(
+            const std::vector<C2Param *> &stackParams,
+            const std::vector<C2Param::Index> &heapParamIndices,
+            std::vector<std::unique_ptr<C2Param>> *const heapParams) const
+            override {
+        hidl_vec<ParamIndex> indices(
+                stackParams.size() + heapParamIndices.size());
+        size_t numIndices = 0;
+        for (C2Param* const& stackParam : stackParams) {
+            if (!stackParam) {
+                LOG(WARNING) << "query -- null stack param encountered.";
+                continue;
+            }
+            indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
+        }
+        size_t numStackIndices = numIndices;
+        for (const C2Param::Index& index : heapParamIndices) {
+            indices[numIndices++] =
+                    static_cast<ParamIndex>(static_cast<uint32_t>(index));
+        }
+        indices.resize(numIndices);
+        if (heapParams) {
+            heapParams->reserve(heapParams->size() + numIndices);
+        }
+        c2_status_t status;
+        Return<void> transResult = mConfigurable->query(
+                indices,
+                true,
+                [&status, &numStackIndices, &stackParams, heapParams](
+                        Status s, const Params& p) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK && status != C2_BAD_INDEX) {
+                        LOG(DEBUG) << "query -- call failed: "
+                                   << status << ".";
+                        return;
+                    }
+                    std::vector<C2Param*> paramPointers;
+                    if (!parseParamsBlob(&paramPointers, p)) {
+                        LOG(ERROR) << "query -- error while parsing params.";
+                        status = C2_CORRUPTED;
+                        return;
+                    }
+                    size_t i = 0;
+                    for (auto it = paramPointers.begin();
+                            it != paramPointers.end(); ) {
+                        C2Param* paramPointer = *it;
+                        if (numStackIndices > 0) {
+                            --numStackIndices;
+                            if (!paramPointer) {
+                                LOG(WARNING) << "query -- null stack param.";
+                                ++it;
+                                continue;
+                            }
+                            for (; i < stackParams.size() && !stackParams[i]; ) {
+                                ++i;
+                            }
+                            if (i >= stackParams.size()) {
+                                LOG(ERROR) << "query -- unexpected error.";
+                                status = C2_CORRUPTED;
+                                return;
+                            }
+                            if (stackParams[i]->index() != paramPointer->index()) {
+                                LOG(WARNING) << "query -- param skipped: "
+                                                "index = "
+                                             << stackParams[i]->index() << ".";
+                                stackParams[i++]->invalidate();
+                                continue;
+                            }
+                            if (!stackParams[i++]->updateFrom(*paramPointer)) {
+                                LOG(WARNING) << "query -- param update failed: "
+                                                "index = "
+                                             << paramPointer->index() << ".";
+                            }
+                        } else {
+                            if (!paramPointer) {
+                                LOG(WARNING) << "query -- null heap param.";
+                                ++it;
+                                continue;
+                            }
+                            if (!heapParams) {
+                                LOG(WARNING) << "query -- "
+                                                "unexpected extra stack param.";
+                            } else {
+                                heapParams->emplace_back(
+                                        C2Param::Copy(*paramPointer));
+                            }
+                        }
+                        ++it;
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "query -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    }
+
+    virtual c2_status_t querySupportedParams_nb(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+        c2_status_t status;
+        Return<void> transResult = mConfigurable->querySupportedParams(
+                std::numeric_limits<uint32_t>::min(),
+                std::numeric_limits<uint32_t>::max(),
+                [&status, params](
+                        Status s,
+                        const hidl_vec<ParamDescriptor>& p) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "querySupportedParams -- call failed: "
+                                   << status << ".";
+                        return;
+                    }
+                    size_t i = params->size();
+                    params->resize(i + p.size());
+                    for (const ParamDescriptor& sp : p) {
+                        if (!objcpy(&(*params)[i++], sp)) {
+                            LOG(ERROR) << "querySupportedParams -- "
+                                       << "invalid returned ParamDescriptor.";
+                            return;
+                        }
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "querySupportedParams -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    }
+
+    virtual c2_status_t querySupportedValues_sm(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const {
+        hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
+        for (size_t i = 0; i < fields.size(); ++i) {
+            if (!objcpy(&inFields[i], fields[i])) {
+                LOG(ERROR) << "querySupportedValues -- bad input";
+                return C2_TRANSACTION_FAILED;
+            }
+        }
+
+        c2_status_t status;
+        Return<void> transResult = mConfigurable->querySupportedValues(
+                inFields,
+                true,
+                [&status, &inFields, &fields](
+                        Status s,
+                        const hidl_vec<FieldSupportedValuesQueryResult>& r) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "querySupportedValues -- call failed: "
+                                   << status << ".";
+                        return;
+                    }
+                    if (r.size() != fields.size()) {
+                        LOG(ERROR) << "querySupportedValues -- "
+                                      "input and output lists "
+                                      "have different sizes.";
+                        status = C2_CORRUPTED;
+                        return;
+                    }
+                    for (size_t i = 0; i < fields.size(); ++i) {
+                        if (!objcpy(&fields[i], inFields[i], r[i])) {
+                            LOG(ERROR) << "querySupportedValues -- "
+                                          "invalid returned value.";
+                            status = C2_CORRUPTED;
+                            return;
+                        }
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "querySupportedValues -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    }
+
+    virtual C2String getName() const {
+        C2String outName;
+        Return<void> transResult = mConfigurable->getName(
+                [&outName](const hidl_string& name) {
+                    outName = name.c_str();
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "getName -- transaction failed.";
+        }
+        return outName;
+    }
+
+    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
+            override {
+        struct SimpleParamReflector : public C2ParamReflector {
+            virtual std::unique_ptr<C2StructDescriptor> describe(
+                    C2Param::CoreIndex coreIndex) const {
+                hidl_vec<ParamIndex> indices(1);
+                indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
+                std::unique_ptr<C2StructDescriptor> descriptor;
+                Return<void> transResult = mBase->getStructDescriptors(
+                        indices,
+                        [&descriptor](
+                                Status s,
+                                const hidl_vec<StructDescriptor>& sd) {
+                            c2_status_t status = static_cast<c2_status_t>(s);
+                            if (status != C2_OK) {
+                                LOG(DEBUG) << "SimpleParamReflector -- "
+                                              "getStructDescriptors() failed: "
+                                           << status << ".";
+                                descriptor.reset();
+                                return;
+                            }
+                            if (sd.size() != 1) {
+                                LOG(DEBUG) << "SimpleParamReflector -- "
+                                              "getStructDescriptors() "
+                                              "returned vector of size "
+                                           << sd.size() << ". "
+                                              "It should be 1.";
+                                descriptor.reset();
+                                return;
+                            }
+                            if (!objcpy(&descriptor, sd[0])) {
+                                LOG(DEBUG) << "SimpleParamReflector -- "
+                                              "getStructDescriptors() returned "
+                                              "corrupted data.";
+                                descriptor.reset();
+                                return;
+                            }
+                        });
+                return descriptor;
+            }
+
+            explicit SimpleParamReflector(sp<IComponentStore> base)
+                : mBase(base) { }
+
+            sp<IComponentStore> mBase;
+        };
+
+        return std::make_shared<SimpleParamReflector>(mStore);
+    }
+
+    virtual std::vector<std::shared_ptr<const C2Component::Traits>>
+            listComponents() override {
+        LOG(ERROR) << "listComponents -- not supported.";
+        return {};
+    }
+};
+
+bool ionPropertiesDefined() {
+    using namespace ::android::base;
+    std::string heapMask =
+        GetProperty("ro.com.android.media.swcodec.ion.heapmask", "undefined");
+    std::string flags =
+        GetProperty("ro.com.android.media.swcodec.ion.flags", "undefined");
+    std::string align =
+        GetProperty("ro.com.android.media.swcodec.ion.align", "undefined");
+    if (heapMask != "undefined" ||
+            flags != "undefined" ||
+            align != "undefined") {
+        LOG(INFO)
+                << "Some system properties for mediaswcodec ION usage are set: "
+                << "heapmask = " << heapMask << ", "
+                << "flags = " << flags << ", "
+                << "align = " << align << ". "
+                << "Preferred Codec2 store is defaulted to \"software\".";
+        return true;
+    }
+    return false;
+}
+
+} // unnamed namespace
+
 extern "C" void RegisterCodecServices() {
-    using namespace ::android::hardware::media::c2::V1_1;
+    using ComponentStore_Latest = ::android::hardware::media::c2::V1_1::
+            utils::ComponentStore;
     LOG(INFO) << "Creating software Codec2 service...";
-    android::sp<IComponentStore> store =
-        new utils::ComponentStore(
-                android::GetCodec2PlatformComponentStore());
+    sp<ComponentStore_Latest> store =
+        new ComponentStore_Latest(::android::GetCodec2PlatformComponentStore());
     if (store == nullptr) {
         LOG(ERROR) <<
                 "Cannot create software Codec2 service.";
     } else {
+        if (!ionPropertiesDefined()) {
+            std::string preferredStoreName = "default";
+            sp<IComponentStore> preferredStore =
+                IComponentStore::getService(preferredStoreName.c_str());
+            if (preferredStore) {
+                ::android::SetPreferredCodec2ComponentStore(
+                        std::make_shared<H2C2ComponentStore>(preferredStore));
+                LOG(INFO) <<
+                        "Preferred Codec2 store is set to \"" <<
+                        preferredStoreName << "\".";
+            } else {
+                LOG(INFO) <<
+                        "Preferred Codec2 store is defaulted to \"software\".";
+            }
+        }
         if (store->registerAsService("software") != android::OK) {
             LOG(ERROR) <<
                     "Cannot register software Codec2 service.";
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 4f8589c..2fd1355 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -204,13 +204,13 @@
     }
 
     // crack any parameters
-    const String16 protoOption("-proto");
-    const String16 clearOption("-clear");
+    const String16 protoOption("--proto");
+    const String16 clearOption("--clear");
     bool clear = false;
-    const String16 sinceOption("-since");
+    const String16 sinceOption("--since");
     nsecs_t ts_since = 0;
-    const String16 helpOption("-help");
-    const String16 onlyOption("-only");
+    const String16 helpOption("--help");
+    const String16 onlyOption("--only");
     std::string only;
     const int n = args.size();
     for (int i = 0; i < n; i++) {
@@ -250,11 +250,11 @@
             // or dumpsys media.metrics audiotrack codec
 
             result.append("Recognized parameters:\n");
-            result.append("-help        this help message\n");
-            result.append("-proto #     dump using protocol #");
-            result.append("-clear       clears out saved records\n");
-            result.append("-only X      process records for component X\n");
-            result.append("-since X     include records since X\n");
+            result.append("--help        this help message\n");
+            result.append("--proto #     dump using protocol #");
+            result.append("--clear       clears out saved records\n");
+            result.append("--only X      process records for component X\n");
+            result.append("--since X     include records since X\n");
             result.append("             (X is milliseconds since the UNIX epoch)\n");
             write(fd, result.string(), result.size());
             return NO_ERROR;
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/TimeMachine.h
index 87de1c4..0440e5b 100644
--- a/services/mediametrics/TimeMachine.h
+++ b/services/mediametrics/TimeMachine.h
@@ -168,7 +168,6 @@
                 ss << "(" << (offset == 0 ? "" : "~") << &timestring.time[offset]
                     << ") " << eptr->second;
                 if (++eptr == timeSequence.end()) {
-                    ss << "}";
                     break;
                 }
                 ss << ", ";
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 877c44d..be5af00 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -58,6 +58,8 @@
         return;
     }
     service->removeResource(mPid, mClientId, false);
+
+    service->overridePid(mPid, -1);
 }
 
 template <typename T>
@@ -150,6 +152,7 @@
     PidResourceInfosMap mapCopy;
     bool supportsMultipleSecureCodecs;
     bool supportsSecureWithNonSecureCodec;
+    std::map<int, int> overridePidMapCopy;
     String8 serviceLog;
     {
         Mutex::Autolock lock(mLock);
@@ -157,6 +160,7 @@
         supportsMultipleSecureCodecs = mSupportsMultipleSecureCodecs;
         supportsSecureWithNonSecureCodec = mSupportsSecureWithNonSecureCodec;
         serviceLog = mServiceLog->toString("    " /* linePrefix */);
+        overridePidMapCopy = mOverridePidMap;
     }
 
     const size_t SIZE = 256;
@@ -197,6 +201,12 @@
             }
         }
     }
+    result.append("  Process Pid override:\n");
+    for (auto it = overridePidMapCopy.begin(); it != overridePidMapCopy.end(); ++it) {
+        snprintf(buffer, SIZE, "    Original Pid: %d,  Override Pid: %d\n",
+            it->first, it->second);
+        result.append(buffer);
+    }
     result.append("  Events logs (most recent at top):\n");
     result.append(serviceLog);
 
@@ -608,6 +618,48 @@
     return Status::ok();
 }
 
+Status ResourceManagerService::overridePid(
+        int originalPid,
+        int newPid) {
+    String8 log = String8::format("overridePid(originalPid %d, newPid %d)",
+            originalPid, newPid);
+    mServiceLog->add(log);
+
+    // allow if this is called from the same process or the process has
+    // permission.
+    if ((AIBinder_getCallingPid() != getpid()) &&
+        (checkCallingPermission(String16(
+             "android.permission.MEDIA_RESOURCE_OVERRIDE_PID")) == false)) {
+      ALOGE(
+          "Permission Denial: can't access overridePid method from pid=%d, "
+          "self pid=%d\n",
+          AIBinder_getCallingPid(), getpid());
+      return Status::fromServiceSpecificError(PERMISSION_DENIED);
+    }
+
+    {
+        Mutex::Autolock lock(mLock);
+        mOverridePidMap.erase(originalPid);
+        if (newPid != -1) {
+            mOverridePidMap.emplace(originalPid, newPid);
+        }
+    }
+
+    return Status::ok();
+}
+
+bool ResourceManagerService::getPriority_l(int pid, int* priority) {
+    int newPid = pid;
+
+    if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
+        newPid = mOverridePidMap[pid];
+        ALOGD("getPriority_l: use override pid %d instead original pid %d",
+                newPid, pid);
+    }
+
+    return mProcessInfo->getPriority(newPid, priority);
+}
+
 bool ResourceManagerService::getAllClients_l(
         int callingPid, MediaResource::Type type,
         Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
@@ -641,7 +693,7 @@
     int lowestPriorityPid;
     int lowestPriority;
     int callingPriority;
-    if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
+    if (!getPriority_l(callingPid, &callingPriority)) {
         ALOGE("getLowestPriorityBiggestClient_l: can't get process priority for pid %d",
                 callingPid);
         return false;
@@ -676,7 +728,7 @@
         }
         int tempPid = mMap.keyAt(i);
         int tempPriority;
-        if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
+        if (!getPriority_l(tempPid, &tempPriority)) {
             ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid);
             // TODO: remove this pid from mMap?
             continue;
@@ -696,12 +748,12 @@
 
 bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) {
     int callingPidPriority;
-    if (!mProcessInfo->getPriority(callingPid, &callingPidPriority)) {
+    if (!getPriority_l(callingPid, &callingPidPriority)) {
         return false;
     }
 
     int priority;
-    if (!mProcessInfo->getPriority(pid, &priority)) {
+    if (!getPriority_l(pid, &priority)) {
         return false;
     }
 
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index ae12d7b..f500c62 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -118,6 +118,10 @@
             const std::vector<MediaResourceParcel>& resources,
             bool* _aidl_return) override;
 
+    Status overridePid(
+            int originalPid,
+            int newPid) override;
+
     Status removeResource(int pid, int64_t clientId, bool checkValid);
 
 private:
@@ -157,6 +161,9 @@
     // Merge r2 into r1
     void mergeResources(MediaResourceParcel& r1, const MediaResourceParcel& r2);
 
+    // Get priority from process's pid
+    bool getPriority_l(int pid, int* priority);
+
     mutable Mutex mLock;
     sp<ProcessInfoInterface> mProcessInfo;
     sp<SystemCallbackInterface> mSystemCB;
@@ -166,6 +173,7 @@
     bool mSupportsSecureWithNonSecureCodec;
     int32_t mCpuBoostCount;
     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+    std::map<int, int> mOverridePidMap;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 168fde9..5d839fa 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -446,6 +446,32 @@
         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
     }
 
+    void testOverridePid() {
+
+        bool result;
+        std::vector<MediaResourceParcel> resources;
+        resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
+        resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
+
+        // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
+        {
+            addResource();
+            mService->mSupportsMultipleSecureCodecs = false;
+            mService->mSupportsSecureWithNonSecureCodec = true;
+
+            // priority too low to reclaim resource
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+
+            // override Low Priority Pid with High Priority Pid
+            mService->overridePid(kLowPriorityPid, kHighPriorityPid);
+            CHECK_STATUS_TRUE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+
+            // restore Low Priority Pid
+            mService->overridePid(kLowPriorityPid, -1);
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+        }
+    }
+
     void testRemoveClient() {
         addResource();
 
@@ -870,4 +896,8 @@
     testCpusetBoost();
 }
 
+TEST_F(ResourceManagerServiceTest, overridePid) {
+    testOverridePid();
+}
+
 } // namespace android