Merge "hdr10+: profile level report"
diff --git a/apex/Android.bp b/apex/Android.bp
index 604b268..51e4c23 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -27,6 +27,8 @@
         "libmpeg2extractor",
         "liboggextractor",
         "libwavextractor",
+        // MediaPlayer2
+        "libmediaplayer2_jni",
     ],
     key: "com.android.media.key",
 }
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 60c9f85..d96f403 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -137,6 +137,7 @@
     shared_libs: [
         "libhwbinder",
         "libcamera2ndk_vendor",
+        "libcamera_metadata",
         "libmediandk",
         "libnativewindow",
         "libutils",
@@ -144,6 +145,9 @@
         "libcutils",
         "liblog",
     ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper",
+    ],
     cflags: [
         "-D__ANDROID_VNDK__",
     ],
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 540d84e..ab796fb 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -80,7 +80,9 @@
 
     if (session->isClosed()) {
         ALOGE("%s: session %p is already closed", __FUNCTION__, session);
-        *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        if (captureSequenceId != nullptr) {
+            *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        }
         return ACAMERA_ERROR_SESSION_CLOSED;
     }
 
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index f395b44..575ee9d 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -34,7 +34,10 @@
 namespace android {
 namespace acam {
 
-using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
+using frameworks::cameraservice::service::V2_0::CameraStatusAndId;
+using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections;
+using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
+using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
 
 // Static member definitions
 const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
@@ -43,6 +46,104 @@
 Mutex                CameraManagerGlobal::sLock;
 CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
 
+/**
+ * The vendor tag descriptor class that takes HIDL vendor tag information as
+ * input. Not part of vendor available VendorTagDescriptor class because that class is used by
+ * default HAL implementation code as well.
+ */
+class HidlVendorTagDescriptor : public VendorTagDescriptor {
+public:
+    /**
+     * Create a VendorTagDescriptor object from the HIDL VendorTagSection
+     * vector.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t createDescriptorFromHidl(const hidl_vec<VendorTagSection>& vts,
+                                             /*out*/ sp<VendorTagDescriptor> *descriptor);
+};
+
+status_t HidlVendorTagDescriptor::createDescriptorFromHidl(const hidl_vec<VendorTagSection> &vts,
+                                                           sp<VendorTagDescriptor> *descriptor) {
+    int tagCount = 0;
+
+    for (size_t s = 0; s < vts.size(); s++) {
+        tagCount += vts[s].tags.size();
+    }
+
+    if (tagCount < 0 || tagCount > INT32_MAX) {
+        ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount);
+        return BAD_VALUE;
+    }
+
+    Vector<uint32_t> tagArray;
+    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+    sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+    desc->mTagCount = tagCount;
+
+    KeyedVector<uint32_t, String8> tagToSectionMap;
+
+    int idx = 0;
+    for (size_t s = 0; s < vts.size(); s++) {
+        const VendorTagSection& section = vts[s];
+        const char *sectionName = section.sectionName.c_str();
+        if (sectionName == NULL) {
+            ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
+            return BAD_VALUE;
+        }
+        String8 sectionString(sectionName);
+        desc->mSections.add(sectionString);
+
+        for (size_t j = 0; j < section.tags.size(); j++) {
+            uint32_t tag = section.tags[j].tagId;
+            if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+                ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+                return BAD_VALUE;
+            }
+
+            tagArray.editItemAt(idx++) = section.tags[j].tagId;
+
+            const char *tagName = section.tags[j].tagName.c_str();
+            if (tagName == NULL) {
+                ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
+                return BAD_VALUE;
+            }
+            desc->mTagToNameMap.add(tag, String8(tagName));
+            tagToSectionMap.add(tag, sectionString);
+
+            int tagType = (int) section.tags[j].tagType;
+            if (tagType < 0 || tagType >= NUM_TYPES) {
+                ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+                return BAD_VALUE;
+            }
+            desc->mTagToTypeMap.emplace(tag, tagType);
+        }
+    }
+
+    for (size_t i = 0; i < tagArray.size(); ++i) {
+        uint32_t tag = tagArray[i];
+        String8 sectionString = tagToSectionMap.valueFor(tag);
+
+        // Set up tag to section index map
+        ssize_t index = desc->mSections.indexOf(sectionString);
+        LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+        desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+        // Set up reverse mapping
+        ssize_t reverseIndex = -1;
+        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+        }
+        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+    }
+
+    *descriptor = std::move(desc);
+    return OK;
+}
+
 CameraManagerGlobal&
 CameraManagerGlobal::getInstance() {
     Mutex::Autolock _l(sLock);
@@ -80,8 +181,34 @@
     return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
 }
 
-// TODO: Add back when vendor tags are supported for libcamera2ndk_vendor when
-//       the HIDL interface supports querying by vendor id.
+bool CameraManagerGlobal::setupVendorTags() {
+    sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
+    Status status = Status::NO_ERROR;
+    std::vector<ProviderIdAndVendorTagSections> providerIdsAndVts;
+    auto remoteRet = mCameraService->getCameraVendorTagSections([&status, &providerIdsAndVts]
+                                                                 (Status s,
+                                                                  auto &IdsAndVts) {
+                                                         status = s;
+                                                         providerIdsAndVts = IdsAndVts; });
+
+    if (!remoteRet.isOk() || status != Status::NO_ERROR) {
+        ALOGE("Failed to retrieve VendorTagSections %s", remoteRet.description().c_str());
+        return false;
+    }
+    // Convert each providers VendorTagSections into a VendorTagDescriptor and
+    // add it to the cache
+    for (auto &providerIdAndVts : providerIdsAndVts) {
+        sp<VendorTagDescriptor> vendorTagDescriptor;
+        if (HidlVendorTagDescriptor::createDescriptorFromHidl(providerIdAndVts.vendorTagSections,
+                                                              &vendorTagDescriptor) != OK) {
+            ALOGE("Failed to convert from Hidl: VendorTagDescriptor");
+            return false;
+        }
+        tagCache->addVendorDescriptor(providerIdAndVts.providerId, vendorTagDescriptor);
+    }
+    VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache);
+    return true;
+}
 
 sp<ICameraService> CameraManagerGlobal::getCameraService() {
     Mutex::Autolock _l(mLock);
@@ -140,6 +267,13 @@
         if (!remoteRet.isOk() || status != Status::NO_ERROR) {
             ALOGE("Failed to add listener to camera service %s", remoteRet.description().c_str());
         }
+
+        // Setup vendor tags
+        if (!setupVendorTags()) {
+            ALOGE("Unable to set up vendor tags");
+            return nullptr;
+        }
+
         for (auto& c : cameraStatuses) {
             onStatusChangedLocked(c);
         }
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index c8d640f..6b1365a 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -142,6 +142,8 @@
 
     void onStatusChanged(const CameraStatusAndId &statusAndId);
     void onStatusChangedLocked(const CameraStatusAndId &statusAndId);
+    bool setupVendorTags();
+
     // Utils for status
     static bool validStatus(CameraDeviceStatus status);
     static bool isStatusAvailable(CameraDeviceStatus status);
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index f9bb3ac..93108b0 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -37,12 +37,7 @@
 #include <media/NdkImage.h>
 #include <media/NdkImageReader.h>
 #include <cutils/native_handle.h>
-
-//#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-//#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#include <VendorTagDescriptor.h>
 
 namespace {
 
@@ -53,6 +48,8 @@
 static constexpr int kTestImageHeight = 480;
 static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
 
+using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+
 class CameraHelper {
    public:
     CameraHelper(const char* id, ACameraManager *manager) :
@@ -527,6 +524,8 @@
             ALOGE("Failed to get cameraIdList: ret=%d", ret);
             return;
         }
+        // TODO: Add more rigorous tests for vendor tags
+        ASSERT_NE(VendorTagDescriptorCache::getGlobalVendorTagCache(), nullptr);
         if (mCameraIdList->numCameras < 1) {
             ALOGW("Device has no camera on board.");
             return;
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 7a10302..6eb2e9f 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -8,7 +8,7 @@
         SineSource.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright libmedia libmedia_omx libmediaextractor libutils libbinder \
+        libstagefright libmedia libmedia_omx libutils libbinder \
         libstagefright_foundation libjpeg libui libgui libcutils liblog \
         libhidlbase \
         android.hardware.media.omx@1.0 \
@@ -36,7 +36,7 @@
         record.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright libmedia libmediaextractor liblog libutils libbinder \
+        libstagefright libmedia liblog libutils libbinder \
         libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
@@ -61,7 +61,7 @@
         recordvideo.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright libmedia libmediaextractor liblog libutils libbinder \
+        libstagefright libmedia liblog libutils libbinder \
         libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
@@ -87,7 +87,7 @@
         audioloop.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright libmedia libmediaextractor liblog libutils libbinder \
+        libstagefright libmedia liblog libutils libbinder \
         libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
@@ -111,7 +111,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libui libgui \
-        libstagefright_foundation libmedia libcutils libmediaextractor
+        libstagefright_foundation libmedia libcutils
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -203,7 +203,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
-        libcutils libc libmediaextractor
+        libcutils libc
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 2532275..2600a2c 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -58,22 +58,26 @@
     return drm_perm_labels[index];
 }
 
-bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm) {
+bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, const char* ssid, drm_perm_t perm) {
     if (selinux_enabled <= 0) {
         return true;
     }
 
-    char *sctx;
+    char *sctx = NULL;
     const char *selinux_class = "drmservice";
     const char *str_perm = get_perm_label(perm);
 
-    if (getpidcon(spid, &sctx) != 0) {
-        ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid);
-        return false;
+    if (ssid == NULL) {
+        android_errorWriteLog(0x534e4554, "121035042");
+
+        if (getpidcon(spid, &sctx) != 0) {
+            ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid);
+            return false;
+        }
     }
 
-    bool allowed = (selinux_check_access(sctx, drmserver_context, selinux_class,
-            str_perm, NULL) == 0);
+    bool allowed = (selinux_check_access(ssid ? ssid : sctx, drmserver_context,
+            selinux_class, str_perm, NULL) == 0);
     freecon(sctx);
 
     return allowed;
@@ -86,10 +90,11 @@
     IPCThreadState* ipcState = IPCThreadState::self();
     uid_t uid = ipcState->getCallingUid();
     pid_t spid = ipcState->getCallingPid();
+    const char* ssid = ipcState->getCallingSid();
 
     for (unsigned int i = 0; i < trustedUids.size(); ++i) {
         if (trustedUids[i] == uid) {
-            return selinuxIsProtectedCallAllowed(spid, perm);
+            return selinuxIsProtectedCallAllowed(spid, ssid, perm);
         }
     }
     return false;
@@ -97,7 +102,9 @@
 
 void DrmManagerService::instantiate() {
     ALOGV("instantiate");
-    defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
+    sp<DrmManagerService> service = new DrmManagerService();
+    service->setRequestingSid(true);
+    defaultServiceManager()->addService(String16("drm.drmManager"), service);
 
     if (0 >= trustedUids.size()) {
         // TODO
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index 7aaeab5..2e27a3c 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -60,7 +60,7 @@
 
     static const char *get_perm_label(drm_perm_t perm);
 
-    static bool selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm);
+    static bool selinuxIsProtectedCallAllowed(pid_t spid, const char* ssid, drm_perm_t perm);
 
     static bool isProtectedCallAllowed(drm_perm_t perm);
 
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 3035c5a..4dda5d7 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -30,16 +30,16 @@
 #include <media/stagefright/MediaErrors.h>
 #include <mediadrm/CryptoHal.h>
 
+using drm::V1_0::BufferType;
+using drm::V1_0::DestinationBuffer;
+using drm::V1_0::ICryptoFactory;
+using drm::V1_0::ICryptoPlugin;
+using drm::V1_0::Mode;
+using drm::V1_0::Pattern;
+using drm::V1_0::SharedBuffer;
+using drm::V1_0::Status;
+using drm::V1_0::SubSample;
 
-using ::android::hardware::drm::V1_0::BufferType;
-using ::android::hardware::drm::V1_0::DestinationBuffer;
-using ::android::hardware::drm::V1_0::ICryptoFactory;
-using ::android::hardware::drm::V1_0::ICryptoPlugin;
-using ::android::hardware::drm::V1_0::Mode;
-using ::android::hardware::drm::V1_0::Pattern;
-using ::android::hardware::drm::V1_0::SharedBuffer;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_memory;
@@ -50,6 +50,7 @@
 using ::android::hidl::manager::V1_0::IServiceManager;
 using ::android::sp;
 
+typedef drm::V1_2::Status Status_V1_2;
 
 namespace android {
 
@@ -76,6 +77,18 @@
     }
 }
 
+static status_t toStatusT_1_2(Status_V1_2 status) {
+    switch (status) {
+    case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
+        return ERROR_DRM_SESSION_LOST_STATE;;
+    case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
+        return ERROR_DRM_FRAME_TOO_LARGE;
+    case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
+        return ERROR_DRM_INSUFFICIENT_SECURITY;
+    default:
+        return toStatusT(static_cast<Status>(status));
+    }
+}
 
 static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
     hidl_vec<uint8_t> vec;
@@ -196,6 +209,9 @@
     for (size_t i = 0; i < mFactories.size(); i++) {
         if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
             mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
+            if (mPlugin != NULL) {
+                mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
+            }
         }
     }
 
@@ -216,6 +232,7 @@
     }
 
     mPlugin.clear();
+    mPluginV1_2.clear();
     return OK;
 }
 
@@ -389,21 +406,33 @@
     status_t err = UNKNOWN_ERROR;
     uint32_t bytesWritten = 0;
 
-    Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode,
-            hPattern, hSubSamples, hSource, offset, hDestination,
-            [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
-                if (status == Status::OK) {
-                    bytesWritten = hBytesWritten;
-                    *errorDetailMsg = toString8(hDetailedError);
-                }
-                err = toStatusT(status);
-            }
-        );
+    Return<void> hResult;
 
-    if (!hResult.isOk()) {
-        err = DEAD_OBJECT;
+    if (mPluginV1_2 != NULL) {
+        hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv),
+                hMode, hPattern, hSubSamples, hSource, offset, hDestination,
+                [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+                    if (status == Status_V1_2::OK) {
+                        bytesWritten = hBytesWritten;
+                        *errorDetailMsg = toString8(hDetailedError);
+                    }
+                    err = toStatusT_1_2(status);
+                }
+            );
+    } else {
+        hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv),
+                hMode, hPattern, hSubSamples, hSource, offset, hDestination,
+                [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+                    if (status == Status::OK) {
+                        bytesWritten = hBytesWritten;
+                        *errorDetailMsg = toString8(hDetailedError);
+                    }
+                    err = toStatusT(status);
+                }
+            );
     }
 
+    err = hResult.isOk() ? err : DEAD_OBJECT;
     if (err == OK) {
         return bytesWritten;
     }
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 66c509f..f4c0341 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -24,7 +24,7 @@
 #include <binder/IServiceManager.h>
 
 #include <android/hardware/drm/1.2/types.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
 
 #include <media/EventMetric.h>
@@ -41,6 +41,7 @@
 
 using drm::V1_0::KeyedVector;
 using drm::V1_0::KeyStatusType;
+using drm::V1_0::KeyRequestType;
 using drm::V1_0::KeyType;
 using drm::V1_0::KeyValue;
 using drm::V1_0::SecureStop;
@@ -60,6 +61,9 @@
 using ::android::os::PersistableBundle;
 using ::android::sp;
 
+typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
+typedef drm::V1_2::Status Status_V1_2;
+
 namespace {
 
 // This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
@@ -239,7 +243,7 @@
         return ERROR_DRM_CANNOT_HANDLE;
         break;
     case Status::ERROR_DRM_INVALID_STATE:
-        return ERROR_DRM_TAMPER_DETECTED;
+        return ERROR_DRM_INVALID_STATE;
         break;
     case Status::BAD_VALUE:
         return BAD_VALUE;
@@ -260,6 +264,19 @@
     }
 }
 
+static status_t toStatusT_1_2(Status_V1_2 status) {
+    switch (status) {
+    case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION:
+        return ERROR_DRM_RESOURCE_CONTENTION;
+    case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
+        return ERROR_DRM_FRAME_TOO_LARGE;
+    case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
+        return ERROR_DRM_INSUFFICIENT_SECURITY;
+    default:
+        return toStatusT(static_cast<Status>(status));
+    }
+}
+
 
 Mutex DrmHal::mLock;
 
@@ -319,8 +336,11 @@
 
     setListener(NULL);
     mInitCheck = NO_INIT;
-
-    if (mPlugin != NULL) {
+    if (mPluginV1_2 != NULL) {
+        if (!mPluginV1_2->setListener(NULL).isOk()) {
+            mInitCheck = DEAD_OBJECT;
+        }
+    } else if (mPlugin != NULL) {
         if (!mPlugin->setListener(NULL).isOk()) {
             mInitCheck = DEAD_OBJECT;
         }
@@ -333,10 +353,10 @@
 Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
     Vector<sp<IDrmFactory>> factories;
 
-    auto manager = hardware::defaultServiceManager();
+    auto manager = hardware::defaultServiceManager1_2();
 
     if (manager != NULL) {
-        manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
+        manager->listManifestByInterface(drm::V1_0::IDrmFactory::descriptor,
                 [&factories](const hidl_vec<hidl_string> &registered) {
                     for (const auto &instance : registered) {
                         auto factory = drm::V1_0::IDrmFactory::getService(instance);
@@ -346,7 +366,7 @@
                     }
                 }
             );
-        manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
+        manager->listManifestByInterface(drm::V1_1::IDrmFactory::descriptor,
                 [&factories](const hidl_vec<hidl_string> &registered) {
                     for (const auto &instance : registered) {
                         auto factory = drm::V1_1::IDrmFactory::getService(instance);
@@ -532,6 +552,22 @@
     return Void();
 }
 
+Return<void> DrmHal::sendSessionLostState(
+        const hidl_vec<uint8_t>& sessionId) {
+
+    mEventLock.lock();
+    sp<IDrmClient> listener = mListener;
+    mEventLock.unlock();
+
+    if (listener != NULL) {
+        Parcel obj;
+        writeByteArray(obj, sessionId);
+        Mutex::Autolock lock(mNotifyLock);
+        listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
+    }
+    return Void();
+}
+
 bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
     Mutex::Autolock autoLock(mLock);
 
@@ -568,16 +604,22 @@
     if (mPlugin == NULL) {
         mInitCheck = ERROR_UNSUPPORTED;
     } else {
-        if (!mPlugin->setListener(this).isOk()) {
-            mPlugin = NULL;
-            mPluginV1_1 = NULL;
-            mPluginV1_2 = NULL;
+        mInitCheck = OK;
+        if (mPluginV1_2 != NULL) {
+            if (!mPluginV1_2->setListener(this).isOk()) {
+                mInitCheck = DEAD_OBJECT;
+            }
+        } else if (!mPlugin->setListener(this).isOk()) {
             mInitCheck = DEAD_OBJECT;
-        } else {
-            mInitCheck = OK;
+        }
+        if (mInitCheck != OK) {
+            mPlugin.clear();
+            mPluginV1_1.clear();
+            mPluginV1_2.clear();
         }
     }
 
+
     return mInitCheck;
 }
 
@@ -694,6 +736,39 @@
     return DEAD_OBJECT;
 }
 
+static DrmPlugin::KeyRequestType toKeyRequestType(
+        KeyRequestType keyRequestType) {
+    switch (keyRequestType) {
+        case KeyRequestType::INITIAL:
+            return DrmPlugin::kKeyRequestType_Initial;
+            break;
+        case KeyRequestType::RENEWAL:
+            return DrmPlugin::kKeyRequestType_Renewal;
+            break;
+        case KeyRequestType::RELEASE:
+            return DrmPlugin::kKeyRequestType_Release;
+            break;
+        default:
+            return DrmPlugin::kKeyRequestType_Unknown;
+            break;
+    }
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType_1_1(
+        KeyRequestType_V1_1 keyRequestType) {
+    switch (keyRequestType) {
+        case KeyRequestType_V1_1::NONE:
+            return DrmPlugin::kKeyRequestType_None;
+            break;
+        case KeyRequestType_V1_1::UPDATE:
+            return DrmPlugin::kKeyRequestType_Update;
+            break;
+        default:
+            return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType));
+            break;
+    }
+}
+
 status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
         Vector<uint8_t> const &initData, String8 const &mimeType,
         DrmPlugin::KeyType keyType, KeyedVector<String8,
@@ -720,73 +795,51 @@
     ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
 
     status_t err = UNKNOWN_ERROR;
+    Return<void> hResult;
 
-    if (mPluginV1_1 != NULL) {
-        Return<void> hResult =
-            mPluginV1_1->getKeyRequest_1_1(
+    if (mPluginV1_2 != NULL) {
+        hResult = mPluginV1_2->getKeyRequest_1_2(
+                toHidlVec(sessionId), toHidlVec(initData),
+                toHidlString(mimeType), hKeyType, hOptionalParameters,
+                [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+                        KeyRequestType_V1_1 hKeyRequestType,
+                        const hidl_string& hDefaultUrl) {
+                    if (status == Status_V1_2::OK) {
+                        request = toVector(hRequest);
+                        defaultUrl = toString8(hDefaultUrl);
+                        *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
+                    }
+                    err = toStatusT_1_2(status);
+                });
+    } else if (mPluginV1_1 != NULL) {
+        hResult = mPluginV1_1->getKeyRequest_1_1(
                 toHidlVec(sessionId), toHidlVec(initData),
                 toHidlString(mimeType), hKeyType, hOptionalParameters,
                 [&](Status status, const hidl_vec<uint8_t>& hRequest,
-                    drm::V1_1::KeyRequestType hKeyRequestType,
-                    const hidl_string& hDefaultUrl) {
-
-            if (status == Status::OK) {
-                request = toVector(hRequest);
-                defaultUrl = toString8(hDefaultUrl);
-
-                switch (hKeyRequestType) {
-                    case drm::V1_1::KeyRequestType::INITIAL:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
-                        break;
-                    case drm::V1_1::KeyRequestType::RENEWAL:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
-                        break;
-                    case drm::V1_1::KeyRequestType::RELEASE:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
-                        break;
-                    case drm::V1_1::KeyRequestType::NONE:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_None;
-                        break;
-                    case drm::V1_1::KeyRequestType::UPDATE:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Update;
-                        break;
-                    default:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
-                        break;
-                }
-                err = toStatusT(status);
-            }
-        });
-        return hResult.isOk() ? err : DEAD_OBJECT;
-    }
-
-    Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
-            toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
-            [&](Status status, const hidl_vec<uint8_t>& hRequest,
-                    drm::V1_0::KeyRequestType hKeyRequestType,
-                    const hidl_string& hDefaultUrl) {
-
-                if (status == Status::OK) {
-                    request = toVector(hRequest);
-                    defaultUrl = toString8(hDefaultUrl);
-
-                    switch (hKeyRequestType) {
-                    case drm::V1_0::KeyRequestType::INITIAL:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
-                        break;
-                    case drm::V1_0::KeyRequestType::RENEWAL:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
-                        break;
-                    case drm::V1_0::KeyRequestType::RELEASE:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
-                        break;
-                    default:
-                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
-                        break;
+                        KeyRequestType_V1_1 hKeyRequestType,
+                        const hidl_string& hDefaultUrl) {
+                    if (status == Status::OK) {
+                        request = toVector(hRequest);
+                        defaultUrl = toString8(hDefaultUrl);
+                        *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
                     }
                     err = toStatusT(status);
-                }
-            });
+                });
+    } else {
+        hResult = mPlugin->getKeyRequest(
+                toHidlVec(sessionId), toHidlVec(initData),
+                toHidlString(mimeType), hKeyType, hOptionalParameters,
+                [&](Status status, const hidl_vec<uint8_t>& hRequest,
+                        KeyRequestType hKeyRequestType,
+                        const hidl_string& hDefaultUrl) {
+                    if (status == Status::OK) {
+                        request = toVector(hRequest);
+                        defaultUrl = toString8(hDefaultUrl);
+                        *keyRequestType = toKeyRequestType(hKeyRequestType);
+                    }
+                    err = toStatusT(status);
+                });
+    }
 
     err = hResult.isOk() ? err : DEAD_OBJECT;
     keyRequestTimer.SetAttribute(err);
@@ -868,18 +921,33 @@
     INIT_CHECK();
 
     status_t err = UNKNOWN_ERROR;
+    Return<void> hResult;
 
-    Return<void> hResult = mPlugin->getProvisionRequest(
-            toHidlString(certType), toHidlString(certAuthority),
-            [&](Status status, const hidl_vec<uint8_t>& hRequest,
-                    const hidl_string& hDefaultUrl) {
-                if (status == Status::OK) {
-                    request = toVector(hRequest);
-                    defaultUrl = toString8(hDefaultUrl);
+    if (mPluginV1_2 != NULL) {
+        Return<void> hResult = mPluginV1_2->getProvisionRequest_1_2(
+                toHidlString(certType), toHidlString(certAuthority),
+                [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+                        const hidl_string& hDefaultUrl) {
+                    if (status == Status_V1_2::OK) {
+                        request = toVector(hRequest);
+                        defaultUrl = toString8(hDefaultUrl);
+                    }
+                    err = toStatusT_1_2(status);
                 }
-                err = toStatusT(status);
-            }
-        );
+            );
+    } else {
+        Return<void> hResult = mPlugin->getProvisionRequest(
+                toHidlString(certType), toHidlString(certAuthority),
+                [&](Status status, const hidl_vec<uint8_t>& hRequest,
+                        const hidl_string& hDefaultUrl) {
+                    if (status == Status::OK) {
+                        request = toVector(hRequest);
+                        defaultUrl = toString8(hDefaultUrl);
+                    }
+                    err = toStatusT(status);
+                }
+            );
+    }
 
     err = hResult.isOk() ? err : DEAD_OBJECT;
     mMetrics.mGetProvisionRequestCounter.Increment(err);
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index a488f86..fc0cceb 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -42,10 +42,42 @@
     return Void();
 }
 
+Return<void> CryptoPlugin::decrypt(
+    bool secure,
+    const hidl_array<uint8_t, 16>& keyId,
+    const hidl_array<uint8_t, 16>& iv,
+    Mode mode,
+    const Pattern& pattern,
+    const hidl_vec<SubSample>& subSamples,
+    const SharedBuffer& source,
+    uint64_t offset,
+    const DestinationBuffer& destination,
+    decrypt_cb _hidl_cb) {
+
+  Status status = Status::ERROR_DRM_UNKNOWN;
+  hidl_string detailedError;
+  uint32_t bytesWritten = 0;
+
+  Return<void> hResult = decrypt_1_2(
+      secure, keyId, iv, mode, pattern, subSamples, source, offset, destination,
+      [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) {
+        status = toStatus_1_0(hStatus);
+        if (status == Status::OK) {
+          bytesWritten = hBytesWritten;
+          detailedError = hDetailedError;
+        }
+      }
+    );
+
+  status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE;
+  _hidl_cb(status, bytesWritten, detailedError);
+  return Void();
+}
+
 // Returns negative values for error code and positive values for the size of
 // decrypted data.  In theory, the output size can be larger than the input
 // size, but in practice this will never happen for AES-CTR.
-Return<void> CryptoPlugin::decrypt(
+Return<void> CryptoPlugin::decrypt_1_2(
         bool secure,
         const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
         const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
@@ -55,17 +87,17 @@
         const SharedBuffer& source,
         uint64_t offset,
         const DestinationBuffer& destination,
-        decrypt_cb _hidl_cb) {
+        decrypt_1_2_cb _hidl_cb) {
     UNUSED(pattern);
 
     if (secure) {
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
             "Secure decryption is not supported with ClearKey.");
         return Void();
     }
 
     if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
-      _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+      _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
                "source decrypt buffer base not set");
       return Void();
     }
@@ -73,7 +105,7 @@
     if (destination.type == BufferType::SHARED_MEMORY) {
       const SharedBuffer& dest = destination.nonsecureMemory;
       if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
                  "destination decrypt buffer base not set");
         return Void();
       }
@@ -81,12 +113,12 @@
 
     sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
     if (sourceBase == nullptr) {
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
+        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
         return Void();
     }
 
     if (source.offset + offset + source.size > sourceBase->getSize()) {
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
         return Void();
     }
 
@@ -98,12 +130,12 @@
         const SharedBuffer& destBuffer = destination.nonsecureMemory;
         sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
         if (destBase == nullptr) {
-            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
             return Void();
         }
 
         if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
-            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
             return Void();
         }
         destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
@@ -128,7 +160,7 @@
 
     if (mode == Mode::UNENCRYPTED) {
         if (haveEncryptedSubsamples) {
-            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
                     "Encrypted subsamples found in allegedly unencrypted data.");
             return Void();
         }
@@ -144,22 +176,21 @@
             }
         }
 
-        _hidl_cb(Status::OK, static_cast<ssize_t>(offset), "");
+        _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), "");
         return Void();
     } else if (mode == Mode::AES_CTR) {
         size_t bytesDecrypted;
-        Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
+        Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
                 static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
-        if (res == Status::OK) {
-            _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), "");
+        if (res == Status_V1_2::OK) {
+            _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), "");
             return Void();
         } else {
-            _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res),
-                    "Decryption Error");
+            _hidl_cb(res, 0, "Decryption Error");
             return Void();
         }
     } else {
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
                 "Selected encryption mode is not supported by the ClearKey DRM Plugin.");
         return Void();
     }
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 7184b53..badb99e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -61,15 +61,23 @@
 namespace V1_2 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_2::KeySetId;
-using ::android::hardware::drm::V1_2::OfflineLicenseState;
+KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) {
+  switch (keyRequestType) {
+    case KeyRequestType_V1_1::NONE:
+    case KeyRequestType_V1_1::UPDATE:
+      return KeyRequestType::UNKNOWN;
+    default:
+      return static_cast<KeyRequestType>(keyRequestType);
+  }
+}
 
 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
         : mSessionLibrary(sessionLibrary),
           mOpenSessionOkCount(0),
           mCloseSessionOkCount(0),
           mCloseSessionNotOpenedCount(0),
-          mNextSecureStopId(kSecureStopIdStart) {
+          mNextSecureStopId(kSecureStopIdStart),
+          mMockError(Status_V1_2::OK) {
     mPlayPolicy.clear();
     initProperties();
     mSecureStops.clear();
@@ -84,6 +92,7 @@
     mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
     mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
     mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
+    mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
 
     std::vector<uint8_t> valueVector;
     valueVector.clear();
@@ -112,6 +121,7 @@
 
 Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
     sp<Session> session = mSessionLibrary->createSession();
+    processMockError(session);
     std::vector<uint8_t> sessionId = session->sessionId();
 
     Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
@@ -123,6 +133,7 @@
 Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
         openSession_1_1_cb _hidl_cb) {
     sp<Session> session = mSessionLibrary->createSession();
+    processMockError(session);
     std::vector<uint8_t> sessionId = session->sessionId();
 
     Status status = setSecurityLevel(sessionId, securityLevel);
@@ -138,6 +149,10 @@
 
     sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
     if (session.get()) {
+        if (session->getMockError() != Status_V1_2::OK) {
+            sendSessionLostState(sessionId);
+            return Status::ERROR_DRM_INVALID_STATE;
+        }
         mCloseSessionOkCount++;
         mSessionLibrary->destroySession(session);
         return Status::OK;
@@ -146,13 +161,13 @@
     return Status::ERROR_DRM_SESSION_NOT_OPENED;
 }
 
-Status DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
+Status_V1_2 DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
         const hidl_vec<uint8_t>& initData,
         const hidl_string& mimeType,
         KeyType keyType,
         const hidl_vec<KeyValue>& optionalParameters,
         std::vector<uint8_t> *request,
-        KeyRequestType *keyRequestType,
+        KeyRequestType_V1_1 *keyRequestType,
         std::string *defaultUrl) {
         UNUSED(optionalParameters);
 
@@ -161,18 +176,18 @@
     // Those tests pass in an empty initData, we use the empty initData to
     // signal such specific use case.
     if (keyType == KeyType::OFFLINE && 0 == initData.size()) {
-        return Status::ERROR_DRM_CANNOT_HANDLE;
+        return Status_V1_2::ERROR_DRM_CANNOT_HANDLE;
     }
 
     *defaultUrl = "";
-    *keyRequestType = KeyRequestType::UNKNOWN;
+    *keyRequestType = KeyRequestType_V1_1::UNKNOWN;
     *request = std::vector<uint8_t>();
 
     if (scope.size() == 0 ||
             (keyType != KeyType::STREAMING &&
             keyType != KeyType::OFFLINE &&
             keyType != KeyType::RELEASE)) {
-        return Status::BAD_VALUE;
+        return Status_V1_2::BAD_VALUE;
     }
 
     const std::vector<uint8_t> scopeId = toVector(scope);
@@ -181,12 +196,16 @@
         std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
         session = mSessionLibrary->findSession(sessionId);
         if (!session.get()) {
-            return Status::ERROR_DRM_SESSION_NOT_OPENED;
+            return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED;
+        } else if (session->getMockError() != Status_V1_2::OK) {
+            return session->getMockError();
         }
-        *keyRequestType = KeyRequestType::INITIAL;
+
+        *keyRequestType = KeyRequestType_V1_1::INITIAL;
     }
 
-    Status status = session->getKeyRequest(initData, mimeType, keyType, request);
+    Status_V1_2 status = static_cast<Status_V1_2>(
+            session->getKeyRequest(initData, mimeType, keyType, request));
 
     if (keyType == KeyType::RELEASE) {
         std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end());
@@ -198,7 +217,7 @@
                     DeviceFiles::kLicenseStateReleasing,
                     emptyResponse)) {
                 ALOGE("Problem releasing offline license");
-                return Status::ERROR_DRM_UNKNOWN;
+                return Status_V1_2::ERROR_DRM_UNKNOWN;
             }
             if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
                 sp<Session> session = mSessionLibrary->createSession();
@@ -209,7 +228,7 @@
         } else {
             ALOGE("Offline license not found, nothing to release");
         }
-        *keyRequestType = KeyRequestType::RELEASE;
+        *keyRequestType = KeyRequestType_V1_1::RELEASE;
     }
     return status;
 }
@@ -223,15 +242,15 @@
         getKeyRequest_cb _hidl_cb) {
     UNUSED(optionalParameters);
 
-    KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
+    KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
     std::string defaultUrl("");
     std::vector<uint8_t> request;
-    Status status = getKeyRequestCommon(
+    Status_V1_2 status = getKeyRequestCommon(
             scope, initData, mimeType, keyType, optionalParameters,
             &request, &keyRequestType, &defaultUrl);
 
-    _hidl_cb(status, toHidlVec(request),
-            static_cast<drm::V1_0::KeyRequestType>(keyRequestType),
+    _hidl_cb(toStatus_1_0(status), toHidlVec(request),
+            toKeyRequestType_V1_0(keyRequestType),
             hidl_string(defaultUrl));
     return Void();
 }
@@ -245,10 +264,31 @@
         getKeyRequest_1_1_cb _hidl_cb) {
     UNUSED(optionalParameters);
 
-    KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
+    KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
     std::string defaultUrl("");
     std::vector<uint8_t> request;
-    Status status = getKeyRequestCommon(
+    Status_V1_2 status = getKeyRequestCommon(
+            scope, initData, mimeType, keyType, optionalParameters,
+            &request, &keyRequestType, &defaultUrl);
+
+    _hidl_cb(toStatus_1_0(status), toHidlVec(request),
+            keyRequestType, hidl_string(defaultUrl));
+    return Void();
+}
+
+Return<void> DrmPlugin::getKeyRequest_1_2(
+        const hidl_vec<uint8_t>& scope,
+        const hidl_vec<uint8_t>& initData,
+        const hidl_string& mimeType,
+        KeyType keyType,
+        const hidl_vec<KeyValue>& optionalParameters,
+        getKeyRequest_1_2_cb _hidl_cb) {
+    UNUSED(optionalParameters);
+
+    KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
+    std::string defaultUrl("");
+    std::vector<uint8_t> request;
+    Status_V1_2 status = getKeyRequestCommon(
             scope, initData, mimeType, keyType, optionalParameters,
             &request, &keyRequestType, &defaultUrl);
 
@@ -434,6 +474,8 @@
         value = mStringProperties[kAlgorithmsKey];
     } else if (name == kListenerTestSupportKey) {
         value = mStringProperties[kListenerTestSupportKey];
+    } else if (name == kDrmErrorTestKey) {
+        value = mStringProperties[kDrmErrorTestKey];
     } else {
         ALOGE("App requested unknown string property %s", name.c_str());
         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
@@ -478,6 +520,16 @@
         return Status::BAD_VALUE;
     }
 
+    if (name == kDrmErrorTestKey) {
+        if (value == kResourceContentionValue) {
+            mMockError = Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION;
+        } else if (value == kLostStateValue) {
+            mMockError = Status_V1_2::ERROR_DRM_SESSION_LOST_STATE;
+        } else if (value == kFrameTooLargeValue) {
+            mMockError = Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE;
+        }
+    }
+
     mStringProperties[key] = std::string(value.c_str());
     return Status::OK;
 }
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
index f4c49b9..a9d7016 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
@@ -68,25 +68,30 @@
     }
 }
 
-Status Session::decrypt(
+Status_V1_2 Session::decrypt(
         const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
         uint8_t* destPtr, const std::vector<SubSample> subSamples,
         size_t* bytesDecryptedOut) {
     Mutex::Autolock lock(mMapLock);
 
+    if (getMockError() != Status_V1_2::OK) {
+        return getMockError();
+    }
+
     std::vector<uint8_t> keyIdVector;
     keyIdVector.clear();
     keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize);
     std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr;
     itr = mKeyMap.find(keyIdVector);
     if (itr == mKeyMap.end()) {
-        return Status::ERROR_DRM_NO_LICENSE;
+        return Status_V1_2::ERROR_DRM_NO_LICENSE;
     }
 
     AesCtrDecryptor decryptor;
-    return decryptor.decrypt(
+    Status status = decryptor.decrypt(
             itr->second /*key*/, iv, srcPtr, destPtr, subSamples,
             subSamples.size(), bytesDecryptedOut);
+    return static_cast<Status_V1_2>(status);
 }
 
 } // namespace clearkey
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
index f83903c..1bbc822 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
@@ -35,6 +35,11 @@
 static const std::string kAlgorithmsValue("");
 static const std::string kListenerTestSupportKey("listenerTestSupport");
 static const std::string kListenerTestSupportValue("true");
+static const std::string kDrmErrorTestKey("drmErrorTest");
+static const std::string kDrmErrorTestValue("");
+static const std::string kResourceContentionValue("resourceContention");
+static const std::string kLostStateValue("lostState");
+static const std::string kFrameTooLargeValue("frameTooLarge");
 
 static const std::string kDeviceIdKey("deviceId");
 static const uint8_t kTestDeviceIdData[] =
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
index 7e9b6bd..2dafa36 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
@@ -17,7 +17,7 @@
 #ifndef CLEARKEY_MACROS_H_
 #define CLEARKEY_MACROS_H_
 
-#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/drm/1.2/types.h>
 
 #include <map>
 
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
index 480dc7e..8680f0c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
@@ -17,7 +17,7 @@
 #ifndef CLEARKEY_CRYPTO_PLUGIN_H_
 #define CLEARKEY_CRYPTO_PLUGIN_H_
 
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 
 #include "ClearKeyTypes.h"
@@ -35,13 +35,14 @@
 namespace V1_2 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_0::DestinationBuffer;
-using ::android::hardware::drm::V1_0::ICryptoPlugin;
-using ::android::hardware::drm::V1_0::Mode;
-using ::android::hardware::drm::V1_0::Pattern;
-using ::android::hardware::drm::V1_0::SharedBuffer;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::DestinationBuffer;
+using drm::V1_0::Mode;
+using drm::V1_0::Pattern;
+using drm::V1_0::SharedBuffer;
+using drm::V1_0::Status;
+using drm::V1_0::SubSample;
+
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
@@ -51,7 +52,9 @@
 using ::android::hidl::memory::V1_0::IMemory;
 using ::android::sp;
 
-struct CryptoPlugin : public ICryptoPlugin {
+typedef drm::V1_2::Status Status_V1_2;
+
+struct CryptoPlugin : public drm::V1_2::ICryptoPlugin {
     explicit CryptoPlugin(const hidl_vec<uint8_t>& sessionId) {
         mInitStatus = setMediaDrmSession(sessionId);
     }
@@ -80,6 +83,18 @@
             const DestinationBuffer& destination,
             decrypt_cb _hidl_cb);
 
+    Return<void> decrypt_1_2(
+            bool secure,
+            const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
+            const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
+            Mode mode,
+            const Pattern& pattern,
+            const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& source,
+            uint64_t offset,
+            const DestinationBuffer& destination,
+            decrypt_1_2_cb _hidl_cb);
+
     Return<void> setSharedBufferBase(const hidl_memory& base,
             uint32_t bufferId);
 
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 256c5d6..a9b897b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -18,6 +18,7 @@
 #define CLEARKEY_DRM_PLUGIN_H_
 
 #include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
 
 #include <map>
 #include <stdio.h>
@@ -34,22 +35,24 @@
 namespace V1_2 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_0::EventType;
-using ::android::hardware::drm::V1_0::IDrmPluginListener;
-using ::android::hardware::drm::V1_0::KeyStatus;
-using ::android::hardware::drm::V1_0::KeyType;
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::SecureStop;
-using ::android::hardware::drm::V1_0::SecureStopId;
-using ::android::hardware::drm::V1_0::SessionId;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::hardware::drm::V1_1::HdcpLevel;
-using ::android::hardware::drm::V1_1::KeyRequestType;
-using ::android::hardware::drm::V1_1::SecureStopRelease;
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::drm::V1_2::IDrmPlugin;
-using ::android::hardware::drm::V1_2::OfflineLicenseState;
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::EventType;
+using drm::V1_0::IDrmPluginListener;
+using drm::V1_0::KeyRequestType;
+using drm::V1_0::KeyStatus;
+using drm::V1_0::KeyType;
+using drm::V1_0::KeyValue;
+using drm::V1_0::SecureStop;
+using drm::V1_0::SecureStopId;
+using drm::V1_0::SessionId;
+using drm::V1_0::Status;
+using drm::V1_1::DrmMetricGroup;
+using drm::V1_1::HdcpLevel;
+using drm::V1_1::SecureStopRelease;
+using drm::V1_1::SecurityLevel;
+using drm::V1_2::IDrmPlugin;
+using drm::V1_2::KeySetId;
+using drm::V1_2::OfflineLicenseState;
 
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -57,6 +60,10 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
+typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
+typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+typedef drm::V1_2::Status Status_V1_2;
+
 struct DrmPlugin : public IDrmPlugin {
     explicit DrmPlugin(SessionLibrary* sessionLibrary);
 
@@ -84,6 +91,14 @@
         const hidl_vec<KeyValue>& optionalParameters,
         getKeyRequest_1_1_cb _hidl_cb) override;
 
+    Return<void> getKeyRequest_1_2(
+        const hidl_vec<uint8_t>& scope,
+        const hidl_vec<uint8_t>& initData,
+        const hidl_string& mimeType,
+        KeyType keyType,
+        const hidl_vec<KeyValue>& optionalParameters,
+        getKeyRequest_1_2_cb _hidl_cb) override;
+
     Return<void> provideKeyResponse(
         const hidl_vec<uint8_t>& scope,
         const hidl_vec<uint8_t>& response,
@@ -116,6 +131,18 @@
         return Void();
     }
 
+    Return<void> getProvisionRequest_1_2(
+        const hidl_string& certificateType,
+        const hidl_string& certificateAuthority,
+        getProvisionRequest_1_2_cb _hidl_cb) {
+        UNUSED(certificateType);
+        UNUSED(certificateAuthority);
+
+        hidl_string defaultUrl;
+        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
+        return Void();
+    }
+
     Return<void> provideProvisionResponse(
         const hidl_vec<uint8_t>& response,
         provideProvisionResponse_cb _hidl_cb) {
@@ -256,12 +283,17 @@
 
     Return<void> setListener(const sp<IDrmPluginListener>& listener) {
         mListener = listener;
+        mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener);
         return Void();
     };
 
-    Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
+    Return<void> sendEvent(
+            EventType eventType,
+            const hidl_vec<uint8_t>& sessionId,
             const hidl_vec<uint8_t>& data) {
-        if (mListener != NULL) {
+        if (mListenerV1_2 != NULL) {
+            mListenerV1_2->sendEvent(eventType, sessionId, data);
+        } else if (mListener != NULL) {
             mListener->sendEvent(eventType, sessionId, data);
         } else {
             ALOGE("Null event listener, event not sent");
@@ -269,8 +301,12 @@
         return Void();
     }
 
-    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
-        if (mListener != NULL) {
+    Return<void> sendExpirationUpdate(
+            const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS) {
+        if (mListenerV1_2 != NULL) {
+            mListenerV1_2->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        } else if (mListener != NULL) {
             mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
         } else {
             ALOGE("Null event listener, event not sent");
@@ -278,9 +314,12 @@
         return Void();
     }
 
-    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+    Return<void> sendKeysChange(
+            const hidl_vec<uint8_t>& sessionId,
             const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
-        if (mListener != NULL) {
+        if (mListenerV1_2 != NULL) {
+            mListenerV1_2->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        } else if (mListener != NULL) {
             mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
         } else {
             ALOGE("Null event listener, event not sent");
@@ -288,6 +327,14 @@
         return Void();
     }
 
+    Return<void> sendSessionLostState(
+            const hidl_vec<uint8_t>& sessionId) {
+        if (mListenerV1_2 != NULL) {
+            mListenerV1_2->sendSessionLostState(sessionId);
+        }
+        return Void();
+    }
+
     Return<void> getSecureStops(getSecureStops_cb _hidl_cb);
 
     Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
@@ -314,13 +361,13 @@
     Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
             SecurityLevel level);
 
-    Status getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
+    Status_V1_2 getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
             const hidl_vec<uint8_t>& initData,
             const hidl_string& mimeType,
             KeyType keyType,
             const hidl_vec<KeyValue>& optionalParameters,
             std::vector<uint8_t> *request,
-            KeyRequestType *getKeyRequestType,
+            KeyRequestType_V1_1 *getKeyRequestType,
             std::string *defaultUrl);
 
     struct ClearkeySecureStop {
@@ -335,12 +382,21 @@
     std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
     std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
     sp<IDrmPluginListener> mListener;
+    sp<IDrmPluginListener_V1_2> mListenerV1_2;
     SessionLibrary *mSessionLibrary;
     int64_t mOpenSessionOkCount;
     int64_t mCloseSessionOkCount;
     int64_t mCloseSessionNotOpenedCount;
     uint32_t mNextSecureStopId;
 
+    // set by property to mock error scenarios
+    Status_V1_2 mMockError;
+
+    void processMockError(const sp<Session> &session) {
+        session->setMockError(mMockError);
+        mMockError = Status_V1_2::OK;
+    }
+
     DeviceFiles mFileHandle;
 
     CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
index f35560d..a159e5a 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
@@ -30,13 +30,16 @@
 namespace V1_2 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::Status;
+using drm::V1_0::SubSample;
+
+typedef drm::V1_2::Status Status_V1_2;
 
 class Session : public RefBase {
 public:
     explicit Session(const std::vector<uint8_t>& sessionId)
-            : mSessionId(sessionId) {}
+        : mSessionId(sessionId), mMockError(Status_V1_2::OK) {}
     virtual ~Session() {}
 
     const std::vector<uint8_t>& sessionId() const { return mSessionId; }
@@ -50,17 +53,23 @@
     Status provideKeyResponse(
             const std::vector<uint8_t>& response);
 
-    Status decrypt(
+    Status_V1_2 decrypt(
             const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
             uint8_t* dstPtr, const std::vector<SubSample> subSamples,
             size_t* bytesDecryptedOut);
 
+    void setMockError(Status_V1_2 error) {mMockError = error;}
+    Status_V1_2 getMockError() const {return mMockError;}
+
 private:
     CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Session);
 
     const std::vector<uint8_t> mSessionId;
     KeyMap mKeyMap;
     Mutex mMapLock;
+
+    // For mocking error return scenarios
+    Status_V1_2 mMockError;
 };
 
 } // namespace clearkey
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
index f6d30c9..b0f8607 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
@@ -68,6 +68,17 @@
     return vec;
 }
 
+inline Status toStatus_1_0(Status_V1_2 status) {
+  switch (status) {
+    case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
+    case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
+    case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
+      return Status::ERROR_DRM_UNKNOWN;
+    default:
+      return static_cast<Status>(status);
+  }
+}
+
 }  // namespace clearkey
 }  // namespace V1_2
 }  // namespace drm
diff --git a/include/media/DataSource.h b/include/media/DataSource.h
index 905bec1..198b27e 120000
--- a/include/media/DataSource.h
+++ b/include/media/DataSource.h
@@ -1 +1 @@
-../../media/libmediaextractor/include/media/DataSource.h
\ No newline at end of file
+stagefright/DataSource.h
\ No newline at end of file
diff --git a/include/media/DataSourceBase.h b/include/media/DataSourceBase.h
index 54c8047..d2ab2f1 120000
--- a/include/media/DataSourceBase.h
+++ b/include/media/DataSourceBase.h
@@ -1 +1 @@
-../../media/libmediaextractor/include/media/DataSourceBase.h
\ No newline at end of file
+stagefright/DataSourceBase.h
\ No newline at end of file
diff --git a/include/media/ExtractorUtils.h b/include/media/ExtractorUtils.h
deleted file mode 120000
index e2dd082..0000000
--- a/include/media/ExtractorUtils.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediaextractor/include/media/ExtractorUtils.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/ExtractorUtils.h b/include/media/ExtractorUtils.h
similarity index 100%
rename from media/libmediaextractor/include/media/ExtractorUtils.h
rename to include/media/ExtractorUtils.h
diff --git a/include/media/MediaSource.h b/include/media/MediaSource.h
index 2e147c4..34bf65d 120000
--- a/include/media/MediaSource.h
+++ b/include/media/MediaSource.h
@@ -1 +1 @@
-../../media/libmediaextractor/include/media/MediaSource.h
\ No newline at end of file
+../../media/libstagefright/include/media/stagefright/MediaSource.h
\ No newline at end of file
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index f1e815b..dfb1a3f 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -16,3 +16,6 @@
     stop audioserver
 on property:vts.native_server.on=0
     start audioserver
+
+on init
+    mkdir /dev/socket/audioserver 0775 audioserver audioserver
diff --git a/media/codec2/components/cmds/Android.bp b/media/codec2/components/cmds/Android.bp
index 6b0977b..35f689e 100644
--- a/media/codec2/components/cmds/Android.bp
+++ b/media/codec2/components/cmds/Android.bp
@@ -15,7 +15,6 @@
         "libcutils",
         "libgui",
         "liblog",
-        "libmediaextractor",
         "libstagefright",
         "libstagefright_foundation",
         "libui",
diff --git a/media/codec2/core/include/C2Component.h b/media/codec2/core/include/C2Component.h
index 8810725..ecf8d2e 100644
--- a/media/codec2/core/include/C2Component.h
+++ b/media/codec2/core/include/C2Component.h
@@ -409,12 +409,13 @@
         kind_t kind; ///< component kind
         rank_t rank; ///< component rank
         C2String mediaType; ///< media type supported by the component
+        C2String owner; ///< name of the component store owning this component
 
         /**
          * name alias(es) for backward compatibility.
          * \note Multiple components can have the same alias as long as their media-type differs.
          */
-        std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
+        std::vector<C2String> aliases; ///< name aliases for backward compatibility
     };
 
     // METHODS AVAILABLE WHEN RUNNING
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index 40be3b3..efc5c89 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -988,7 +988,10 @@
     /** specialization for easy enums */
     template<typename E>
     inline static NamedValuesType namedValuesFor(const C2EasyEnum<E> &) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         return namedValuesFor(*(E*)nullptr);
+#pragma GCC diagnostic pop
     }
 
 private:
@@ -1104,7 +1107,10 @@
 template<typename B>
 struct C2FieldDescriptor::_NamedValuesGetter<B, true> {
     inline static C2FieldDescriptor::NamedValuesType getNamedValues() {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         return C2FieldDescriptor::namedValuesFor(*(B*)nullptr);
+#pragma GCC diagnostic pop
     }
 };
 
@@ -1599,11 +1605,13 @@
     /// \internal
     /// \todo: create separate values vs. flags initializer as for flags we want
     /// to list both allowed and required flags
-    template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
+    template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)nullptr))>
     C2FieldSupportedValues(bool flags, const T*)
         : type(flags ? FLAGS : VALUES),
           range{(T)0, (T)0, (T)0, (T)0, (T)0} {
-              C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)0);
+              C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)nullptr);
         if (flags) {
             values.emplace_back(0); // min-mask defaults to 0
         }
@@ -1612,6 +1620,7 @@
         }
     }
 };
+#pragma GCC diagnostic pop
 
 /**
  * Supported values for a specific field.
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index ff3e534..f5cc9ff 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -557,6 +557,7 @@
                 for (size_t i = 0; i < t.size(); ++i) {
                     c2_status_t status = objcpy(
                             &mTraitsList[i], &mAliasesBuffer[i], t[i]);
+                    mTraitsList[i].owner = mInstanceName;
                     if (status != C2_OK) {
                         ALOGE("listComponents -- corrupted output.");
                         return;
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 184f215..a8cc62d 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -73,10 +73,10 @@
 constexpr OMX_U32 kMaxIndicesToCheck = 32;
 
 status_t queryOmxCapabilities(
-        const char* name, const char* mime, bool isEncoder,
+        const char* name, const char* mediaType, bool isEncoder,
         MediaCodecInfo::CapabilitiesWriter* caps) {
 
-    const char *role = GetComponentRole(isEncoder, mime);
+    const char *role = GetComponentRole(isEncoder, mediaType);
     if (role == nullptr) {
         return BAD_VALUE;
     }
@@ -128,8 +128,8 @@
         return err;
     }
 
-    bool isVideo = hasPrefix(mime, "video/") == 0;
-    bool isImage = hasPrefix(mime, "image/") == 0;
+    bool isVideo = hasPrefix(mediaType, "video/") == 0;
+    bool isImage = hasPrefix(mediaType, "image/") == 0;
 
     if (isVideo || isImage) {
         OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
@@ -149,7 +149,7 @@
             // AVC components may not list the constrained profiles explicitly, but
             // decoders that support a profile also support its constrained version.
             // Encoders must explicitly support constrained profiles.
-            if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
+            if (!isEncoder && strcasecmp(mediaType, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
                 if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
                     caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
                 } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
@@ -193,7 +193,7 @@
                         asString(portFormat.eColorFormat), portFormat.eColorFormat);
             }
         }
-    } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
+    } else if (strcasecmp(mediaType, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
         // More audio codecs if they have profiles.
         OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
         InitOMXParams(&param);
@@ -228,14 +228,17 @@
         if (omxNode->configureVideoTunnelMode(
                 kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
             // tunneled playback includes adaptive playback
-            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
-                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
-        } else if (omxNode->setPortMode(
-                kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
-                omxNode->prepareForAdaptivePlayback(
-                kPortIndexOutput, OMX_TRUE,
-                1280 /* width */, 720 /* height */) == OK) {
-            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
+        } else {
+            // tunneled playback is not supported
+            caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK);
+            if (omxNode->setPortMode(
+                    kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
+                    omxNode->prepareForAdaptivePlayback(
+                            kPortIndexOutput, OMX_TRUE,
+                            1280 /* width */, 720 /* height */) != OK) {
+                // adaptive playback is not supported
+                caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK);
+            }
         }
     }
 
@@ -243,11 +246,20 @@
         OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
         InitOMXParams(&params);
         params.nPortIndex = kPortIndexOutput;
-        // TODO: should we verify if fallback is supported?
+
+        OMX_VIDEO_PARAM_INTRAREFRESHTYPE fallbackParams;
+        InitOMXParams(&fallbackParams);
+        fallbackParams.nPortIndex = kPortIndexOutput;
+        fallbackParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
+
         if (omxNode->getConfig(
                 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
-                &params, sizeof(params)) == OK) {
-            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
+                &params, sizeof(params)) != OK &&
+                omxNode->getParameter(
+                    OMX_IndexParamVideoIntraRefresh, &fallbackParams,
+                    sizeof(fallbackParams)) != OK) {
+            // intra refresh is not supported
+            caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH);
         }
     }
 
@@ -270,12 +282,26 @@
                 writer->addMediaCodecInfo();
         info->setName(name.c_str());
         info->setOwner("default");
-        info->setEncoder(encoder);
+        typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0;
+        if (encoder) {
+            attrs |= MediaCodecInfo::kFlagIsEncoder;
+        }
+        // NOTE: we don't support software-only codecs in OMX
+        if (!hasPrefix(name, "OMX.google.")) {
+            attrs |= MediaCodecInfo::kFlagIsVendor;
+            if (properties.quirkSet.find("attribute::software-codec")
+                    == properties.quirkSet.end()) {
+                attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+            }
+        }
+        info->setAttributes(attrs);
         info->setRank(omxRank);
-        for (const MediaCodecsXmlParser::Type& type : properties.typeMap) {
-            const std::string &mime = type.first;
+        // OMX components don't have aliases
+        for (const MediaCodecsXmlParser::Type &type : properties.typeMap) {
+            const std::string &mediaType = type.first;
+
             std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
-                    info->addMime(mime.c_str());
+                    info->addMediaType(mediaType.c_str());
             const MediaCodecsXmlParser::AttributeMap &attrMap = type.second;
             for (const MediaCodecsXmlParser::Attribute& attr : attrMap) {
                 const std::string &key = attr.first;
@@ -289,13 +315,13 @@
             }
             status_t err = queryOmxCapabilities(
                     name.c_str(),
-                    mime.c_str(),
+                    mediaType.c_str(),
                     encoder,
                     caps.get());
             if (err != OK) {
-                ALOGE("Failed to query capabilities for %s (mime: %s). Error: %d",
+                ALOGI("Failed to query capabilities for %s (media type: %s). Error: %d",
                         name.c_str(),
-                        mime.c_str(),
+                        mediaType.c_str(),
                         static_cast<int>(err));
             }
         }
@@ -407,20 +433,40 @@
             break;
         }
 
+        ALOGV("canonName = %s", canonName.c_str());
         std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
         codecInfo->setName(trait.name.c_str());
-        codecInfo->setOwner("codec2");
+        codecInfo->setOwner(("codec2::" + trait.owner).c_str());
+        const MediaCodecsXmlParser::CodecProperties &codec = parser.getCodecMap().at(canonName);
+
         bool encoder = trait.kind == C2Component::KIND_ENCODER;
-        codecInfo->setEncoder(encoder);
+        typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0;
+
+        if (encoder) {
+            attrs |= MediaCodecInfo::kFlagIsEncoder;
+        }
+        if (trait.owner == "software") {
+            attrs |= MediaCodecInfo::kFlagIsSoftwareOnly;
+        } else {
+            attrs |= MediaCodecInfo::kFlagIsVendor;
+            if (trait.owner == "vendor-software") {
+                attrs |= MediaCodecInfo::kFlagIsSoftwareOnly;
+            } else if (codec.quirkSet.find("attribute::software-codec") == codec.quirkSet.end()) {
+                attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+            }
+        }
+        codecInfo->setAttributes(attrs);
         codecInfo->setRank(rank);
-        const MediaCodecsXmlParser::CodecProperties &codec =
-            parser.getCodecMap().at(canonName);
+
+        for (const std::string &alias : codec.aliases) {
+            codecInfo->addAlias(alias.c_str());
+        }
 
         for (auto typeIt = codec.typeMap.begin(); typeIt != codec.typeMap.end(); ++typeIt) {
             const std::string &mediaType = typeIt->first;
             const MediaCodecsXmlParser::AttributeMap &attrMap = typeIt->second;
             std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
-                codecInfo->addMime(mediaType.c_str());
+                codecInfo->addMediaType(mediaType.c_str());
             for (auto attrIt = attrMap.begin(); attrIt != attrMap.end(); ++attrIt) {
                 std::string key, value;
                 std::tie(key, value) = *attrIt;
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index df8de9b..ffeff42 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -280,8 +280,8 @@
     ReadOptions::SeekMode mode;
     if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
         size_t size;
-        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
-        mCurrentTimeUs = seekFrame * 20000ll;
+        int64_t seekFrame = seekTimeUs / 20000LL;  // 20ms per frame.
+        mCurrentTimeUs = seekFrame * 20000LL;
 
         size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
         if (index >= mOffsetTableLength) {
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index e4bbc07..84fbcee 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -806,14 +806,42 @@
 
 bool SniffFLAC(DataSourceHelper *source, float *confidence)
 {
-    // first 4 is the signature word
-    // second 4 is the sizeof STREAMINFO
-    // 042 is the mandatory STREAMINFO
-    // no need to read rest of the header, as a premature EOF will be caught later
-    uint8_t header[4+4];
-    if (source->readAt(0, header, sizeof(header)) != sizeof(header)
-            || memcmp("fLaC\0\0\0\042", header, 4+4))
-    {
+    // Skip ID3 tags
+    off64_t pos = 0;
+    uint8_t header[10];
+    for (;;) {
+        if (source->readAt(pos, header, sizeof(header)) != sizeof(header)) {
+            return false; // no more file to read.
+        }
+
+        // check for ID3 tag
+        if (memcmp("ID3", header, 3) != 0) {
+            break; // not an ID3 tag.
+        }
+
+        // skip the ID3v2 data and check again
+        const unsigned id3Len = 10 +
+                (((header[6] & 0x7f) << 21)
+                 | ((header[7] & 0x7f) << 14)
+                 | ((header[8] & 0x7f) << 7)
+                 | (header[9] & 0x7f));
+        pos += id3Len;
+
+        ALOGV("skipped ID3 tag of len %u new starting offset is %#016llx",
+                id3Len, (long long)pos);
+    }
+
+    // Check FLAC header.
+    // https://xiph.org/flac/format.html#stream
+    //
+    // Note: content stored big endian.
+    // byte offset  bit size  content
+    // 0            32        fLaC
+    // 4            8         metadata type STREAMINFO (0) (note: OR with 0x80 if last metadata)
+    // 5            24        size of metadata, for STREAMINFO (0x22).
+
+    if (memcmp("fLaC\x00\x00\x00\x22", header, 8) != 0 &&
+        memcmp("fLaC\x80\x00\x00\x22", header, 8) != 0) {
         return false;
     }
 
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 9eb72a7..ca51b88 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -71,7 +71,7 @@
     size_t numFrames = U32_AT(&vbriHeader[14]);
 
     int64_t durationUs =
-        numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
+        numFrames * 1000000LL * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
 
     ALOGV("duration = %.2f secs", durationUs / 1E6);
 
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index b816093..2a94671 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -28,9 +28,8 @@
 
     static_libs: [
         "libcrypto",
-        "libstagefright_foundation",
+        "libstagefright_foundation_without_imemory",
         "libstagefright_mpeg2support",
-        "libmediaextractor",
         "libutils",
         "libstagefright",
         "libstagefright_esds",
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 554d252..731584d 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -734,6 +734,9 @@
     if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
         AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
     }
+    if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+    }
     mbuf->release();
     return AMEDIA_OK;
 }
@@ -790,6 +793,7 @@
 }
 
 media_status_t MPEG2PSExtractor::WrappedTrack::start() {
+    mTrack->mBufferGroup = mBufferGroup;
     return mTrack->start();
 }
 
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 3bb2af7..e1509ee 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -224,6 +224,9 @@
     if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
         AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
     }
+    if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+    }
     mbuf->release();
     return AMEDIA_OK;
 }
@@ -373,7 +376,7 @@
         }
 
         // Wait only for 2 seconds to detect audio/video streams.
-        if (ALooper::GetNowUs() - startTime > 2000000ll) {
+        if (ALooper::GetNowUs() - startTime > 2000000LL) {
             break;
         }
     }
@@ -385,7 +388,7 @@
         List<int64_t> durations;
         // Estimate duration --- stabilize until you get <500ms deviation.
         while (feedMore() == OK
-                && ALooper::GetNowUs() - startTime <= 2000000ll) {
+                && ALooper::GetNowUs() - startTime <= 2000000LL) {
             if (mSeekSyncPoints->size() > prevSyncSize) {
                 prevSyncSize = mSeekSyncPoints->size();
                 int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 6efbfee..596c1c8 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -515,10 +515,10 @@
         ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes",
                 sizeof(header), (long long)offset, n);
 
-        if (n < 0) {
-            return n;
-        } else if (n == 0) {
+        if (n == 0 || n == ERROR_END_OF_STREAM) {
             return AMEDIA_ERROR_END_OF_STREAM;
+        } else if (n < 0) {
+            return AMEDIA_ERROR_UNKNOWN;
         } else {
             return AMEDIA_ERROR_IO;
         }
@@ -872,7 +872,7 @@
 
             ALOGV("readPage returned %zd", n);
 
-            return n == ERROR_END_OF_STREAM ? AMEDIA_ERROR_END_OF_STREAM : AMEDIA_ERROR_UNKNOWN;
+            return (media_status_t) n;
         }
 
         // Prevent a harmless unsigned integer overflow by clamping to 0
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 1493b26..8e36c77 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -373,6 +373,13 @@
      * so the recorded volume may be very low.
      */
     AAUDIO_INPUT_PRESET_UNPROCESSED = 9,
+
+    /**
+     * Use this preset for capturing audio meant to be processed in real time
+     * and played back for live performance (e.g karaoke).
+     * The capture path will minimize latency and coupling with playback path.
+     */
+    AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE = 10,
 };
 typedef int32_t aaudio_input_preset_t;
 
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index bd42697..88da53a 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -158,6 +158,7 @@
         case AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION:
         case AAUDIO_INPUT_PRESET_VOICE_RECOGNITION:
         case AAUDIO_INPUT_PRESET_UNPROCESSED:
+        case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
             break; // valid
         default:
             ALOGE("input preset not valid = %d", mInputPreset);
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index f5b3ad4..723cbf1 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -210,6 +210,7 @@
     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
     STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
+    STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
     if (preset == AAUDIO_UNSPECIFIED) {
         preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
     }
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index b01af25..dbf8712 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -130,6 +130,7 @@
     AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
     AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
     AAUDIO_INPUT_PRESET_UNPROCESSED,
+    AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
 };
 
 static void checkAttributesUsage(aaudio_performance_mode_t perfMode) {
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 9601d6d..3ab38cd 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -143,11 +143,18 @@
     return NO_ERROR;
 }
 
-void AudioMix::excludeUid(uid_t uid) const {
+void AudioMix::setExcludeUid(uid_t uid) const {
     AudioMixMatchCriterion crit;
     crit.mRule = RULE_EXCLUDE_UID;
     crit.mValue.mUid = uid;
     mCriteria.add(crit);
 }
 
+void AudioMix::setMatchUid(uid_t uid) const {
+    AudioMixMatchCriterion crit;
+    crit.mRule = RULE_MATCH_UID;
+    crit.mValue.mUid = uid;
+    mCriteria.add(crit);
+}
+
 } // namespace android
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 96e1235..786fb9a 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -100,7 +100,8 @@
     status_t readFromParcel(Parcel *parcel);
     status_t writeToParcel(Parcel *parcel) const;
 
-    void excludeUid(uid_t uid) const;
+    void setExcludeUid(uid_t uid) const;
+    void setMatchUid(uid_t uid) const;
 
     mutable Vector<AudioMixMatchCriterion> mCriteria;
     uint32_t        mMixType;
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 76b4adc..f39eb0c 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -115,6 +115,7 @@
         {AUDIO_SOURCE_VOICE_RECOGNITION, "voice_recognition"},
         {AUDIO_SOURCE_VOICE_COMMUNICATION, "voice_communication"},
         {AUDIO_SOURCE_UNPROCESSED, "unprocessed"},
+        {AUDIO_SOURCE_VOICE_PERFORMANCE, "voice_performance"},
 };
 
 /** Find the stream type enum corresponding to the stream type name or return false */
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 7d759e0..3efb5de 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -220,7 +220,6 @@
         "libexpat",
         "libcamera_client",
         "libstagefright_foundation",
-        "libmediaextractor",
         "libgui",
         "libdl",
         "libaudioutils",
@@ -277,7 +276,6 @@
         "libbinder",
         "libcutils",
         "liblog",
-        "libmediaextractor",
         "libmediandk",
         "libnativewindow",
         "libmediandk_utils",
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index 5308e1c..86ad997 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -28,6 +28,15 @@
 
 namespace android {
 
+/** This redundant redeclaration is needed for C++ pre 14 */
+constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_FRAME_PARSING[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];
+
 void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
         Vector<ProfileLevel> *profileLevels) const {
     profileLevels->clear();
@@ -40,16 +49,11 @@
     colorFormats->appendVector(mColorFormats);
 }
 
-uint32_t MediaCodecInfo::Capabilities::getFlags() const {
-    return mFlags;
-}
-
 const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
     return mDetails;
 }
 
-MediaCodecInfo::Capabilities::Capabilities()
-  : mFlags(0) {
+MediaCodecInfo::Capabilities::Capabilities() {
     mDetails = new AMessage;
 }
 
@@ -73,12 +77,10 @@
             caps->mColorFormats.push_back(color);
         }
     }
-    uint32_t flags = static_cast<uint32_t>(parcel.readInt32());
     sp<AMessage> details = AMessage::FromParcel(parcel);
     if (details == NULL)
         return NULL;
     if (caps != NULL) {
-        caps->mFlags = flags;
         caps->mDetails = details;
     }
     return caps;
@@ -96,7 +98,6 @@
     for (size_t i = 0; i < mColorFormats.size(); i++) {
         parcel->writeInt32(mColorFormats.itemAt(i));
     }
-    parcel->writeInt32(mFlags);
     mDetails->writeToParcel(parcel);
     return OK;
 }
@@ -111,6 +112,14 @@
     mCap->mDetails->setInt32(key, value);
 }
 
+void MediaCodecInfo::CapabilitiesWriter::removeDetail(const char* key) {
+    if (mCap->mDetails->removeEntryAt(mCap->mDetails->findEntryByName(key)) == OK) {
+        ALOGD("successfully removed detail %s", key);
+    } else {
+        ALOGD("detail %s wasn't present to remove", key);
+    }
+}
+
 void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
         uint32_t profile, uint32_t level) {
     ProfileLevel profileLevel;
@@ -129,32 +138,32 @@
     }
 }
 
-void MediaCodecInfo::CapabilitiesWriter::addFlags(uint32_t flags) {
-    mCap->mFlags |= flags;
-}
-
 MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
         MediaCodecInfo::Capabilities* cap) : mCap(cap) {
 }
 
-bool MediaCodecInfo::isEncoder() const {
-    return mIsEncoder;
+MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const {
+    return mAttributes;
 }
 
-uint32_t MediaCodecInfo::rank() const {
+uint32_t MediaCodecInfo::getRank() const {
     return mRank;
 }
 
-void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
-    mimes->clear();
+void MediaCodecInfo::getAliases(Vector<AString> *aliases) const {
+    *aliases = mAliases;
+}
+
+void MediaCodecInfo::getSupportedMediaTypes(Vector<AString> *mediaTypes) const {
+    mediaTypes->clear();
     for (size_t ix = 0; ix < mCaps.size(); ix++) {
-        mimes->push_back(mCaps.keyAt(ix));
+        mediaTypes->push_back(mCaps.keyAt(ix));
     }
 }
 
 const sp<MediaCodecInfo::Capabilities>
-MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
-    ssize_t ix = getCapabilityIndex(mime);
+MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const {
+    ssize_t ix = getCapabilityIndex(mediaType);
     if (ix >= 0) {
         return mCaps.valueAt(ix);
     }
@@ -173,21 +182,26 @@
 sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
     AString name = AString::FromParcel(parcel);
     AString owner = AString::FromParcel(parcel);
-    bool isEncoder = static_cast<bool>(parcel.readInt32());
+    Attributes attributes = static_cast<Attributes>(parcel.readInt32());
     uint32_t rank = parcel.readUint32();
     sp<MediaCodecInfo> info = new MediaCodecInfo;
     info->mName = name;
     info->mOwner = owner;
-    info->mIsEncoder = isEncoder;
+    info->mAttributes = attributes;
     info->mRank = rank;
+    size_t numAliases = static_cast<size_t>(parcel.readInt32());
+    for (size_t i = 0; i < numAliases; i++) {
+        AString alias = AString::FromParcel(parcel);
+        info->mAliases.add(alias);
+    }
     size_t size = static_cast<size_t>(parcel.readInt32());
     for (size_t i = 0; i < size; i++) {
-        AString mime = AString::FromParcel(parcel);
+        AString mediaType = AString::FromParcel(parcel);
         sp<Capabilities> caps = Capabilities::FromParcel(parcel);
         if (caps == NULL)
             return NULL;
         if (info != NULL) {
-            info->mCaps.add(mime, caps);
+            info->mCaps.add(mediaType, caps);
         }
     }
     return info;
@@ -196,8 +210,12 @@
 status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
     mName.writeToParcel(parcel);
     mOwner.writeToParcel(parcel);
-    parcel->writeInt32(mIsEncoder);
+    parcel->writeInt32(mAttributes);
     parcel->writeUint32(mRank);
+    parcel->writeInt32(mAliases.size());
+    for (const AString &alias : mAliases) {
+        alias.writeToParcel(parcel);
+    }
     parcel->writeInt32(mCaps.size());
     for (size_t i = 0; i < mCaps.size(); i++) {
         mCaps.keyAt(i).writeToParcel(parcel);
@@ -206,10 +224,10 @@
     return OK;
 }
 
-ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
-    if (mime) {
+ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const {
+    if (mediaType) {
         for (size_t ix = 0; ix < mCaps.size(); ix++) {
-            if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
+            if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
                 return ix;
             }
         }
@@ -217,19 +235,26 @@
     return -1;
 }
 
-MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
+MediaCodecInfo::MediaCodecInfo()
+    : mAttributes((MediaCodecInfo::Attributes)0),
+      mRank(0x100) {
 }
 
 void MediaCodecInfoWriter::setName(const char* name) {
     mInfo->mName = name;
 }
 
+void MediaCodecInfoWriter::addAlias(const char* name) {
+    mInfo->mAliases.add(name);
+}
+
 void MediaCodecInfoWriter::setOwner(const char* owner) {
     mInfo->mOwner = owner;
 }
 
-void MediaCodecInfoWriter::setEncoder(bool isEncoder) {
-    mInfo->mIsEncoder = isEncoder;
+void MediaCodecInfoWriter::setAttributes(
+        typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) {
+    mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes;
 }
 
 void MediaCodecInfoWriter::setRank(uint32_t rank) {
@@ -237,21 +262,21 @@
 }
 
 std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
-        MediaCodecInfoWriter::addMime(const char *mime) {
-    ssize_t ix = mInfo->getCapabilityIndex(mime);
+        MediaCodecInfoWriter::addMediaType(const char *mediaType) {
+    ssize_t ix = mInfo->getCapabilityIndex(mediaType);
     if (ix >= 0) {
         return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
                 new MediaCodecInfo::CapabilitiesWriter(
                 mInfo->mCaps.valueAt(ix).get()));
     }
     sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
-    mInfo->mCaps.add(AString(mime), caps);
+    mInfo->mCaps.add(AString(mediaType), caps);
     return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
             new MediaCodecInfo::CapabilitiesWriter(caps.get()));
 }
 
-bool MediaCodecInfoWriter::removeMime(const char *mime) {
-    ssize_t ix = mInfo->getCapabilityIndex(mime);
+bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) {
+    ssize_t ix = mInfo->getCapabilityIndex(mediaType);
     if (ix >= 0) {
         mInfo->mCaps.removeItemsAt(ix);
         return true;
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index b5a7172..0ab0e9b 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -93,6 +93,8 @@
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ECHO_REFERENCE),
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
     // STUB must be after DEFAULT, so the latter is picked up by toString first.
     MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
@@ -357,6 +359,8 @@
     MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_COMMUNICATION),
     MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_REMOTE_SUBMIX),
     MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_UNPROCESSED),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_PERFORMANCE),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_ECHO_REFERENCE),
     MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_FM_TUNER),
     MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_HOTWORD),
     TERMINATOR
diff --git a/media/libmedia/include/media/CryptoHal.h b/media/libmedia/include/media/CryptoHal.h
index ff8789d..73c029f 100644
--- a/media/libmedia/include/media/CryptoHal.h
+++ b/media/libmedia/include/media/CryptoHal.h
@@ -21,6 +21,7 @@
 #include <android/hardware/drm/1.0/ICryptoFactory.h>
 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
 #include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
 
 #include <mediadrm/ICrypto.h>
 #include <utils/KeyedVector.h>
@@ -72,6 +73,7 @@
 
     const Vector<sp<ICryptoFactory>> mFactories;
     sp<ICryptoPlugin> mPlugin;
+    sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
 
     /**
      * mInitCheck is:
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index 3302982..de0f3c7 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -20,11 +20,11 @@
 
 #include <android/hardware/drm/1.0/IDrmFactory.h>
 #include <android/hardware/drm/1.0/IDrmPlugin.h>
-#include <android/hardware/drm/1.0/IDrmPluginListener.h>
 #include <android/hardware/drm/1.1/IDrmFactory.h>
 #include <android/hardware/drm/1.1/IDrmPlugin.h>
 #include <android/hardware/drm/1.2/IDrmFactory.h>
 #include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
 
 #include <media/MediaAnalyticsItem.h>
 #include <mediadrm/DrmMetrics.h>
@@ -43,6 +43,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
+typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+
 namespace android {
 
 struct DrmSessionClientInterface;
@@ -54,7 +56,7 @@
 
 struct DrmHal : public BnDrm,
              public IBinder::DeathRecipient,
-             public IDrmPluginListener {
+                public IDrmPluginListener_V1_2 {
     DrmHal();
     virtual ~DrmHal();
 
@@ -176,6 +178,8 @@
     Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
             const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
 
+    Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
+
     virtual void binderDied(const wp<IBinder> &the_late_who);
 
 private:
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index b3777d3..54f565a 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -30,6 +30,8 @@
 #include <utils/Vector.h>
 #include <utils/StrongPointer.h>
 
+#include <type_traits>
+
 namespace android {
 
 struct AMessage;
@@ -51,21 +53,47 @@
 
     struct CapabilitiesWriter;
 
+    enum Attributes : int32_t {
+        // attribute flags
+        kFlagIsEncoder = 1 << 0,
+        kFlagIsVendor = 1 << 1,
+        kFlagIsSoftwareOnly = 1 << 2,
+        kFlagIsHardwareAccelerated = 1 << 3,
+    };
+
     struct Capabilities : public RefBase {
-        enum {
-            // decoder flags
-            kFlagSupportsAdaptivePlayback = 1 << 0,
-            kFlagSupportsSecurePlayback = 1 << 1,
-            kFlagSupportsTunneledPlayback = 1 << 2,
+        constexpr static char FEATURE_ADAPTIVE_PLAYBACK[] = "feature-adaptive-playback";
+        constexpr static char FEATURE_DYNAMIC_TIMESTAMP[] = "feature-dynamic-timestamp";
+        constexpr static char FEATURE_FRAME_PARSING[] = "feature-frame-parsing";
+        constexpr static char FEATURE_INTRA_REFRESH[] = "feature-frame-parsing";
+        constexpr static char FEATURE_MULTIPLE_FRAMES[] = "feature-multiple-frames";
+        constexpr static char FEATURE_SECURE_PLAYBACK[] = "feature-secure-playback";
+        constexpr static char FEATURE_TUNNELED_PLAYBACK[] = "feature-tunneled-playback";
 
-            // encoder flags
-            kFlagSupportsIntraRefresh = 1 << 0,
-
-        };
-
+        /**
+         * Returns the supported levels for each supported profile in a target array.
+         *
+         * @param profileLevels target array for the profile levels.
+         */
         void getSupportedProfileLevels(Vector<ProfileLevel> *profileLevels) const;
+
+        /**
+         * Returns the supported color formats in a target array. Only used for video/image
+         * components.
+         *
+         * @param colorFormats target array for the color formats.
+         */
         void getSupportedColorFormats(Vector<uint32_t> *colorFormats) const;
-        uint32_t getFlags() const;
+
+        /**
+         * Returns metadata associated with this codec capability.
+         *
+         * This contains:
+         * - features,
+         * - performance data.
+         *
+         * TODO: expose this as separate API-s and wrap here.
+         */
         const sp<AMessage> getDetails() const;
 
     protected:
@@ -73,7 +101,6 @@
         SortedVector<ProfileLevel> mProfileLevelsSorted;
         Vector<uint32_t> mColorFormats;
         SortedVector<uint32_t> mColorFormatsSorted;
-        uint32_t mFlags;
         sp<AMessage> mDetails;
 
         Capabilities();
@@ -93,8 +120,7 @@
     /**
      * This class is used for modifying information inside a `Capabilities`
      * object. An object of type `CapabilitiesWriter` can be obtained by calling
-     * `MediaCodecInfoWriter::addMime()` or
-     * `MediaCodecInfoWriter::updateMime()`.
+     * `MediaCodecInfoWriter::addMediaType()`.
      */
     struct CapabilitiesWriter {
         /**
@@ -122,6 +148,13 @@
          */
         void addDetail(const char* key, int32_t value);
         /**
+         * Removes a key-value pair from the list of details. If the key is not
+         * present, this call does nothing.
+         *
+         * @param key The key.
+         */
+        void removeDetail(const char* key);
+        /**
          * Add a profile-level pair. If this profile-level pair already exists,
          * it will be ignored.
          *
@@ -136,13 +169,7 @@
          * @param format The color format.
          */
         void addColorFormat(uint32_t format);
-        /**
-         * Add flags. The underlying operation is bitwise-or. In other words,
-         * bits that have already been set will be ignored.
-         *
-         * @param flags The additional flags.
-         */
-        void addFlags(uint32_t flags);
+
     private:
         /**
          * The associated `Capabilities` object.
@@ -158,19 +185,42 @@
         friend MediaCodecInfoWriter;
     };
 
-    bool isEncoder() const;
-    void getSupportedMimes(Vector<AString> *mimes) const;
-    const sp<Capabilities> getCapabilitiesFor(const char *mime) const;
+    inline bool isEncoder() const {
+        return getAttributes() & kFlagIsEncoder;
+    }
+
+    Attributes getAttributes() const;
+    void getSupportedMediaTypes(Vector<AString> *mediaTypes) const;
+    const sp<Capabilities> getCapabilitiesFor(const char *mediaType) const;
     const char *getCodecName() const;
 
     /**
+     * Returns a vector containing alternate names for the codec.
+     *
+     * \param aliases the destination array for the aliases. This is cleared.
+     *
+     * Multiple codecs may share alternate names as long as their supported media types are
+     * distinct; however, these will result in different aliases for the MediaCodec user as
+     * the canonical codec has to be resolved without knowing the media type in
+     * MediaCodec::CreateByComponentName.
+     */
+    void getAliases(Vector<AString> *aliases) const;
+
+    /**
      * Return the name of the service that hosts the codec. This value is not
      * visible at the Java level.
      *
      * Currently, this is the "instance name" of the IOmx service.
      */
     const char *getOwnerName() const;
-    uint32_t rank() const;
+
+    /**
+     * Returns the rank of the component.
+     *
+     * Technically this is defined to be per media type, but that makes ordering the MediaCodecList
+     * impossible as MediaCodecList is ordered by codec name.
+     */
+    uint32_t getRank() const;
 
     /**
      * Serialization over Binder
@@ -181,11 +231,12 @@
 private:
     AString mName;
     AString mOwner;
-    bool mIsEncoder;
+    Attributes mAttributes;
     KeyedVector<AString, sp<Capabilities> > mCaps;
+    Vector<AString> mAliases;
     uint32_t mRank;
 
-    ssize_t getCapabilityIndex(const char *mime) const;
+    ssize_t getCapabilityIndex(const char *mediaType) const;
 
     /**
      * Construct an `MediaCodecInfo` object. After the construction, its
@@ -219,6 +270,13 @@
      */
     void setName(const char* name);
     /**
+     * Adds an alias (alternate name) for the codec. Multiple codecs can share an alternate name
+     * as long as their supported media types are distinct.
+     *
+     * @param name an alternate name.
+     */
+    void addAlias(const char* name);
+    /**
      * Set the owner name of the codec.
      *
      * This "owner name" is the name of the `IOmx` instance that supports this
@@ -228,32 +286,32 @@
      */
     void setOwner(const char* owner);
     /**
-     * Set whether this codec is an encoder or a decoder.
+     * Sets codec attributes.
      *
-     * @param isEncoder Whether this codec is an encoder or a decoder.
+     * @param attributes Codec attributes.
      */
-    void setEncoder(bool isEncoder = true);
+    void setAttributes(typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes);
     /**
-     * Add a mime to an indexed list and return a `CapabilitiesWriter` object
+     * Add a media type to an indexed list and return a `CapabilitiesWriter` object
      * that can be used for modifying the associated `Capabilities`.
      *
-     * If the mime already exists, this function will return the
-     * `CapabilitiesWriter` associated with the mime.
+     * If the media type already exists, this function will return the
+     * `CapabilitiesWriter` associated with the media type.
      *
-     * @param[in] mime The name of a new mime to add.
+     * @param[in] mediaType The name of a new media type to add.
      * @return writer The `CapabilitiesWriter` object for modifying the
-     * `Capabilities` associated with the mime. `writer` will be valid
-     * regardless of whether `mime` already exists or not.
+     * `Capabilities` associated with the media type. `writer` will be valid
+     * regardless of whether `mediaType` already exists or not.
      */
-    std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMime(
-            const char* mime);
+    std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMediaType(
+            const char* mediaType);
     /**
-     * Remove a mime.
+     * Remove a media type.
      *
-     * @param mime The name of the mime to remove.
-     * @return `true` if `mime` is removed; `false` if `mime` is not found.
+     * @param mediaType The name of the media type to remove.
+     * @return `true` if `mediaType` is removed; `false` if `mediaType` is not found.
      */
-    bool removeMime(const char* mime);
+    bool removeMediaType(const char* mediaType);
     /**
      * Set rank of the codec. MediaCodecList will stable-sort the list according
      * to rank in non-descending order.
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
deleted file mode 100644
index 4758cd6..0000000
--- a/media/libmediaextractor/Android.bp
+++ /dev/null
@@ -1,60 +0,0 @@
-cc_library {
-    name: "libmediaextractor",
-
-    include_dirs: [
-        "frameworks/av/include",
-        "frameworks/av/media/libmediaextractor/include",
-    ],
-
-    export_include_dirs: ["include"],
-
-    cflags: [
-        "-Wno-multichar",
-        "-Werror",
-        "-Wall",
-    ],
-
-    static: {
-        cflags: [
-            "-Wno-multichar",
-            "-Werror",
-            "-Wall",
-            "-DNO_IMEMORY",
-        ],
-    },
-
-    shared_libs: [
-        "libbinder",
-        "libstagefright_foundation",
-        "libutils",
-        "liblog",
-    ],
-
-    header_libs: [
-        "media_ndk_headers",
-    ],
-
-    export_header_lib_headers: [
-        "media_ndk_headers",
-    ],
-
-    srcs: [
-        "DataSourceBase.cpp",
-        "MediaBuffer.cpp",
-        "MediaBufferBase.cpp",
-        "MediaBufferGroup.cpp",
-        "MediaSource.cpp",
-        "MetaData.cpp",
-        "MetaDataBase.cpp",
-    ],
-
-    clang: true,
-
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-}
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 38f42dc..b3f7404 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -21,7 +21,6 @@
         "libgui",
         "liblog",
         "libmedia_omx",
-        "libmediaextractor",
         "libstagefright_foundation",
         "libui",
         "libutils",
diff --git a/media/libmediaplayer2/JavaVMHelper.cpp b/media/libmediaplayer2/JavaVMHelper.cpp
index 90aaa7f..8d03ed0 100644
--- a/media/libmediaplayer2/JavaVMHelper.cpp
+++ b/media/libmediaplayer2/JavaVMHelper.cpp
@@ -19,6 +19,7 @@
 #include "mediaplayer2/JavaVMHelper.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <utils/threads.h>
 
 #include <stdlib.h>
 
@@ -27,6 +28,109 @@
 // static
 std::atomic<JavaVM *> JavaVMHelper::sJavaVM(NULL);
 
+/*
+ * Makes the current thread visible to the VM.
+ *
+ * The JNIEnv pointer returned is only valid for the current thread, and
+ * thus must be tucked into thread-local storage.
+ */
+static int javaAttachThread(const char* threadName, JNIEnv** pEnv) {
+    JavaVMAttachArgs args;
+    JavaVM* vm;
+    jint result;
+
+    vm = JavaVMHelper::getJavaVM();
+    if (vm == NULL) {
+        return JNI_ERR;
+    }
+
+    args.version = JNI_VERSION_1_4;
+    args.name = (char*) threadName;
+    args.group = NULL;
+
+    result = vm->AttachCurrentThread(pEnv, (void*) &args);
+    if (result != JNI_OK) {
+        ALOGI("NOTE: attach of thread '%s' failed\n", threadName);
+    }
+
+    return result;
+}
+
+/*
+ * Detach the current thread from the set visible to the VM.
+ */
+static int javaDetachThread(void) {
+    JavaVM* vm;
+    jint result;
+
+    vm = JavaVMHelper::getJavaVM();
+    if (vm == NULL) {
+        return JNI_ERR;
+    }
+
+    result = vm->DetachCurrentThread();
+    if (result != JNI_OK) {
+        ALOGE("ERROR: thread detach failed\n");
+    }
+    return result;
+}
+
+/*
+ * When starting a native thread that will be visible from the VM, we
+ * bounce through this to get the right attach/detach action.
+ * Note that this function calls free(args)
+ */
+static int javaThreadShell(void* args) {
+    void* start = ((void**)args)[0];
+    void* userData = ((void **)args)[1];
+    char* name = (char*) ((void **)args)[2];        // we own this storage
+    free(args);
+    JNIEnv* env;
+    int result;
+
+    /* hook us into the VM */
+    if (javaAttachThread(name, &env) != JNI_OK) {
+        return -1;
+    }
+
+    /* start the thread running */
+    result = (*(android_thread_func_t)start)(userData);
+
+    /* unhook us */
+    javaDetachThread();
+    free(name);
+
+    return result;
+}
+
+/*
+ * This is invoked from androidCreateThreadEtc() via the callback
+ * set with androidSetCreateThreadFunc().
+ *
+ * We need to create the new thread in such a way that it gets hooked
+ * into the VM before it really starts executing.
+ */
+static int javaCreateThreadEtc(
+        android_thread_func_t entryFunction,
+        void* userData,
+        const char* threadName,
+        int32_t threadPriority,
+        size_t threadStackSize,
+        android_thread_id_t* threadId) {
+    void** args = (void**) malloc(3 * sizeof(void*));   // javaThreadShell must free
+    int result;
+
+    LOG_ALWAYS_FATAL_IF(threadName == nullptr, "threadName not provided to javaCreateThreadEtc");
+
+    args[0] = (void*) entryFunction;
+    args[1] = userData;
+    args[2] = (void*) strdup(threadName);   // javaThreadShell must free
+
+    result = androidCreateRawThreadEtc(javaThreadShell, args,
+        threadName, threadPriority, threadStackSize, threadId);
+    return result;
+}
+
 // static
 JNIEnv *JavaVMHelper::getJNIEnv() {
     JNIEnv *env;
@@ -40,9 +144,19 @@
     return env;
 }
 
+//static
+JavaVM *JavaVMHelper::getJavaVM() {
+    return sJavaVM.load();
+}
+
 // static
 void JavaVMHelper::setJavaVM(JavaVM *vm) {
     sJavaVM.store(vm);
+
+    // Ensure that Thread(/*canCallJava*/ true) in libutils is attached to the VM.
+    // This is supposed to be done by runtime, but when libutils is used with linker
+    // namespace, CreateThreadFunc should be initialized separately within the namespace.
+    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
 }
 
 }  // namespace android
diff --git a/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h b/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
index 35091b7..4b56aca 100644
--- a/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
+++ b/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
@@ -26,6 +26,7 @@
 
 struct JavaVMHelper {
     static JNIEnv *getJNIEnv();
+    static JavaVM *getJavaVM();
     static void setJavaVM(JavaVM *vm);
 
 private:
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 51879fd..55867a5 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -24,7 +24,6 @@
         "liblog",
         "libmedia",
         "libmedia_omx",
-        "libmediaextractor",
         "libmediadrm",
         "libmediametrics",
         "libmediautils",
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index fd53090..f556e37 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -284,6 +284,15 @@
 EntryIterator DumpReader::handleFormat(const FormatEntry &fmtEntry,
         String8 *timestamp, String8 *body)
 {
+    String8 timestampLocal;
+    String8 bodyLocal;
+    if (timestamp == nullptr) {
+        timestamp = &timestampLocal;
+    }
+    if (body == nullptr) {
+        body = &bodyLocal;
+    }
+
     // log timestamp
     const int64_t ts = fmtEntry.timestamp();
     timestamp->clear();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 2ea5286..a1a2660 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -566,8 +566,8 @@
       mDequeueCounter(0),
       mMetadataBuffersToSubmit(0),
       mNumUndequeuedBuffers(0),
-      mRepeatFrameDelayUs(-1ll),
-      mMaxPtsGapUs(0ll),
+      mRepeatFrameDelayUs(-1LL),
+      mMaxPtsGapUs(0LL),
       mMaxFps(-1),
       mFps(-1.0),
       mCaptureFps(-1.0),
@@ -1822,15 +1822,15 @@
         if (!msg->findInt64(
                     "repeat-previous-frame-after",
                     &mRepeatFrameDelayUs)) {
-            mRepeatFrameDelayUs = -1ll;
+            mRepeatFrameDelayUs = -1LL;
         }
 
         // only allow 32-bit value, since we pass it as U32 to OMX.
         if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
-            mMaxPtsGapUs = 0ll;
+            mMaxPtsGapUs = 0LL;
         } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
             ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
-            mMaxPtsGapUs = 0ll;
+            mMaxPtsGapUs = 0LL;
         }
 
         if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
@@ -1838,7 +1838,7 @@
         }
 
         // notify GraphicBufferSource to allow backward frames
-        if (mMaxPtsGapUs < 0ll) {
+        if (mMaxPtsGapUs < 0LL) {
             mMaxFps = -1;
         }
 
@@ -6707,7 +6707,7 @@
 
     mCodec->mDequeueCounter = 0;
     mCodec->mMetadataBuffersToSubmit = 0;
-    mCodec->mRepeatFrameDelayUs = -1ll;
+    mCodec->mRepeatFrameDelayUs = -1LL;
     mCodec->mInputFormat.clear();
     mCodec->mOutputFormat.clear();
     mCodec->mBaseOutputFormat.clear();
@@ -6849,7 +6849,7 @@
         return err;
     }
 
-    if (mCodec->mRepeatFrameDelayUs > 0ll) {
+    if (mCodec->mRepeatFrameDelayUs > 0LL) {
         err = statusFromBinderStatus(
                 mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
                         mCodec->mRepeatFrameDelayUs));
@@ -6862,7 +6862,7 @@
         }
     }
 
-    if (mCodec->mMaxPtsGapUs != 0ll) {
+    if (mCodec->mMaxPtsGapUs != 0LL) {
         OMX_PARAM_U32TYPE maxPtsGapParams;
         InitOMXParams(&maxPtsGapParams);
         maxPtsGapParams.nPortIndex = kPortIndexInput;
@@ -8682,14 +8682,17 @@
         if (omxNode->configureVideoTunnelMode(
                 kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
             // tunneled playback includes adaptive playback
-            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
-                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
-        } else if (omxNode->setPortMode(
-                kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
-                omxNode->prepareForAdaptivePlayback(
-                kPortIndexOutput, OMX_TRUE,
-                1280 /* width */, 720 /* height */) == OK) {
-            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
+        } else {
+            // tunneled playback is not supported
+            caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK);
+            if (omxNode->setPortMode(
+                    kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) != OK &&
+                    omxNode->prepareForAdaptivePlayback(
+                        kPortIndexOutput, OMX_TRUE,
+                        1280 /* width */, 720 /* height */) != OK) {
+                // adaptive playback is not supported
+                caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK);
+            }
         }
     }
 
@@ -8697,11 +8700,20 @@
         OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
         InitOMXParams(&params);
         params.nPortIndex = kPortIndexOutput;
-        // TODO: should we verify if fallback is supported?
+
+        OMX_VIDEO_PARAM_INTRAREFRESHTYPE fallbackParams;
+        InitOMXParams(&fallbackParams);
+        fallbackParams.nPortIndex = kPortIndexOutput;
+        fallbackParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
+
         if (omxNode->getConfig(
                 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
-                &params, sizeof(params)) == OK) {
-            caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
+                &params, sizeof(params)) != OK &&
+                omxNode->getParameter(
+                    OMX_IndexParamVideoIntraRefresh, &fallbackParams,
+                    sizeof(fallbackParams)) != OK) {
+            // intra refresh is not supported
+            caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH);
         }
     }
 
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 249f2a4..f45cc58 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -94,6 +94,7 @@
         "CameraSource.cpp",
         "CameraSourceTimeLapse.cpp",
         "DataConverter.cpp",
+        "DataSourceBase.cpp",
         "DataSourceFactory.cpp",
         "DataURISource.cpp",
         "ClearFileSource.cpp",
@@ -113,6 +114,7 @@
         "MediaCodecSource.cpp",
         "MediaExtractor.cpp",
         "MediaExtractorFactory.cpp",
+        "MediaSource.cpp",
         "MediaSync.cpp",
         "MediaTrack.cpp",
         "http/ClearMediaHTTP.cpp",
@@ -150,7 +152,6 @@
         "libmedia",
         "libmedia_omx",
         "libaudioclient",
-        "libmediaextractor",
         "libmediametrics",
         "libmediautils",
         "libui",
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 9de1e22..5027303 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -337,7 +337,7 @@
     } else {
         // This should not happen in normal case.
         ALOGW("Failed to get audio timestamp, fallback to use systemclock");
-        timeUs = systemTime() / 1000ll;
+        timeUs = systemTime() / 1000LL;
         // Estimate the real sampling time of the 1st sample in this buffer
         // from AudioRecord's latency. (Apply this adjustment first so that
         // the start time logic is not affected.)
diff --git a/media/libmediaextractor/DataSourceBase.cpp b/media/libstagefright/DataSourceBase.cpp
similarity index 100%
rename from media/libmediaextractor/DataSourceBase.cpp
rename to media/libstagefright/DataSourceBase.cpp
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index c62c05a..42b98b1 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -39,7 +39,7 @@
 
 namespace android {
 
-static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec
+static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
 static const size_t kRetryCount = 50; // must be >0
 
 sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
@@ -274,7 +274,7 @@
     size_t retriesLeft = kRetryCount;
     do {
         size_t index;
-        int64_t ptsUs = 0ll;
+        int64_t ptsUs = 0LL;
         uint32_t flags = 0;
 
         // Queue as many inputs as we possibly can, then block on dequeuing
@@ -406,7 +406,7 @@
     : FrameDecoder(componentName, trackMeta, source),
       mIsAvcOrHevc(false),
       mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
-      mTargetTimeUs(-1ll),
+      mTargetTimeUs(-1LL),
       mNumFrames(0),
       mNumFramesDecoded(0) {
 }
@@ -487,7 +487,7 @@
         const sp<MediaCodecBuffer> &videoFrameBuffer,
         const sp<AMessage> &outputFormat,
         int64_t timeUs, bool *done) {
-    bool shouldOutput = (mTargetTimeUs < 0ll) || (timeUs >= mTargetTimeUs);
+    bool shouldOutput = (mTargetTimeUs < 0LL) || (timeUs >= mTargetTimeUs);
 
     // If this is not the target frame, skip color convert.
     if (!shouldOutput) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 770535c..a9715c9 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -240,7 +240,7 @@
         size -= length;
     }
 
-    out->meta()->setInt64("timeUs", 0ll);
+    out->meta()->setInt64("timeUs", 0LL);
 
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", kNotifyBuffer);
@@ -842,7 +842,7 @@
     int64_t timeUs;
     CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
 
-    uint32_t PTS = (timeUs * 9ll) / 100ll;
+    uint32_t PTS = (timeUs * 9LL) / 100LL;
 
     size_t PES_packet_length = accessUnit->size() + 8;
     bool padding = (accessUnit->size() < (188 - 18));
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index b45eb03..7df1a2d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -487,7 +487,7 @@
 
     mInterleaveDurationUs = 1000000;
 
-    mStartTimestampUs = -1ll;
+    mStartTimestampUs = -1LL;
     mStartTimeOffsetMs = -1;
     mStartTimeOffsetBFramesUs = 0;
     mPaused = false;
@@ -1745,7 +1745,7 @@
 
 void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
     ALOGI("setStartTimestampUs: %" PRId64, timeUs);
-    CHECK_GE(timeUs, 0ll);
+    CHECK_GE(timeUs, 0LL);
     Mutex::Autolock autoLock(mLock);
     if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
         mStartTimestampUs = timeUs;
@@ -3099,7 +3099,7 @@
 
             if (mResumed) {
                 int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
-                if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
+                if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0LL, "for %s track", trackName)) {
                     copy->release();
                     mSource->stop();
                     mIsMalformed = true;
@@ -3120,7 +3120,7 @@
             TimestampDebugHelperEntry timestampDebugEntry;
             timestampUs -= previousPausedDurationUs;
             timestampDebugEntry.pts = timestampUs;
-            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+            if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
                 copy->release();
                 mSource->stop();
                 mIsMalformed = true;
@@ -3159,7 +3159,7 @@
 
                 cttsOffsetTimeUs =
                         timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
-                if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
+                if (WARN_UNLESS(cttsOffsetTimeUs >= 0LL, "for %s track", trackName)) {
                     copy->release();
                     mSource->stop();
                     mIsMalformed = true;
@@ -3217,7 +3217,7 @@
                 }
             }
 
-            if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+            if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
                 copy->release();
                 mSource->stop();
                 mIsMalformed = true;
@@ -3238,7 +3238,7 @@
             currDurationTicks =
                 ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
-            if (currDurationTicks < 0ll) {
+            if (currDurationTicks < 0LL) {
                 ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
                         (long long)timestampUs, (long long)lastTimestampUs, trackName);
                 copy->release();
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 41dbfd4..4f9bc6d 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -28,7 +28,7 @@
 
 // Maximum allowed time backwards from anchor change.
 // If larger than this threshold, it's treated as discontinuity.
-static const int64_t kAnchorFluctuationAllowedUs = 10000ll;
+static const int64_t kAnchorFluctuationAllowedUs = 10000LL;
 
 MediaClock::Timer::Timer(const sp<AMessage> &notify, int64_t mediaTimeUs, int64_t adjustRealUs)
     : mNotify(notify),
@@ -110,7 +110,7 @@
     if (mAnchorTimeRealUs != -1) {
         int64_t oldNowMediaUs =
             mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
-        if (nowMediaUs < oldNowMediaUs
+        if (nowMediaUs < oldNowMediaUs + kAnchorFluctuationAllowedUs
                 && nowMediaUs > oldNowMediaUs - kAnchorFluctuationAllowedUs) {
             return;
         }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index bd9e2bb..2547888 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -911,10 +911,10 @@
             continue;
         }
         mCodecInfo = mcl->getCodecInfo(codecIdx);
-        Vector<AString> mimes;
-        mCodecInfo->getSupportedMimes(&mimes);
-        for (size_t i = 0; i < mimes.size(); i++) {
-            if (mimes[i].startsWith("video/")) {
+        Vector<AString> mediaTypes;
+        mCodecInfo->getSupportedMediaTypes(&mediaTypes);
+        for (size_t i = 0; i < mediaTypes.size(); i++) {
+            if (mediaTypes[i].startsWith("video/")) {
                 mIsVideo = true;
                 break;
             }
@@ -2699,7 +2699,7 @@
             int64_t timeoutUs;
             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
 
-            if (timeoutUs == 0ll) {
+            if (timeoutUs == 0LL) {
                 PostReplyWithError(replyID, -EAGAIN);
                 break;
             }
@@ -2707,7 +2707,7 @@
             mFlags |= kFlagDequeueInputPending;
             mDequeueInputReplyID = replyID;
 
-            if (timeoutUs > 0ll) {
+            if (timeoutUs > 0LL) {
                 sp<AMessage> timeoutMsg =
                     new AMessage(kWhatDequeueInputTimedOut, this);
                 timeoutMsg->setInt32(
@@ -2773,7 +2773,7 @@
             int64_t timeoutUs;
             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
 
-            if (timeoutUs == 0ll) {
+            if (timeoutUs == 0LL) {
                 PostReplyWithError(replyID, -EAGAIN);
                 break;
             }
@@ -2781,7 +2781,7 @@
             mFlags |= kFlagDequeueOutputPending;
             mDequeueOutputReplyID = replyID;
 
-            if (timeoutUs > 0ll) {
+            if (timeoutUs > 0LL) {
                 sp<AMessage> timeoutMsg =
                     new AMessage(kWhatDequeueOutputTimedOut, this);
                 timeoutMsg->setInt32(
@@ -3042,7 +3042,7 @@
     msg->setSize("index", bufferIndex);
     msg->setSize("offset", 0);
     msg->setSize("size", csd->size());
-    msg->setInt64("timeUs", 0ll);
+    msg->setInt64("timeUs", 0LL);
     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
     msg->setPointer("errorDetailMsg", &errorDetailMsg);
 
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index eaff283..93478e9 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -215,13 +215,9 @@
             mCodecInfos.begin(),
             mCodecInfos.end(),
             [](const sp<MediaCodecInfo> &info1, const sp<MediaCodecInfo> &info2) {
-                if (info2 == nullptr) {
-                    return false;
-                } else if (info1 == nullptr) {
-                    return true;
-                } else {
-                    return info1->rank() < info2->rank();
-                }
+                // null is lowest
+                return info1 == nullptr
+                        || (info2 != nullptr && info1->getRank() < info2->getRank());
             });
 }
 
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index cac53f4..dd7c3e6 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -228,18 +228,18 @@
             continue;
         }
 
-        Vector<AString> mimes;
-        info->getSupportedMimes(&mimes);
-        for (size_t i = 0; i < mimes.size(); ++i) {
+        Vector<AString> mediaTypes;
+        info->getSupportedMediaTypes(&mediaTypes);
+        for (size_t i = 0; i < mediaTypes.size(); ++i) {
             const sp<MediaCodecInfo::Capabilities> &caps =
-                    info->getCapabilitiesFor(mimes[i].c_str());
+                    info->getCapabilitiesFor(mediaTypes[i].c_str());
             if (!forceToMeasure &&
                 (caps->getDetails()->contains("max-supported-instances") ||
                  caps->getDetails()->contains("max-concurrent-instances"))) {
                 continue;
             }
 
-            size_t max = doProfileCodecs(info->isEncoder(), name, mimes[i], caps);
+            size_t max = doProfileCodecs(info->isEncoder(), name, mediaTypes[i], caps);
             if (max > 0) {
                 CodecSettings settings;
                 char maxStr[32];
@@ -248,7 +248,7 @@
 
                 AString key = name;
                 key.append(" ");
-                key.append(mimes[i]);
+                key.append(mediaTypes[i]);
 
                 if (info->isEncoder()) {
                     encoder_results->add(key, settings);
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 20881a4..0f75822 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -372,7 +372,7 @@
     msg->postAndAwaitResponse(&response);
     int64_t timeUs;
     if (!response->findInt64("time-us", &timeUs)) {
-        timeUs = -1ll;
+        timeUs = -1LL;
     }
     return timeUs;
 }
@@ -452,9 +452,9 @@
       mEncoderDataSpace(0),
       mPersistentSurface(persistentSurface),
       mInputBufferTimeOffsetUs(0),
-      mFirstSampleSystemTimeUs(-1ll),
+      mFirstSampleSystemTimeUs(-1LL),
       mPausePending(false),
-      mFirstSampleTimeUs(-1ll),
+      mFirstSampleTimeUs(-1LL),
       mGeneration(0) {
     CHECK(mLooper != NULL);
 
@@ -687,13 +687,13 @@
         size_t bufferIndex = *mAvailEncoderInputIndices.begin();
         mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
 
-        int64_t timeUs = 0ll;
+        int64_t timeUs = 0LL;
         uint32_t flags = 0;
         size_t size = 0;
 
         if (mbuf != NULL) {
             CHECK(mbuf->meta_data().findInt64(kKeyTime, &timeUs));
-            if (mFirstSampleSystemTimeUs < 0ll) {
+            if (mFirstSampleSystemTimeUs < 0LL) {
                 mFirstSampleSystemTimeUs = systemTime() / 1000;
                 if (mPausePending) {
                     mPausePending = false;
@@ -767,7 +767,7 @@
     }
     int64_t startTimeUs;
     if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
-        startTimeUs = -1ll;
+        startTimeUs = -1LL;
     }
 
     if (mStarted) {
@@ -914,7 +914,7 @@
                 if (mIsVideo) {
                     int64_t decodingTimeUs;
                     if (mFlags & FLAG_USE_SURFACE_INPUT) {
-                        if (mFirstSampleSystemTimeUs < 0ll) {
+                        if (mFirstSampleSystemTimeUs < 0LL) {
                             mFirstSampleSystemTimeUs = systemTime() / 1000;
                             if (mPausePending) {
                                 mPausePending = false;
@@ -926,7 +926,7 @@
                         // Timestamp offset is already adjusted in GraphicBufferSource.
                         // GraphicBufferSource is supposed to discard samples
                         // queued before start, and offset timeUs by start time
-                        CHECK_GE(timeUs, 0ll);
+                        CHECK_GE(timeUs, 0LL);
                         // TODO:
                         // Decoding time for surface source is unavailable,
                         // use presentation time for now. May need to move
@@ -954,7 +954,7 @@
                 }
                 mbuf->meta_data().setInt64(kKeyTime, timeUs);
             } else {
-                mbuf->meta_data().setInt64(kKeyTime, 0ll);
+                mbuf->meta_data().setInt64(kKeyTime, 0LL);
                 mbuf->meta_data().setInt32(kKeyIsCodecConfig, true);
             }
             if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
@@ -1081,7 +1081,7 @@
             MetaData *params = static_cast<MetaData *>(obj.get());
             int64_t pauseStartTimeUs = -1;
             if (params == NULL || !params->findInt64(kKeyTime, &pauseStartTimeUs)) {
-                pauseStartTimeUs = -1ll;
+                pauseStartTimeUs = -1LL;
             }
             onPause(pauseStartTimeUs);
         }
diff --git a/media/libmediaextractor/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
similarity index 100%
rename from media/libmediaextractor/MediaSource.cpp
rename to media/libstagefright/MediaSource.cpp
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ba14e5d..a3f55da 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -36,7 +36,7 @@
 
 // Maximum late time allowed for a video frame to be rendered. When a video
 // frame arrives later than this number, it will be discarded without rendering.
-static const int64_t kMaxAllowedVideoLateTimeUs = 40000ll;
+static const int64_t kMaxAllowedVideoLateTimeUs = 40000LL;
 
 namespace android {
 
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index f158491..036e79d 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -172,6 +172,10 @@
             meta.setData(kKeySEI,
                     MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
         }
+        if (format->mFormat->findBuffer("audio-presentation-info", &valbuf)) {
+            meta.setData(kKeyAudioPresentationInfo,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
     } else {
         *buffer = nullptr;
     }
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 7025af7..522c81d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -440,12 +440,12 @@
     if (mFetching) {
         if (mFinalStatus != OK && mNumRetriesLeft > 0) {
             // We failed this time and will try again in 3 seconds.
-            delayUs = 3000000ll;
+            delayUs = 3000000LL;
         } else {
             delayUs = 0;
         }
     } else {
-        delayUs = 100000ll;
+        delayUs = 100000LL;
     }
 
     (new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
@@ -740,7 +740,7 @@
     }
 
     if (keepAliveSecs >= 0) {
-        mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
+        mKeepAliveIntervalUs = keepAliveSecs * 1000000LL;
     } else {
         mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
     }
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f5178dd..83b87d9 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -41,7 +41,7 @@
 
 NuMediaExtractor::Sample::Sample()
     : mBuffer(NULL),
-      mSampleTimeUs(-1ll) {
+      mSampleTimeUs(-1LL) {
 }
 
 NuMediaExtractor::Sample::Sample(MediaBufferBase *buffer, int64_t timeUs)
@@ -50,8 +50,8 @@
 }
 
 NuMediaExtractor::NuMediaExtractor()
-    : mTotalBitrate(-1ll),
-      mDurationUs(-1ll) {
+    : mTotalBitrate(-1LL),
+      mDurationUs(-1LL) {
 }
 
 NuMediaExtractor::~NuMediaExtractor() {
@@ -209,8 +209,8 @@
         return ERROR_UNSUPPORTED;
     }
 
-    mTotalBitrate = 0ll;
-    mDurationUs = -1ll;
+    mTotalBitrate = 0LL;
+    mDurationUs = -1LL;
 
     for (size_t i = 0; i < mImpl->countTracks(); ++i) {
         sp<MetaData> meta = mImpl->getTrackMetaData(i);
@@ -225,8 +225,8 @@
             CHECK(meta->findCString(kKeyMIMEType, &mime));
             ALOGV("track of type '%s' does not publish bitrate", mime);
 
-            mTotalBitrate = -1ll;
-        } else if (mTotalBitrate >= 0ll) {
+            mTotalBitrate = -1LL;
+        } else if (mTotalBitrate >= 0LL) {
             mTotalBitrate += bitrate;
         }
 
@@ -503,7 +503,7 @@
     }
 
     MediaSource::ReadOptions options;
-    if (seekTimeUs >= 0ll) {
+    if (seekTimeUs >= 0LL) {
         options.setSeekTo(seekTimeUs, mode);
         info->mFinalResult = OK;
         releaseTrackSamples(info);
@@ -768,7 +768,7 @@
 
     off64_t size;
     if (mDurationUs > 0 && mDataSource->getSize(&size) == OK) {
-        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
+        *bitrate = size * 8000000LL / mDurationUs;  // in bits/sec
         return true;
     }
 
@@ -795,30 +795,34 @@
 }
 
 // Return OK if we have received an audio presentation info.
+// Return ERROR_END_OF_STREAM if no tracks are available.
 // Return ERROR_UNSUPPORTED if the track has no audio presentation.
 // Return INVALID_OPERATION if audio presentation metadata version does not match.
 status_t NuMediaExtractor::getAudioPresentations(
-        size_t trackIndex, AudioPresentationCollection *presentations) const {
+        size_t trackIndex, AudioPresentationCollection *presentations) {
     Mutex::Autolock autoLock(mLock);
-
-    if (mImpl == NULL) {
-        return -EINVAL;
+    ssize_t minIndex = fetchAllTrackSamples();
+    if (minIndex < 0) {
+        return ERROR_END_OF_STREAM;
     }
+    for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+        TrackInfo *info = &mSelectedTracks.editItemAt(i);
 
-    if (trackIndex >= mImpl->countTracks()) {
-        return -ERANGE;
+        if (info->mTrackIndex == trackIndex) {
+            sp<MetaData> meta = new MetaData(info->mSamples.begin()->mBuffer->meta_data());
+
+            uint32_t type;
+            const void *data;
+            size_t size;
+            if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
+                std::istringstream inStream(std::string(static_cast<const char*>(data), size));
+                return deserializeAudioPresentations(&inStream, presentations);
+            }
+            ALOGV("Track %zu does not contain any audio presentation", trackIndex);
+            return ERROR_UNSUPPORTED;
+        }
     }
-
-    sp<MetaData> meta = mImpl->getTrackMetaData(trackIndex);
-
-    uint32_t type;
-    const void *data;
-    size_t size;
-    if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
-        std::istringstream inStream(std::string(static_cast<const char*>(data), size));
-        return deserializeAudioPresentations(&inStream, presentations);
-    }
-    ALOGE("Source does not contain any audio presentation");
+    ALOGV("Source does not contain any audio presentation");
     return ERROR_UNSUPPORTED;
 }
 
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index 96b896b..382c947 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -57,14 +57,9 @@
 }
 
 status_t queryCapabilities(
-        const IOmxStore::NodeInfo& node, const char* mime, bool isEncoder,
+        const IOmxStore::NodeInfo& node, const char* mediaType, bool isEncoder,
         MediaCodecInfo::CapabilitiesWriter* caps) {
     sp<ACodec> codec = new ACodec();
-    status_t err = codec->queryCapabilities(
-            node.owner.c_str(), node.name.c_str(), mime, isEncoder, caps);
-    if (err != OK) {
-        return err;
-    }
     for (const auto& attribute : node.attributes) {
         // All features have an int32 value except
         // "feature-bitrate-modes", which has a string value.
@@ -81,6 +76,12 @@
                     attribute.key.c_str(), attribute.value.c_str());
         }
     }
+    // query capabilities may remove capabilities that are not actually supported by the codec
+    status_t err = codec->queryCapabilities(
+            node.owner.c_str(), node.name.c_str(), mediaType, isEncoder, caps);
+    if (err != OK) {
+        return err;
+    }
     return OK;
 }
 
@@ -163,7 +164,10 @@
                     info = c2i->second.get();
                     info->setName(nodeName.c_str());
                     info->setOwner(node.owner.c_str());
-                    info->setEncoder(isEncoder);
+                    info->setAttributes(
+                            // all OMX codecs are vendor codecs (in the vendor partition), but
+                            // treat OMX.google codecs as non-hardware-accelerated and  non-vendor
+                            (isEncoder ? MediaCodecInfo::kFlagIsEncoder : 0));
                     info->setRank(defaultRank);
                 } else {
                     // The node has been seen before. Simply retrieve the
@@ -180,7 +184,19 @@
                         info = c2i->second.get();
                         info->setName(nodeName.c_str());
                         info->setOwner(node.owner.c_str());
-                        info->setEncoder(isEncoder);
+                        typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs =
+                            MediaCodecInfo::kFlagIsVendor;
+                        if (isEncoder) {
+                            attrs |= MediaCodecInfo::kFlagIsEncoder;
+                        }
+                        if (std::count_if(
+                                node.attributes.begin(), node.attributes.end(),
+                                [](const IOmxStore::Attribute &i) -> bool {
+                                    return i.key == "attribute::software-codec";
+                                                                          })) {
+                            attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+                        }
+                        info->setAttributes(attrs);
                         info->setRank(defaultRank);
                     } else {
                         // If preferPlatformNodes is true, this node must be
@@ -195,12 +211,12 @@
                 }
             }
             std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
-                    info->addMime(typeName.c_str());
+                    info->addMediaType(typeName.c_str());
             if (queryCapabilities(
                     node, typeName.c_str(), isEncoder, caps.get()) != OK) {
-                ALOGW("Fail to add mime %s to codec %s",
+                ALOGW("Fail to add media type %s to codec %s",
                         typeName.c_str(), nodeName.c_str());
-                info->removeMime(typeName.c_str());
+                info->removeMediaType(typeName.c_str());
             }
         }
 
@@ -219,7 +235,18 @@
                     info = c2i->second.get();
                     info->setName(nodeName.c_str());
                     info->setOwner(node->owner.c_str());
-                    info->setEncoder(isEncoder);
+                    typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs =
+                        MediaCodecInfo::kFlagIsVendor;
+                    if (isEncoder) {
+                        attrs |= MediaCodecInfo::kFlagIsEncoder;
+                    }
+                    if (std::count_if(
+                            node->attributes.begin(), node->attributes.end(),
+                            [](const IOmxStore::Attribute &i) -> bool {
+                                return i.key == "attribute::software-codec";
+                                                                      })) {
+                        attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+                    }
                     info->setRank(defaultRank);
                 } else {
                     // The node has been seen before. Simply retrieve the
@@ -227,13 +254,13 @@
                     info = c2i->second.get();
                 }
                 std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
-                        info->addMime(typeName.c_str());
+                        info->addMediaType(typeName.c_str());
                 if (queryCapabilities(
                         *node, typeName.c_str(), isEncoder, caps.get()) != OK) {
-                    ALOGW("Fail to add mime %s to codec %s "
+                    ALOGW("Fail to add media type %s to codec %s "
                           "after software codecs",
                           typeName.c_str(), nodeName.c_str());
-                    info->removeMime(typeName.c_str());
+                    info->removeMediaType(typeName.c_str());
                 }
             }
         }
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 74b7340..cf4edae 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -127,6 +127,8 @@
         { "colorstandard", METADATA_KEY_COLOR_STANDARD },
         { "colortransfer", METADATA_KEY_COLOR_TRANSFER },
         { "colorrange", METADATA_KEY_COLOR_RANGE },
+        { "samplerate", METADATA_KEY_SAMPLERATE },
+        { "bitspersample", METADATA_KEY_BITS_PER_SAMPLE },
     };
     static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
 
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
index 7496752..49cea9e 100644
--- a/media/libstagefright/ThrottledSource.cpp
+++ b/media/libstagefright/ThrottledSource.cpp
@@ -51,7 +51,7 @@
     // How long would it have taken to transfer everything we ever
     // transferred given the limited bandwidth.
     int64_t durationUs =
-        mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
+        mTotalTransferred * 1000000LL / mBandwidthLimitBytesPerSecond;
 
     int64_t whenUs = mStartTimeUs + durationUs;
 
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 163cd05..49e485a 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -2020,7 +2020,7 @@
 
 HLSTime::HLSTime(const sp<AMessage>& meta) :
     mSeq(-1),
-    mTimeUs(-1ll),
+    mTimeUs(-1LL),
     mMeta(meta) {
     if (meta != NULL) {
         CHECK(meta->findInt32("discontinuitySeq", &mSeq));
@@ -2029,7 +2029,7 @@
 }
 
 int64_t HLSTime::getSegmentTimeUs() const {
-    int64_t segmentStartTimeUs = -1ll;
+    int64_t segmentStartTimeUs = -1LL;
     if (mMeta != NULL) {
         CHECK(mMeta->findInt64("segmentStartTimeUs", &segmentStartTimeUs));
 
diff --git a/media/libstagefright/VideoFrameScheduler2.cpp b/media/libstagefright/VideoFrameScheduler2.cpp
index e02ae7d..fc76904 100644
--- a/media/libstagefright/VideoFrameScheduler2.cpp
+++ b/media/libstagefright/VideoFrameScheduler2.cpp
@@ -36,7 +36,7 @@
 
 namespace android {
 
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr);
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr);
 
 /* ======================================================================= */
 /*                               VsyncTracker                              */
@@ -46,19 +46,19 @@
 public:
     VsyncTracker();
     ~VsyncTracker() {}
-    long getVsyncPeriod();
-    long getVsyncTime(long periodOffset);
-    void addSample(long timestamp);
+    nsecs_t getVsyncPeriod();
+    nsecs_t getVsyncTime(nsecs_t periodOffset);
+    void addSample(nsecs_t timestamp);
 
 private:
     static const int kMaxSamples = 32;
     static const int kMinSamplesForUpdate = 6;
     int mNumSamples;
     int mFirstSample;
-    long mReferenceTime;
-    long mPhase;
-    long mPeriod;
-    long mTimestampSamples[kMaxSamples];
+    nsecs_t mReferenceTime;
+    nsecs_t mPhase;
+    nsecs_t mPeriod;
+    nsecs_t mTimestampSamples[kMaxSamples];
     Mutex mLock;
 
     void updateModelLocked();
@@ -75,19 +75,39 @@
     }
 }
 
-long VsyncTracker::getVsyncPeriod() {
+nsecs_t VsyncTracker::getVsyncPeriod() {
     Mutex::Autolock dataLock(mLock);
     return mPeriod;
 }
 
-long VsyncTracker::getVsyncTime(long periodOffset) {
+nsecs_t VsyncTracker::getVsyncTime(nsecs_t periodOffset) {
     Mutex::Autolock dataLock(mLock);
-    const long now = systemTime();
-    long phase = mReferenceTime + mPhase;
-    return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+    const nsecs_t now = systemTime();
+    nsecs_t phase = mReferenceTime + mPhase;
+
+    // result = (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase
+    // prevent overflow
+    nsecs_t result = (now - phase) / mPeriod;
+    if (result > LONG_LONG_MAX - periodOffset - 1) {
+        return LONG_LONG_MAX;
+    } else {
+        result += periodOffset + 1;
+    }
+    if (result > LONG_LONG_MAX / mPeriod) {
+        return LONG_LONG_MAX;
+    } else {
+        result *= mPeriod;
+    }
+    if (result > LONG_LONG_MAX - phase) {
+        return LONG_LONG_MAX;
+    } else {
+        result += phase;
+    }
+
+    return result;
 }
 
-void VsyncTracker::addSample(long timestamp) {
+void VsyncTracker::addSample(nsecs_t timestamp) {
     Mutex::Autolock dataLock(mLock);
     if (mNumSamples == 0) {
         mPhase = 0;
@@ -107,17 +127,17 @@
     if (mNumSamples < kMinSamplesForUpdate) {
         return;
     }
-    long durationSum = 0;
-    long minDuration = LONG_MAX;
-    long maxDuration = 0;
+    nsecs_t durationSum = 0;
+    nsecs_t minDuration = LONG_MAX;
+    nsecs_t maxDuration = 0;
 
     for (int i = 1; i < mNumSamples; i++) {
         int idx = (mFirstSample + i) % kMaxSamples;
         int prev = (idx + kMaxSamples - 1) % kMaxSamples;
         long duration = mTimestampSamples[idx] - mTimestampSamples[prev];
         durationSum += duration;
-        minDuration = min(minDuration, duration);
-        maxDuration = max(maxDuration, duration);
+        if (minDuration > duration) { minDuration = duration; }
+        if (maxDuration < duration) { maxDuration = duration; }
     }
 
     durationSum -= (minDuration + maxDuration);
@@ -154,9 +174,9 @@
 /*                                   JNI                                   */
 /* ======================================================================= */
 
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr) {
-    static const long kOneMillisecInNanosec = 1000000;
-    static const long kOneSecInNanosec = kOneMillisecInNanosec * 1000;
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr) {
+    static const nsecs_t kOneMillisecInNanosec = 1000000;
+    static const nsecs_t kOneSecInNanosec = kOneMillisecInNanosec * 1000;
 
     JNIEnv *env = JavaVMHelper::getJNIEnv();
     jclass jDisplayManagerGlobalCls = env->FindClass(
@@ -178,19 +198,19 @@
 
     jmethodID jGetRefreshRate = env->GetMethodID(jDisplayCls, "getRefreshRate", "()F");
     jfloat javaRefreshRate = env->CallFloatMethod(javaDisplayObj, jGetRefreshRate);
-    long vsyncPeriod = (long) (kOneSecInNanosec / (float) javaRefreshRate);
+    nsecs_t vsyncPeriod = (nsecs_t) (kOneSecInNanosec / (float) javaRefreshRate);
 
     jmethodID jGetAppVsyncOffsetNanos = env->GetMethodID(
             jDisplayCls, "getAppVsyncOffsetNanos", "()J");
     jlong javaAppVsyncOffset = env->CallLongMethod(javaDisplayObj, jGetAppVsyncOffsetNanos);
-    *appVsyncOffsetPtr = (long) javaAppVsyncOffset;
+    *appVsyncOffsetPtr = (nsecs_t) javaAppVsyncOffset;
 
     jmethodID jGetPresentationDeadlineNanos = env->GetMethodID(
             jDisplayCls, "getPresentationDeadlineNanos", "()J");
     jlong javaPresentationDeadline = env->CallLongMethod(
             javaDisplayObj, jGetPresentationDeadlineNanos);
 
-    *sfVsyncOffsetPtr = vsyncPeriod - ((long) javaPresentationDeadline - kOneMillisecInNanosec);
+    *sfVsyncOffsetPtr = vsyncPeriod - ((nsecs_t) javaPresentationDeadline - kOneMillisecInNanosec);
 }
 
 /* ======================================================================= */
diff --git a/media/libstagefright/bqhelper/FrameDropper.cpp b/media/libstagefright/bqhelper/FrameDropper.cpp
index d2a2473..387ac5a 100644
--- a/media/libstagefright/bqhelper/FrameDropper.cpp
+++ b/media/libstagefright/bqhelper/FrameDropper.cpp
@@ -35,7 +35,7 @@
 
 status_t FrameDropper::setMaxFrameRate(float maxFrameRate) {
     if (maxFrameRate < 0) {
-        mMinIntervalUs = -1ll;
+        mMinIntervalUs = -1LL;
         return OK;
     }
 
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 8c1da76..a4374c9 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -292,20 +292,20 @@
     mSuspended(false),
     mLastFrameTimestampUs(-1),
     mStopTimeUs(-1),
-    mLastActionTimeUs(-1ll),
-    mSkipFramesBeforeNs(-1ll),
-    mFrameRepeatIntervalUs(-1ll),
+    mLastActionTimeUs(-1LL),
+    mSkipFramesBeforeNs(-1LL),
+    mFrameRepeatIntervalUs(-1LL),
     mRepeatLastFrameGeneration(0),
     mOutstandingFrameRepeatCount(0),
     mFrameRepeatBlockedOnCodecBuffer(false),
     mFps(-1.0),
     mCaptureFps(-1.0),
-    mBaseCaptureUs(-1ll),
-    mBaseFrameUs(-1ll),
+    mBaseCaptureUs(-1LL),
+    mBaseFrameUs(-1LL),
     mFrameCount(0),
-    mPrevCaptureUs(-1ll),
-    mPrevFrameUs(-1ll),
-    mInputBufferTimeOffsetUs(0ll) {
+    mPrevCaptureUs(-1LL),
+    mPrevFrameUs(-1LL),
+    mInputBufferTimeOffsetUs(0LL) {
     ALOGV("GraphicBufferSource");
 
     String8 name("GraphicBufferSource");
@@ -392,7 +392,7 @@
         submitEndOfInputStream_l();
     }
 
-    if (mFrameRepeatIntervalUs > 0ll && mLooper == NULL) {
+    if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
         mReflector = new AHandlerReflector<GraphicBufferSource>(this);
 
         mLooper = new ALooper;
@@ -655,7 +655,7 @@
 
     // only submit sample if start time is unspecified, or sample
     // is queued after the specified start time
-    if (mSkipFramesBeforeNs < 0ll || item.mTimestampNs >= mSkipFramesBeforeNs) {
+    if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
         // if start time is set, offset time stamp by start time
         if (mSkipFramesBeforeNs > 0) {
             item.mTimestampNs -= mSkipFramesBeforeNs;
@@ -677,7 +677,7 @@
     } else {
         // Don't set the last buffer id if we're not repeating,
         // we'll be holding on to the last buffer for nothing.
-        if (mFrameRepeatIntervalUs > 0ll) {
+        if (mFrameRepeatIntervalUs > 0LL) {
             setLatestBuffer_l(item);
         }
         ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
@@ -755,7 +755,7 @@
             && (mFps > 2 * mCaptureFps
             || mCaptureFps > 2 * mFps)) {
         // Time lapse or slow motion mode
-        if (mPrevCaptureUs < 0ll) {
+        if (mPrevCaptureUs < 0LL) {
             // first capture
             mPrevCaptureUs = mBaseCaptureUs = timeUs;
             // adjust the first sample timestamp.
@@ -1123,19 +1123,19 @@
         mSuspended = false;
         mEndOfStream = false;
         mEndOfStreamSent = false;
-        mSkipFramesBeforeNs = -1ll;
+        mSkipFramesBeforeNs = -1LL;
         mFrameDropper.clear();
-        mFrameRepeatIntervalUs = -1ll;
+        mFrameRepeatIntervalUs = -1LL;
         mRepeatLastFrameGeneration = 0;
         mOutstandingFrameRepeatCount = 0;
         mLatestBuffer.mBuffer.reset();
         mFrameRepeatBlockedOnCodecBuffer = false;
         mFps = -1.0;
         mCaptureFps = -1.0;
-        mBaseCaptureUs = -1ll;
-        mBaseFrameUs = -1ll;
-        mPrevCaptureUs = -1ll;
-        mPrevFrameUs = -1ll;
+        mBaseCaptureUs = -1LL;
+        mBaseFrameUs = -1LL;
+        mPrevCaptureUs = -1LL;
+        mPrevFrameUs = -1LL;
         mFrameCount = 0;
         mInputBufferTimeOffsetUs = 0;
         mStopTimeUs = -1;
@@ -1201,7 +1201,7 @@
 
     Mutex::Autolock autoLock(mMutex);
 
-    if (mExecuting || repeatAfterUs <= 0ll) {
+    if (mExecuting || repeatAfterUs <= 0LL) {
         return INVALID_OPERATION;
     }
 
@@ -1213,7 +1213,7 @@
     Mutex::Autolock autoLock(mMutex);
 
     // timeOffsetUs must be negative for adjustment.
-    if (timeOffsetUs >= 0ll) {
+    if (timeOffsetUs >= 0LL) {
         return INVALID_OPERATION;
     }
 
@@ -1247,7 +1247,7 @@
 
     mSkipFramesBeforeNs =
             (skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
-            (skipFramesBeforeUs * 1000) : -1ll;
+            (skipFramesBeforeUs * 1000) : -1LL;
 
     return OK;
 }
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index d393c7a..41bc16c 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -738,7 +738,7 @@
                 } else {
                     int64_t currentTime = mBufferTimestamps.top();
                     currentTime += mStreamInfo->aacSamplesPerFrame *
-                            1000000ll / mStreamInfo->aacSampleRate;
+                            1000000LL / mStreamInfo->aacSampleRate;
                     mBufferTimestamps.add(currentTime);
                 }
             } else {
@@ -989,7 +989,7 @@
                         // adjust/interpolate next time stamp
                         *currentBufLeft -= decodedSize;
                         *nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
-                                1000000ll / mStreamInfo->aacSampleRate;
+                                1000000LL / mStreamInfo->aacSampleRate;
                         ALOGV("adjusted nextTimeStamp/size to %lld/%d",
                                 (long long) *nextTimeStamp, *currentBufLeft);
                     } else {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 96e668e..6e437cf 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -63,7 +63,7 @@
       mInputSize(0),
       mInputFrame(NULL),
       mAllocatedFrameSize(0),
-      mInputTimeUs(-1ll),
+      mInputTimeUs(-1LL),
       mSawInputEOS(false),
       mSignalledError(false) {
     initPorts();
@@ -587,7 +587,7 @@
             // "Time" on the input buffer has in effect advanced by the
             // number of audio frames we just advanced nOffset by.
             inHeader->nTimeStamp +=
-                (copy * 1000000ll / mSampleRate)
+                (copy * 1000000LL / mSampleRate)
                     / (mNumChannels * sizeof(int16_t));
 
             if (inHeader->nFilledLen == 0) {
@@ -725,7 +725,7 @@
     mAllocatedFrameSize = 0;
 
     mSentCodecSpecificData = false;
-    mInputTimeUs = -1ll;
+    mInputTimeUs = -1LL;
     mSawInputEOS = false;
     mSignalledError = false;
 }
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index b7e84ec..34dd011 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -505,7 +505,7 @@
 
             outHeader->nTimeStamp =
                 mAnchorTimeUs
-                    + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;
+                    + (mNumSamplesOutput * 1000000LL) / kSampleRateNB;
 
             mNumSamplesOutput += kNumSamplesPerFrameNB;
         } else {
@@ -513,7 +513,7 @@
 
             outHeader->nTimeStamp =
                 mAnchorTimeUs
-                    + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;
+                    + (mNumSamplesOutput * 1000000LL) / kSampleRateWB;
 
             mNumSamplesOutput += kNumSamplesPerFrameWB;
         }
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index f97c44f..85ab64e 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -49,7 +49,7 @@
       mBitRate(0),
       mMode(MR475),
       mInputSize(0),
-      mInputTimeUs(-1ll),
+      mInputTimeUs(-1LL),
       mSawInputEOS(false),
       mSignalledError(false) {
     initPorts();
@@ -340,7 +340,7 @@
             // "Time" on the input buffer has in effect advanced by the
             // number of audio frames we just advanced nOffset by.
             inHeader->nTimeStamp +=
-                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+                (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
 
             if (inHeader->nFilledLen == 0) {
                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index a644b66..7fb8a4c 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -50,7 +50,7 @@
       mBitRate(0),
       mMode(VOAMRWB_MD66),
       mInputSize(0),
-      mInputTimeUs(-1ll),
+      mInputTimeUs(-1LL),
       mSawInputEOS(false),
       mSignalledError(false) {
     initPorts();
@@ -387,7 +387,7 @@
             // "Time" on the input buffer has in effect advanced by the
             // number of audio frames we just advanced nOffset by.
             inHeader->nTimeStamp +=
-                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+                (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
 
             if (inHeader->nFilledLen == 0) {
                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 3924fc2..bf5e243 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -607,7 +607,7 @@
             timeTaken = mTimeEnd - mTimeStart;
 
             ALOGV("timeTaken=%6lldus delay=%6lldus numBytes=%6d",
-                    (long long) (timeTaken / 1000ll), (long long) (timeDelay / 1000ll),
+                    (long long) (timeTaken / 1000LL), (long long) (timeDelay / 1000LL),
                    s_dec_op.u4_num_bytes_consumed);
             if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
                 mFlushNeeded = true;
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 7a4cca9..c14983a 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -372,7 +372,7 @@
 
         int32_t step = 4 << segment;
 
-        int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
+        int32_t abs = (0x80L << exponent) + step * mantissa + step / 2 - 4 * 33;
 
         *out++ = (x < 0x80) ? -abs : abs;
     }
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index fda7028..a8fcdd1 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -382,6 +382,7 @@
     if (portIndex == 0 && mInitialized) {
         CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE);
     }
+    mFramesConfigured = false;
 }
 
 void SoftMPEG4::onReset() {
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index cd984f0..80083f7 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -407,7 +407,7 @@
         }
 
         outHeader->nTimeStamp =
-            mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
+            mAnchorTimeUs + (mNumFramesOutput * 1000000LL) / mSamplingRate;
 
         if (inHeader) {
             CHECK_GE((int32_t)inHeader->nFilledLen, mConfig->inputBufferUsedLength);
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index c6dc326..4f61aa8 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -582,7 +582,7 @@
         outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
 
         outHeader->nTimeStamp = mAnchorTimeUs +
-                                (mNumFramesOutput * 1000000ll) /
+                                (mNumFramesOutput * 1000000LL) /
                                 kRate;
 
         mNumFramesOutput += numFrames;
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index ce8d458..76a400c 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -554,7 +554,7 @@
 
         outHeader->nTimeStamp =
             mAnchorTimeUs
-                + (mNumFramesOutput * 1000000ll) / mVi->rate;
+                + (mNumFramesOutput * 1000000LL) / mVi->rate;
 
         mNumFramesOutput += numFrames;
 
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index 1d792fd..8a86a0d 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -649,7 +649,7 @@
                     mCurrentTimestamp = inHeader->nTimeStamp;
                     mLastInHeader = inHeader;
                 } else {
-                    mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000ll / mSampFreq;
+                    mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000LL / mSampFreq;
                 }
             } else {
                 inBuffer = inHeader->pBuffer + inHeader->nOffset;
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 768cbd6..a276722 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -66,7 +66,7 @@
 
 // static
 int64_t ALooper::GetNowUs() {
-    return systemTime(SYSTEM_TIME_MONOTONIC) / 1000ll;
+    return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
 }
 
 ALooper::ALooper()
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index dcf1ab8..dd1d904 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -4,8 +4,8 @@
     vendor_available: true,
 }
 
-cc_library {
-    name: "libstagefright_foundation",
+cc_defaults {
+    name: "libstagefright_foundation_defaults",
     vendor_available: true,
     vndk: {
         enabled: true,
@@ -25,6 +25,7 @@
     header_libs: [
         "libhardware_headers",
         "libstagefright_foundation_headers",
+        "media_ndk_headers",
         "media_plugin_headers",
     ],
 
@@ -64,8 +65,13 @@
         "AudioPresentationInfo.cpp",
         "ByteUtils.cpp",
         "ColorUtils.cpp",
+        "MediaBuffer.cpp",
+        "MediaBufferBase.cpp",
+        "MediaBufferGroup.cpp",
         "MediaDefs.cpp",
         "MediaKeys.cpp",
+        "MetaData.cpp",
+        "MetaDataBase.cpp",
         "avc_utils.cpp",
         "base64.cpp",
         "hexdump.cpp",
@@ -81,3 +87,20 @@
         cfi: true,
     },
 }
+
+cc_library {
+    name: "libstagefright_foundation",
+    defaults: ["libstagefright_foundation_defaults"],
+}
+
+cc_library_static {
+    name: "libstagefright_foundation_without_imemory",
+    defaults: ["libstagefright_foundation_defaults"],
+
+    cflags: [
+        "-Wno-multichar",
+        "-Werror",
+        "-Wall",
+        "-DNO_IMEMORY",
+    ],
+}
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libstagefright/foundation/MediaBuffer.cpp
similarity index 93%
rename from media/libmediaextractor/MediaBuffer.cpp
rename to media/libstagefright/foundation/MediaBuffer.cpp
index bab3a03..9beac05 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libstagefright/foundation/MediaBuffer.cpp
@@ -59,9 +59,11 @@
 #ifndef NO_IMEMORY
     } else {
         ALOGV("creating memoryDealer");
-        sp<MemoryDealer> memoryDealer =
-                new MemoryDealer(size + sizeof(SharedControl), "MediaBuffer");
-        mMemory = memoryDealer->allocate(size + sizeof(SharedControl));
+        size_t newSize = 0;
+        if (!__builtin_add_overflow(size, sizeof(SharedControl), &newSize)) {
+            sp<MemoryDealer> memoryDealer = new MemoryDealer(newSize, "MediaBuffer");
+            mMemory = memoryDealer->allocate(newSize);
+        }
         if (mMemory == NULL) {
             ALOGW("Failed to allocate shared memory, trying regular allocation!");
             mData = malloc(size);
diff --git a/media/libmediaextractor/MediaBufferBase.cpp b/media/libstagefright/foundation/MediaBufferBase.cpp
similarity index 100%
rename from media/libmediaextractor/MediaBufferBase.cpp
rename to media/libstagefright/foundation/MediaBufferBase.cpp
diff --git a/media/libmediaextractor/MediaBufferGroup.cpp b/media/libstagefright/foundation/MediaBufferGroup.cpp
similarity index 100%
rename from media/libmediaextractor/MediaBufferGroup.cpp
rename to media/libstagefright/foundation/MediaBufferGroup.cpp
diff --git a/media/libmediaextractor/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
similarity index 100%
rename from media/libmediaextractor/MetaData.cpp
rename to media/libstagefright/foundation/MetaData.cpp
diff --git a/media/libmediaextractor/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
similarity index 100%
rename from media/libmediaextractor/MetaDataBase.cpp
rename to media/libstagefright/foundation/MetaDataBase.cpp
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index c4a072b..c0ee14e 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -32,7 +32,6 @@
         "libcrypto",
         "libcutils",
         "libmedia",
-        "libmediaextractor",
         "libmediandk",
         "libstagefright",
         "libstagefright_foundation",
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 86872c5..2ecfa43 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -44,10 +44,10 @@
 
 // static
 // Bandwidth Switch Mark Defaults
-const int64_t LiveSession::kUpSwitchMarkUs = 15000000ll;
-const int64_t LiveSession::kDownSwitchMarkUs = 20000000ll;
-const int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
-const int64_t LiveSession::kResumeThresholdUs = 100000ll;
+const int64_t LiveSession::kUpSwitchMarkUs = 15000000LL;
+const int64_t LiveSession::kDownSwitchMarkUs = 20000000LL;
+const int64_t LiveSession::kUpSwitchMarginUs = 5000000LL;
+const int64_t LiveSession::kResumeThresholdUs = 100000LL;
 
 //TODO: redefine this mark to a fair value
 // default buffer underflow mark
@@ -66,9 +66,9 @@
     // Bandwidth estimation parameters
     static const int32_t kShortTermBandwidthItems = 3;
     static const int32_t kMinBandwidthHistoryItems = 20;
-    static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
-    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
-    static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec
+    static const int64_t kMinBandwidthHistoryWindowUs = 5000000LL; // 5 sec
+    static const int64_t kMaxBandwidthHistoryWindowUs = 30000000LL; // 30 sec
+    static const int64_t kMaxBandwidthHistoryAgeUs = 60000000LL; // 60 sec
 
     struct BandwidthEntry {
         int64_t mTimestampUs;
@@ -284,7 +284,7 @@
       mPrevBufferPercentage(-1),
       mCurBandwidthIndex(-1),
       mOrigBandwidthIndex(-1),
-      mLastBandwidthBps(-1ll),
+      mLastBandwidthBps(-1LL),
       mLastBandwidthStable(false),
       mBandwidthEstimator(new BandwidthEstimator()),
       mMaxWidth(720),
@@ -294,8 +294,8 @@
       mSwapMask(0),
       mSwitchGeneration(0),
       mSubtitleGeneration(0),
-      mLastDequeuedTimeUs(0ll),
-      mRealTimeBaseUs(0ll),
+      mLastDequeuedTimeUs(0LL),
+      mRealTimeBaseUs(0LL),
       mReconfigurationInProgress(false),
       mSwitchInProgress(false),
       mUpSwitchMark(kUpSwitchMarkUs),
@@ -844,7 +844,7 @@
                     // (If we don't have that cushion we'd rather cancel and try again.)
                     int64_t delayUs =
                         switchUp ?
-                            (kUnderflowMarkMs * 1000ll + 1000000ll)
+                            (kUnderflowMarkMs * 1000LL + 1000000LL)
                             : 0;
                     bool needResumeUntil = false;
                     sp<AMessage> stopParams = msg;
@@ -954,7 +954,7 @@
 
 // static
 bool LiveSession::isBandwidthValid(const BandwidthItem &item) {
-    static const int64_t kBlacklistWindowUs = 300 * 1000000ll;
+    static const int64_t kBlacklistWindowUs = 300 * 1000000LL;
     return item.mLastFailureUs < 0
             || ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs;
 }
@@ -1060,7 +1060,7 @@
             BandwidthItem item;
 
             item.mPlaylistIndex = i;
-            item.mLastFailureUs = -1ll;
+            item.mLastFailureUs = -1LL;
 
             sp<AMessage> meta;
             AString uri;
@@ -1114,7 +1114,7 @@
 
     mPlaylist->pickRandomMediaItems();
     changeConfiguration(
-            0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
+            0LL /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
 }
 
 void LiveSession::finishDisconnect() {
@@ -1175,7 +1175,7 @@
     FetcherInfo info;
     info.mFetcher = new PlaylistFetcher(
             notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
-    info.mDurationUs = -1ll;
+    info.mDurationUs = -1LL;
     info.mToBeRemoved = false;
     info.mToBeResumed = false;
     mFetcherLooper->registerHandler(info.mFetcher);
@@ -1466,7 +1466,7 @@
 }
 
 status_t LiveSession::getDuration(int64_t *durationUs) const {
-    int64_t maxDurationUs = -1ll;
+    int64_t maxDurationUs = -1LL;
     for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
         int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
 
@@ -1592,7 +1592,7 @@
         // Delay fetcher removal if not picking tracks, AND old fetcher
         // has stream mask that overlaps new variant. (Okay to discard
         // old fetcher now, if completely no overlap.)
-        if (discardFetcher && timeUs < 0ll && !pickTrack
+        if (discardFetcher && timeUs < 0LL && !pickTrack
                 && (fetcher->getStreamTypeMask() & streamMask)) {
             discardFetcher = false;
             delayRemoval = true;
@@ -1604,7 +1604,7 @@
         } else {
             float threshold = 0.0f; // default to pause after current block (47Kbytes)
             bool disconnect = false;
-            if (timeUs >= 0ll) {
+            if (timeUs >= 0LL) {
                 // seeking, no need to finish fetching
                 disconnect = true;
             } else if (delayRemoval) {
@@ -1620,7 +1620,7 @@
     }
 
     sp<AMessage> msg;
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         // skip onChangeConfiguration2 (decoder destruction) if not seeking.
         msg = new AMessage(kWhatChangeConfiguration3, this);
     } else {
@@ -1654,9 +1654,9 @@
     if (!mReconfigurationInProgress) {
         int32_t pickTrack = 0;
         msg->findInt32("pickTrack", &pickTrack);
-        changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
+        changeConfiguration(-1LL /* timeUs */, -1, pickTrack);
     } else {
-        msg->post(1000000ll); // retry in 1 sec
+        msg->post(1000000LL); // retry in 1 sec
     }
 }
 
@@ -1788,7 +1788,7 @@
     CHECK(msg->findInt64("timeUs", &timeUs));
     CHECK(msg->findInt32("pickTrack", &pickTrack));
 
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         if (!pickTrack) {
             // mSwapMask contains streams that are in both old and new variant,
             // (in mNewStreamMask & mStreamMask) but with different URIs
@@ -2062,7 +2062,7 @@
 void LiveSession::schedulePollBuffering() {
     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
     msg->setInt32("generation", mPollBufferingGeneration);
-    msg->post(1000000ll);
+    msg->post(1000000LL);
 }
 
 void LiveSession::cancelPollBuffering() {
@@ -2208,13 +2208,13 @@
         int64_t readyMarkUs =
             (mInPreparationPhase ?
                 mBufferingSettings.mInitialMarkMs :
-                mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
+                mBufferingSettings.mResumePlaybackMarkMs) * 1000LL;
         if (bufferedDurationUs > readyMarkUs
                 || mPacketSources[i]->isFinished(0)) {
             ++readyCount;
         }
         if (!mPacketSources[i]->isFinished(0)) {
-            if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) {
+            if (bufferedDurationUs < kUnderflowMarkMs * 1000LL) {
                 ++underflowCount;
             }
             if (bufferedDurationUs > mUpSwitchMark) {
@@ -2300,7 +2300,7 @@
         ssize_t lowestValid = getLowestValidBandwidthIndex();
         if (mCurBandwidthIndex > lowestValid) {
             cancelBandwidthSwitch();
-            changeConfiguration(-1ll, lowestValid);
+            changeConfiguration(-1LL, lowestValid);
             return true;
         }
     }
@@ -2370,7 +2370,7 @@
             // if not yet prepared, just restart again with new bw index.
             // this is faster and playback experience is cleaner.
             changeConfiguration(
-                    mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
+                    mInPreparationPhase ? 0 : -1LL, bandwidthIndex);
             return true;
         }
     }
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index d06d9f2..16179d3 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -258,7 +258,7 @@
       mIsEvent(false),
       mFirstSeqNumber(-1),
       mLastSeqNumber(-1),
-      mTargetDurationUs(-1ll),
+      mTargetDurationUs(-1LL),
       mDiscontinuitySeq(0),
       mDiscontinuityCount(0),
       mSelectedIndex(-1) {
@@ -716,7 +716,7 @@
             ALOGE("Media playlist missing #EXT-X-TARGETDURATION");
             return ERROR_MALFORMED;
         }
-        mTargetDurationUs = targetDurationSecs * 1000000ll;
+        mTargetDurationUs = targetDurationSecs * 1000000LL;
 
         mFirstSeqNumber = 0;
         if (mMeta != NULL) {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 823f90e..562c625 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -50,8 +50,8 @@
 namespace android {
 
 // static
-const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll;
-const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
+const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000LL;
+const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000LL;
 // LCM of 188 (size of a TS packet) & 1k works well
 const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
 
@@ -152,25 +152,25 @@
       mURI(uri),
       mFetcherID(id),
       mStreamTypeMask(0),
-      mStartTimeUs(-1ll),
-      mSegmentStartTimeUs(-1ll),
-      mDiscontinuitySeq(-1ll),
+      mStartTimeUs(-1LL),
+      mSegmentStartTimeUs(-1LL),
+      mDiscontinuitySeq(-1LL),
       mStartTimeUsRelative(false),
-      mLastPlaylistFetchTimeUs(-1ll),
-      mPlaylistTimeUs(-1ll),
+      mLastPlaylistFetchTimeUs(-1LL),
+      mPlaylistTimeUs(-1LL),
       mSeqNumber(-1),
       mNumRetries(0),
       mStartup(true),
       mIDRFound(false),
       mSeekMode(LiveSession::kSeekModeExactPosition),
       mTimeChangeSignaled(false),
-      mNextPTSTimeUs(-1ll),
+      mNextPTSTimeUs(-1LL),
       mMonitorQueueGeneration(0),
       mSubtitleGeneration(subtitleGeneration),
-      mLastDiscontinuitySeq(-1ll),
+      mLastDiscontinuitySeq(-1LL),
       mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
       mFirstPTSValid(false),
-      mFirstTimeUs(-1ll),
+      mFirstTimeUs(-1LL),
       mVideoBuffer(new AnotherPacketSource(NULL)),
       mSampleAesKeyItemChanged(false),
       mThresholdRatio(-1.0f),
@@ -200,7 +200,7 @@
     CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
     CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
 
-    int64_t segmentStartUs = 0ll;
+    int64_t segmentStartUs = 0LL;
     for (int32_t index = 0;
             index < seqNumber - firstSeqNumberInPlaylist; ++index) {
         sp<AMessage> itemMeta;
@@ -240,13 +240,13 @@
 int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
     int64_t nowUs = ALooper::GetNowUs();
 
-    if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) {
+    if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0LL) {
         CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
-        return 0ll;
+        return 0LL;
     }
 
     if (mPlaylist->isComplete()) {
-        return (~0llu >> 1);
+        return (~0LLU >> 1);
     }
 
     int64_t targetDurationUs = mPlaylist->getTargetDuration();
@@ -295,7 +295,7 @@
     }
 
     int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs;
-    return delayUs > 0ll ? delayUs : 0ll;
+    return delayUs > 0LL ? delayUs : 0LL;
 }
 
 status_t PlaylistFetcher::decryptBuffer(
@@ -857,7 +857,7 @@
         targetDurationUs = mPlaylist->getTargetDuration();
     }
 
-    int64_t bufferedDurationUs = 0ll;
+    int64_t bufferedDurationUs = 0LL;
     status_t finalResult = OK;
     if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
         sp<AnotherPacketSource> packetSource =
@@ -870,7 +870,7 @@
         // enqueued to prevent us from waiting on a non-existent stream;
         // when we cannot make out from the manifest what streams are included in
         // a playlist we might assume extra streams.
-        bufferedDurationUs = -1ll;
+        bufferedDurationUs = -1LL;
         for (size_t i = 0; i < mPacketSources.size(); ++i) {
             if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
                     || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
@@ -882,13 +882,13 @@
 
             FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
 
-            if (bufferedDurationUs == -1ll
+            if (bufferedDurationUs == -1LL
                  || bufferedStreamDurationUs < bufferedDurationUs) {
                 bufferedDurationUs = bufferedStreamDurationUs;
             }
         }
-        if (bufferedDurationUs == -1ll) {
-            bufferedDurationUs = 0ll;
+        if (bufferedDurationUs == -1LL) {
+            bufferedDurationUs = 0LL;
         }
     }
 
@@ -901,12 +901,12 @@
         // onDownloadNext();
         sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
         msg->setInt32("generation", mMonitorQueueGeneration);
-        msg->post(1000l);
+        msg->post(1000L);
     } else {
         // We'd like to maintain buffering above durationToBufferUs, so try
         // again when buffer just about to go below durationToBufferUs
         // (or after targetDurationUs / 2, whichever is smaller).
-        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
+        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000LL;
         if (delayUs > targetDurationUs / 2) {
             delayUs = targetDurationUs / 2;
         }
@@ -1073,10 +1073,10 @@
         }
     }
 
-    mSegmentFirstPTS = -1ll;
+    mSegmentFirstPTS = -1LL;
 
     if (mPlaylist != NULL && mSeqNumber < 0) {
-        CHECK_GE(mStartTimeUs, 0ll);
+        CHECK_GE(mStartTimeUs, 0LL);
 
         if (mSegmentStartTimeUs < 0) {
             if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
@@ -1379,7 +1379,7 @@
                         & (LiveSession::STREAMTYPE_AUDIO
                         | LiveSession::STREAMTYPE_VIDEO))) {
             mSession->addBandwidthMeasurement(bytesRead, delayUs);
-            if (delayUs > 2000000ll) {
+            if (delayUs > 2000000LL) {
                 FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
                         bytesRead, (double)delayUs / 1.0e6);
             }
@@ -1553,7 +1553,7 @@
         // if the previous fetcher paused in the middle of a segment, we
         // want to start at a segment that overlaps the last sample
         minDiffUs = -mPlaylist->getTargetDuration();
-        maxDiffUs = 0ll;
+        maxDiffUs = 0LL;
     } else {
         // if the previous fetcher paused at the end of a segment, ideally
         // we want to start at the segment that's roughly aligned with its
@@ -1704,7 +1704,7 @@
         mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
     }
 
-    if (mNextPTSTimeUs >= 0ll) {
+    if (mNextPTSTimeUs >= 0LL) {
         sp<AMessage> extra = new AMessage;
         // Since we are using absolute timestamps, signal an offset of 0 to prevent
         // ATSParser from skewing the timestamps of access units.
@@ -1719,7 +1719,7 @@
         mTSParser->signalDiscontinuity(
                 ATSParser::DISCONTINUITY_TIME, extra);
 
-        mNextPTSTimeUs = -1ll;
+        mNextPTSTimeUs = -1LL;
     }
 
     if (mSampleAesKeyItemChanged) {
@@ -1740,7 +1740,7 @@
     // setRange to indicate consumed bytes.
     buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
 
-    if (mSegmentFirstPTS < 0ll) {
+    if (mSegmentFirstPTS < 0LL) {
         // get the smallest first PTS from all streams present in this parser
         for (size_t i = mPacketSources.size(); i > 0;) {
             i--;
@@ -1764,12 +1764,12 @@
             if (meta != NULL) {
                 int64_t timeUs;
                 CHECK(meta->findInt64("timeUs", &timeUs));
-                if (mSegmentFirstPTS < 0ll || timeUs < mSegmentFirstPTS) {
+                if (mSegmentFirstPTS < 0LL || timeUs < mSegmentFirstPTS) {
                     mSegmentFirstPTS = timeUs;
                 }
             }
         }
-        if (mSegmentFirstPTS < 0ll) {
+        if (mSegmentFirstPTS < 0LL) {
             // didn't find any TS packet, can return early
             return OK;
         }
@@ -1988,8 +1988,8 @@
         return OK;
     }
 
-    if (mNextPTSTimeUs >= 0ll) {
-        mNextPTSTimeUs = -1ll;
+    if (mNextPTSTimeUs >= 0LL) {
+        mNextPTSTimeUs = -1LL;
     }
 
     // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
@@ -2088,17 +2088,17 @@
         packetSource->setFormat(meta);
     }
 
-    int64_t numSamples = 0ll;
+    int64_t numSamples = 0LL;
     int32_t sampleRate;
     CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
 
-    int64_t timeUs = (PTS * 100ll) / 9ll;
+    int64_t timeUs = (PTS * 100LL) / 9LL;
     if (mStartup && !mFirstPTSValid) {
         mFirstPTSValid = true;
         mFirstTimeUs = timeUs;
     }
 
-    if (mSegmentFirstPTS < 0ll) {
+    if (mSegmentFirstPTS < 0LL) {
         mSegmentFirstPTS = timeUs;
         if (!mStartTimeUsRelative) {
             // Duplicated logic from how we handle .ts playlists.
@@ -2148,7 +2148,7 @@
 
         CHECK_LE(offset + aac_frame_length, buffer->size());
 
-        int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
+        int64_t unitTimeUs = timeUs + numSamples * 1000000LL / sampleRate;
         offset += aac_frame_length;
 
         // Each AAC frame encodes 1024 samples.
@@ -2209,7 +2209,7 @@
 }
 
 void PlaylistFetcher::updateDuration() {
-    int64_t durationUs = 0ll;
+    int64_t durationUs = 0LL;
     for (size_t index = 0; index < mPlaylist->size(); ++index) {
         sp<AMessage> itemMeta;
         CHECK(mPlaylist->itemAt(
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index b489183..792a68a 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -43,7 +43,7 @@
     }
 
     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
-        off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset;
+        off64_t available = (offset >= (off64_t)mSize) ? 0LL : mSize - offset;
 
         size_t copy = (available > (off64_t)size) ? size : available;
         memcpy(data, mData + offset, copy);
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libstagefright/include/media/stagefright/DataSource.h
similarity index 100%
rename from media/libmediaextractor/include/media/DataSource.h
rename to media/libstagefright/include/media/stagefright/DataSource.h
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libstagefright/include/media/stagefright/DataSourceBase.h
similarity index 100%
rename from media/libmediaextractor/include/media/DataSourceBase.h
rename to media/libstagefright/include/media/stagefright/DataSourceBase.h
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
deleted file mode 120000
index 1d49c1a..0000000
--- a/media/libstagefright/include/media/stagefright/MediaBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MediaBuffer.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MediaBuffer.h
rename to media/libstagefright/include/media/stagefright/MediaBuffer.h
diff --git a/media/libstagefright/include/media/stagefright/MediaBufferBase.h b/media/libstagefright/include/media/stagefright/MediaBufferBase.h
deleted file mode 120000
index 80e49b0..0000000
--- a/media/libstagefright/include/media/stagefright/MediaBufferBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MediaBufferBase.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libstagefright/include/media/stagefright/MediaBufferBase.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
rename to media/libstagefright/include/media/stagefright/MediaBufferBase.h
diff --git a/media/libstagefright/include/media/stagefright/MediaBufferGroup.h b/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
deleted file mode 120000
index 009b3d9..0000000
--- a/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MediaBufferGroup.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h b/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
rename to media/libstagefright/include/media/stagefright/MediaBufferGroup.h
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 984c23d..c06c288 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -31,6 +31,21 @@
 constexpr int32_t AVCProfileConstrainedBaseline = 0x10000;
 constexpr int32_t AVCProfileConstrainedHigh     = 0x80000;
 
+inline static const char *asString_AVCProfile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case AVCProfileBaseline:            return "Baseline";
+        case AVCProfileMain:                return "Main";
+        case AVCProfileExtended:            return "Extended";
+        case AVCProfileHigh:                return "High";
+        case AVCProfileHigh10:              return "High10";
+        case AVCProfileHigh422:             return "High422";
+        case AVCProfileHigh444:             return "High444";
+        case AVCProfileConstrainedBaseline: return "ConstrainedBaseline";
+        case AVCProfileConstrainedHigh:     return "ConstrainedHigh";
+        default:                            return def;
+    }
+}
+
 constexpr int32_t AVCLevel1       = 0x01;
 constexpr int32_t AVCLevel1b      = 0x02;
 constexpr int32_t AVCLevel11      = 0x04;
@@ -48,6 +63,35 @@
 constexpr int32_t AVCLevel5       = 0x4000;
 constexpr int32_t AVCLevel51      = 0x8000;
 constexpr int32_t AVCLevel52      = 0x10000;
+constexpr int32_t AVCLevel6       = 0x20000;
+constexpr int32_t AVCLevel61      = 0x40000;
+constexpr int32_t AVCLevel62      = 0x80000;
+
+inline static const char *asString_AVCLevel(int32_t i, const char *def = "??") {
+    switch (i) {
+        case AVCLevel1:     return "1";
+        case AVCLevel1b:    return "1b";
+        case AVCLevel11:    return "1.1";
+        case AVCLevel12:    return "1.2";
+        case AVCLevel13:    return "1.3";
+        case AVCLevel2:     return "2";
+        case AVCLevel21:    return "2.1";
+        case AVCLevel22:    return "2.2";
+        case AVCLevel3:     return "3";
+        case AVCLevel31:    return "3.1";
+        case AVCLevel32:    return "3.2";
+        case AVCLevel4:     return "4";
+        case AVCLevel41:    return "4.1";
+        case AVCLevel42:    return "4.2";
+        case AVCLevel5:     return "5";
+        case AVCLevel51:    return "5.1";
+        case AVCLevel52:    return "5.2";
+        case AVCLevel6:     return "6";
+        case AVCLevel61:    return "6.1";
+        case AVCLevel62:    return "6.2";
+        default:            return def;
+    }
+}
 
 constexpr int32_t H263ProfileBaseline             = 0x01;
 constexpr int32_t H263ProfileH320Coding           = 0x02;
@@ -59,6 +103,21 @@
 constexpr int32_t H263ProfileInterlace            = 0x80;
 constexpr int32_t H263ProfileHighLatency          = 0x100;
 
+inline static const char *asString_H263Profile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case H263ProfileBaseline:           return "Baseline";
+        case H263ProfileH320Coding:         return "H320Coding";
+        case H263ProfileBackwardCompatible: return "BackwardCompatible";
+        case H263ProfileISWV2:              return "ISWV2";
+        case H263ProfileISWV3:              return "ISWV3";
+        case H263ProfileHighCompression:    return "HighCompression";
+        case H263ProfileInternet:           return "Internet";
+        case H263ProfileInterlace:          return "Interlace";
+        case H263ProfileHighLatency:        return "HighLatency";
+        default:                            return def;
+    }
+}
+
 constexpr int32_t H263Level10      = 0x01;
 constexpr int32_t H263Level20      = 0x02;
 constexpr int32_t H263Level30      = 0x04;
@@ -68,6 +127,20 @@
 constexpr int32_t H263Level60      = 0x40;
 constexpr int32_t H263Level70      = 0x80;
 
+inline static const char *asString_H263Level(int32_t i, const char *def = "??") {
+    switch (i) {
+        case H263Level10:   return "10";
+        case H263Level20:   return "20";
+        case H263Level30:   return "30";
+        case H263Level40:   return "40";
+        case H263Level45:   return "45";
+        case H263Level50:   return "50";
+        case H263Level60:   return "60";
+        case H263Level70:   return "70";
+        default:            return def;
+    }
+}
+
 constexpr int32_t MPEG4ProfileSimple              = 0x01;
 constexpr int32_t MPEG4ProfileSimpleScalable      = 0x02;
 constexpr int32_t MPEG4ProfileCore                = 0x04;
@@ -85,6 +158,28 @@
 constexpr int32_t MPEG4ProfileAdvancedScalable    = 0x4000;
 constexpr int32_t MPEG4ProfileAdvancedSimple      = 0x8000;
 
+inline static const char *asString_MPEG4Profile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case MPEG4ProfileSimple:            return "Simple";
+        case MPEG4ProfileSimpleScalable:    return "SimpleScalable";
+        case MPEG4ProfileCore:              return "Core";
+        case MPEG4ProfileMain:              return "Main";
+        case MPEG4ProfileNbit:              return "Nbit";
+        case MPEG4ProfileScalableTexture:   return "ScalableTexture";
+        case MPEG4ProfileSimpleFace:        return "SimpleFace";
+        case MPEG4ProfileSimpleFBA:         return "SimpleFBA";
+        case MPEG4ProfileBasicAnimated:     return "BasicAnimated";
+        case MPEG4ProfileHybrid:            return "Hybrid";
+        case MPEG4ProfileAdvancedRealTime:  return "AdvancedRealTime";
+        case MPEG4ProfileCoreScalable:      return "CoreScalable";
+        case MPEG4ProfileAdvancedCoding:    return "AdvancedCoding";
+        case MPEG4ProfileAdvancedCore:      return "AdvancedCore";
+        case MPEG4ProfileAdvancedScalable:  return "AdvancedScalable";
+        case MPEG4ProfileAdvancedSimple:    return "AdvancedSimple";
+        default:                            return def;
+    }
+}
+
 constexpr int32_t MPEG4Level0      = 0x01;
 constexpr int32_t MPEG4Level0b     = 0x02;
 constexpr int32_t MPEG4Level1      = 0x04;
@@ -96,6 +191,22 @@
 constexpr int32_t MPEG4Level5      = 0x80;
 constexpr int32_t MPEG4Level6      = 0x100;
 
+inline static const char *asString_MPEG4Level(int32_t i, const char *def = "??") {
+    switch (i) {
+        case MPEG4Level0:   return "0";
+        case MPEG4Level0b:  return "0b";
+        case MPEG4Level1:   return "1";
+        case MPEG4Level2:   return "2";
+        case MPEG4Level3:   return "3";
+        case MPEG4Level3b:  return "3b";
+        case MPEG4Level4:   return "4";
+        case MPEG4Level4a:  return "4a";
+        case MPEG4Level5:   return "5";
+        case MPEG4Level6:   return "6";
+        default:            return def;
+    }
+}
+
 constexpr int32_t MPEG2ProfileSimple              = 0x00;
 constexpr int32_t MPEG2ProfileMain                = 0x01;
 constexpr int32_t MPEG2Profile422                 = 0x02;
@@ -103,12 +214,35 @@
 constexpr int32_t MPEG2ProfileSpatial             = 0x04;
 constexpr int32_t MPEG2ProfileHigh                = 0x05;
 
+inline static const char *asString_MPEG2Profile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case MPEG2ProfileSimple:    return "Simple";
+        case MPEG2ProfileMain:      return "Main";
+        case MPEG2Profile422:       return "422";
+        case MPEG2ProfileSNR:       return "SNR";
+        case MPEG2ProfileSpatial:   return "Spatial";
+        case MPEG2ProfileHigh:      return "High";
+        default:                    return def;
+    }
+}
+
 constexpr int32_t MPEG2LevelLL     = 0x00;
 constexpr int32_t MPEG2LevelML     = 0x01;
 constexpr int32_t MPEG2LevelH14    = 0x02;
 constexpr int32_t MPEG2LevelHL     = 0x03;
 constexpr int32_t MPEG2LevelHP     = 0x04;
 
+inline static const char *asString_MPEG2Level(int32_t i, const char *def = "??") {
+    switch (i) {
+        case MPEG2LevelLL:  return "LL";
+        case MPEG2LevelML:  return "ML";
+        case MPEG2LevelH14: return "H14";
+        case MPEG2LevelHL:  return "HL";
+        case MPEG2LevelHP:  return "HP";
+        default:            return def;
+    }
+}
+
 constexpr int32_t AACObjectMain       = 1;
 constexpr int32_t AACObjectLC         = 2;
 constexpr int32_t AACObjectSSR        = 3;
@@ -122,13 +256,48 @@
 constexpr int32_t AACObjectELD        = 39;
 constexpr int32_t AACObjectXHE        = 42;
 
+inline static const char *asString_AACObject(int32_t i, const char *def = "??") {
+    switch (i) {
+        case AACObjectMain:         return "Main";
+        case AACObjectLC:           return "LC";
+        case AACObjectSSR:          return "SSR";
+        case AACObjectLTP:          return "LTP";
+        case AACObjectHE:           return "HE";
+        case AACObjectScalable:     return "Scalable";
+        case AACObjectERLC:         return "ERLC";
+        case AACObjectERScalable:   return "ERScalable";
+        case AACObjectLD:           return "LD";
+        case AACObjectHE_PS:        return "HE_PS";
+        case AACObjectELD:          return "ELD";
+        case AACObjectXHE:          return "XHE";
+        default:                    return def;
+    }
+}
+
 constexpr int32_t VP8Level_Version0 = 0x01;
 constexpr int32_t VP8Level_Version1 = 0x02;
 constexpr int32_t VP8Level_Version2 = 0x04;
 constexpr int32_t VP8Level_Version3 = 0x08;
 
+inline static const char *asString_VP8Level(int32_t i, const char *def = "??") {
+    switch (i) {
+        case VP8Level_Version0: return "V0";
+        case VP8Level_Version1: return "V1";
+        case VP8Level_Version2: return "V2";
+        case VP8Level_Version3: return "V3";
+        default:                return def;
+    }
+}
+
 constexpr int32_t VP8ProfileMain = 0x01;
 
+inline static const char *asString_VP8Profile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case VP8ProfileMain:    return "Main";
+        default:                return def;
+    }
+}
+
 constexpr int32_t VP9Profile0 = 0x01;
 constexpr int32_t VP9Profile1 = 0x02;
 constexpr int32_t VP9Profile2 = 0x04;
@@ -138,6 +307,20 @@
 constexpr int32_t VP9Profile2HDR10Plus = 0x4000;
 constexpr int32_t VP9Profile3HDR10Plus = 0x8000;
 
+inline static const char *asString_VP9Profile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case VP9Profile0:           return "0";
+        case VP9Profile1:           return "1";
+        case VP9Profile2:           return "2";
+        case VP9Profile3:           return "3";
+        case VP9Profile2HDR:        return "2HDR";
+        case VP9Profile3HDR:        return "3HDR";
+        case VP9Profile2HDR10Plus:  return "2HDRPlus";
+        case VP9Profile3HDR10Plus:  return "3HDRPlus";
+        default:                    return def;
+    }
+}
+
 constexpr int32_t VP9Level1  = 0x1;
 constexpr int32_t VP9Level11 = 0x2;
 constexpr int32_t VP9Level2  = 0x4;
@@ -153,10 +336,39 @@
 constexpr int32_t VP9Level61 = 0x1000;
 constexpr int32_t VP9Level62 = 0x2000;
 
+inline static const char *asString_VP9Level(int32_t i, const char *def = "??") {
+    switch (i) {
+        case VP9Level1:     return "1";
+        case VP9Level11:    return "1.1";
+        case VP9Level2:     return "2";
+        case VP9Level21:    return "2.1";
+        case VP9Level3:     return "3";
+        case VP9Level31:    return "3.1";
+        case VP9Level4:     return "4";
+        case VP9Level41:    return "4.1";
+        case VP9Level5:     return "5";
+        case VP9Level51:    return "5.1";
+        case VP9Level52:    return "5.2";
+        case VP9Level6:     return "6";
+        case VP9Level61:    return "6.1";
+        case VP9Level62:    return "6.2";
+        default:            return def;
+    }
+}
+
 constexpr int32_t AV1Profile0 = 0x01;
 constexpr int32_t AV1Profile1 = 0x02;
 constexpr int32_t AV1Profile2 = 0x04;
 
+inline static const char *asString_AV1Profile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case AV1Profile0:       return "0";
+        case AV1Profile1:       return "1";
+        case AV1Profile2:       return "2";
+        default:                return def;
+    }
+}
+
 constexpr int32_t AV1Level2  = 0x1;
 constexpr int32_t AV1Level21 = 0x2;
 constexpr int32_t AV1Level22 = 0x4;
@@ -182,12 +394,53 @@
 constexpr int32_t AV1Level72 = 0x400000;
 constexpr int32_t AV1Level73 = 0x800000;
 
+inline static const char *asString_AV1Level(int32_t i, const char *def = "??") {
+    switch (i) {
+        case AV1Level2:     return "2";
+        case AV1Level21:    return "2.1";
+        case AV1Level22:    return "2.2";
+        case AV1Level23:    return "2.3";
+        case AV1Level3:     return "3";
+        case AV1Level31:    return "3.1";
+        case AV1Level32:    return "3.2";
+        case AV1Level33:    return "3.3";
+        case AV1Level4:     return "4";
+        case AV1Level41:    return "4.1";
+        case AV1Level42:    return "4.2";
+        case AV1Level43:    return "4.3";
+        case AV1Level5:     return "5";
+        case AV1Level51:    return "5.1";
+        case AV1Level52:    return "5.2";
+        case AV1Level53:    return "5.3";
+        case AV1Level6:     return "6";
+        case AV1Level61:    return "6.1";
+        case AV1Level62:    return "6.2";
+        case AV1Level63:    return "6.3";
+        case AV1Level7:     return "7";
+        case AV1Level71:    return "7.1";
+        case AV1Level72:    return "7.2";
+        case AV1Level73:    return "7.3";
+        default:            return def;
+    }
+}
+
 constexpr int32_t HEVCProfileMain        = 0x01;
 constexpr int32_t HEVCProfileMain10      = 0x02;
 constexpr int32_t HEVCProfileMainStill   = 0x04;
 constexpr int32_t HEVCProfileMain10HDR10 = 0x1000;
 constexpr int32_t HEVCProfileMain10HDR10Plus = 0x2000;
 
+inline static const char *asString_HEVCProfile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case HEVCProfileMain:               return "Main";
+        case HEVCProfileMain10:             return "Main10";
+        case HEVCProfileMainStill:          return "MainStill";
+        case HEVCProfileMain10HDR10:        return "Main10HDR10";
+        case HEVCProfileMain10HDR10Plus:    return "Main10HDR10Plus";
+        default:                            return def;
+    }
+}
+
 constexpr int32_t HEVCMainTierLevel1  = 0x1;
 constexpr int32_t HEVCHighTierLevel1  = 0x2;
 constexpr int32_t HEVCMainTierLevel2  = 0x4;
@@ -215,6 +468,38 @@
 constexpr int32_t HEVCMainTierLevel62 = 0x1000000;
 constexpr int32_t HEVCHighTierLevel62 = 0x2000000;
 
+inline static const char *asString_HEVCTierLevel(int32_t i, const char *def = "??") {
+    switch (i) {
+        case HEVCMainTierLevel1:    return "Main 1";
+        case HEVCHighTierLevel1:    return "High 1";
+        case HEVCMainTierLevel2:    return "Main 2";
+        case HEVCHighTierLevel2:    return "High 2";
+        case HEVCMainTierLevel21:   return "Main 2.1";
+        case HEVCHighTierLevel21:   return "High 2.1";
+        case HEVCMainTierLevel3:    return "Main 3";
+        case HEVCHighTierLevel3:    return "High 3";
+        case HEVCMainTierLevel31:   return "Main 3.1";
+        case HEVCHighTierLevel31:   return "High 3.1";
+        case HEVCMainTierLevel4:    return "Main 4";
+        case HEVCHighTierLevel4:    return "High 4";
+        case HEVCMainTierLevel41:   return "Main 4.1";
+        case HEVCHighTierLevel41:   return "High 4.1";
+        case HEVCMainTierLevel5:    return "Main 5";
+        case HEVCHighTierLevel5:    return "High 5";
+        case HEVCMainTierLevel51:   return "Main 5.1";
+        case HEVCHighTierLevel51:   return "High 5.1";
+        case HEVCMainTierLevel52:   return "Main 5.2";
+        case HEVCHighTierLevel52:   return "High 5.2";
+        case HEVCMainTierLevel6:    return "Main 6";
+        case HEVCHighTierLevel6:    return "High 6";
+        case HEVCMainTierLevel61:   return "Main 6.1";
+        case HEVCHighTierLevel61:   return "High 6.1";
+        case HEVCMainTierLevel62:   return "Main 6.2";
+        case HEVCHighTierLevel62:   return "High 6.2";
+        default:                    return def;
+    }
+}
+
 constexpr int32_t DolbyVisionProfileDvavPer = 0x1;
 constexpr int32_t DolbyVisionProfileDvavPen = 0x2;
 constexpr int32_t DolbyVisionProfileDvheDer = 0x4;
@@ -226,6 +511,22 @@
 constexpr int32_t DolbyVisionProfileDvheSt = 0x100;
 constexpr int32_t DolbyVisionProfileDvavSe = 0x200;
 
+inline static const char *asString_DolbyVisionProfile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case DolbyVisionProfileDvavPer: return "DvavPer";
+        case DolbyVisionProfileDvavPen: return "DvavPen";
+        case DolbyVisionProfileDvheDer: return "DvheDer";
+        case DolbyVisionProfileDvheDen: return "DvheDen";
+        case DolbyVisionProfileDvheDtr: return "DvheDtr";
+        case DolbyVisionProfileDvheStn: return "DvheStn";
+        case DolbyVisionProfileDvheDth: return "DvheDth";
+        case DolbyVisionProfileDvheDtb: return "DvheDtb";
+        case DolbyVisionProfileDvheSt:  return "DvheSt";
+        case DolbyVisionProfileDvavSe:  return "DvavSe";
+        default:                        return def;
+    }
+}
+
 constexpr int32_t DolbyVisionLevelHd24    = 0x1;
 constexpr int32_t DolbyVisionLevelHd30    = 0x2;
 constexpr int32_t DolbyVisionLevelFhd24   = 0x4;
@@ -236,10 +537,34 @@
 constexpr int32_t DolbyVisionLevelUhd48   = 0x80;
 constexpr int32_t DolbyVisionLevelUhd60   = 0x100;
 
+inline static const char *asString_DolbyVisionLevel(int32_t i, const char *def = "??") {
+    switch (i) {
+        case DolbyVisionLevelHd24:  return "Hd24";
+        case DolbyVisionLevelHd30:  return "Hd30";
+        case DolbyVisionLevelFhd24: return "Fhd24";
+        case DolbyVisionLevelFhd30: return "Fhd30";
+        case DolbyVisionLevelFhd60: return "Fhd60";
+        case DolbyVisionLevelUhd24: return "Uhd24";
+        case DolbyVisionLevelUhd30: return "Uhd30";
+        case DolbyVisionLevelUhd48: return "Uhd48";
+        case DolbyVisionLevelUhd60: return "Uhd60";
+        default:                    return def;
+    }
+}
+
 constexpr int32_t BITRATE_MODE_CBR = 2;
 constexpr int32_t BITRATE_MODE_CQ = 0;
 constexpr int32_t BITRATE_MODE_VBR = 1;
 
+inline static const char *asString_BitrateMode(int32_t i, const char *def = "??") {
+    switch (i) {
+        case BITRATE_MODE_CBR:  return "CBR";
+        case BITRATE_MODE_CQ:   return "CQ";
+        case BITRATE_MODE_VBR:  return "VBR";
+        default:                return def;
+    }
+}
+
 constexpr int32_t COLOR_Format12bitRGB444             = 3;
 constexpr int32_t COLOR_Format16bitARGB1555           = 5;
 constexpr int32_t COLOR_Format16bitARGB4444           = 4;
@@ -293,6 +618,64 @@
 constexpr int32_t COLOR_QCOM_FormatYUV420SemiPlanar   = 0x7fa30c00;
 constexpr int32_t COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
 
+inline static const char *asString_ColorFormat(int32_t i, const char *def = "??") {
+    switch (i) {
+        case COLOR_Format12bitRGB444:               return "12bitRGB444";
+        case COLOR_Format16bitARGB1555:             return "16bitARGB1555";
+        case COLOR_Format16bitARGB4444:             return "16bitARGB4444";
+        case COLOR_Format16bitBGR565:               return "16bitBGR565";
+        case COLOR_Format16bitRGB565:               return "16bitRGB565";
+        case COLOR_Format18bitARGB1665:             return "18bitARGB1665";
+        case COLOR_Format18BitBGR666:               return "18BitBGR666";
+        case COLOR_Format18bitRGB666:               return "18bitRGB666";
+        case COLOR_Format19bitARGB1666:             return "19bitARGB1666";
+        case COLOR_Format24BitABGR6666:             return "24BitABGR6666";
+        case COLOR_Format24bitARGB1887:             return "24bitARGB1887";
+        case COLOR_Format24BitARGB6666:             return "24BitARGB6666";
+        case COLOR_Format24bitBGR888:               return "24bitBGR888";
+        case COLOR_Format24bitRGB888:               return "24bitRGB888";
+        case COLOR_Format25bitARGB1888:             return "25bitARGB1888";
+        case COLOR_Format32bitABGR8888:             return "32bitABGR8888";
+        case COLOR_Format32bitARGB8888:             return "32bitARGB8888";
+        case COLOR_Format32bitBGRA8888:             return "32bitBGRA8888";
+        case COLOR_Format8bitRGB332:                return "8bitRGB332";
+        case COLOR_FormatCbYCrY:                    return "CbYCrY";
+        case COLOR_FormatCrYCbY:                    return "CrYCbY";
+        case COLOR_FormatL16:                       return "L16";
+        case COLOR_FormatL2:                        return "L2";
+        case COLOR_FormatL24:                       return "L24";
+        case COLOR_FormatL32:                       return "L32";
+        case COLOR_FormatL4:                        return "L4";
+        case COLOR_FormatL8:                        return "L8";
+        case COLOR_FormatMonochrome:                return "Monochrome";
+        case COLOR_FormatRawBayer10bit:             return "RawBayer10bit";
+        case COLOR_FormatRawBayer8bit:              return "RawBayer8bit";
+        case COLOR_FormatRawBayer8bitcompressed:    return "RawBayer8bitcompressed";
+        case COLOR_FormatRGBAFlexible:              return "RGBAFlexible";
+        case COLOR_FormatRGBFlexible:               return "RGBFlexible";
+        case COLOR_FormatSurface:                   return "Surface";
+        case COLOR_FormatYCbYCr:                    return "YCbYCr";
+        case COLOR_FormatYCrYCb:                    return "YCrYCb";
+        case COLOR_FormatYUV411PackedPlanar:        return "YUV411PackedPlanar";
+        case COLOR_FormatYUV411Planar:              return "YUV411Planar";
+        case COLOR_FormatYUV420Flexible:            return "YUV420Flexible";
+        case COLOR_FormatYUV420PackedPlanar:        return "YUV420PackedPlanar";
+        case COLOR_FormatYUV420PackedSemiPlanar:    return "YUV420PackedSemiPlanar";
+        case COLOR_FormatYUV420Planar:              return "YUV420Planar";
+        case COLOR_FormatYUV420SemiPlanar:          return "YUV420SemiPlanar";
+        case COLOR_FormatYUV422Flexible:            return "YUV422Flexible";
+        case COLOR_FormatYUV422PackedPlanar:        return "YUV422PackedPlanar";
+        case COLOR_FormatYUV422PackedSemiPlanar:    return "YUV422PackedSemiPlanar";
+        case COLOR_FormatYUV422Planar:              return "YUV422Planar";
+        case COLOR_FormatYUV422SemiPlanar:          return "YUV422SemiPlanar";
+        case COLOR_FormatYUV444Flexible:            return "YUV444Flexible";
+        case COLOR_FormatYUV444Interleaved:         return "YUV444Interleaved";
+        case COLOR_QCOM_FormatYUV420SemiPlanar:     return "QCOM_YUV420SemiPlanar";
+        case COLOR_TI_FormatYUV420PackedSemiPlanar: return "TI_YUV420PackedSemiPlanar";
+        default:                                    return def;
+    }
+}
+
 constexpr char FEATURE_AdaptivePlayback[]       = "adaptive-playback";
 constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
 constexpr char FEATURE_PartialFrame[] = "partial-frame";
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index 6a5c6b6..09639e2 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -70,7 +70,12 @@
     ERROR_DRM_DEVICE_REVOKED                 = DRM_ERROR_BASE - 9,
     ERROR_DRM_RESOURCE_BUSY                  = DRM_ERROR_BASE - 10,
     ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = DRM_ERROR_BASE - 11,
-    ERROR_DRM_LAST_USED_ERRORCODE            = DRM_ERROR_BASE - 11,
+    ERROR_DRM_INSUFFICIENT_SECURITY          = DRM_ERROR_BASE - 12,
+    ERROR_DRM_FRAME_TOO_LARGE                = DRM_ERROR_BASE - 13,
+    ERROR_DRM_RESOURCE_CONTENTION            = DRM_ERROR_BASE - 14,
+    ERROR_DRM_SESSION_LOST_STATE             = DRM_ERROR_BASE - 15,
+    ERROR_DRM_INVALID_STATE                  = DRM_ERROR_BASE - 16,
+    ERROR_DRM_LAST_USED_ERRORCODE            = DRM_ERROR_BASE - 16,
 
     ERROR_DRM_VENDOR_MAX                     = DRM_ERROR_BASE - 500,
     ERROR_DRM_VENDOR_MIN                     = DRM_ERROR_BASE - 999,
diff --git a/media/libmediaextractor/include/media/MediaSource.h b/media/libstagefright/include/media/stagefright/MediaSource.h
similarity index 100%
rename from media/libmediaextractor/include/media/MediaSource.h
rename to media/libstagefright/include/media/stagefright/MediaSource.h
diff --git a/media/libstagefright/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
deleted file mode 120000
index 160f8d3..0000000
--- a/media/libstagefright/include/media/stagefright/MetaData.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MetaData.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MetaData.h
rename to media/libstagefright/include/media/stagefright/MetaData.h
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
deleted file mode 120000
index 1e12193..0000000
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MetaDataBase.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MetaDataBase.h
rename to media/libstagefright/include/media/stagefright/MetaDataBase.h
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 8dc8d38..f34f9b6 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -96,8 +96,7 @@
 
     bool getCachedDuration(int64_t *durationUs, bool *eos) const;
 
-    status_t getAudioPresentations(size_t trackIdx,
-            AudioPresentationCollection *presentations) const;
+    status_t getAudioPresentations(size_t trackIdx, AudioPresentationCollection *presentations);
 
 protected:
     virtual ~NuMediaExtractor();
diff --git a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
index be911cc..891b9a0 100644
--- a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
+++ b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
@@ -34,8 +34,8 @@
 private:
     void updateVsync() override;
 
-    long mAppVsyncOffset;
-    long mSfVsyncOffset;
+    nsecs_t mAppVsyncOffset;
+    nsecs_t mSfVsyncOffset;
     sp<VsyncTracker> mVsyncTracker;
     sp<ChoreographerThread> mChoreographerThread;
     Mutex mLock;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 345f85d..1482072 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -217,6 +217,9 @@
     sp<IDescrambler> mDescrambler;
     AudioPresentationCollection mAudioPresentations;
 
+    // Send audio presentations along with access units.
+    void addAudioPresentations(const sp<ABuffer> &buffer);
+
     // Flush accumulated payload if necessary --- i.e. at EOS or at the start of
     // another payload. event is set if the flushed payload is PES with a sync
     // frame.
@@ -758,21 +761,21 @@
     // reasonable amount of time. To handle the wrap-around, use fancy math
     // to get an extended PTS that is within [-0xffffffff, 0xffffffff]
     // of the latest recovered PTS.
-    if (mLastRecoveredPTS < 0ll) {
+    if (mLastRecoveredPTS < 0LL) {
         // Use the original 33bit number for 1st frame, the reason is that
         // if 1st frame wraps to negative that's far away from 0, we could
         // never start. Only start wrapping around from 2nd frame.
         mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
     } else {
         mLastRecoveredPTS = static_cast<int64_t>(
-                ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000ll)
+                ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000LL)
                 & 0xfffffffe00000000ull) | PTS_33bit);
         // We start from 0, but recovered PTS could be slightly below 0.
         // Clamp it to 0 as rest of the pipeline doesn't take negative pts.
         // (eg. video is read first and starts at 0, but audio starts at 0xfffffff0)
-        if (mLastRecoveredPTS < 0ll) {
+        if (mLastRecoveredPTS < 0LL) {
             ALOGI("Clamping negative recovered PTS (%" PRId64 ") to 0", mLastRecoveredPTS);
-            mLastRecoveredPTS = 0ll;
+            mLastRecoveredPTS = 0LL;
         }
     }
 
@@ -822,7 +825,7 @@
 
     int64_t timeUs = (PTS * 100) / 9;
 
-    if (mParser->mAbsoluteTimeAnchorUs >= 0ll) {
+    if (mParser->mAbsoluteTimeAnchorUs >= 0LL) {
         timeUs += mParser->mAbsoluteTimeAnchorUs;
     }
 
@@ -1708,6 +1711,13 @@
     return err;
 }
 
+void ATSParser::Stream::addAudioPresentations(const sp<ABuffer> &buffer) {
+    std::ostringstream outStream(std::ios::out);
+    serializeAudioPresentations(mAudioPresentations, &outStream);
+    sp<ABuffer> ap = ABuffer::CreateAsCopy(outStream.str().data(), outStream.str().size());
+    buffer->meta()->setBuffer("audio-presentation-info", ap);
+}
+
 void ATSParser::Stream::onPayloadData(
         unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
         unsigned PES_scrambling_control,
@@ -1723,7 +1733,7 @@
 
     ALOGV("onPayloadData mStreamType=0x%02x size: %zu", mStreamType, size);
 
-    int64_t timeUs = 0ll;  // no presentation timestamp available.
+    int64_t timeUs = 0LL;  // no presentation timestamp available.
     if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
         timeUs = mProgram->convertPTSToTimestamp(PTS);
     }
@@ -1758,8 +1768,10 @@
                     }
                 }
                 mSource = new AnotherPacketSource(meta);
+                if (mAudioPresentations.size() > 0) {
+                    addAudioPresentations(accessUnit);
+                }
                 mSource->queueAccessUnit(accessUnit);
-                mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
                 ALOGV("onPayloadData: created AnotherPacketSource PID 0x%08x of type 0x%02x",
                         mElementaryPID, mStreamType);
             }
@@ -1771,8 +1783,10 @@
             if (mSource->getFormat() == NULL) {
                 mSource->setFormat(mQueue->getFormat());
             }
+            if (mAudioPresentations.size() > 0) {
+                addAudioPresentations(accessUnit);
+            }
             mSource->queueAccessUnit(accessUnit);
-            mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
         }
 
         // Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
@@ -1855,10 +1869,10 @@
 
 ATSParser::ATSParser(uint32_t flags)
     : mFlags(flags),
-      mAbsoluteTimeAnchorUs(-1ll),
+      mAbsoluteTimeAnchorUs(-1LL),
       mTimeOffsetValid(false),
-      mTimeOffsetUs(0ll),
-      mLastRecoveredPTS(-1ll),
+      mTimeOffsetUs(0LL),
+      mLastRecoveredPTS(-1LL),
       mNumTSPacketsParsed(0),
       mNumPCRs(0) {
     mPSISections.add(0 /* PID */, new PSISection);
@@ -1900,7 +1914,7 @@
         if ((mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)
                 && extra->findInt64(
                     kATSParserKeyRecentMediaTimeUs, &mediaTimeUs)) {
-            if (mAbsoluteTimeAnchorUs >= 0ll) {
+            if (mAbsoluteTimeAnchorUs >= 0LL) {
                 mediaTimeUs -= mAbsoluteTimeAnchorUs;
             }
             if (mTimeOffsetValid) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index e2c5031..62e3a4b 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -35,7 +35,7 @@
 
 namespace android {
 
-const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
+const int64_t kNearEOSMarkUs = 2000000LL; // 2 secs
 
 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
     : mIsAudio(false),
@@ -223,6 +223,12 @@
                     kKeyMpegUserData, 0, mpegUserData->data(), mpegUserData->size());
         }
 
+        sp<ABuffer> ap;
+        if (buffer->meta()->findBuffer("audio-presentation-info", &ap) && ap != NULL) {
+            bufmeta.setData(
+                    kKeyAudioPresentationInfo, 0, ap->data(), ap->size());
+        }
+
         int32_t cryptoMode;
         if (buffer->meta()->findInt32("cryptoMode", &cryptoMode)) {
             int32_t cryptoKey;
@@ -293,7 +299,7 @@
     if (buffer->meta()->findInt32("discontinuity", &discontinuity)){
         ALOGV("queueing a discontinuity with queueAccessUnit");
 
-        mLastQueuedTimeUs = 0ll;
+        mLastQueuedTimeUs = 0LL;
         mEOSResult = OK;
         mLatestEnqueuedMeta = NULL;
 
@@ -697,23 +703,4 @@
     return firstMeta;
 }
 
-void AnotherPacketSource::convertAudioPresentationInfoToMetadata(
-        const AudioPresentationCollection& presentations) {
-    sp<MetaData> meta = getFormat();
-    if (meta == NULL) {
-        return;
-    }
-    if (presentations.empty()) {
-        // Clear audio presentation info in metadata.
-        Mutex::Autolock autoLock(mLock);
-        meta->remove(kKeyAudioPresentationInfo);
-    } else {
-        std::ostringstream outStream(std::ios::out);
-        serializeAudioPresentations(presentations, &outStream);
-        Mutex::Autolock autoLock(mLock);
-        meta->setData(kKeyAudioPresentationInfo, MetaData::TYPE_NONE,
-                outStream.str().data(), outStream.str().size());
-    }
-}
-
 }  // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 57a6c33..f4a6acb 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -85,8 +85,6 @@
     void trimBuffersAfterMeta(const sp<AMessage> &meta);
     sp<AMessage> trimBuffersBeforeMeta(const sp<AMessage> &meta);
 
-    void convertAudioPresentationInfoToMetadata(const AudioPresentationCollection &presentations);
-
 protected:
     virtual ~AnotherPacketSource();
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index fb8b9fd..b91edcd 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1111,7 +1111,7 @@
     memcpy(accessUnit->data(), mBuffer->data() + 4, payloadSize);
 
     int64_t timeUs = fetchTimestamp(payloadSize + 4);
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         ALOGE("Negative timeUs");
         return NULL;
     }
@@ -1147,7 +1147,7 @@
         return NULL;
     }
 
-    if (info.mTimestampUs < 0ll) {
+    if (info.mTimestampUs < 0LL) {
         ALOGE("Negative info.mTimestampUs");
         return NULL;
     }
@@ -1317,7 +1317,7 @@
 
     }
 
-    if (timeUs == 0ll) {
+    if (timeUs == 0LL) {
         ALOGV("Returning 0 timestamp");
     }
 
@@ -1460,7 +1460,7 @@
             mBuffer->setRange(0, mBuffer->size() - nextScan);
 
             int64_t timeUs = fetchTimestamp(nextScan);
-            if (timeUs < 0ll) {
+            if (timeUs < 0LL) {
                 ALOGE("Negative timeUs");
                 return NULL;
             }
@@ -1545,7 +1545,7 @@
     mBuffer->setRange(0, mBuffer->size() - frameSize);
 
     int64_t timeUs = fetchTimestamp(frameSize);
-    if (timeUs < 0ll) {
+    if (timeUs < 0LL) {
         ALOGE("Negative timeUs");
         return NULL;
     }
@@ -1732,7 +1732,7 @@
                 mBuffer->setRange(0, mBuffer->size() - offset);
 
                 int64_t timeUs = fetchTimestamp(offset);
-                if (timeUs < 0ll) {
+                if (timeUs < 0LL) {
                     ALOGE("Negative timeUs");
                     return NULL;
                 }
@@ -1929,7 +1929,7 @@
                     mBuffer->setRange(0, size);
 
                     int64_t timeUs = fetchTimestamp(offset);
-                    if (timeUs < 0ll) {
+                    if (timeUs < 0LL) {
                         ALOGE("Negative timeus");
                         return NULL;
                     }
diff --git a/media/libstagefright/omx/1.0/Omx.cpp b/media/libstagefright/omx/1.0/Omx.cpp
index 4e2d398..121bb1a 100644
--- a/media/libstagefright/omx/1.0/Omx.cpp
+++ b/media/libstagefright/omx/1.0/Omx.cpp
@@ -124,11 +124,11 @@
         } else {
             uint32_t quirks = 0;
             for (const auto& quirk : codec->second.quirkSet) {
-                if (quirk == "requires-allocate-on-input-ports") {
+                if (quirk == "quirk::requires-allocate-on-input-ports") {
                     quirks |= OMXNodeInstance::
                             kRequiresAllocateBufferOnInputPorts;
                 }
-                if (quirk == "requires-allocate-on-output-ports") {
+                if (quirk == "quirk::requires-allocate-on-output-ports") {
                     quirks |= OMXNodeInstance::
                             kRequiresAllocateBufferOnOutputPorts;
                 }
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 68b375a..d7aacff 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -355,9 +355,9 @@
       mQuirks(0),
       mBufferIDCount(0),
       mRestorePtsFailed(false),
-      mMaxTimestampGapUs(0ll),
-      mPrevOriginalTimeUs(-1ll),
-      mPrevModifiedTimeUs(-1ll)
+      mMaxTimestampGapUs(0LL),
+      mPrevOriginalTimeUs(-1LL),
+      mPrevModifiedTimeUs(-1LL)
 {
     mName = ADebug::GetDebugName(name);
     DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
@@ -1948,7 +1948,7 @@
 int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) {
     int64_t originalTimeUs = timestamp;
 
-    if (mMaxTimestampGapUs > 0ll) {
+    if (mMaxTimestampGapUs > 0LL) {
         /* Cap timestamp gap between adjacent frames to specified max
          *
          * In the scenario of cast mirroring, encoding could be suspended for
@@ -1956,7 +1956,7 @@
          * where encoder's rate control logic produces huge frames after a
          * long period of suspension.
          */
-        if (mPrevOriginalTimeUs >= 0ll) {
+        if (mPrevOriginalTimeUs >= 0LL) {
             int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
             timestamp = (timestampGapUs < mMaxTimestampGapUs ?
                 timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
@@ -1964,7 +1964,7 @@
         ALOGV("IN  timestamp: %lld -> %lld",
             static_cast<long long>(originalTimeUs),
             static_cast<long long>(timestamp));
-    } else if (mMaxTimestampGapUs < 0ll) {
+    } else if (mMaxTimestampGapUs < 0LL) {
         /*
          * Apply a fixed timestamp gap between adjacent frames.
          *
@@ -1972,7 +1972,7 @@
          * on frames could go forward or backward. Some encoders may silently
          * drop frames when it goes backward (or even stay unchanged).
          */
-        if (mPrevOriginalTimeUs >= 0ll) {
+        if (mPrevOriginalTimeUs >= 0LL) {
             timestamp = mPrevModifiedTimeUs - mMaxTimestampGapUs;
         }
         ALOGV("IN  timestamp: %lld -> %lld",
@@ -1983,7 +1983,7 @@
     mPrevOriginalTimeUs = originalTimeUs;
     mPrevModifiedTimeUs = timestamp;
 
-    if (mMaxTimestampGapUs != 0ll && !mRestorePtsFailed) {
+    if (mMaxTimestampGapUs != 0LL && !mRestorePtsFailed) {
         mOriginalTimeUs.add(timestamp, originalTimeUs);
     }
 
@@ -2016,7 +2016,7 @@
 void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
     Mutex::Autolock autoLock(mLock);
 
-    if (mMaxTimestampGapUs == 0ll || mRestorePtsFailed) {
+    if (mMaxTimestampGapUs == 0LL || mRestorePtsFailed) {
         return;
     }
 
diff --git a/media/libstagefright/omx/tests/Android.bp b/media/libstagefright/omx/tests/Android.bp
index 31bc837..fb03229 100644
--- a/media/libstagefright/omx/tests/Android.bp
+++ b/media/libstagefright/omx/tests/Android.bp
@@ -9,7 +9,6 @@
         "libbinder",
         "libmedia",
         "libmedia_omx",
-        "libmediaextractor",
         "libutils",
         "liblog",
         "libstagefright_foundation",
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 201a5df..b964bc0 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -417,7 +417,7 @@
     if (sessionDesc->getDurationUs(&durationUs)) {
         mFormat->setInt64(kKeyDuration, durationUs);
     } else {
-        mFormat->setInt64(kKeyDuration, -1ll);
+        mFormat->setInt64(kKeyDuration, -1LL);
     }
 
     mInitCheck = OK;
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
index c7a65c2..befc226 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.cpp
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -36,7 +36,7 @@
 
         if (status == WRONG_SEQUENCE_NUMBER) {
             if (mFirstFailureTimeUs >= 0) {
-                if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000ll) {
+                if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000LL) {
                     mFirstFailureTimeUs = -1;
 
                     // LOG(VERBOSE) << "waited too long for packet.";
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a86ab74..6a4706d 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -50,7 +50,7 @@
 }
 
 // static
-const int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTPConnection::kSelectTimeoutUs = 1000LL;
 
 struct ARTPConnection::StreamInfo {
     int mRTPSocket;
@@ -118,7 +118,7 @@
     bumpSocketBufferSize(*rtcpSocket);
 
     /* rand() * 1000 may overflow int type, use long long */
-    unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
+    unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
     start &= ~1;
 
     for (unsigned port = start; port < 65536; port += 2) {
@@ -307,7 +307,7 @@
 
     int64_t nowUs = ALooper::GetNowUs();
     if (mLastReceiverReportTimeUs <= 0
-            || mLastReceiverReportTimeUs + 5000000ll <= nowUs) {
+            || mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
         sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
         List<StreamInfo>::iterator it = mStreams.begin();
         while (it != mStreams.end()) {
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4827cd2..4afa6f4 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -180,7 +180,7 @@
     }
 
     int64_t nowUs = ALooper::GetNowUs();
-    if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000ll > nowUs) {
+    if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000LL > nowUs) {
         // Send FIR requests at most every 5 secs.
         return;
     }
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 49e01c0..4f86773 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -420,10 +420,10 @@
 uint64_t ARTPWriter::GetNowNTP() {
     uint64_t nowUs = ALooper::GetNowUs();
 
-    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+    nowUs += ((70LL * 365 + 17) * 24) * 60 * 60 * 1000000LL;
 
-    uint64_t hi = nowUs / 1000000ll;
-    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
+    uint64_t hi = nowUs / 1000000LL;
+    uint64_t lo = ((1LL << 32) * (nowUs % 1000000LL)) / 1000000LL;
 
     return (hi << 32) | lo;
 }
@@ -576,7 +576,7 @@
     int64_t timeUs;
     CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
 
     const uint8_t *mediaData =
         (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
@@ -671,7 +671,7 @@
     int64_t timeUs;
     CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
 
-    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
 
     const uint8_t *mediaData =
         (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 33c1c18..20cb415 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -39,7 +39,7 @@
 namespace android {
 
 // static
-const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000LL;
 
 // static
 const AString ARTSPConnection::sUserAgent =
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 23269af..4b6f928 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -364,14 +364,14 @@
         // adjust time-stamps after pause/resume
         if (mResumed) {
             int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
-            CHECK_GE(durExcludingEarlierPausesUs, 0ll);
+            CHECK_GE(durExcludingEarlierPausesUs, 0LL);
             int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
             CHECK_GE(pausedDurationUs, lastDurationUs);
             previousPausedDurationUs += pausedDurationUs - lastDurationUs;
             mResumed = false;
         }
         timestampUs -= previousPausedDurationUs;
-        CHECK_GE(timestampUs, 0ll);
+        CHECK_GE(timestampUs, 0LL);
 
         int32_t isSync = false;
         md.findInt32(kKeyIsSyncFrame, &isSync);
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 2dec9fa..6e541ba 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -26,8 +26,9 @@
 #include <sys/stat.h>
 #include <expat.h>
 
-#include <cctype>
 #include <algorithm>
+#include <cctype>
+#include <string>
 
 namespace android {
 
@@ -326,8 +327,8 @@
         case SECTION_DECODER:
         case SECTION_ENCODER:
         {
-            if (strEq(name, "Quirk")) {
-                (void)addQuirk(attrs);
+            if (strEq(name, "Quirk") || strEq(name, "Attribute")) {
+                (void)addQuirk(attrs, name);
             } else if (strEq(name, "Type")) {
                 (void)addTypeFromAttributes(attrs,
                         (mCurrentSection == SECTION_ENCODER));
@@ -348,6 +349,8 @@
             if (outside &&
                     (strEq(name, "Limit") || strEq(name, "Feature"))) {
                 ALOGW("ignoring %s specified outside of a Type", name);
+            } else if (strEq(name, "Alias")) {
+                (void)addAlias(attrs);
             } else if (strEq(name, "Limit")) {
                 (void)addLimit(attrs);
             } else if (strEq(name, "Feature")) {
@@ -579,7 +582,7 @@
     return OK;
 }
 
-status_t MediaCodecsXmlParser::addQuirk(const char **attrs) {
+status_t MediaCodecsXmlParser::addQuirk(const char **attrs, const char *tag) {
     if (mCurrentCodec == mCodecMap.end()) {
         return BAD_VALUE;
     }
@@ -606,7 +609,12 @@
         return BAD_VALUE;
     }
 
-    mCurrentCodec->second.quirkSet.emplace(name);
+    std::string tagString = tag;
+    std::transform(tagString.begin(), tagString.end(), tagString.begin(), ::tolower);
+    tagString.append("::");
+    tagString.append(name);
+    mCurrentCodec->second.quirkSet.emplace(tagString.c_str());
+    ALOGI("adding %s to %s", tagString.c_str(), mCurrentCodec->first.c_str());
     return OK;
 }
 
@@ -760,6 +768,7 @@
             strEq(a_name, "quality") ||
             strEq(a_name, "size") ||
             strEq(a_name, "measured-blocks-per-second") ||
+            strHasPrefix(a_name, "performance-point-") ||
             strHasPrefix(a_name, "measured-frame-rate-")) {
         // "range" is specified in exactly one of the following forms:
         // 1) min-max
@@ -964,6 +973,34 @@
     return OK;
 }
 
+status_t MediaCodecsXmlParser::addAlias(const char **attrs) {
+    size_t i = 0;
+    const char *name = nullptr;
+
+    while (attrs[i] != nullptr) {
+        if (strEq(attrs[i], "name")) {
+            if (attrs[++i] == nullptr) {
+                ALOGE("addAlias: name is null");
+                return BAD_VALUE;
+            }
+            name = attrs[i];
+        } else {
+            ALOGE("addAlias: unrecognized attribute: %s", attrs[i]);
+            return BAD_VALUE;
+        }
+        ++i;
+    }
+
+    // Every feature must have a name.
+    if (name == nullptr) {
+        ALOGE("alias with no 'name' attribute");
+        return BAD_VALUE;
+    }
+
+    mCurrentCodec->second.aliases.emplace_back(name);
+    return OK;
+}
+
 const MediaCodecsXmlParser::AttributeMap&
         MediaCodecsXmlParser::getServiceAttributeMap() const {
     return mServiceAttributeMap;
@@ -1041,11 +1078,18 @@
 
             NodeInfo nodeInfo;
             nodeInfo.name = codecName;
+            // NOTE: no aliases are exposed in role info
+            // attribute quirks are exposed as node attributes
             nodeInfo.attributeList.reserve(typeAttributeMap.size());
             for (const auto& attribute : typeAttributeMap) {
                 nodeInfo.attributeList.push_back(
                         Attribute{attribute.first, attribute.second});
             }
+            for (const std::string &quirk : codec.second.quirkSet) {
+                if (strHasPrefix(quirk.c_str(), "attribute::")) {
+                    nodeInfo.attributeList.push_back(Attribute{quirk, "present"});
+                }
+            }
             nodeList->insert(std::make_pair(
                     std::move(order), std::move(nodeInfo)));
         }
diff --git a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
index cc69e52..fd949da 100644
--- a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
+++ b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
@@ -65,6 +65,7 @@
         size_t order;      ///< Order of appearance in the file (starting from 0)
         QuirkSet quirkSet; ///< Set of quirks requested by this codec
         TypeMap typeMap;   ///< Map of types supported by this codec
+        std::vector<std::string> aliases; ///< Name aliases for this codec
     };
 
     typedef std::pair<std::string, CodecProperties> Codec;
@@ -76,6 +77,7 @@
     struct NodeInfo {
         std::string name;
         std::vector<Attribute> attributeList;
+        // note: aliases are not exposed here as they are not part of the role map
     };
 
     /**
@@ -171,8 +173,9 @@
     void addMediaCodec(bool encoder, const char *name,
             const char *type = nullptr);
 
-    status_t addQuirk(const char **attrs);
+    status_t addQuirk(const char **attrs, const char *tag);
     status_t addTypeFromAttributes(const char **attrs, bool encoder);
+    status_t addAlias(const char **attrs);
     status_t addLimit(const char **attrs);
     status_t addFeature(const char **attrs);
     void addType(const char *name);
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 73bd2ca..74754ea 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -78,7 +78,6 @@
         "libmedia_omx",
         "libmedia_jni",
         "libmediadrm",
-        "libmediaextractor",
         "libstagefright",
         "libstagefright_foundation",
         "libstagefright_bufferqueue_helper",
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index f697bd1..8296598 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -448,6 +448,16 @@
         meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
     }
 
+    const void *audioPresentationsPointer;
+    size_t audioPresentationsLength;
+    if (sampleMeta->findData(
+            kKeyAudioPresentationInfo, &dataType,
+            &audioPresentationsPointer, &audioPresentationsLength)) {
+        sp<ABuffer> audioPresentationsData = ABuffer::CreateAsCopy(
+                audioPresentationsPointer, audioPresentationsLength);
+        meta->setBuffer(AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, audioPresentationsData);
+    }
+
     return AMEDIA_OK;
 }
 
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 538a0eb..63a9ec4 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -322,6 +322,13 @@
                         }
                     }
                     status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
+                    // remove stale audio patch with same input as sink if any
+                    for (auto& iter : mPatches) {
+                        if (iter.second.mAudioPatch.sinks[0].ext.mix.handle == thread->id()) {
+                            mPatches.erase(iter.first);
+                            break;
+                        }
+                    }
                 } else {
                     sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice();
                     status = hwDevice->createAudioPatch(patch->num_sources,
@@ -376,6 +383,14 @@
             }
 
             status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
+
+            // remove stale audio patch with same output as source if any
+            for (auto& iter : mPatches) {
+                if (iter.second.mAudioPatch.sources[0].ext.mix.handle == thread->id()) {
+                    mPatches.erase(iter.first);
+                    break;
+                }
+            }
         } break;
         default:
             status = BAD_VALUE;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c6941c0..607d2d1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -494,6 +494,8 @@
     case AUDIO_SOURCE_VOICE_COMMUNICATION:  return "voice communication";
     case AUDIO_SOURCE_REMOTE_SUBMIX:        return "remote submix";
     case AUDIO_SOURCE_UNPROCESSED:          return "unprocessed";
+    case AUDIO_SOURCE_VOICE_PERFORMANCE:    return "voice performance";
+    case AUDIO_SOURCE_ECHO_REFERENCE:       return "echo reference";
     case AUDIO_SOURCE_FM_TUNER:             return "FM tuner";
     case AUDIO_SOURCE_HOTWORD:              return "hotword";
     default:                                return "unknown";
@@ -3850,6 +3852,7 @@
         type |= patch->sinks[i].ext.device.type;
     }
 
+    audio_port_handle_t sinkPortId = patch->sinks[0].id;
 #ifdef ADD_BATTERY_DATA
     // when changing the audio output device, call addBatteryData to notify
     // the change
@@ -3879,7 +3882,7 @@
 
     // mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
     // the thread is created so that the first patch creation triggers an ioConfigChanged callback
-    bool configChanged = mPrevOutDevice != type;
+    bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
     mOutDevice = type;
     mPatch = *patch;
 
@@ -3908,6 +3911,7 @@
     }
     if (configChanged) {
         mPrevOutDevice = type;
+        mDeviceId = sinkPortId;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
     }
     return status;
@@ -8145,6 +8149,7 @@
 
     // store new device and send to effects
     mInDevice = patch->sources[0].ext.device.type;
+    audio_port_handle_t deviceId = patch->sources[0].id;
     mPatch = *patch;
     for (size_t i = 0; i < mEffectChains.size(); i++) {
         mEffectChains[i]->setDevice_l(mInDevice);
@@ -8186,9 +8191,10 @@
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    if (mInDevice != mPrevInDevice) {
+    if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
         mPrevInDevice = mInDevice;
+        mDeviceId = deviceId;
     }
 
     return status;
@@ -8285,7 +8291,7 @@
         audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
     : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
       mSessionId(AUDIO_SESSION_NONE),
-      mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
+      mPortId(AUDIO_PORT_HANDLE_NONE),
       mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
       mActiveTracks(&this->mLocalLog),
       mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
@@ -8769,7 +8775,7 @@
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    if (isOutput() && mPrevOutDevice != mOutDevice) {
+    if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
         mPrevOutDevice = type;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
@@ -8780,7 +8786,7 @@
         }
         mDeviceId = deviceId;
     }
-    if (!isOutput() && mPrevInDevice != mInDevice) {
+    if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
         mPrevInDevice = type;
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
         sp<MmapStreamCallback> callback = mCallback.promote();
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index e8b2158..5d06773 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -485,6 +485,10 @@
                 audio_devices_t         mPrevOutDevice;   // previous output device
                 audio_devices_t         mPrevInDevice;    // previous input device
                 struct audio_patch      mPatch;
+                /**
+                 * @brief mDeviceId  current device port unique identifier
+                 */
+                audio_port_handle_t     mDeviceId = AUDIO_PORT_HANDLE_NONE;
                 audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
@@ -1704,7 +1708,6 @@
 
                 audio_attributes_t      mAttr;
                 audio_session_t         mSessionId;
-                audio_port_handle_t     mDeviceId;
                 audio_port_handle_t     mPortId;
 
                 wp<MmapStreamCallback>  mCallback;
diff --git a/services/audiopolicy/TEST_MAPPING b/services/audiopolicy/TEST_MAPPING
new file mode 100644
index 0000000..a94fd87
--- /dev/null
+++ b/services/audiopolicy/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+       "name": "audiopolicy_tests"
+    },
+    {
+       "name": "systemaudio_tests"
+    }
+  ]
+}
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 30b0044..46a2a40 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -83,7 +83,10 @@
  * @param[in] inputSource to consider. Valid sources are:
  * - AUDIO_SOURCE_VOICE_COMMUNICATION
  * - AUDIO_SOURCE_CAMCORDER
+ * - AUDIO_SOURCE_VOICE_PERFORMANCE
+ * - AUDIO_SOURCE_UNPROCESSED
  * - AUDIO_SOURCE_MIC
+ * - AUDIO_SOURCE_ECHO_REFERENCE
  * - AUDIO_SOURCE_FM_TUNER
  * - AUDIO_SOURCE_VOICE_RECOGNITION
  * - AUDIO_SOURCE_HOTWORD
@@ -96,10 +99,16 @@
 {
     switch (inputSource) {
     case AUDIO_SOURCE_VOICE_COMMUNICATION:
-        return 6;
+        return 9;
     case AUDIO_SOURCE_CAMCORDER:
-        return 5;
+        return 8;
+    case AUDIO_SOURCE_VOICE_PERFORMANCE:
+        return 7;
+    case AUDIO_SOURCE_UNPROCESSED:
+        return 6;
     case AUDIO_SOURCE_MIC:
+        return 5;
+    case AUDIO_SOURCE_ECHO_REFERENCE:
         return 4;
     case AUDIO_SOURCE_FM_TUNER:
         return 3;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 5099ebb..d52eb3d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -133,18 +133,14 @@
         mDefaultOutputDevice->attach(module);
         defaultInputDevice->attach(module);
 
-        sp<OutputProfile> outProfile;
-        outProfile = new OutputProfile(String8("primary"));
-        outProfile->attach(module);
+        sp<OutputProfile> outProfile = new OutputProfile(String8("primary"));
         outProfile->addAudioProfile(
                 new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
         outProfile->addSupportedDevice(mDefaultOutputDevice);
         outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
         module->addOutputProfile(outProfile);
 
-        sp<InputProfile> inProfile;
-        inProfile = new InputProfile(String8("primary"));
-        inProfile->attach(module);
+        sp<InputProfile> inProfile = new InputProfile(String8("primary"));
         inProfile->addAudioProfile(micProfile);
         inProfile->addSupportedDevice(defaultInputDevice);
         module->addInputProfile(inProfile);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 776d98f..4d0916e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -360,10 +360,12 @@
                 break;
             }
         }
-        if (!deviceMatch) {
+        if (deviceMatch) {
+            mix->setMatchUid(uid);
+        } else {
             // this mix doesn't go to one of the listed devices for the given uid,
             // modify its rules to exclude the uid
-            mix->excludeUid(uid);
+            mix->setExcludeUid(uid);
         }
     }
 
@@ -382,7 +384,7 @@
         for (size_t j = 0; j < mix->mCriteria.size(); j++) {
             const uint32_t rule = mix->mCriteria[j].mRule;
             // is this rule affecting the uid?
-            if (rule == RULE_EXCLUDE_UID
+            if ((rule == RULE_EXCLUDE_UID || rule == RULE_MATCH_UID)
                     && uid == mix->mCriteria[j].mValue.mUid) {
                 foundUidRule = true;
                 criteriaToRemove.push_back(j);
diff --git a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
index a597e87..efc69da 100644
--- a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
+++ b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
@@ -19,10 +19,8 @@
 class AudioPolicyManagerInterface;
 class AudioPolicyPluginInterface;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 class Engine;
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
index baaefd2..7631976 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
@@ -7,15 +7,19 @@
 #
 ################################################################################################
 
-ifeq (1, 0)
-
 LOCAL_PATH := $(call my-dir)
 
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
 PFW_CORE := external/parameter-framework
-BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
+#@TODO: upstream new domain generator
+#BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
 PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
 PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
 
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
+
 ##################################################################
 # CONFIGURATION FILES
 ##################################################################
@@ -25,7 +29,8 @@
 LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework
 LOCAL_SRC_FILES := $(LOCAL_MODULE).in
 
 AUDIO_PATTERN = @TUNING_ALLOWED@
@@ -46,7 +51,8 @@
 LOCAL_MODULE := PolicyClass.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
 LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
@@ -54,12 +60,12 @@
 LOCAL_MODULE := PolicySubsystem.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_REQUIRED_MODULES := \
     PolicySubsystem-CommonTypes.xml \
-    PolicySubsystem-Volume.xml \
-    libpolicy-subsystem \
+    libpolicy-subsystem
 
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
 LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
@@ -67,7 +73,8 @@
 LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
 LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
 
@@ -76,15 +83,16 @@
 LOCAL_MODULE := parameter-framework.policy
 LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-        PolicyClass.xml \
-        PolicySubsystem.xml \
-        ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+    policy_criteria.xml \
+    policy_criterion_types.xml \
+    PolicySubsystem.xml \
+    PolicyClass.xml \
+    ParameterFrameworkConfigurationPolicy.xml
 
 ifeq ($(pfw_rebuild_settings),true)
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
 PFW_EDD_FILES := \
         $(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
         $(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -100,6 +108,17 @@
         $(LOCAL_PATH)/Settings/device_for_input_source.pfw \
         $(LOCAL_PATH)/Settings/volumes.pfw
 
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+    $(PFW_EDD_FILES)
+
+
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
+
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
 include $(BUILD_PFW_SETTINGS)
 else
 # Use the existing file
@@ -107,19 +126,27 @@
 include $(BUILD_PREBUILT)
 endif # pfw_rebuild_settings
 
+endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 0)
+
 ######### Policy PFW Settings - No Output #########
+ifeq (0, 1)
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := parameter-framework.policy.no-output
 LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-        PolicyClass.xml \
-        PolicySubsystem.xml \
-        ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+    policy_criteria.xml \
+    policy_criterion_types.xml \
+    PolicySubsystem.xml \
+    PolicyClass.xml \
+    ParameterFrameworkConfigurationPolicy.xml
 
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
 PFW_EDD_FILES := \
         $(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
         $(LOCAL_PATH)/Settings/strategy_for_stream.pfw \
@@ -128,20 +155,26 @@
         $(LOCAL_PATH)/Settings/volumes.pfw
 
 include $(BUILD_PFW_SETTINGS)
-
+endif # ifeq (0, 1)
 ######### Policy PFW Settings - No Input #########
+ifeq (0, 1)
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := parameter-framework.policy.no-input
 LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
 LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
-        PolicyClass.xml \
-        PolicySubsystem.xml \
-        ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+    policy_criteria.xml \
+    policy_criterion_types.xml \
+    PolicySubsystem.xml \
+    PolicyClass.xml \
+    ParameterFrameworkConfigurationPolicy.xml
 
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
 PFW_EDD_FILES := \
         $(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
         $(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -160,3 +193,9 @@
 include $(BUILD_PFW_SETTINGS)
 
 endif # ifeq (1, 0)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#######################################################################
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
index f5615cd..f80a07f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    SystemClassName="Policy" ServerPort="5019" TuningAllowed="@TUNING_ALLOWED@">
+    SystemClassName="Policy" ServerPort="/dev/socket/audioserver/policy_debug"
+    TuningAllowed="@TUNING_ALLOWED@">
 
     <SubsystemPlugins>
         <Location Folder="">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
index b43f83b..0710441 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
@@ -8472,7 +8472,7 @@
     <Configurations>
       <Configuration Name="Sonification">
         <CompoundRule Type="All">
-          <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="RingTone"/>
+          <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="Ringtone"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="Phone">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
index b3115e7..fbea9e2 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
@@ -24,7 +24,7 @@
 			# In case of Ring or Alarm stream type active, switching to sonification
 			# @todo: handle this dynamic case. As a WA, using Ringtone mode...
 			#
-			TelephonyMode Is RingTone
+			TelephonyMode Is Ringtone
 
 			/Policy/policy/usages/assistance_accessibility/applicable_strategy/strategy = sonification
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
index 917d4a7..f923610 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
@@ -9,7 +9,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -37,7 +37,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -65,7 +65,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -93,7 +93,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -121,7 +121,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -149,7 +149,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -177,7 +177,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -205,7 +205,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
@@ -233,7 +233,7 @@
 				bluetooth_sco = 0
 				bluetooth_sco_headset = 0
 				bluetooth_sco_carkit = 0
-				bluetooth_a2dp = 0>
+				bluetooth_a2dp = 0
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
index 461e44a..daa7f68 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
@@ -37,6 +37,10 @@
             <BitParameter Name="speaker_safe" Size="1" Pos="22"/>
             <BitParameter Name="ip" Size="1" Pos="23"/>
             <BitParameter Name="bus" Size="1" Pos="24"/>
+            <BitParameter Name="proxy" Size="1" Pos="25"/>
+            <BitParameter Name="usb_headset" Size="1" Pos="26"/>
+            <BitParameter Name="hearing_aid" Size="1" Pos="27"/>
+            <BitParameter Name="echo_canceller" Size="1" Pos="28"/>
             <BitParameter Name="stub" Size="1" Pos="30"/>
         </BitParameterBlock>
     </ComponentType>
@@ -67,6 +71,9 @@
             <BitParameter Name="loopback" Size="1" Pos="18"/>
             <BitParameter Name="ip" Size="1" Pos="19"/>
             <BitParameter Name="bus" Size="1" Pos="20"/>
+            <BitParameter Name="proxy" Size="1" Pos="21"/>
+            <BitParameter Name="usb_headset" Size="1" Pos="22"/>
+            <BitParameter Name="bluetooth_ble" Size="1" Pos="23"/>
             <BitParameter Name="stub" Size="1" Pos="30"/>
         </BitParameterBlock>
     </ComponentType>
@@ -144,7 +151,7 @@
 
     <!--#################### STRATEGY COMMON TYPES BEGIN ####################-->
 
-    <ComponentType Name="StrategyConfig" Mapping="Strategy:'%1'">
+    <ComponentType Name="StrategyConfig" Mapping="Strategy">
         <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
     </ComponentType>
 
@@ -170,7 +177,7 @@
         </EnumParameter>
     </ComponentType>
 
-    <ComponentType Name="Stream">
+    <ComponentType Name="Stream"  Mapping="Stream">
         <Component Name="applicable_strategy" Type="Strategy"/>
         <Component Name="applicable_volume_profile" Type="VolumeProfileType"
                    Description="Volume profile followed by a given stream type."/>
@@ -181,7 +188,7 @@
     <!--#################### USAGE COMMON TYPES BEGIN ####################-->
 
     <ComponentType Name="Usage">
-        <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage:'%1'"/>
+        <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage"/>
     </ComponentType>
 
     <!--#################### USAGE COMMON TYPES END ####################-->
@@ -190,7 +197,7 @@
 
     <ComponentType Name="InputSource">
         <Component Name="applicable_input_device" Type="InputDevicesMask"
-                   Mapping="InputSource:'%1'" Description="Selected Input device"/>
+                   Mapping="InputSource" Description="Selected Input device"/>
     </ComponentType>
 
     <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
index ad9c356..45d1e8a 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
@@ -13,54 +13,40 @@
 
         <!--#################### STRATEGY BEGIN ####################-->
 
-        <ComponentType Name="Strategies" Description="Identifier must match the enum value to make
-                             the link between the PolicyManager and PFW">
-            <Component Name="media" Type="StrategyConfig" Mapping="Amend1:Media,Identifier:0"/>
-            <Component Name="phone" Type="StrategyConfig" Mapping="Amend1:Phone,Identifier:1"/>
-            <Component Name="sonification" Type="StrategyConfig"
-                                           Mapping="Amend1:Sonification,Identifier:2"/>
-            <Component Name="sonification_respectful" Type="StrategyConfig"
-                       Mapping="Amend1:SonificationRespectful,Identifier:3"/>
-            <Component Name="dtmf" Type="StrategyConfig" Mapping="Amend1:Dtmf,Identifier:4"/>
-            <Component Name="enforced_audible" Type="StrategyConfig"
-                                               Mapping="Amend1:EnforcedAudible,Identifier:5"/>
-            <Component Name="transmitted_through_speaker" Type="StrategyConfig"
-                       Mapping="Amend1:TransmittedThroughSpeaker,Identifier:6"/>
-            <Component Name="accessibility" Type="StrategyConfig"
-                                            Mapping="Amend1:Accessibility,Identifier:7"/>
-            <Component Name="rerouting" Type="StrategyConfig"
-                                        Mapping="Amend1:Rerouting,Identifier:8"/>
+        <ComponentType Name="Strategies">
+            <Component Name="media" Type="StrategyConfig" Mapping="Name:STRATEGY_MEDIA"/>
+            <Component Name="phone" Type="StrategyConfig" Mapping="Name:STRATEGY_PHONE"/>
+            <Component Name="sonification" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION"/>
+            <Component Name="sonification_respectful" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION_RESPECTFUL"/>
+            <Component Name="dtmf" Type="StrategyConfig" Mapping="Name:STRATEGY_DTMF"/>
+            <Component Name="enforced_audible" Type="StrategyConfig" Mapping="Name:STRATEGY_ENFORCED_AUDIBLE"/>
+            <Component Name="transmitted_through_speaker" Type="StrategyConfig" Mapping="Name:STRATEGY_TRANSMITTED_THROUGH_SPEAKER"/>
+            <Component Name="accessibility" Type="StrategyConfig" Mapping="Name:STRATEGY_ACCESSIBILITY"/>
+            <Component Name="rerouting" Type="StrategyConfig" Mapping=",Name:STRATEGY_REROUTING"/>
         </ComponentType>
 
         <!--#################### STRATEGY END ####################-->
 
         <!--#################### STREAM BEGIN ####################-->
 
-        <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition,
-                             identifier mapping must match the value of the enum">
-            <Component Name="voice_call" Type="Stream" Mapping="Stream:VoiceCall,Identifier:0"/>
-            <Component Name="system" Type="Stream" Mapping="Stream:System,Identifier:1"/>
-            <Component Name="ring" Type="Stream" Mapping="Stream:Ring,Identifier:2"/>
-            <Component Name="music" Type="Stream" Mapping="Stream:Music,Identifier:3"/>
-            <Component Name="alarm" Type="Stream" Mapping="Stream:Alarm,Identifier:4"/>
-            <Component Name="notification" Type="Stream"
-                                           Mapping="Stream:Notification,Identifier:5"/>
-            <Component Name="bluetooth_sco" Type="Stream"
-                                            Mapping="Stream:BluetoothSco,Identifier:6"/>
-            <Component Name="enforced_audible" Type="Stream"
-                                               Mapping="Stream:EnforceAudible,Identifier:7"
-                       Description="Sounds that cannot be muted by user and must
-                                    be routed to speaker"/>
-            <Component Name="dtmf" Type="Stream" Mapping="Stream:Dtmf,Identifier:8"/>
-            <Component Name="tts" Type="Stream" Mapping="Stream:Tts,Identifier:9"
-                             Description="Transmitted Through Speaker.
-                                          Plays over speaker only, silent on other devices"/>
-            <Component Name="accessibility" Type="Stream"
-                                            Mapping="Stream:Accessibility,Identifier:10"
+        <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+            <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+            <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+            <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+            <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+            <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+            <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+            <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+                       Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+            <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+            <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+                             Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+            <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
                              Description="For accessibility talk back prompts"/>
-            <Component Name="rerouting" Type="Stream" Mapping="Stream:Rerouting,Identifier:11"
+            <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
                              Description="For dynamic policy output mixes"/>
-            <Component Name="patch" Type="Stream" Mapping="Stream:Patch,Identifier:12"
+            <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
                              Description="For internal audio flinger tracks. Fixed volume"/>
         </ComponentType>
 
@@ -68,36 +54,34 @@
 
         <!--#################### USAGE BEGIN ####################-->
 
-        <ComponentType Name="Usages" Description="associated to audio_usage_t definition,
-                             identifier mapping must match the value of the enum">
-            <Component Name="unknown" Type="Usage" Mapping="Amend1:Unknown,Identifier:0"/>
-            <Component Name="media" Type="Usage" Mapping="Amend1:Media,Identifier:1"/>
+        <ComponentType Name="Usages" Description="associated to audio_usage_t definition">
+            <Component Name="unknown" Type="Usage" Mapping="Name:AUDIO_USAGE_UNKNOWN"/>
+            <Component Name="media" Type="Usage" Mapping="Name:AUDIO_USAGE_MEDIA"/>
             <Component Name="voice_communication" Type="Usage"
-                                                  Mapping="Amend1:VoiceCommunication,Identifier:2"/>
+                       Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION"/>
             <Component Name="voice_communication_signalling" Type="Usage"
-                       Mapping="Amend1:VoiceCommunicationSignalling,Identifier:3"/>
-            <Component Name="alarm" Type="Usage" Mapping="Amend1:Alarm,Identifier:4"/>
-            <Component Name="notification" Type="Usage" Mapping="Amend1:Notification,Identifier:5"/>
+                       Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+            <Component Name="alarm" Type="Usage" Mapping="Name:AUDIO_USAGE_ALARM"/>
+            <Component Name="notification" Type="Usage" Mapping="Name:AUDIO_USAGE_NOTIFICATION"/>
             <Component Name="notification_telephony_ringtone" Type="Usage"
-                       Mapping="Amend1:NotificationTelephonyRingtone,Identifier:6"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
             <Component Name="notification_communication_request" Type="Usage"
-                       Mapping="Amend1:NotificationCommunicationRequest,Identifier:7"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
             <Component Name="notification_communication_instant" Type="Usage"
-                       Mapping="Amend1:NotificationCommunicationInstant,Identifier:8"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
             <Component Name="notification_communication_delayed" Type="Usage"
-                       Mapping="Amend1:NotificationCommunicationDelated,Identifier:9"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
             <Component Name="notification_event" Type="Usage"
-                                                 Mapping="Amend1:NotificationEvent,Identifier:10"/>
+                       Mapping="Name:AUDIO_USAGE_NOTIFICATION_EVENT"/>
             <Component Name="assistance_accessibility" Type="Usage"
-                       Mapping="Amend1:AssistanceAccessibility,Identifier:11"/>
+                       Mapping="Name:AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
             <Component Name="assistance_navigation_guidance" Type="Usage"
-                       Mapping="Amend1:AssistanceNavigationGuidance,Identifier:12"/>
+                       Mapping="Name:AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
             <Component Name="assistance_sonification" Type="Usage"
-                       Mapping="Amend1:AssistanceSonification,Identifier:13"/>
-            <Component Name="game" Type="Usage" Mapping="Amend1:BluetoothSco,Identifier:14"/>
-            <Component Name="virtual_source" Type="Usage"
-                                             Mapping="Amend1:VirtualSource,Identifier:15"/>
-            <Component Name="assistant" Type="Usage" Mapping="Amend1:Assistant,Identifier:16"/>
+                       Mapping="Name:AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+            <Component Name="game" Type="Usage" Mapping="Name:AUDIO_USAGE_GAME"/>
+            <Component Name="virtual_source" Type="Usage" Mapping="Name:AUDIO_USAGE_VIRTUAL_SOURCE"/>
+            <Component Name="assistant" Type="Usage" Mapping="Name:AUDIO_USAGE_ASSISTANT"/>
         </ComponentType>
 
         <!--#################### USAGE END ####################-->
@@ -106,25 +90,25 @@
 
         <ComponentType Name="InputSources" Description="associated to audio_source_t definition,
                              identifier mapping must match the value of the enum">
-            <Component Name="default" Type="InputSource" Mapping="Amend1:Default,Identifier:0"/>
-            <Component Name="mic" Type="InputSource" Mapping="Amend1:Mic,Identifier:1"/>
+            <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+            <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
             <Component Name="voice_uplink" Type="InputSource"
-                                           Mapping="Amend1:VoiceUplink,Identifier:2"/>
+                                           Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
             <Component Name="voice_downlink" Type="InputSource"
-                                             Mapping="Amend1:VoiceDownlink,Identifier:3"/>
+                                             Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
             <Component Name="voice_call" Type="InputSource"
-                                         Mapping="Amend1:VoiceCall,Identifier:4"/>
-            <Component Name="camcorder" Type="InputSource" Mapping="Amend1:Camcorder,Identifier:5"/>
+                                         Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+            <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
             <Component Name="voice_recognition" Type="InputSource"
-                                                Mapping="Amend1:VoiceRecognition,Identifier:6"/>
+                                                Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
             <Component Name="voice_communication" Type="InputSource"
-                                                  Mapping="Amend1:VoiceCommunication,Identifier:7"/>
+                                                  Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
             <Component Name="remote_submix" Type="InputSource"
-                                            Mapping="Amend1:RemoteSubmix,Identifier:8"/>
+                                            Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
             <Component Name="unprocessed" Type="InputSource"
-                                            Mapping="Amend1:Unprocessed,Identifier:9"/>
-            <Component Name="fm_tuner" Type="InputSource" Mapping="Amend1:FmTuner,Identifier:1998"/>
-            <Component Name="hotword" Type="InputSource" Mapping="Amend1:Hotword,Identifier:1999"/>
+                                            Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+            <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
+            <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
         </ComponentType>
 
         <!--#################### INPUT SOURCE END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt b/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
deleted file mode 100644
index 480cbe1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-ExclusiveCriterion TelephonyMode                :   Normal          RingTone                InCall              InCommunication
-InclusiveCriterion AvailableInputDevices        :   Communication Ambient BuiltinMic BluetoothScoHeadset WiredHeadset Hdmi TelephonyRx BackMic RemoteSubmix AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice FmTuner TvTuner Line Spdif BluetoothA2dp Loopback Ip Bus Stub
-InclusiveCriterion AvailableOutputDevices       :   Earpiece Speaker WiredSpeaker WiredHeadset WiredHeadphone BluetoothSco BluetoothScoHeadset BluetoothScoCarkit BluetoothA2dp BluetoothA2dpHeadphones BluetoothA2dpSpeaker Hdmi AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice RemoteSubmix TelephonyTx Line HdmiArc Spdif Fm AuxLine SpeakerSafe Ip Bus Stub
-ExclusiveCriterion ForceUseForCommunication     :   ForceNone       ForceSpeaker            ForceBtSco
-ExclusiveCriterion ForceUseForMedia             :   ForceNone       ForceSpeaker			ForceHeadphones         ForceBtA2dp         ForceWiredAccessory ForceAnalogDock ForceDigitalDock    ForceNoBtA2dp       ForceSystemEnforced
-ExclusiveCriterion ForceUseForRecord            :   ForceNone       ForceBtSco              ForceWiredAccessory
-ExclusiveCriterion ForceUseForDock              :   ForceNone       ForceWiredAccessory     ForceBtCarDock      ForceBtDeskDock     ForceAnalogDock ForceDigitalDock
-ExclusiveCriterion ForceUseForSystem            :   ForceNone       ForceSystemEnforced
-ExclusiveCriterion ForceUseForHdmiSystemAudio   :   ForceNone       ForceHdmiSystemEnforced
-ExclusiveCriterion ForceUseForEncodedSurround   :   ForceNone       ForceEncodedSurroundNever   ForceEncodedSurroundAlways
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index 3559cf1..db1f038 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libaudiopolicyengineconfigurable  \
     libparameter \
+    libmedia_helper \
     liblog \
 
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
index eac4efe..f91f8d7 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
@@ -17,6 +17,7 @@
 #include "InputSource.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
 
 using std::string;
 
@@ -33,9 +34,13 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<audio_source_t>(context.getItemAsInteger(MappingKeyIdentifier));
+    std::string name(context.getItem(MappingKeyName));
+
+    if(not android::SourceTypeConverter::fromString(name, mId)) {
+        LOG_ALWAYS_FATAL("Invalid Input Source name: %s, invalid XML structure file", name.c_str());
+    }
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addInputSource(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addInputSource(name, mId);
 }
 
 bool InputSource::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 98d10a9..7374fc3 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -65,22 +65,22 @@
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<Stream>(
             mStreamComponentName,
-            (1 << MappingKeyIdentifier))
+            (1 << MappingKeyName))
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<Strategy>(
             mStrategyComponentName,
-            (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+            0)
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<Usage>(
             mUsageComponentName,
-            (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+            (1 << MappingKeyName))
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<InputSource>(
             mInputSourceComponentName,
-            (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+            (1 << MappingKeyName))
         );
 }
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
index 746c3a8..876bcb0 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
@@ -17,10 +17,38 @@
 #include "Strategy.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <RoutingStrategy.h>
 
 using std::string;
 using android::routing_strategy;
 
+namespace detail {
+
+constexpr std::pair<routing_strategy, const char*> routingStrategyMap[] = {
+    {android::STRATEGY_MEDIA, "STRATEGY_MEDIA"},
+    {android::STRATEGY_PHONE, "STRATEGY_PHONE"},
+    {android::STRATEGY_SONIFICATION, "STRATEGY_SONIFICATION"},
+    {android::STRATEGY_SONIFICATION_RESPECTFUL, "STRATEGY_SONIFICATION_RESPECTFUL"},
+    {android::STRATEGY_DTMF, "STRATEGY_DTMF"},
+    {android::STRATEGY_ENFORCED_AUDIBLE, "STRATEGY_ENFORCED_AUDIBLE"},
+    {android::STRATEGY_TRANSMITTED_THROUGH_SPEAKER, "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"},
+    {android::STRATEGY_ACCESSIBILITY, "STRATEGY_ACCESSIBILITY"},
+    {android::STRATEGY_REROUTING, "STRATEGY_REROUTING"},
+};
+
+bool fromString(const char *literalName, routing_strategy &type)
+{
+    for (auto& pair : routingStrategyMap) {
+        if (strcmp(pair.second, literalName) == 0) {
+            type = pair.first;
+            return true;
+        }
+    }
+    return false;
+}
+
+}
+
 Strategy::Strategy(const string &mappingValue,
                    CInstanceConfigurableElement *instanceConfigurableElement,
                    const CMappingContext &context,
@@ -35,10 +63,12 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<routing_strategy>(context.getItemAsInteger(MappingKeyIdentifier));
-
+    std::string name(context.getItem(MappingKeyName));
+    if (not detail::fromString(name.c_str(), mId)) {
+        LOG_ALWAYS_FATAL("Invalid Strategy %s, invalid XML structure file", name.c_str());
+    }
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addStrategy(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addStrategy(instanceConfigurableElement->getName(), mId);
 }
 
 bool Strategy::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
index c642a23..46c9e1c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
@@ -17,6 +17,7 @@
 #include "Stream.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
 
 using std::string;
 using android::routing_strategy;
@@ -29,10 +30,14 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
+    std::string name(context.getItem(MappingKeyName));
+
+    if (not android::StreamTypeConverter::fromString(name, mId)) {
+        LOG_ALWAYS_FATAL("Invalid Stream type name: %s, invalid XML structure file", name.c_str());
+    }
 
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addStream(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addStream(name, mId);
 }
 
 bool Stream::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
index 78199f8..925d631 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
@@ -17,6 +17,7 @@
 #include "Usage.h"
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
 
 using std::string;
 using android::routing_strategy;
@@ -34,10 +35,13 @@
                            instanceConfigurableElement->getBelongingSubsystem())),
       mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
 {
-    mId = static_cast<audio_usage_t>(context.getItemAsInteger(MappingKeyIdentifier));
+    std::string name(context.getItem(MappingKeyName));
 
+    if (not android::UsageTypeConverter::fromString(name, mId)) {
+        LOG_ALWAYS_FATAL("Invalid Usage name: %s, invalid XML structure file", name.c_str());
+    }
     // Declares the strategy to audio policy engine
-    mPolicyPluginInterface->addUsage(getFormattedMappingValue(), mId);
+    mPolicyPluginInterface->addUsage(name, mId);
 }
 
 bool Usage::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
new file mode 100644
index 0000000..4d41d42
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
@@ -0,0 +1,4 @@
+userdebug_or_eng(`
+  allow audioserver audioserver_socket:dir rw_dir_perms;
+  allow audioserver audioserver_socket:sock_file create_file_perms;
+')
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file.te b/services/audiopolicy/engineconfigurable/sepolicy/file.te
new file mode 100644
index 0000000..7db1937
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file.te
@@ -0,0 +1,2 @@
+# Policy Engine remote connection for runtime debug of parameter framework
+type audioserver_socket, file_type, coredomain_socket;
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file_contexts b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
new file mode 100644
index 0000000..950fcce
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
@@ -0,0 +1 @@
+/dev/socket/audioserver(/.*)?    u:object_r:audioserver_socket:s0
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index b72ded8..1f8ed8d 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -28,10 +28,8 @@
 #include <stdint.h>
 #include <string>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * Collection of policy element as a map indexed with a their UID type.
diff --git a/services/audiopolicy/engineconfigurable/src/Element.h b/services/audiopolicy/engineconfigurable/src/Element.h
index 52e77e5..1b55c8c 100644
--- a/services/audiopolicy/engineconfigurable/src/Element.h
+++ b/services/audiopolicy/engineconfigurable/src/Element.h
@@ -22,10 +22,8 @@
 #include <system/audio.h>
 #include <utils/Log.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 template <typename Key>
 class Element
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 0d18ffa..009cf90 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -35,10 +35,9 @@
 using std::string;
 using std::map;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
 template <>
 StrategyCollection &Engine::getCollection<routing_strategy>()
 {
@@ -220,8 +219,10 @@
 }
 
 status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
-                                          audio_policy_dev_state_t /*state*/)
+                                          audio_policy_dev_state_t state)
 {
+    mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
+
     if (audio_is_output_device(devDesc->type())) {
         return mPolicyParameterMgr->setAvailableOutputDevices(
                     mApmObserver->getAvailableOutputDevices().types());
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 328d23d..ba4f889 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -21,12 +21,10 @@
 #include <AudioPolicyPluginInterface.h>
 #include "Collection.h"
 
-namespace android
-{
+namespace android {
 class AudioPolicyManagerObserver;
 
-namespace audio_policy
-{
+namespace audio_policy {
 
 class ParameterManagerWrapper;
 class VolumeProfile;
diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
index 9aa89b2..2442590 100644
--- a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
+++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
@@ -21,10 +21,8 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 EngineInstance::EngineInstance()
 {
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index ae39fef..d252d3f 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -20,13 +20,13 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
 status_t Element<audio_source_t>::setIdentifier(audio_source_t identifier)
 {
-    if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD) {
+    if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD
+        && identifier != AUDIO_SOURCE_FM_TUNER && identifier != AUDIO_SOURCE_ECHO_REFERENCE) {
         return BAD_VALUE;
     }
     mIdentifier = identifier;
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.h b/services/audiopolicy/engineconfigurable/src/InputSource.h
index 6c498dc..64b390e 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.h
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.h
@@ -18,10 +18,8 @@
 
 #include "Element.h"
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * Specialization of policy base class element for audio_source_t
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.cpp b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
index a539914..310b35e 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
@@ -20,10 +20,8 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 status_t Element<routing_strategy>::setIdentifier(routing_strategy identifier)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.h b/services/audiopolicy/engineconfigurable/src/Strategy.h
index 1157d55..f2487fd 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.h
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.h
@@ -19,10 +19,8 @@
 #include "Element.h"
 #include <RoutingStrategy.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * @tparam audio_devices_t: Applicable output device(s) for this strategy.
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index 0ed364f..73fb94d 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -21,10 +21,8 @@
 
 using std::string;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h
index 6902003..2bf70b3 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.h
+++ b/services/audiopolicy/engineconfigurable/src/Stream.h
@@ -21,10 +21,9 @@
 #include <RoutingStrategy.h>
 #include <map>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
 /**
  * @tparam routing_strategy: Applicable strategy for this stream.
  */
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.cpp b/services/audiopolicy/engineconfigurable/src/Usage.cpp
index 5d20828..8c0dfba 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Usage.cpp
@@ -18,10 +18,8 @@
 
 #include "Usage.h"
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 status_t Element<audio_usage_t>::setIdentifier(audio_usage_t identifier)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.h b/services/audiopolicy/engineconfigurable/src/Usage.h
index d69e0e0..72a452f 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.h
+++ b/services/audiopolicy/engineconfigurable/src/Usage.h
@@ -19,10 +19,8 @@
 #include "Element.h"
 #include <RoutingStrategy.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 /**
  * @tparam routing_strategy: Applicable strategy for this usage.
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
new file mode 100644
index 0000000..d8f29dc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2018 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.
+
+python_binary_host {
+    name: "buildPolicyCriterionTypes.py",
+    owner: "renault",
+    main: "buildPolicyCriterionTypes.py",
+    srcs: [
+        "buildPolicyCriterionTypes.py",
+    ],
+    version: {
+        py2: {
+            enabled: true,
+        },
+        py3: {
+            enabled: false,
+        },
+    },
+}
+
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
new file mode 100755
index 0000000..0fb70a6
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python
+
+#
+# Copyright 2018, 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.
+#
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+#           --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+#           --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+#           --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+#           --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+def parseArgs():
+    argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+        audio criterion type file generator.\n\
+        Exit with the number of (recoverable or not) error that occured.")
+    argparser.add_argument('--androidaudiobaseheader',
+            help="Android Audio Base C header file, Mandatory.",
+            metavar="ANDROID_AUDIO_BASE_HEADER",
+            type=argparse.FileType('r'),
+            required=True)
+    argparser.add_argument('--audiopolicyconfigurationfile',
+            help="Android Audio Policy Configuration file, Mandatory.",
+            metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+            type=argparse.FileType('r'),
+            required=True)
+    argparser.add_argument('--criteriontypes',
+            help="Criterion types XML base file, in \
+            '<criterion_types> \
+                <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/>' \
+        format. Mandatory.",
+            metavar="CRITERION_TYPE_FILE",
+            type=argparse.FileType('r'),
+            required=True)
+    argparser.add_argument('--outputfile',
+            help="Criterion types outputfile file. Mandatory.",
+            metavar="CRITERION_TYPE_OUTPUT_FILE",
+            type=argparse.FileType('w'),
+            required=True)
+    argparser.add_argument('--verbose',
+            action='store_true')
+
+    return argparser.parse_args()
+
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+    logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+    criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+    criterion_types_root = criterion_types_in_tree.getroot()
+
+    for criterion_name, values_dict in criterionTypes.items():
+        for criterion_type in criterion_types_root.findall('criterion_type'):
+            if criterion_type.get('name') == criterion_name:
+                values_node = ET.SubElement(criterion_type, "values")
+                ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+                for key, value in ordered_values.items():
+                    value_node = ET.SubElement(values_node, "value")
+                    value_node.set('numerical', str(value))
+                    value_node.set('literal', key)
+
+    if addressCriteria:
+        for criterion_name, values_list in addressCriteria.items():
+            for criterion_type in criterion_types_root.findall('criterion_type'):
+                if criterion_type.get('name') == criterion_name:
+                    values_node = ET.SubElement(criterion_type, "values")
+                    index = 0
+                    for value in values_list:
+                        value_node = ET.SubElement(values_node, "value", literal=value)
+                        value_node.set('numerical', str(1 << index))
+                        index += 1
+
+    xmlstr = ET.tostring(criterion_types_root, encoding='utf8', method='xml')
+    reparsed = MINIDOM.parseString(xmlstr)
+    prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+    prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+    outputFile.write(prettyXmlStr.encode('utf-8'))
+
+def capitalizeLine(line):
+    return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+    logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+    #
+    # extract all devices addresses from audio policy configuration file
+    #
+    address_criteria_mapping_table = {
+        'sink' : "OutputDevicesAddressesType",
+        'source' : "InputDevicesAddressesType" }
+
+    address_criteria = {
+        'OutputDevicesAddressesType' : [],
+        'InputDevicesAddressesType' : [] }
+
+    oldWorkingDir = os.getcwd()
+    print "Current working directory %s" % oldWorkingDir
+
+    newDir = os.path.join(oldWorkingDir , audiopolicyconfigurationfile.name)
+
+    policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+    os.chdir(os.path.dirname(os.path.normpath(newDir)))
+
+    print "new working directory %s" % os.getcwd()
+
+    policy_root = policy_in_tree.getroot()
+    EI.include(policy_root)
+
+    os.chdir(oldWorkingDir)
+
+    for device in policy_root.iter('devicePort'):
+        for key in address_criteria_mapping_table.keys():
+            if device.get('role') == key and device.get('address') :
+                logging.info("{}: <{}>".format(key, device.get('address')))
+                address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
+
+    for criteria in address_criteria:
+        values = ','.join(address_criteria[criteria])
+        logging.info("{}: <{}>".format(criteria, values))
+
+    return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+#   -Android Mode
+#   -Output devices type
+#   -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile):
+    #
+    # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+    #
+    criterion_mapping_table = {
+        'AUDIO_MODE' : "AndroidModeType",
+        'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+        'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+    all_criteria = {
+        'AndroidModeType' : {},
+        'OutputDevicesMaskType' : {},
+        'InputDevicesMaskType' : {} }
+
+    #
+    # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+    #
+    ignored_values = [ 'CNT', 'MAX', 'ALL', 'NONE' ]
+
+    criteria_pattern = re.compile(
+        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))\_" \
+        r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+        r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+
+    logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+    for line_number, line in enumerate(androidaudiobaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiobaseheaderFile.name, line_number, line))
+
+            criterion_name = criterion_mapping_table[match.groupdict()['type']]
+            literal = ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+            numerical_value = match.groupdict()['values']
+
+            # for AUDIO_DEVICE_IN: need to remove sign bit
+            if criterion_name == "InputDevicesMaskType":
+                numerical_value = str(int(numerical_value, 0) & ~2147483648)
+
+            # Remove duplicated numerical values
+            if int(numerical_value, 0) in all_criteria[criterion_name].values():
+                logging.info("criterion {} duplicated values:".format(criterion_name))
+                logging.info("{}:{}".format(numerical_value, literal))
+                logging.info("KEEPING LATEST")
+                for key in all_criteria[criterion_name].keys():
+                    if all_criteria[criterion_name][key] == int(numerical_value, 0):
+                        del all_criteria[criterion_name][key]
+
+            all_criteria[criterion_name][literal] = int(numerical_value, 0)
+
+            logging.debug("type:{},".format(criterion_name))
+            logging.debug("iteral:{},".format(literal))
+            logging.debug("values:{}.".format(numerical_value))
+
+    return all_criteria
+
+
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+
+    all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader)
+
+    address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+    criterion_types = args.criteriontypes
+
+    generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+    exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
new file mode 100644
index 0000000..2b86469
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
@@ -0,0 +1,35 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_TOOL := domainGeneratorPolicy.py
+$(LOCAL_BUILT_MODULE): MY_TOPLEVEL_FILE := $(PFW_TOPLEVEL_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERIA_FILE := $(PFW_CRITERIA_FILE)
+$(LOCAL_BUILT_MODULE): MY_TUNING_FILE := $(PFW_TUNING_FILE)
+$(LOCAL_BUILT_MODULE): MY_EDD_FILES := $(PFW_EDD_FILES)
+$(LOCAL_BUILT_MODULE): MY_DOMAIN_FILES := $(PFW_DOMAIN_FILES)
+$(LOCAL_BUILT_MODULE): MY_SCHEMAS_DIR := $(PFW_SCHEMAS_DIR)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) domainGeneratorPolicy.py
+
+	"$(MY_TOOL)" --validate \
+		--toplevel-config "$(MY_TOPLEVEL_FILE)" \
+		--criteria "$(MY_CRITERIA_FILE)" \
+		--criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+		--initial-settings $(MY_TUNING_FILE) \
+		--add-edds $(MY_EDD_FILES) \
+		--add-domains $(MY_DOMAIN_FILES) \
+		--schemas-dir $(MY_SCHEMAS_DIR) > "$@"
+
+
+# Clear variables for further use
+PFW_TOPLEVEL_FILE :=
+PFW_STRUCTURE_FILES :=
+PFW_CRITERIA_FILE :=
+PFW_CRITERION_TYPES_FILE :=
+PFW_TUNING_FILE :=
+PFW_EDD_FILES :=
+PFW_DOMAIN_FILES :=
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
diff --git a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
new file mode 100755
index 0000000..7929402
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -0,0 +1,268 @@
+#!/usr/bin/python
+
+#
+# Copyright 2018, 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.
+#
+
+import EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+
+#
+# In order to build the XML Settings file at build time, an instance of the parameter-framework
+# shall be started and fed with all the criterion types/criteria that will be used by
+# the engineconfigurable.
+# This scripts allows generates the settings from the same audio_criterion_types.xml /
+# audio_criteria.xml files used at run time by the engineconfigurable
+#
+
+def parseArgs():
+    argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+        Settings file generator.\n\
+        Exit with the number of (recoverable or not) error that occured.")
+    argparser.add_argument('--toplevel-config',
+            help="Top-level parameter-framework configuration file. Mandatory.",
+            metavar="TOPLEVEL_CONFIG_FILE",
+            required=True)
+    argparser.add_argument('--criteria',
+            help="Criteria file, in XML format: \
+                  in '<criteria> \
+                          <criterion name="" type=""/> \
+                      </criteria>' \
+        format. Mandatory.",
+            metavar="CRITERIA_FILE",
+            type=argparse.FileType('r'),
+            required=True)
+    argparser.add_argument('--criteriontypes',
+            help="Criterion types XML file, in \
+            '<criterion_types> \
+                <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/> \
+             </criterion_types>' \
+        format. Mandatory.",
+            metavar="CRITERION_TYPE_FILE",
+            type=argparse.FileType('r'),
+            required=False)
+    argparser.add_argument('--initial-settings',
+            help="Initial XML settings file (containing a \
+        <ConfigurableDomains>  tag",
+            nargs='?',
+            default=None,
+            metavar="XML_SETTINGS_FILE")
+    argparser.add_argument('--add-domains',
+            help="List of single domain files (each containing a single \
+        <ConfigurableDomain> tag",
+            metavar="XML_DOMAIN_FILE",
+            nargs='*',
+            dest='xml_domain_files',
+            default=[])
+    argparser.add_argument('--add-edds',
+            help="List of files in EDD syntax (aka \".pfw\" files)",
+            metavar="EDD_FILE",
+            type=argparse.FileType('r'),
+            nargs='*',
+            default=[],
+            dest='edd_files')
+    argparser.add_argument('--schemas-dir',
+            help="Directory of parameter-framework XML Schemas for generation \
+        validation",
+            default=None)
+    argparser.add_argument('--target-schemas-dir',
+            help="Ignored. Kept for retro-compatibility")
+    argparser.add_argument('--validate',
+            help="Validate the settings against XML schemas",
+            action='store_true')
+    argparser.add_argument('--verbose',
+            action='store_true')
+
+    return argparser.parse_args()
+
+#
+# Parses audio_criterion_types.xml / audio_criteria.xml files used at run time by the
+# engineconfigurable and outputs a dictionnary of criteria.
+# For each criteria, the name, type (aka inclusive (bitfield) or exclusive (enum), the values
+# are provided.
+#
+def parseCriteriaAndCriterionTypes(criteriaFile, criterionTypesFile):
+    # Parse criteria and criterion types XML files
+    #
+    criteria_tree = ET.parse(criteriaFile)
+    logging.info("Importing criteriaFile {}".format(criteriaFile))
+    criterion_types_tree = ET.parse(criterionTypesFile)
+    logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+
+    criteria_root = criteria_tree.getroot()
+    criterion_types_root = criterion_types_tree.getroot()
+
+    all_criteria = []
+    for criterion in criteria_root.findall('criterion'):
+        criterion_name = criterion.get('name')
+        type_name = criterion.get('type')
+        logging.info("Importing criterion_name {}".format(criterion_name))
+        logging.info("Importing type_name {}".format(type_name))
+
+        for criterion_types in criterion_types_tree.findall('criterion_type'):
+            criterion_type_name = criterion_types.get('name')
+            if criterion_type_name == type_name:
+                criterion_inclusiveness = criterion_types.get('type')
+
+                criterion_values = []
+
+                values_node = criterion_types.find('values')
+                if values_node:
+                    for value in values_node.findall('value'):
+                        criterion_values.append(value.get('literal'))
+
+                if len(criterion_values) == 0:
+                    criterion_values.append('')
+
+                logging.info("Importing criterion_type_name {}".format(criterion_type_name))
+                logging.info("Importing criterion_inclusiveness {}".format(criterion_inclusiveness))
+                logging.info("Importing criterion_values {}".format(criterion_values))
+
+                all_criteria.append({
+                    "name" : criterion_name,
+                    "inclusive" : criterion_inclusiveness,
+                    "values" : criterion_values})
+                break
+
+    return all_criteria
+
+#
+# Parses the Edd files (aka .pfw extension file), which is a simplified language to write the
+# parameter framework settings.
+#
+def parseEdd(EDDFiles):
+    parsed_edds = []
+
+    for edd_file in EDDFiles:
+        try:
+            root = EddParser.Parser().parse(edd_file)
+        except EddParser.MySyntaxError as ex:
+            logging.critical(str(ex))
+            logging.info("EXIT ON FAILURE")
+            exit(2)
+
+        try:
+            root.propagate()
+        except EddParser.MyPropagationError, ex :
+            logging.critical(str(ex))
+            logging.info("EXIT ON FAILURE")
+            exit(1)
+
+        parsed_edds.append((edd_file.name, root))
+    return parsed_edds
+
+#
+# Generates all the required commands to be sent to the instance of parameter-framework launched
+# at runtime to generate the XML Settings file.
+# It takes as input the collection of criteria, the domains and the simplified settings read from
+# pfw.
+#
+def generateDomainCommands(logging, all_criteria, initial_settings, xml_domain_files, parsed_edds):
+        # create and inject all the criteria
+        logging.info("Creating all criteria")
+        for criterion in all_criteria:
+            yield ["createSelectionCriterion", criterion['inclusive'],
+                   criterion['name']] + criterion['values']
+
+        yield ["start"]
+
+        # Import initial settings file
+        if initial_settings:
+            logging.info("Importing initial settings file {}".format(initial_settings))
+            yield ["importDomainsWithSettingsXML", initial_settings]
+
+        # Import each standalone domain files
+        for domain_file in xml_domain_files:
+            logging.info("Importing single domain file {}".format(domain_file))
+            yield ["importDomainWithSettingsXML", domain_file]
+
+        # Generate the script for each EDD file
+        for filename, parsed_edd in parsed_edds:
+            logging.info("Translating and injecting EDD file {}".format(filename))
+            translator = PfwScriptTranslator()
+            parsed_edd.translate(translator)
+            for command in translator.getScript():
+                yield command
+
+#
+# Entry point of the domain generator.
+#       -Parses Criterion types and criteria files
+#       -Parses settings written in simplified pfw language.
+#       -Launches a parameter-framework
+#       -Translates the settings into command that can be interpreted by parameter-framework.
+#       -Use the exports command and output them in XML Settings file.
+#
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+
+    all_criteria = parseCriteriaAndCriterionTypes(args.criteria, args.criteriontypes)
+
+    #
+    # EDD files (aka ".pfw" files)
+    #
+    parsed_edds = parseEdd(args.edd_files)
+
+    # We need to modify the toplevel configuration file to account for differences
+    # between development setup and target (installation) setup, in particular, the
+    # TuningMwith ode must be enforced, regardless of what will be allowed on the target
+    fake_toplevel_config = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".xml",
+                                                       prefix="TMPdomainGeneratorPFConfig_")
+
+    install_path = os.path.dirname(os.path.realpath(args.toplevel_config))
+    hostConfig.configure(
+            infile=args.toplevel_config,
+            outfile=fake_toplevel_config,
+            structPath=install_path)
+    fake_toplevel_config.close()
+
+    # Create the connector. Pipe its input to us in order to write commands;
+    # connect its output to stdout in order to have it dump the domains
+    # there; connect its error output to stderr.
+    connector = subprocess.Popen(["domainGeneratorConnector",
+                            fake_toplevel_config.name,
+                            'verbose' if args.verbose else 'no-verbose',
+                            'validate' if args.validate else 'no-validate',
+                            args.schemas_dir],
+                           stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
+
+    initial_settings = None
+    if args.initial_settings:
+        initial_settings = os.path.realpath(args.initial_settings)
+
+    for command in generateDomainCommands(logging, all_criteria, initial_settings,
+                                       args.xml_domain_files, parsed_edds):
+        connector.stdin.write('\0'.join(command))
+        connector.stdin.write("\n")
+
+    # Closing the connector's input triggers the domain generation
+    connector.stdin.close()
+    connector.wait()
+    os.remove(fake_toplevel_config.name)
+    return connector.returncode
+
+# If this file is directly executed
+if __name__ == "__main__":
+    exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
new file mode 100644
index 0000000..4814376
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
@@ -0,0 +1,24 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_ANDROID_AUDIO_BASE_HEADER_FILE := $(ANDROID_AUDIO_BASE_HEADER_FILE)
+$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_CONFIGURATION_FILE := $(AUDIO_POLICY_CONFIGURATION_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TOOL := $(HOST_OUT)/bin/buildPolicyCriterionTypes.py
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) \
+    buildPolicyCriterionTypes.py \
+    $(CRITERION_TYPES_FILE) \
+    $(ANDROID_AUDIO_BASE_HEADER_FILE)
+
+	"$(MY_CRITERION_TOOL)" \
+		--androidaudiobaseheader "$(MY_ANDROID_AUDIO_BASE_HEADER_FILE)" \
+		--audiopolicyconfigurationfile "$(MY_AUDIO_POLICY_CONFIGURATION_FILE)" \
+		--criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+		--outputfile "$(@)"
+
+# Clear variables for further use
+CRITERION_TYPES_FILE :=
+ANDROID_AUDIO_BASE_HEADER_FILE :=
+AUDIO_POLICY_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.mk b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
index b128a38..d19a364 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.mk
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
@@ -1,5 +1,8 @@
 LOCAL_PATH:= $(call my-dir)
 
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+PROVISION_CRITERION_TYPES := $(TOOLS)/provision_criterion_types_from_android_headers.mk
+
 ##################################################################
 # WRAPPER LIBRARY
 ##################################################################
@@ -10,12 +13,22 @@
     $(LOCAL_PATH)/include \
     frameworks/av/services/audiopolicy/engineconfigurable/include \
     frameworks/av/services/audiopolicy/engineconfigurable/interface \
+    frameworks/av/services/audiopolicy/common/include \
+    external/libxml2/include \
+    external/icu/icu4c/source/common
 
-LOCAL_SRC_FILES:= ParameterManagerWrapper.cpp
+LOCAL_SRC_FILES:= \
+    ParameterManagerWrapper.cpp \
+    ParameterManagerWrapperConfig.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libparameter \
-    libmedia_helper
+    libmedia_helper \
+    libicuuc \
+    libxml2
+
+LOCAL_STATIC_LIBRARIES := \
+    libaudiopolicycomponents
 
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
 
@@ -31,11 +44,35 @@
 # CONFIGURATION FILE
 ##################################################################
 
-# specific management of audio_policy_criteria.conf
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
 include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_criteria.conf
+LOCAL_MODULE := policy_wrapper_configuration.xml
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
+LOCAL_VENDOR_MODULE := true
 LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criteria.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criterion_types.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+    $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+
+AUDIO_POLICY_CONFIGURATION_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+ANDROID_AUDIO_BASE_HEADER_FILE := system/media/audio/include/system/audio-base.h
+CRITERION_TYPES_FILE := $(LOCAL_PATH)/config/policy_criterion_types.xml.in
+
+include $(PROVISION_CRITERION_TYPES)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 9b0442e..fc6c1e4 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,7 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include "ParameterManagerWrapper.h"
-#include "audio_policy_criteria_conf.h"
+#include "ParameterManagerWrapperConfig.h"
 #include <ParameterMgrPlatformConnector.h>
 #include <SelectionCriterionTypeInterface.h>
 #include <SelectionCriterionInterface.h>
@@ -38,6 +38,7 @@
 using std::string;
 using std::map;
 using std::vector;
+using CriterionTypes = std::map<std::string, ISelectionCriterionTypeInterface *>;
 
 /// PFW related definitions
 // Logger
@@ -56,16 +57,36 @@
     }
 };
 
-namespace android
-{
+namespace android {
 
 using utilities::convertTo;
 
-namespace audio_policy
-{
+namespace audio_policy {
+
 const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
     "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
 
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+ * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
+ */
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
+    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
+    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
+    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
+    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
+    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
+    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
+    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
+};
+
 template <>
 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
 template <>
@@ -80,15 +101,64 @@
     // Logger
     mPfwConnector->setLogger(mPfwConnectorLogger);
 
-    // Load criteria file
-    if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) &&
-        (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) {
-        ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found",
-              __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
-              gAudioPolicyCriteriaConfFilePath);
+    status_t loadResult = loadConfig();
+    if (loadResult < 0) {
+        ALOGE("Policy Wrapper configuration is partially invalid.");
     }
 }
 
+status_t ParameterManagerWrapper::loadConfig()
+{
+    auto result = wrapper_config::parse();
+    if (result.parsedConfig == nullptr) {
+        return -ENOENT;
+    }
+    ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+
+    CriterionTypes criterionTypes;
+    for (auto criterionType : result.parsedConfig->criterionTypes) {
+        ALOG_ASSERT(criterionTypes.find(criterionType.name) == criterionTypes.end(),
+                          "CriterionType %s already added", criterionType.name.c_str());
+        ALOGV("%s: Adding new criterionType %s", __FUNCTION__, criterionType.name.c_str());
+
+        auto criterionTypePfw =
+                mPfwConnector->createSelectionCriterionType(criterionType.isInclusive);
+
+        for (auto pair : criterionType.valuePairs) {
+            std::string error;
+            ALOGV("%s: Adding pair %d,%s for criterionType %s", __FUNCTION__, pair.first,
+                  pair.second.c_str(), criterionType.name.c_str());
+            criterionTypePfw->addValuePair(pair.first, pair.second, error);
+        }
+        criterionTypes[criterionType.name] = criterionTypePfw;
+    }
+
+    for (auto criterion : result.parsedConfig->criteria) {
+        ALOG_ASSERT(mPolicyCriteria.find(criterion.name) == mPolicyCriteria.end(),
+                    "%s: Criterion %s already added", __FUNCTION__, criterion.name.c_str());
+
+        auto criterionType =
+                getElement<ISelectionCriterionTypeInterface>(criterion.typeName, criterionTypes);
+        ALOG_ASSERT(criterionType != nullptr, "No %s Criterion type found for criterion %s",
+                    criterion.typeName.c_str(), criterion.name.c_str());
+
+        auto criterionPfw = mPfwConnector->createSelectionCriterion(criterion.name, criterionType);
+        mPolicyCriteria[criterion.name] = criterionPfw;
+
+        if (not criterion.defaultLiteralValue.empty()) {
+            int numericalValue = 0;
+            if (not criterionType->getNumericalValue(criterion.defaultLiteralValue.c_str(),
+                                                     numericalValue)) {
+                ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
+                      criterion.defaultLiteralValue.c_str());
+                continue;
+            }
+            criterionPfw->setCriterionState(numericalValue);
+        }
+    }
+    return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
 ParameterManagerWrapper::~ParameterManagerWrapper()
 {
     // Unset logger
@@ -112,112 +182,6 @@
     return NO_ERROR;
 }
 
-
-void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
-{
-    ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
-                      "CriterionType %s already added", typeName.c_str());
-    ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
-
-    mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
-}
-
-void ParameterManagerWrapper::addCriterionTypeValuePair(
-    const string &typeName,
-    uint32_t numericValue,
-    const string &literalValue)
-{
-    ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
-                      "CriterionType %s not found", typeName.c_str());
-    ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
-          numericValue, literalValue.c_str(), typeName.c_str());
-    ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
-    std::string error;
-    criterionType->addValuePair(numericValue, literalValue, error);
-}
-
-void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node;
-    for (node = root->first_child; node != NULL; node = node->next) {
-
-        ALOG_ASSERT(node != NULL, "error in parsing file");
-        const char *typeName = node->name;
-        char *valueNames = strndup(node->value, strlen(node->value));
-
-        addCriterionType(typeName, isInclusive);
-
-        uint32_t index = 0;
-        char *ctx;
-        char *valueName = strtok_r(valueNames, ",", &ctx);
-        while (valueName != NULL) {
-            if (strlen(valueName) != 0) {
-
-                // Conf file may use or not pair, if no pair, use incremental index, else
-                // use provided index.
-                if (strchr(valueName, ':') != NULL) {
-
-                    char *first = strtok(valueName, ":");
-                    char *second = strtok(NULL, ":");
-                    ALOG_ASSERT((first != NULL) && (strlen(first) != 0) &&
-                                      (second != NULL) && (strlen(second) != 0),
-                                      "invalid value pair");
-
-                    if (!convertTo<string, uint32_t>(first, index)) {
-                        ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first);
-                    }
-                    addCriterionTypeValuePair(typeName, index, second);
-                } else {
-
-                    uint32_t pfwIndex = isInclusive ? 1 << index : index;
-                    addCriterionTypeValuePair(typeName, pfwIndex, valueName);
-                    index += 1;
-                }
-            }
-            valueName = strtok_r(NULL, ",", &ctx);
-        }
-        free(valueNames);
-    }
-}
-
-void ParameterManagerWrapper::loadInclusiveCriterionType(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gInclusiveCriterionTypeTag.c_str());
-    if (node == NULL) {
-        return;
-    }
-    loadCriterionType(node, true);
-}
-
-void ParameterManagerWrapper::loadExclusiveCriterionType(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gExclusiveCriterionTypeTag.c_str());
-    if (node == NULL) {
-        return;
-    }
-    loadCriterionType(node, false);
-}
-
-void ParameterManagerWrapper::parseChildren(cnode *root, string &defaultValue, string &type)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node;
-    for (node = root->first_child; node != NULL; node = node->next) {
-        ALOG_ASSERT(node != NULL, "error in parsing file");
-
-        if (string(node->name) == gDefaultTag) {
-            defaultValue = node->value;
-        } else if (string(node->name) == gTypeTag) {
-            type = node->value;
-        } else {
-             ALOGE("%s: Unrecognized %s %s node", __FUNCTION__, node->name, node->value);
-        }
-    }
-}
-
 template <typename T>
 T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
 {
@@ -236,97 +200,6 @@
     return it != elementsMap.end() ? it->second : NULL;
 }
 
-void ParameterManagerWrapper::loadCriteria(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gCriterionTag.c_str());
-
-    if (node == NULL) {
-        ALOGW("%s: no inclusive criteria found", __FUNCTION__);
-        return;
-    }
-    for (node = node->first_child; node != NULL; node = node->next) {
-        loadCriterion(node);
-    }
-}
-
-void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
-                              const string &defaultLiteralValue)
-{
-    ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
-                "Route Criterion %s already added", name.c_str());
-
-    ISelectionCriterionTypeInterface *criterionType =
-            getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
-
-    ISelectionCriterionInterface *criterion =
-            mPfwConnector->createSelectionCriterion(name, criterionType);
-
-    mPolicyCriteria[name] = criterion;
-    int numericalValue = 0;
-    if (!criterionType->getNumericalValue(defaultLiteralValue.c_str(),  numericalValue)) {
-        ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
-              defaultLiteralValue.c_str());
-    }
-    criterion->setCriterionState(numericalValue);
-}
-
-void ParameterManagerWrapper::loadCriterion(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    const char *criterionName = root->name;
-
-    ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
-                      "Criterion %s already added", criterionName);
-
-    string paramKeyName = "";
-    string path = "";
-    string typeName = "";
-    string defaultValue = "";
-
-    parseChildren(root, defaultValue, typeName);
-
-    addCriterion(criterionName, typeName, defaultValue);
-}
-
-void ParameterManagerWrapper::loadConfig(cnode *root)
-{
-    ALOG_ASSERT(root != NULL, "error in parsing file");
-    cnode *node = config_find(root, gPolicyConfTag.c_str());
-    if (node == NULL) {
-        ALOGW("%s: Could not find node for pfw", __FUNCTION__);
-        return;
-    }
-    ALOGD("%s: Loading conf for pfw", __FUNCTION__);
-    loadInclusiveCriterionType(node);
-    loadExclusiveCriterionType(node);
-    loadCriteria(node);
-}
-
-
-status_t ParameterManagerWrapper::loadAudioPolicyCriteriaConfig(const char *path)
-{
-    ALOG_ASSERT(path != NULL, "error in parsing file: empty path");
-    cnode *root;
-    char *data;
-    ALOGD("%s", __FUNCTION__);
-    data = (char *)load_file(path, NULL);
-    if (data == NULL) {
-        return -ENODEV;
-    }
-    root = config_node("", "");
-    ALOG_ASSERT(root != NULL, "Unable to allocate a configuration node");
-    config_load(root, data);
-
-    loadConfig(root);
-
-    config_free(root);
-    free(root);
-    free(data);
-    ALOGD("%s: loaded", __FUNCTION__);
-    return NO_ERROR;
-}
-
 bool ParameterManagerWrapper::isStarted()
 {
     return mPfwConnector && mPfwConnector->isStarted();
@@ -335,9 +208,9 @@
 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
 {
     ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -351,9 +224,9 @@
 audio_mode_t ParameterManagerWrapper::getPhoneState() const
 {
     const ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
         return AUDIO_MODE_NORMAL;
     }
     return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -370,7 +243,7 @@
     ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -390,7 +263,7 @@
     const ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
         return AUDIO_POLICY_FORCE_NONE;
     }
     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -404,12 +277,45 @@
     return interface->getLiteralValue(valueToCheck, literalValue);
 }
 
+status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+                                                           audio_policy_dev_state_t state)
+{
+    std::string criterionName = audio_is_output_device(devDesc->type()) ?
+                gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
+
+    ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->mAddress.string(),
+          state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
+    ISelectionCriterionInterface *criterion =
+            getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
+
+    if (criterion == NULL) {
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
+        return DEAD_OBJECT;
+    }
+
+    auto criterionType = criterion->getCriterionType();
+    int deviceAddressId;
+    if (not criterionType->getNumericalValue(devDesc->mAddress.string(), deviceAddressId)) {
+        ALOGE("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->mAddress.c_str());
+        return BAD_TYPE;
+    }
+    int currentValueMask = criterion->getCriterionState();
+    if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+        currentValueMask |= deviceAddressId;
+    }
+    else {
+        currentValueMask &= ~deviceAddressId;
+    }
+    criterion->setCriterionState(currentValueMask);
+    return NO_ERROR;
+}
+
 status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
 {
     ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
@@ -420,9 +326,9 @@
 status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
 {
     ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionTag, mPolicyCriteria);
+            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionTag.c_str());
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(outputDevices);
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
new file mode 100644
index 0000000..bc6d046
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2018 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 "APM::AudioPolicyEngine/PFWWrapperConfig"
+#define LOG_NDEBUG 0
+
+#include "ParameterManagerWrapperConfig.h"
+
+#include <media/convert.h>
+#include <utils/Log.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <istream>
+
+
+namespace android {
+
+using utilities::convertTo;
+
+namespace audio_policy {
+namespace wrapper_config {
+namespace detail {
+
+std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
+{
+    xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar *)attribute);
+    if (xmlValue == NULL) {
+        return "";
+    }
+    std::string value((const char *)xmlValue);
+    xmlFree(xmlValue);
+    return value;
+}
+
+template <class Trait>
+static status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
+                                      typename Trait::Collection &collection,
+                                      size_t &nbSkippedElement)
+{
+    const xmlNode *root = cur->xmlChildrenNode;
+    while (root != NULL) {
+        if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
+            xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+            root = root->next;
+            continue;
+        }
+        const xmlNode *child = root;
+        if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
+            child = child->xmlChildrenNode;
+        }
+        while (child != NULL) {
+            if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) {
+                status_t status = Trait::deserialize(doc, child, collection);
+                if (status == NO_ERROR) {
+                    nbSkippedElement += 1;
+                }
+            }
+            child = child->next;
+        }
+        if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+            return NO_ERROR;
+        }
+        root = root->next;
+    }
+    return NO_ERROR;
+}
+
+const char *const ValueTraits::tag = "value";
+const char *const ValueTraits::collectionTag = "values";
+
+const char ValueTraits::Attributes::literal[] = "literal";
+const char ValueTraits::Attributes::numerical[] = "numerical";
+
+status_t ValueTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &values)
+{
+    std::string literal = getXmlAttribute(child, Attributes::literal);
+    if (literal.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+        return BAD_VALUE;
+    }
+    uint32_t numerical = 0;
+    std::string numericalTag = getXmlAttribute(child, Attributes::numerical);
+    if (numericalTag.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+        return BAD_VALUE;
+    }
+    if (!convertTo(numericalTag, numerical)) {
+        ALOGE("%s: : Invalid value(%s)", __FUNCTION__, numericalTag.c_str());
+        return BAD_VALUE;
+    }
+    values.push_back({numerical, literal});
+    return NO_ERROR;
+}
+
+const char *const CriterionTypeTraits::tag = "criterion_type";
+const char *const CriterionTypeTraits::collectionTag = "criterion_types";
+
+const char CriterionTypeTraits::Attributes::name[] = "name";
+const char CriterionTypeTraits::Attributes::type[] = "type";
+
+status_t CriterionTypeTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
+                                          Collection &criterionTypes)
+{
+    std::string name = getXmlAttribute(child, Attributes::name);
+    if (name.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::name, name.c_str());
+
+    std::string type = getXmlAttribute(child, Attributes::type);
+    if (type.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::type);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::type, type.c_str());
+    bool isInclusive(type == "inclusive");
+
+    ValuePairs pairs;
+    size_t nbSkippedElements = 0;
+    detail::deserializeCollection<detail::ValueTraits>(doc, child, pairs, nbSkippedElements);
+
+    criterionTypes.push_back({name, isInclusive, pairs});
+    return NO_ERROR;
+}
+
+const char *const CriterionTraits::tag = "criterion";
+const char *const CriterionTraits::collectionTag = "criteria";
+
+const char CriterionTraits::Attributes::name[] = "name";
+const char CriterionTraits::Attributes::type[] = "type";
+const char CriterionTraits::Attributes::defaultVal[] = "default";
+
+status_t CriterionTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &criteria)
+{
+    std::string name = getXmlAttribute(child, Attributes::name);
+    if (name.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
+
+    std::string defaultValue = getXmlAttribute(child, Attributes::defaultVal);
+    if (defaultValue.empty()) {
+        // Not mandatory to provide a default value for a criterion, even it is recommanded...
+        ALOGV("%s: No attribute %s found", __FUNCTION__, Attributes::defaultVal);
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::defaultVal, defaultValue.c_str());
+
+    std::string typeName = getXmlAttribute(child, Attributes::type);
+    if (typeName.empty()) {
+        ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+        return BAD_VALUE;
+    }
+    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::type, typeName.c_str());
+
+    criteria.push_back({name, typeName, defaultValue});
+    return NO_ERROR;
+}
+} // namespace detail
+
+ParsingResult parse(const char* path) {
+    xmlDocPtr doc;
+    doc = xmlParseFile(path);
+    if (doc == NULL) {
+        ALOGE("%s: Could not parse document %s", __FUNCTION__, path);
+        return {nullptr, 0};
+    }
+    xmlNodePtr cur = xmlDocGetRootElement(doc);
+    if (cur == NULL) {
+        ALOGE("%s: Could not parse: empty document %s", __FUNCTION__, path);
+        xmlFreeDoc(doc);
+        return {nullptr, 0};
+    }
+    if (xmlXIncludeProcess(doc) < 0) {
+        ALOGE("%s: libxml failed to resolve XIncludes on document %s", __FUNCTION__, path);
+        return {nullptr, 0};
+    }
+    size_t nbSkippedElements = 0;
+    auto config = std::make_unique<Config>();
+
+    detail::deserializeCollection<detail::CriterionTraits>(
+                doc, cur, config->criteria, nbSkippedElements);
+    detail::deserializeCollection<detail::CriterionTypeTraits>(
+                doc, cur, config->criterionTypes, nbSkippedElements);
+
+    return {std::move(config), nbSkippedElements};
+}
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
new file mode 100644
index 0000000..467d0e1
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <utils/Errors.h>
+
+struct _xmlNode;
+struct _xmlDoc;
+
+namespace android {
+namespace audio_policy {
+namespace wrapper_config {
+
+/** Default path of audio policy usages configuration file. */
+constexpr char DEFAULT_PATH[] = "/vendor/etc/policy_wrapper_configuration.xml";
+
+/** Directories where the effect libraries will be search for. */
+constexpr const char* POLICY_USAGE_LIBRARY_PATH[] = {"/odm/etc/", "/vendor/etc/", "/system/etc/"};
+
+using ValuePair = std::pair<uint32_t, std::string>;
+using ValuePairs = std::vector<ValuePair>;
+
+struct CriterionType
+{
+    std::string name;
+    bool isInclusive;
+    ValuePairs valuePairs;
+};
+
+using CriterionTypes = std::vector<CriterionType>;
+
+struct Criterion
+{
+    std::string name;
+    std::string typeName;
+    std::string defaultLiteralValue;
+};
+
+using Criteria = std::vector<Criterion>;
+
+struct Config {
+    float version;
+    Criteria criteria;
+    CriterionTypes criterionTypes;
+};
+
+namespace detail
+{
+struct ValueTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char literal[];
+        static const char numerical[];
+    };
+
+    typedef ValuePair Element;
+    typedef ValuePair *PtrElement;
+    typedef ValuePairs Collection;
+
+    static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+                                         Collection &collection);
+};
+
+struct CriterionTypeTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char type[];
+    };
+
+    typedef CriterionType Element;
+    typedef CriterionType *PtrElement;
+    typedef CriterionTypes Collection;
+
+    static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+                                         Collection &collection);
+};
+
+struct CriterionTraits
+{
+    static const char *const tag;
+    static const char *const collectionTag;
+
+    struct Attributes
+    {
+        static const char name[];
+        static const char type[];
+        static const char defaultVal[];
+    };
+
+    typedef Criterion Element;
+    typedef Criterion *PtrElement;
+    typedef Criteria Collection;
+
+    static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+                                         Collection &collection);
+};
+} // namespace detail
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+    /** Parsed config, nullptr if the xml lib could not load the file */
+    std::unique_ptr<Config> parsedConfig;
+    size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Parses the provided audio policy usage configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult parse(const char* path = DEFAULT_PATH);
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h b/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
deleted file mode 100644
index e4fd176..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-#include <system/audio_policy.h>
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-//      Definitions for audio policy criteria configuration file (audio_policy_criteria.conf)   //
-//                                                                                              //
-//      @TODO: scripted from audio.h & audio_policy,h                                           //
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static const char *const gAudioPolicyCriteriaConfFilePath =
-    "/system/etc/audio_policy_criteria.conf";
-static const char *const gAudioPolicyCriteriaVendorConfFilePath =
-    "/vendor/etc/audio_policy_criteria.conf";
-
-/**
- * PFW instances tags
- */
-static const std::string &gPolicyConfTag = "Policy";
-static const std::string &gDefaultTag = "Default";
-static const std::string &gTypeTag = "Type";
-
-/**
- * PFW elements tags
- */
-static const std::string &gInclusiveCriterionTypeTag = "InclusiveCriterionType";
-static const std::string &gExclusiveCriterionTypeTag = "ExclusiveCriterionType";
-static const std::string &gCriterionTag = "Criterion";
-
-/**
- * PFW known criterion tags
- */
-static const std::string &gInputDeviceCriterionTag = "AvailableInputDevices";
-static const std::string &gOutputDeviceCriterionTag = "AvailableOutputDevices";
-static const std::string &gPhoneStateCriterionTag = "TelephonyMode";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const std::string gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
-    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
-    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
-    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
-    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
-    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
-    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
-    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
-    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
-};
-
-
-
-
-
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf b/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
deleted file mode 100644
index 043d5a6..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
+++ /dev/null
@@ -1,146 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Criteria file example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-#########################################################
-# Criterion type Example:
-# For each criterion, a couple of numerical, literal values must be provided to the PFW.
-# The numerical part is not mandatory. If not filled by the user, a default numerical value will be
-# automatically provided by audio HAL using the following logic:
-#   - Exclusive criterion:
-#          * 0 -> first literal value,
-#          * 1 -> second literal value,
-#               ...
-#          * N -> (N+1)th literal value.
-#   - Inclusive criterion:
-#          * 1 << 0 -> first literal value,
-#          * 1 << 1 -> second literal value,
-#               ...
-#          * 1 << N -> (N+1)th literal value,
-#
-#########################################################
-# Policy {
-#    InclusiveCriterionType|ExclusiveCriterionType {
-#        <Criterion Name>  [numerical value 1:]<literal value 1>,[numerical value 2:]<literal value 2>,<literal value 3>,...
-#    }
-# }
-
-#########################################################
-# Criterion:
-#########################################################
-# Policy {
-#    Criterion {
-#        <Criterion Name> {
-#            Type            <Criterion type name>
-#            Default         <default value of the criterion>
-#        }
-#    }
-# }
-
-Policy {
-    InclusiveCriterionType {
-        #
-        # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
-        # AUDIO_DEVICE_OUT_* within <system/audio.h> file of android.
-        #
-        OutputDevicesMaskType   Earpiece,Speaker,WiredHeadset,WiredHeadphone,BluetoothSco,BluetoothScoHeadset,BluetoothScoCarkit,BluetoothA2dp,BluetoothA2dpHeadphones,BluetoothA2dpSpeaker,Hdmi,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,RemoteSubmix,TelephonyTx,Line,HdmiArc,Spdif,Fm,AuxLine,SpeakerSafe
-        #
-        # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
-        # AUDIO_DEVICE_IN_* within <system/audio.h> file of android.
-        # Note also that direction bit will be decimated by AudioHAL in order to allow using a mask
-        # with the cardinality of 1 between a bit and an input device.
-        #
-        InputDevicesMaskType    Communication,Ambient,BuiltinMic,BluetoothScoHeadset,WiredHeadset,Hdmi,TelephonyRx,BackMic,RemoteSubmix,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,FmTuner,TvTune,Line,Spdif,BluetoothA2dp,Loopback
-    }
-    ExclusiveCriterionType {
-        #
-        # The values of the mode MUST be aligned with the definition of the audio_mode_t
-        # from system/audio.h
-        #
-        AndroidModeType     0:Normal,1:RingTone,2:InCall,3:InCommunication
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForCommunicationType    0:ForceNone,1:ForceSpeaker,3:ForceBtSco
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForMediaType            0:ForceNone,1:ForceSpeaker,2:ForceHeadphones,4:ForceBtA2dp,5:ForceWiredAccessory,8:ForceAnalogDock,9:ForceDigitalDock,10:ForceNoBtA2dp
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForRecordType           0:ForceNone,3:ForceBtSco,5:ForceWiredAccessory
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForDockType             0:ForceNone,5:ForceWiredAccessory,6:ForceBtCarDock,7:ForceBtDeskDock,8:ForceAnalogDock,9:ForceDigitalDock
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForSystemType           0:ForceNone,11:ForceSystemEnforced
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio.h
-        #
-        ForceUseForHdmiSystemAudioType  0:ForceNone,12:ForceHdmiSystemEnforced
-        #
-        # The values of the mode MUST be aligned with the definition of the
-        # audio_policy_forced_config_t from system/audio_policy.h
-        #
-        ForceUseForEncodedSurroundType  0:ForceNone,13:ForceEncodedSurroundNever,14:ForceEncodedSurroundAlways
-    }
-
-    Criterion {
-        AvailableInputDevices {
-            Type            InputDevicesMaskType
-            Default         none
-        }
-        AvailableOutputDevices {
-            Type            OutputDevicesMaskType
-            Default         none
-        }
-        TelephonyMode {
-            Type            AndroidModeType
-            Default         Normal
-        }
-        ForceUseForCommunication {
-            Type            ForceUseForCommunicationType
-            Default         ForceNone
-        }
-        ForceUseForMedia {
-            Type            ForceUseForMediaType
-            Default         ForceNone
-        }
-        ForceUseForRecord {
-            Type            ForceUseForRecordType
-            Default         ForceNone
-        }
-        ForceUseForDock {
-            Type            ForceUseForDockType
-            Default         ForceNone
-        }
-        ForceUseForSystem {
-            Type            ForceUseForSystemType
-            Default         ForceNone
-        }
-        ForceUseForHdmiSystemAudio {
-            Type            ForceUseForHdmiSystemAudioType
-            Default         ForceNone
-        }
-        ForceUseForEncodedSurround {
-            Type            ForceUseForEncodedSurroundType
-            Default         ForceNone
-        }
-    }
-}
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
new file mode 100644
index 0000000..ec82b2e
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+-->
+<criteria>
+    <criterion name="AvailableInputDevices" type="InputDevicesMaskType" default="none"/>
+    <criterion name="AvailableOutputDevices" type="OutputDevicesMaskType" default="none"/>
+    <criterion name="AvailableOutputDevicesAddresses" type="OutputDevicesAddressesType" default="none"/>
+    <criterion name="AvailableInputDevicesAddresses" type="InputDevicesAddressesType" default="none"/>
+    <criterion name="TelephonyMode" type="AndroidModeType" default="Normal"/>
+    <criterion name="ForceUseForCommunication" type="ForceUseForCommunicationType" default="ForceNone"/>
+    <criterion name="ForceUseForMedia" type="ForceUseForMediaType" default="ForceNone"/>
+    <criterion name="ForceUseForRecord" type="ForceUseForRecordType" default="ForceNone"/>
+    <criterion name="ForceUseForDock" type="ForceUseForDockType" default="ForceNone"/>
+    <criterion name="ForceUseForSystem" type="ForceUseForSystemType" default="ForceNone"/>
+    <criterion name="ForceUseForHdmiSystemAudio" type="ForceUseForHdmiSystemAudioType" default="ForceNone"/>
+    <criterion name="ForceUseForEncodedSurround" type="ForceUseForEncodedSurroundType" default="ForceNone"/>
+    <criterion name="ForceUseForVibrateRinging" type="ForceUseForVibrateRingingType" default="ForceNone"/>
+</criteria>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
new file mode 100644
index 0000000..6cb799f
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
@@ -0,0 +1,91 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+-->
+<criterion_types>
+    <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="OutputDevicesAddressesType" type="inclusive"/>
+    <criterion_type name="InputDevicesAddressesType" type="inclusive"/>
+    <criterion_type name="AndroidModeType" type="exclusive"/>
+    <criterion_type name="BooleanType" type="exclusive">
+        <values>
+            <value literal="False" numerical="0"/>
+            <value literal="True" numerical="1"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceSpeaker" numerical="1"/>
+            <value literal="ForceBtSco" numerical="3"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForMediaType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceSpeaker" numerical="1"/>
+            <value literal="ForceHeadphones" numerical="2"/>
+            <value literal="ForceBtA2dp" numerical="4"/>
+            <value literal="ForceWiredAccessory" numerical="5"/>
+            <value literal="ForceAnalogDock" numerical="8"/>
+            <value literal="ForceDigitalDock" numerical="9"/>
+            <value literal="ForceNoBtA2dp" numerical="10"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForRecordType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceBtSco" numerical="3"/>
+            <value literal="ForceWiredAccessory" numerical="5"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForDockType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceWiredAccessory" numerical="5"/>
+            <value literal="ForceBtCarDock" numerical="6"/>
+            <value literal="ForceBtDeskDock" numerical="7"/>
+            <value literal="ForceAnalogDock" numerical="8"/>
+            <value literal="ForceDigitalDock" numerical="9"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForSystemType" type="exclusive" >
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceSystemEnforced" numerical="11"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceHdmiSystemEnforced" numerical="12"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceEncodedSurroundNever" numerical="13"/>
+            <value literal="ForceEncodedSurroundAlways" numerical="14"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+        <values>
+            <value literal="ForceNone" numerical="0"/>
+            <value literal="ForceBtSco" numerical="3"/>
+        </values>
+    </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
new file mode 100644
index 0000000..5d9193b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2018 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.
+-->
+<!--
+    These are the minimum required criteria to be used by Audio HAL to ensure a basic
+    user experience on an Android device
+-->
+<configuration name="audio_policy_wrapper_configuration" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+    <xi:include href="policy_criterion_types.xml"/>
+    <xi:include href="policy_criteria.xml"/>
+
+</configuration>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index 4c1acfe..1a634a1 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,10 +16,15 @@
 
 #pragma once
 
+#include <AudioGain.h>
+#include <AudioPort.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <utils/Errors.h>
 #include <utils/RWLock.h>
+#include <utils/RefBase.h>
 #include <list>
 #include <map>
 #include <string>
@@ -27,27 +32,17 @@
 
 class CParameterMgrPlatformConnector;
 class ISelectionCriterionInterface;
-class ISelectionCriterionTypeInterface;
 struct cnode;
 
 class ParameterMgrPlatformConnectorLogger;
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
 class ParameterManagerWrapper
 {
 private:
-    typedef std::pair<int, const char *> CriterionTypeValuePair;
-
-    typedef std::map<std::string, ISelectionCriterionInterface *> CriterionCollection;
-    typedef std::map<std::string, ISelectionCriterionTypeInterface *> CriterionTypeCollection;
-    typedef CriterionCollection::iterator CriterionMapIterator;
-    typedef CriterionCollection::const_iterator CriterionMapConstIterator;
-    typedef CriterionTypeCollection::iterator CriterionTypeMapIterator;
-    typedef CriterionTypeCollection::const_iterator CriteriaTypeMapConstIterator;
+    using Criteria = std::map<std::string, ISelectionCriterionInterface *>;
 
 public:
     ParameterManagerWrapper();
@@ -120,6 +115,9 @@
      */
     status_t setAvailableOutputDevices(audio_devices_t outputDevices);
 
+    status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+                                      audio_policy_dev_state_t state);
+
 private:
     /**
      * Apply the configuration of the platform on the policy parameter manager.
@@ -136,93 +134,11 @@
     /**
      * Load the criterion configuration file.
      *
-     * @param[in] path Criterion conf file path.
-     *
      * @return NO_ERROR is parsing successful, error code otherwise.
      */
-    status_t loadAudioPolicyCriteriaConfig(const char *path);
+    status_t loadConfig();
 
-    /**
-     * Add a criterion type to AudioPolicyPfw.
-     *
-     * @param[in] typeName of the PFW criterion type.
-     * @param[in] isInclusive attribute of the criterion type.
-     */
-    void addCriterionType(const std::string &typeName, bool isInclusive);
-
-    /**
-     * Add a criterion type value pair to AudioPolicyPfw.
-     *
-     * @param[in] typeName criterion type name to which this value pair is added to.
-     * @param[in] numeric part of the value pair.
-     * @param[in] literal part of the value pair.
-     */
-    void addCriterionTypeValuePair(const std::string &typeName, uint32_t numeric,
-                                   const std::string &literal);
-
-    /**
-     * Add a criterion to AudioPolicyPfw.
-     *
-     * @param[in] name of the PFW criterion.
-     * @param[in] typeName criterion type name to which this criterion is associated to.
-     * @param[in] defaultLiteralValue of the PFW criterion.
-     */
-    void addCriterion(const std::string &name,
-                      const std::string &typeName,
-                      const std::string &defaultLiteralValue);
-    /**
-     * Parse and load the inclusive criterion type from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadInclusiveCriterionType(cnode *root);
-
-    /**
-     * Parse and load the exclusive criterion type from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadExclusiveCriterionType(cnode *root);
-
-    /**
-     * Parse and load the criteria from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadCriteria(cnode *root);
-
-    /**
-     * Parse and load a criterion from configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadCriterion(cnode *root);
-
-    /**
-     * Parse and load the criterion types from configuration file.
-     *
-     * @param[in] root node of the configuration file
-     * @param[in] isInclusive true if inclusive, false is exclusive.
-     */
-    void loadCriterionType(cnode *root, bool isInclusive);
-
-    /**
-     * Load the configuration file.
-     *
-     * @param[in] root node of the configuration file.
-     */
-    void loadConfig(cnode *root);
-
-    /**
-     * Parse and load the chidren node from a given root node.
-     *
-     * @param[in] root node of the configuration file
-     * @param[out] defaultValue of the parameter manager element to retrieve.
-     * @param[out] type of the parameter manager element to retrieve.
-    */
-    void parseChildren(cnode *root, std::string &defaultValue, std::string &type);
-
-    /**
+     /**
      * Retrieve an element from a map by its name.
      *
      * @tparam T type of element to search.
@@ -266,8 +182,7 @@
 
     bool isValueValidForCriterion(ISelectionCriterionInterface *criterion, int valueToCheck);
 
-    CriterionTypeCollection mPolicyCriterionTypes; /**< Policy Criterion Type map. */
-    CriterionCollection mPolicyCriteria; /**< Policy Criterion Map. */
+    Criteria mPolicyCriteria; /**< Policy Criterion Map. */
 
     CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
     ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 69395f3..0ef6f52 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -631,6 +631,7 @@
         case AUDIO_SOURCE_UNPROCESSED:
         case AUDIO_SOURCE_HOTWORD:
         case AUDIO_SOURCE_CAMCORDER:
+        case AUDIO_SOURCE_VOICE_PERFORMANCE:
             inputSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
             break;
         default:
@@ -737,16 +738,32 @@
             device = AUDIO_DEVICE_IN_VOICE_CALL;
         }
         break;
+    case AUDIO_SOURCE_VOICE_PERFORMANCE:
+        if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
+            device = AUDIO_DEVICE_IN_USB_HEADSET;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+            device = AUDIO_DEVICE_IN_USB_DEVICE;
+        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+        }
+        break;
     case AUDIO_SOURCE_REMOTE_SUBMIX:
         if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
             device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
         }
         break;
-     case AUDIO_SOURCE_FM_TUNER:
+    case AUDIO_SOURCE_FM_TUNER:
         if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
             device = AUDIO_DEVICE_IN_FM_TUNER;
         }
         break;
+    case AUDIO_SOURCE_ECHO_REFERENCE:
+        if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) {
+            device = AUDIO_DEVICE_IN_ECHO_REFERENCE;
+        }
+        break;
     default:
         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
         break;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 29b0561..919a90d 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -330,11 +330,12 @@
         return BAD_VALUE;
     }
 
-    // HOTWORD and FM_TUNER are two special case sources > MAX.
+    // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
     if (source < AUDIO_SOURCE_DEFAULT ||
             (source > AUDIO_SOURCE_MAX &&
              source != AUDIO_SOURCE_HOTWORD &&
-             source != AUDIO_SOURCE_FM_TUNER)) {
+             source != AUDIO_SOURCE_FM_TUNER &&
+             source != AUDIO_SOURCE_ECHO_REFERENCE)) {
         ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
         return BAD_VALUE;
     }
@@ -534,7 +535,8 @@
     CAMCORDER_SRC_TAG,
     VOICE_REC_SRC_TAG,
     VOICE_COMM_SRC_TAG,
-    UNPROCESSED_SRC_TAG
+    UNPROCESSED_SRC_TAG,
+    VOICE_PERFORMANCE_SRC_TAG
 };
 
 // returns the audio_source_t enum corresponding to the input source name or
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 80503fd..2c904d9 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -336,8 +336,11 @@
     }
 
     // already checked by client, but double-check in case the client wrapper is bypassed
-    if (attr->source < AUDIO_SOURCE_DEFAULT && attr->source >= AUDIO_SOURCE_CNT &&
-            attr->source != AUDIO_SOURCE_HOTWORD && attr->source != AUDIO_SOURCE_FM_TUNER) {
+    if ((attr->source < AUDIO_SOURCE_DEFAULT)
+            || (attr->source >= AUDIO_SOURCE_CNT
+                && attr->source != AUDIO_SOURCE_HOTWORD
+                && attr->source != AUDIO_SOURCE_FM_TUNER
+                && attr->source != AUDIO_SOURCE_ECHO_REFERENCE)) {
         return BAD_VALUE;
     }
 
@@ -367,7 +370,8 @@
 
     if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
         attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
-        attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+        attr->source == AUDIO_SOURCE_VOICE_CALL ||
+        attr->source == AUDIO_SOURCE_ECHO_REFERENCE) &&
         !captureAudioOutputAllowed(pid, uid)) {
         return PERMISSION_DENIED;
     }
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 56af152..24326bb 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -112,10 +112,34 @@
     std::set<audio_patch_handle_t> mActivePatches;
 };
 
+class PatchCountCheck {
+  public:
+    explicit PatchCountCheck(AudioPolicyManagerTestClient *client)
+            : mClient{client},
+              mInitialCount{mClient->getActivePatchesCount()} {}
+    void assertDelta(int delta) const {
+        ASSERT_EQ(mInitialCount + delta, mClient->getActivePatchesCount()); }
+    void assertNoChange() const { assertDelta(0); }
+  private:
+    const AudioPolicyManagerTestClient *mClient;
+    const size_t mInitialCount;
+};
+
 class AudioPolicyManagerTest : public testing::Test {
   protected:
-    virtual void SetUp();
-    virtual void TearDown();
+    void SetUp() override;
+    void TearDown() override;
+    virtual void SetUpConfig(AudioPolicyConfig *config) { (void)config; }
+
+    void dumpToLog();
+    void getOutputForAttr(
+            audio_port_handle_t *selectedDeviceId,
+            audio_format_t format,
+            int channelMask,
+            int sampleRate,
+            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+            audio_port_handle_t *portId = nullptr);
+    PatchCountCheck snapPatchCount() { return PatchCountCheck(mClient.get()); }
 
     std::unique_ptr<AudioPolicyManagerTestClient> mClient;
     std::unique_ptr<AudioPolicyTestManager> mManager;
@@ -125,6 +149,7 @@
     mClient.reset(new AudioPolicyManagerTestClient);
     mManager.reset(new AudioPolicyTestManager(mClient.get()));
     mManager->getConfig().setDefault();
+    SetUpConfig(&mManager->getConfig());  // Subclasses may want to customize the config.
     ASSERT_EQ(NO_ERROR, mManager->initialize());
     ASSERT_EQ(NO_ERROR, mManager->initCheck());
 }
@@ -134,11 +159,7 @@
     mClient.reset();
 }
 
-TEST_F(AudioPolicyManagerTest, InitSuccess) {
-    // SetUp must finish with no assertions.
-}
-
-TEST_F(AudioPolicyManagerTest, Dump) {
+void AudioPolicyManagerTest::dumpToLog() {
     int pipefd[2];
     ASSERT_NE(-1, pipe(pipefd));
     pid_t cpid = fork();
@@ -168,10 +189,43 @@
     }
 }
 
+void AudioPolicyManagerTest::getOutputForAttr(
+        audio_port_handle_t *selectedDeviceId,
+        audio_format_t format,
+        int channelMask,
+        int sampleRate,
+        audio_output_flags_t flags,
+        audio_port_handle_t *portId) {
+    audio_attributes_t attr = {};
+    audio_io_handle_t output = AUDIO_PORT_HANDLE_NONE;
+    audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
+    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+    config.sample_rate = sampleRate;
+    config.channel_mask = channelMask;
+    config.format = format;
+    *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    audio_port_handle_t localPortId;
+    if (!portId) portId = &localPortId;
+    *portId = AUDIO_PORT_HANDLE_NONE;
+    ASSERT_EQ(OK, mManager->getOutputForAttr(
+                    &attr, &output, AUDIO_SESSION_NONE, &stream, 0 /*uid*/, &config, &flags,
+                    selectedDeviceId, portId));
+    ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+}
+
+
+TEST_F(AudioPolicyManagerTest, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTest, Dump) {
+    dumpToLog();
+}
+
 TEST_F(AudioPolicyManagerTest, CreateAudioPatchFailure) {
     audio_patch patch{};
     audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
-    const size_t patchCountBefore = mClient->getActivePatchesCount();
+    const PatchCountCheck patchCount = snapPatchCount();
     ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(nullptr, &handle, 0));
     ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, nullptr, 0));
     ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
@@ -198,20 +252,182 @@
     ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
     // Verify that the handle is left unchanged.
     ASSERT_EQ(AUDIO_PATCH_HANDLE_NONE, handle);
-    ASSERT_EQ(patchCountBefore, mClient->getActivePatchesCount());
+    patchCount.assertNoChange();
 }
 
 TEST_F(AudioPolicyManagerTest, CreateAudioPatchFromMix) {
     audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
     uid_t uid = 42;
-    const size_t patchCountBefore = mClient->getActivePatchesCount();
+    const PatchCountCheck patchCount = snapPatchCount();
     ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
     PatchBuilder patchBuilder;
     patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
             addSink(mManager->getConfig().getDefaultOutputDevice());
     ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
     ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
-    ASSERT_EQ(patchCountBefore + 1, mClient->getActivePatchesCount());
+    patchCount.assertDelta(1);
 }
 
 // TODO: Add patch creation tests that involve already existing patch
+
+class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
+  protected:
+    void SetUpConfig(AudioPolicyConfig *config) override;
+    void TearDown() override;
+
+    sp<DeviceDescriptor> mMsdOutputDevice;
+    sp<DeviceDescriptor> mMsdInputDevice;
+};
+
+void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
+    // TODO: Consider using Serializer to load part of the config from a string.
+    mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
+    sp<AudioProfile> pcmOutputProfile = new AudioProfile(
+            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+    sp<AudioProfile> ac3OutputProfile = new AudioProfile(
+            AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+    mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
+    mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
+    mMsdInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUS);
+    // Match output profile from AudioPolicyConfig::setDefault.
+    sp<AudioProfile> pcmInputProfile = new AudioProfile(
+            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
+    mMsdInputDevice->addAudioProfile(pcmInputProfile);
+    config->addAvailableDevice(mMsdOutputDevice);
+    config->addAvailableDevice(mMsdInputDevice);
+
+    sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
+    HwModuleCollection modules = config->getHwModules();
+    modules.add(msdModule);
+    config->setHwModules(modules);
+    mMsdOutputDevice->attach(msdModule);
+    mMsdInputDevice->attach(msdModule);
+
+    sp<OutputProfile> msdOutputProfile = new OutputProfile(String8("msd input"));
+    msdOutputProfile->addAudioProfile(pcmOutputProfile);
+    msdOutputProfile->addSupportedDevice(mMsdOutputDevice);
+    msdModule->addOutputProfile(msdOutputProfile);
+    sp<OutputProfile> msdCompressedOutputProfile =
+            new OutputProfile(String8("msd compressed input"));
+    msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile);
+    msdCompressedOutputProfile->setFlags(
+            AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
+            AUDIO_OUTPUT_FLAG_NON_BLOCKING);
+    msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
+    msdModule->addOutputProfile(msdCompressedOutputProfile);
+
+    sp<InputProfile> msdInputProfile = new InputProfile(String8("msd output"));
+    msdInputProfile->addAudioProfile(pcmInputProfile);
+    msdInputProfile->addSupportedDevice(mMsdInputDevice);
+    msdModule->addInputProfile(msdInputProfile);
+
+    // Add a profile with another encoding to the default device to test routing
+    // of streams that are not supported by MSD.
+    sp<AudioProfile> dtsOutputProfile = new AudioProfile(
+            AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+    config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+    sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile(String8("encoded"));
+    primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
+    primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
+    primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());
+    config->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+            addOutputProfile(primaryEncodedOutputProfile);
+}
+
+void AudioPolicyManagerTestMsd::TearDown() {
+    mMsdOutputDevice.clear();
+    mMsdInputDevice.clear();
+    AudioPolicyManagerTest::TearDown();
+}
+
+TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
+    ASSERT_TRUE(mMsdOutputDevice);
+    ASSERT_TRUE(mMsdInputDevice);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, Dump) {
+    dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
+    const PatchCountCheck patchCount = snapPatchCount();
+    mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
+            AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
+    patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
+    const PatchCountCheck patchCount = snapPatchCount();
+    audio_port_handle_t selectedDeviceId;
+    getOutputForAttr(&selectedDeviceId,
+            AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
+    const PatchCountCheck patchCount = snapPatchCount();
+    audio_port_handle_t selectedDeviceId;
+    getOutputForAttr(&selectedDeviceId,
+            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
+    const PatchCountCheck patchCount = snapPatchCount();
+    audio_port_handle_t selectedDeviceId;
+    getOutputForAttr(&selectedDeviceId,
+            AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    patchCount.assertDelta(1);
+    getOutputForAttr(&selectedDeviceId,
+            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+    ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+    patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
+    const PatchCountCheck patchCount = snapPatchCount();
+    audio_port_handle_t selectedDeviceId;
+    getOutputForAttr(&selectedDeviceId,
+            AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+    ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
+    patchCount.assertNoChange();
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
+    // Switch between formats that are supported and not supported by MSD.
+    {
+        const PatchCountCheck patchCount = snapPatchCount();
+        audio_port_handle_t selectedDeviceId, portId;
+        getOutputForAttr(&selectedDeviceId,
+                AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
+                &portId);
+        ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+        patchCount.assertDelta(1);
+        mManager->releaseOutput(portId);
+        patchCount.assertDelta(1);  // compared to the state at the block entry
+        // TODO: make PatchCountCheck asserts more obvious. It's easy to
+        // miss the fact that it is immutable.
+    }
+    {
+        const PatchCountCheck patchCount = snapPatchCount();
+        audio_port_handle_t selectedDeviceId, portId;
+        getOutputForAttr(&selectedDeviceId,
+                AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
+                &portId);
+        ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
+        patchCount.assertDelta(-1);
+        mManager->releaseOutput(portId);
+        patchCount.assertNoChange();
+    }
+    {
+        const PatchCountCheck patchCount = snapPatchCount();
+        audio_port_handle_t selectedDeviceId;
+        getOutputForAttr(&selectedDeviceId,
+                AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+        ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+        patchCount.assertNoChange();
+    }
+}
diff --git a/services/mediacodec/MediaCodecUpdateService.cpp b/services/mediacodec/MediaCodecUpdateService.cpp
index aee890d..0e6892d 100644
--- a/services/mediacodec/MediaCodecUpdateService.cpp
+++ b/services/mediacodec/MediaCodecUpdateService.cpp
@@ -18,14 +18,10 @@
 //#define LOG_NDEBUG 0
 
 #include <android/dlext.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <dirent.h>
 #include <dlfcn.h>
 #include <media/CodecServiceRegistrant.h>
 #include <utils/Log.h>
-#include <ziparchive/zip_archive.h>
-#include <cutils/properties.h>
+#include <utils/String8.h>
 
 #include "MediaCodecUpdateService.h"
 
@@ -47,90 +43,53 @@
 }
 
 namespace android {
-namespace media {
 
-binder::Status MediaCodecUpdateService::loadPlugins(const ::std::string& apkPath) {
-    ALOGV("loadPlugins %s", apkPath.c_str());
+void loadFromApex(const char *libDirPath) {
+    ALOGV("loadFromApex: path=%s", libDirPath);
 
-    ZipArchiveHandle zipHandle;
-    void *registrantLib = NULL;
-    int32_t ret = OpenArchive(apkPath.c_str(), &zipHandle);
+    String8 libPath = String8(libDirPath) + "/libmedia_codecserviceregistrant.so";
 
-    if (ret == 0) {
-        char abilist32[PROPERTY_VALUE_MAX];
-        property_get("ro.product.cpu.abilist32", abilist32, "armeabi-v7a");
+    android_namespace_t *codecNs = android_create_namespace("codecs",
+            nullptr,  // ld_library_path
+            libDirPath,
+            ANDROID_NAMESPACE_TYPE_ISOLATED,
+            nullptr,  // permitted_when_isolated_path
+            nullptr); // parent
 
-        auto abis = base::Split(abilist32, ",");
-        if (abis.empty()) {
-            ALOGW("abilist is empty, trying armeabi-v7a ...");
-            abis.push_back("armeabi-v7a");
-        }
-
-        // TODO: Only try the first entry in abilist32 for now.
-        // We probably should try the next if it fails.
-        String8 libPathInApk = String8("lib/") + String8(abis[0].c_str());
-        String8 defaultLibPath = String8(apkPath.c_str()) + "!/" + libPathInApk;
-        String8 libPath = defaultLibPath + "/libmedia_codecserviceregistrant.so";
-        String8 zipEntryPath = libPathInApk + "/libmedia_codecserviceregistrant.so";
-
-        ZipEntry entry;
-        ret = FindEntry(zipHandle, ZipString(zipEntryPath), &entry);
-
-        if (ret == 0) {
-            android_namespace_t *codecNs = android_create_namespace("codecs",
-                    nullptr,  // ld_library_path
-                    defaultLibPath.c_str(),
-                    ANDROID_NAMESPACE_TYPE_ISOLATED,
-                    nullptr,  // permitted_when_isolated_path
-                    nullptr); // parent
-
-            if (codecNs != nullptr) {
-                String8 linked_libraries(LINKED_LIBRARIES);
-                if (android_link_namespaces(
-                        codecNs, nullptr, linked_libraries.c_str())) {
-                    const android_dlextinfo dlextinfo = {
-                            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-                            .library_namespace = codecNs,
-                    };
-
-                    registrantLib = android_dlopen_ext(
-                            libPath.string(),
-                            RTLD_NOW | RTLD_LOCAL, &dlextinfo);
-
-                    if (registrantLib == NULL) {
-                        ALOGE("Failed to load lib from archive: %s", dlerror());
-                    }
-                } else {
-                    ALOGE("Failed to link namespace");
-                }
-            } else {
-                ALOGE("Failed to create codec namespace");
-            }
-        } else {
-            ALOGE("Failed to find entry (ret=%d)", ret);
-        }
-
-        CloseArchive(zipHandle);
-    } else {
-        ALOGE("Failed to open archive (ret=%d)", ret);
+    if (codecNs == nullptr) {
+        ALOGE("Failed to create codec namespace");
+        return;
     }
 
-    if (registrantLib) {
-        RegisterCodecServicesFunc registerCodecServices =
-                reinterpret_cast<RegisterCodecServicesFunc>(
-                dlsym(registrantLib, "RegisterCodecServices"));
-        if (registerCodecServices) {
-            registerCodecServices();
-        } else {
-            LOG(WARNING) << "Cannot register codec services "
-                    "-- corrupted library.";
-        }
-    } else {
-        LOG(ERROR) << "Cannot find codec service registrant.";
+    String8 linked_libraries(LINKED_LIBRARIES);
+    if (!android_link_namespaces(codecNs, nullptr, linked_libraries.c_str())) {
+        ALOGE("Failed to link namespace");
+        return;
     }
 
-    return binder::Status::ok();
+    const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE,
+            .library_namespace = codecNs,
+    };
+
+    void *registrantLib = android_dlopen_ext(
+            libPath.string(),
+            RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+
+    if (registrantLib == nullptr) {
+        ALOGE("Failed to load lib from archive: %s", dlerror());
+    }
+
+    RegisterCodecServicesFunc registerCodecServices =
+            reinterpret_cast<RegisterCodecServicesFunc>(
+            dlsym(registrantLib, "RegisterCodecServices"));
+
+    if (registerCodecServices == nullptr) {
+        ALOGE("Cannot register codec services -- corrupted library.");
+        return;
+    }
+
+    registerCodecServices();
 }
 
-}   // namespace media
 }   // namespace android
diff --git a/services/mediacodec/MediaCodecUpdateService.h b/services/mediacodec/MediaCodecUpdateService.h
index 7b7cee9..09d6dbe 100644
--- a/services/mediacodec/MediaCodecUpdateService.h
+++ b/services/mediacodec/MediaCodecUpdateService.h
@@ -17,24 +17,10 @@
 #ifndef ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
 #define ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
 
-#include <binder/BinderService.h>
-#include <android/media/BnMediaUpdateService.h>
-
 namespace android {
-namespace media {
 
-class MediaCodecUpdateService
-    : public BinderService<MediaCodecUpdateService>, public BnMediaUpdateService
-{
-    friend class BinderService<MediaCodecUpdateService>;
-public:
-    MediaCodecUpdateService() : BnMediaUpdateService() { }
-    virtual ~MediaCodecUpdateService() { }
-    static const char* getServiceName() { return "media.codec.update"; }
-    binder::Status loadPlugins(const ::std::string& apkPath);
-};
+void loadFromApex(const char *libDirPath);
 
-}   // namespace media
 }   // namespace android
 
 #endif  // ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index 79fea25..1168825 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -20,11 +20,7 @@
 // from LOCAL_C_INCLUDES
 #include "minijail.h"
 
-#include <android-base/properties.h>
-#include <binder/ProcessState.h>
-#include <dlfcn.h>
 #include <hidl/HidlTransportSupport.h>
-#include <media/CodecServiceRegistrant.h>
 
 #include "MediaCodecUpdateService.h"
 
@@ -49,32 +45,10 @@
     signal(SIGPIPE, SIG_IGN);
     SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
 
-    std::string value = base::GetProperty("ro.build.type", "unknown");
-    if (value == "userdebug" || value == "eng") {
-        media::MediaCodecUpdateService::instantiate();
-    }
-
-    android::ProcessState::self()->startThreadPool();
-
     ::android::hardware::configureRpcThreadpool(64, false);
 
-    // Registration of customized codec services
-    void *registrantLib = dlopen(
-            "libmedia_codecserviceregistrant.so",
-            RTLD_NOW | RTLD_LOCAL);
-    if (registrantLib) {
-        RegisterCodecServicesFunc registerCodecServices =
-                reinterpret_cast<RegisterCodecServicesFunc>(
-                dlsym(registrantLib, "RegisterCodecServices"));
-        if (registerCodecServices) {
-            registerCodecServices();
-        } else {
-            LOG(WARNING) << "Cannot register codec services "
-                    "-- corrupted library.";
-        }
-    } else {
-        LOG(ERROR) << "Cannot find codec service registrant.";
-    }
+    // codec libs are currently 32-bit only
+    loadFromApex("/apex/com.android.media.swcodec/lib");
 
     ::android::hardware::joinRpcThreadpool();
 }
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 6101c8a..dd64881 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -46,6 +46,7 @@
 LOCAL_INIT_RC := mediaextractor.rc
 LOCAL_C_INCLUDES := frameworks/av/media/libmedia
 LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SANITIZE := scudo
 include $(BUILD_EXECUTABLE)
 
 # service seccomp filter
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index 8d3359a..5f42711 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -42,6 +42,12 @@
 static const char kVendorSeccompPolicyPath[] =
         "/vendor/etc/seccomp_policy/mediaextractor.policy";
 
+// Disable Scudo's mismatch allocation check, as it is being triggered
+// by some third party code.
+extern "C" const char *__scudo_default_options() {
+    return "DeallocationTypeMismatch=false";
+}
+
 int main(int argc __unused, char** argv)
 {
     limitProcessMemory(
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
index 35ac458..607a03e 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
@@ -11,6 +11,7 @@
 mmap: 1
 madvise: 1
 openat: 1
+open: 1
 clock_gettime: 1
 writev: 1
 brk: 1