Merge "NdkMediaDrm: get app name from /proc/self/cmdline"
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 701ced7..477c371 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -15,7 +15,7 @@
 apex {
     name: "test_com.android.media",
     manifest: "test_manifest.json",
-    file_contexts: "com.android.media",
+    file_contexts: ":com.android.media-file_contexts",
     defaults: ["com.android.media-defaults"],
     installable: false,
 }
@@ -23,7 +23,7 @@
 apex {
     name: "test_com.android.media.swcodec",
     manifest: "test_manifest_codec.json",
-    file_contexts: "com.android.media.swcodec",
+    file_contexts: ":com.android.media.swcodec-file_contexts",
     defaults: ["com.android.media.swcodec-defaults"],
     installable: false,
 }
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 8eb030a..7a0f63b 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -76,6 +76,10 @@
 
 sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
     Mutex::Autolock _l(mLock);
+    return getCameraServiceLocked();
+}
+
+sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
     if (mCameraService.get() == nullptr) {
         if (isCameraServiceDisabled()) {
             return mCameraService;
@@ -216,8 +220,12 @@
     if (pair.second) {
         for (auto& pair : mDeviceStatusMap) {
             const String8& cameraId = pair.first;
-            int32_t status = pair.second;
-
+            int32_t status = pair.second.status;
+            // Don't send initial callbacks for camera ids which don't support
+            // camera2
+            if (!pair.second.supportsHAL3) {
+                continue;
+            }
             sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
             ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
                     callback->onCameraAvailable : callback->onCameraUnavailable;
@@ -236,20 +244,32 @@
     mCallbacks.erase(cb);
 }
 
+bool CameraManagerGlobal::supportsCamera2ApiLocked(const String8 &cameraId) {
+    bool camera2Support = false;
+    auto cs = getCameraServiceLocked();
+    binder::Status serviceRet =
+        cs->supportsCameraApi(String16(cameraId),
+                hardware::ICameraService::API_VERSION_2, &camera2Support);
+    if (!serviceRet.isOk()) {
+        ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId  %s",
+                __FUNCTION__, cameraId.c_str());
+        return false;
+    }
+    return camera2Support;
+}
+
 void CameraManagerGlobal::getCameraIdList(std::vector<String8>* cameraIds) {
     // Ensure that we have initialized/refreshed the list of available devices
-    auto cs = getCameraService();
     Mutex::Autolock _l(mLock);
-
+    // Needed to make sure we're connected to cameraservice
+    getCameraServiceLocked();
     for(auto& deviceStatus : mDeviceStatusMap) {
-        if (deviceStatus.second == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
-                deviceStatus.second == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
+        if (deviceStatus.second.status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
+                deviceStatus.second.status ==
+                        hardware::ICameraServiceListener::STATUS_ENUMERATING) {
             continue;
         }
-        bool camera2Support = false;
-        binder::Status serviceRet = cs->supportsCameraApi(String16(deviceStatus.first),
-                hardware::ICameraService::API_VERSION_2, &camera2Support);
-        if (!serviceRet.isOk() || !camera2Support) {
+        if (!deviceStatus.second.supportsHAL3) {
             continue;
         }
         cameraIds->push_back(deviceStatus.first);
@@ -377,7 +397,7 @@
     bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
     int32_t oldStatus = firstStatus ?
             status : // first status
-            mDeviceStatusMap[cameraId];
+            mDeviceStatusMap[cameraId].status;
 
     if (!firstStatus &&
             isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
@@ -385,16 +405,19 @@
         return;
     }
 
+    bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
     // Iterate through all registered callbacks
-    mDeviceStatusMap[cameraId] = status;
-    for (auto cb : mCallbacks) {
-        sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
-        ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
-                cb.mAvailable : cb.mUnavailable;
-        msg->setPointer(kCallbackFpKey, (void *) cbFp);
-        msg->setPointer(kContextKey, cb.mContext);
-        msg->setString(kCameraIdKey, AString(cameraId));
-        msg->post();
+    mDeviceStatusMap[cameraId] = StatusAndHAL3Support(status, supportsHAL3);
+    if (supportsHAL3) {
+        for (auto cb : mCallbacks) {
+            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+            ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFp);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId));
+            msg->post();
+        }
     }
     if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
         mDeviceStatusMap.erase(cameraId);
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 8c1da36..e945ba0 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -66,9 +66,9 @@
 
   private:
     sp<hardware::ICameraService> mCameraService;
-    const int          kCameraServicePollDelay = 500000; // 0.5s
-    const char*        kCameraServiceName      = "media.camera";
-    Mutex              mLock;
+    const int                    kCameraServicePollDelay = 500000; // 0.5s
+    const char*                  kCameraServiceName      = "media.camera";
+    Mutex                        mLock;
 
     class DeathNotifier : public IBinder::DeathRecipient {
       public:
@@ -156,12 +156,14 @@
     sp<CallbackHandler> mHandler;
     sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
 
+    sp<hardware::ICameraService> getCameraServiceLocked();
     void onCameraAccessPrioritiesChanged();
     void onStatusChanged(int32_t status, const String8& cameraId);
     void onStatusChangedLocked(int32_t status, const String8& cameraId);
     // Utils for status
     static bool validStatus(int32_t status);
     static bool isStatusAvailable(int32_t status);
+    bool supportsCamera2ApiLocked(const String8 &cameraId);
 
     // The sort logic must match the logic in
     // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
@@ -184,8 +186,16 @@
         }
     };
 
+    struct StatusAndHAL3Support {
+        int32_t status = hardware::ICameraServiceListener::STATUS_NOT_PRESENT;
+        bool supportsHAL3 = false;
+        StatusAndHAL3Support(int32_t st, bool HAL3support):
+                status(st), supportsHAL3(HAL3support) { };
+        StatusAndHAL3Support() = default;
+    };
+
     // Map camera_id -> status
-    std::map<String8, int32_t, CameraIdComparator> mDeviceStatusMap;
+    std::map<String8, StatusAndHAL3Support, CameraIdComparator> mDeviceStatusMap;
 
     // For the singleton instance
     static Mutex sLock;
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 26e147b..4c411be 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -17,7 +17,6 @@
     srcs: [
         "DrmPluginPath.cpp",
         "DrmSessionManager.cpp",
-        "IMediaDrmService.cpp",
         "SharedLibrary.cpp",
         "DrmHal.cpp",
         "CryptoHal.cpp",
@@ -39,14 +38,14 @@
 
     shared_libs: [
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libdl",
         "liblog",
         "libmedia",
         "libmediadrmmetrics_lite",
-        "libmediametrics",
+        "libmediametrics#1",
         "libmediautils",
-        "libresourcemanagerservice",
         "libstagefright_foundation",
         "libutils",
         "android.hardware.drm@1.0",
@@ -56,6 +55,10 @@
         "libhidlbase",
     ],
 
+    static_libs: [
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
     export_shared_lib_headers: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
@@ -92,8 +95,6 @@
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
-        "libbinder",
-        "libhidlbase",
         "liblog",
         "libmediametrics",
         "libprotobuf-cpp-lite",
@@ -131,8 +132,6 @@
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
         "libbase",
-        "libbinder",
-        "libhidlbase",
         "liblog",
         "libmediametrics",
         "libprotobuf-cpp-full",
@@ -146,3 +145,25 @@
     ],
 }
 
+cc_library_shared {
+    name: "libmediadrmmetrics_consumer",
+    srcs: [
+        "DrmMetricsConsumer.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libmedia/include"
+    ],
+
+    shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
+        "libbinder",
+        "libhidlbase",
+        "liblog",
+        "libmediadrm",
+        "libmediadrmmetrics_full",
+        "libutils",
+    ],
+}
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 6a0e75e..55b9bb8 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -45,6 +45,7 @@
 using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::HidlMemory;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
@@ -255,10 +256,7 @@
  * size.  Once the heap base is established, shared memory buffers
  * are sent by providing an offset into the heap and a buffer size.
  */
-int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
-    using ::android::hardware::fromHeap;
-    using ::android::hardware::HidlMemory;
-
+int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) {
     if (heap == NULL || mHeapSeqNum < 0) {
         ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
         return -1;
@@ -268,9 +266,8 @@
 
     int32_t seqNum = mHeapSeqNum++;
     uint32_t bufferId = static_cast<uint32_t>(seqNum);
-    sp<HidlMemory> hidlMemory = fromHeap(heap);
-    mHeapBases.add(seqNum, HeapBase(bufferId, heap->getSize()));
-    Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, bufferId);
+    mHeapSizes.add(seqNum, heap->size());
+    Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
     return seqNum;
 }
@@ -285,64 +282,40 @@
      * TODO: Add a releaseSharedBuffer method in a future DRM HAL
      * API version to make this explicit.
      */
-    ssize_t index = mHeapBases.indexOfKey(seqNum);
+    ssize_t index = mHeapSizes.indexOfKey(seqNum);
     if (index >= 0) {
         if (mPlugin != NULL) {
-            uint32_t bufferId = mHeapBases[index].getBufferId();
+            uint32_t bufferId = static_cast<uint32_t>(seqNum);
             Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
             ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
         }
-        mHeapBases.removeItem(seqNum);
+        mHeapSizes.removeItem(seqNum);
     }
 }
 
-status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
-    ssize_t offset;
-    size_t size;
-
-    if (memory == NULL || buffer == NULL) {
-        return UNEXPECTED_NULL;
-    }
-
-    sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
-    if (heap == NULL) {
-        return UNEXPECTED_NULL;
-    }
-
+status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) {
+    int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
     // memory must be in one of the heaps that have been set
-    if (mHeapBases.indexOfKey(seqNum) < 0) {
+    if (mHeapSizes.indexOfKey(seqNum) < 0) {
         return UNKNOWN_ERROR;
     }
 
-    // heap must be the same size as the one that was set in setHeapBase
-    if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) {
-        android_errorWriteLog(0x534e4554, "76221123");
-        return UNKNOWN_ERROR;
-     }
-
     // memory must be within the address space of the heap
-    // TODO: Using unsecurePointer() has some associated security pitfalls
-    //       (see declaration for details).
-    //       Either document why it is safe in this case or address the
-    //       issue (e.g. by copying).
-    if (memory->unsecurePointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset()  ||
-            heap->getSize() < memory->offset() + memory->size() ||
-            SIZE_MAX - memory->offset() < memory->size()) {
+    size_t heapSize = mHeapSizes.valueFor(seqNum);
+    if (heapSize < buffer.offset + buffer.size ||
+            SIZE_MAX - buffer.offset < buffer.size) {
         android_errorWriteLog(0x534e4554, "76221123");
         return UNKNOWN_ERROR;
     }
 
-    buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId();
-    buffer->offset = offset >= 0 ? offset : 0;
-    buffer->size = size;
     return OK;
 }
 
 ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
         CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-        const ICrypto::SourceBuffer &source, size_t offset,
+        const ::SharedBuffer &hSource, size_t offset,
         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-        const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+        const ::DestinationBuffer &hDestination, AString *errorDetailMsg) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -380,28 +353,21 @@
     }
     auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
 
-    int32_t heapSeqNum = source.mHeapSeqNum;
     bool secure;
-    ::DestinationBuffer hDestination;
-    if (destination.mType == kDestinationTypeSharedMemory) {
-        hDestination.type = BufferType::SHARED_MEMORY;
-        status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum,
-                &hDestination.nonsecureMemory);
+    if (hDestination.type == BufferType::SHARED_MEMORY) {
+        status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
         if (status != OK) {
             return status;
         }
         secure = false;
-    } else if (destination.mType == kDestinationTypeNativeHandle) {
-        hDestination.type = BufferType::NATIVE_HANDLE;
-        hDestination.secureMemory = hidl_handle(destination.mHandle);
+    } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
         secure = true;
     } else {
         android_errorWriteLog(0x534e4554, "70526702");
         return UNKNOWN_ERROR;
     }
 
-    ::SharedBuffer hSource;
-    status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource);
+    status_t status = checkSharedBuffer(hSource);
     if (status != OK) {
         return status;
     }
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 53a7446..757ccda 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,14 +20,14 @@
 
 #include <utils/Log.h>
 
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <android/binder_manager.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
 #include <android/hardware/drm/1.2/types.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
-#include <android/media/BnResourceManagerClient.h>
 #include <hidl/ServiceManagement.h>
 #include <media/EventMetric.h>
+#include <media/MediaMetrics.h>
 #include <media/PluginMetricsReporting.h>
 #include <media/drm/DrmAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -38,6 +38,7 @@
 #include <mediadrm/DrmHal.h>
 #include <mediadrm/DrmSessionClientInterface.h>
 #include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
 
 #include <vector>
 
@@ -98,17 +99,6 @@
 
 #define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
 
-static inline int getCallingPid() {
-    return IPCThreadState::self()->getCallingPid();
-}
-
-static bool checkPermission(const char* permissionString) {
-    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
-    bool ok = checkCallingPermission(String16(permissionString));
-    if (!ok) ALOGE("Request requires %s", permissionString);
-    return ok;
-}
-
 static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
     Vector<uint8_t> vector;
     vector.appendArray(vec.data(), vec.size());
@@ -298,17 +288,16 @@
 
 Mutex DrmHal::mLock;
 
-struct DrmHal::DrmSessionClient : public android::media::BnResourceManagerClient {
+struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
     explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
       : mSessionId(sessionId),
         mDrm(drm) {}
 
-    ::android::binder::Status reclaimResource(bool* _aidl_return) override;
-    ::android::binder::Status getName(::std::string* _aidl_return) override;
+    ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+    ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
 
     const Vector<uint8_t> mSessionId;
 
-protected:
     virtual ~DrmSessionClient();
 
 private:
@@ -317,24 +306,25 @@
     DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
 };
 
-::android::binder::Status DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+    auto sessionId = mSessionId;
     sp<DrmHal> drm = mDrm.promote();
     if (drm == NULL) {
         *_aidl_return = true;
-        return ::android::binder::Status::ok();
+        return ::ndk::ScopedAStatus::ok();
     }
-    status_t err = drm->closeSession(mSessionId);
+    status_t err = drm->closeSession(sessionId);
     if (err != OK) {
         *_aidl_return = false;
-        return ::android::binder::Status::ok();
+        return ::ndk::ScopedAStatus::ok();
     }
     drm->sendEvent(EventType::SESSION_RECLAIMED,
-            toHidlVec(mSessionId), hidl_vec<uint8_t>());
+            toHidlVec(sessionId), hidl_vec<uint8_t>());
     *_aidl_return = true;
-    return ::android::binder::Status::ok();
+    return ::ndk::ScopedAStatus::ok();
 }
 
-::android::binder::Status DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
     String8 name;
     sp<DrmHal> drm = mDrm.promote();
     if (drm == NULL) {
@@ -349,7 +339,7 @@
     }
     name.append("]");
     *_aidl_return = name;
-    return ::android::binder::Status::ok();
+    return ::ndk::ScopedAStatus::ok();
 }
 
 DrmHal::DrmSessionClient::~DrmSessionClient() {
@@ -453,6 +443,7 @@
         const uint8_t uuid[16], const String8& appPackageName) {
     mAppPackageName = appPackageName;
     mMetrics.SetAppPackageName(appPackageName);
+    mMetrics.SetAppUid(AIBinder_getCallingUid());
 
     sp<IDrmPlugin> plugin;
     Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
@@ -749,7 +740,7 @@
             // reclaimSession may call back to closeSession, since mLock is
             // shared between Drm instances, we should unlock here to avoid
             // deadlock.
-            retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+            retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
             mLock.lock();
         } else {
             retry = false;
@@ -757,9 +748,10 @@
     } while (retry);
 
     if (err == OK) {
-        sp<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
-        DrmSessionManager::Instance()->addSession(getCallingPid(), client, sessionId);
-        mOpenSessions.push(client);
+        std::shared_ptr<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
+        DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
+                std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
+        mOpenSessions.push_back(client);
         mMetrics.SetSessionStart(sessionId);
     }
 
@@ -775,9 +767,9 @@
     if (status.isOk()) {
         if (status == Status::OK) {
             DrmSessionManager::Instance()->removeSession(sessionId);
-            for (size_t i = 0; i < mOpenSessions.size(); i++) {
-                if (isEqualSessionId(mOpenSessions[i]->mSessionId, sessionId)) {
-                    mOpenSessions.removeAt(i);
+            for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+                if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+                    mOpenSessions.erase(i);
                     break;
                 }
             }
@@ -1371,11 +1363,11 @@
     return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
 }
 
-status_t DrmHal::getMetrics(PersistableBundle* metrics) {
-    if (metrics == nullptr) {
+status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer> &consumer) {
+    if (consumer == nullptr) {
         return UNEXPECTED_NULL;
     }
-    mMetrics.Export(metrics);
+    consumer->consumeFrameworkMetrics(mMetrics);
 
     // Append vendor metrics if they are supported.
     if (mPluginV1_1 != NULL) {
@@ -1402,11 +1394,7 @@
                     if (status != Status::OK) {
                       ALOGV("Error getting plugin metrics: %d", status);
                     } else {
-                        PersistableBundle pluginBundle;
-                        if (MediaDrmMetrics::HidlMetricsToBundle(
-                                pluginMetrics, &pluginBundle) == OK) {
-                            metrics->putPersistableBundle(String16(vendor), pluginBundle);
-                        }
+                      consumer->consumeHidlMetrics(vendor, pluginMetrics);
                     }
                     err = toStatusT(status);
                 });
@@ -1540,10 +1528,6 @@
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
-        return -EPERM;
-    }
-
     DrmSessionManager::Instance()->useSession(sessionId);
 
     status_t err = UNKNOWN_ERROR;
@@ -1563,21 +1547,21 @@
 
 void DrmHal::reportFrameworkMetrics() const
 {
-    std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm"));
-    item->setPkgName(mMetrics.GetAppPackageName().c_str());
+    mediametrics_handle_t item(mediametrics_create("mediadrm"));
+    mediametrics_setUid(item, mMetrics.GetAppUid());
     String8 vendor;
     String8 description;
     status_t result = getPropertyStringInternal(String8("vendor"), vendor);
     if (result != OK) {
         ALOGE("Failed to get vendor from drm plugin: %d", result);
     } else {
-        item->setCString("vendor", vendor.c_str());
+        mediametrics_setCString(item, "vendor", vendor.c_str());
     }
     result = getPropertyStringInternal(String8("description"), description);
     if (result != OK) {
         ALOGE("Failed to get description from drm plugin: %d", result);
     } else {
-        item->setCString("description", description.c_str());
+        mediametrics_setCString(item, "description", description.c_str());
     }
 
     std::string serializedMetrics;
@@ -1588,11 +1572,12 @@
     std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
                                                         serializedMetrics.size());
     if (!b64EncodedMetrics.empty()) {
-        item->setCString("serialized_metrics", b64EncodedMetrics.c_str());
+        mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
     }
-    if (!item->selfrecord()) {
+    if (!mediametrics_selfRecord(item)) {
         ALOGE("Failed to self record framework metrics");
     }
+    mediametrics_delete(item);
 }
 
 void DrmHal::reportPluginMetrics() const
@@ -1606,7 +1591,7 @@
         std::string metricsString = toBase64StringNoPad(metricsVector.array(),
                                                         metricsVector.size());
         status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
-                                                       description, mAppPackageName);
+                                                       description, mMetrics.GetAppUid());
         if (res != OK) {
             ALOGE("Metrics were retrieved but could not be reported: %d", res);
         }
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index 3080802..996fd19 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -29,143 +29,12 @@
 using ::android::String16;
 using ::android::String8;
 using ::android::drm_metrics::DrmFrameworkMetrics;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
 using ::android::hardware::drm::V1_0::EventType;
 using ::android::hardware::drm::V1_2::KeyStatusType;
 using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::os::PersistableBundle;
 
 namespace {
 
-template <typename T> std::string GetAttributeName(T type);
-
-template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
-    static const char *type_names[] = {"USABLE", "EXPIRED",
-                                       "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
-                                       "INTERNAL_ERROR"};
-    if (((size_t)type) > arraysize(type_names)) {
-        return "UNKNOWN_TYPE";
-    }
-    return type_names[(size_t)type];
-}
-
-template <> std::string GetAttributeName<EventType>(EventType type) {
-    static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
-                                       "KEY_EXPIRED", "VENDOR_DEFINED",
-                                       "SESSION_RECLAIMED"};
-    if (((size_t)type) > arraysize(type_names)) {
-        return "UNKNOWN_TYPE";
-    }
-    return type_names[(size_t)type];
-}
-
-template <typename T>
-void ExportCounterMetric(const android::CounterMetric<T> &counter,
-                         PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    std::string success_count_name = counter.metric_name() + ".ok.count";
-    std::string error_count_name = counter.metric_name() + ".error.count";
-    std::vector<int64_t> status_values;
-    counter.ExportValues(
-        [&](const android::status_t status, const int64_t value) {
-            if (status == android::OK) {
-                metrics->putLong(android::String16(success_count_name.c_str()),
-                                 value);
-            } else {
-                int64_t total_errors(0);
-                metrics->getLong(android::String16(error_count_name.c_str()),
-                                 &total_errors);
-                metrics->putLong(android::String16(error_count_name.c_str()),
-                                 total_errors + value);
-                status_values.push_back(status);
-            }
-        });
-    if (!status_values.empty()) {
-        std::string error_list_name = counter.metric_name() + ".error.list";
-        metrics->putLongVector(android::String16(error_list_name.c_str()),
-                               status_values);
-    }
-}
-
-template <typename T>
-void ExportCounterMetricWithAttributeNames(
-    const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    counter.ExportValues([&](const T &attribute, const int64_t value) {
-        std::string name = counter.metric_name() + "." +
-                           GetAttributeName(attribute) + ".count";
-        metrics->putLong(android::String16(name.c_str()), value);
-    });
-}
-
-template <typename T>
-void ExportEventMetric(const android::EventMetric<T> &event,
-                       PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    std::string success_count_name = event.metric_name() + ".ok.count";
-    std::string error_count_name = event.metric_name() + ".error.count";
-    std::string timing_name = event.metric_name() + ".ok.average_time_micros";
-    std::vector<int64_t> status_values;
-    event.ExportValues([&](const android::status_t &status,
-                           const android::EventStatistics &value) {
-        if (status == android::OK) {
-            metrics->putLong(android::String16(success_count_name.c_str()),
-                             value.count);
-            metrics->putLong(android::String16(timing_name.c_str()),
-                             value.mean);
-        } else {
-            int64_t total_errors(0);
-            metrics->getLong(android::String16(error_count_name.c_str()),
-                             &total_errors);
-            metrics->putLong(android::String16(error_count_name.c_str()),
-                             total_errors + value.count);
-            status_values.push_back(status);
-        }
-    });
-    if (!status_values.empty()) {
-        std::string error_list_name = event.metric_name() + ".error.list";
-        metrics->putLongVector(android::String16(error_list_name.c_str()),
-                               status_values);
-    }
-}
-
-void ExportSessionLifespans(
-    const std::map<std::string, std::pair<int64_t, int64_t>> &mSessionLifespans,
-    PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-
-    if (mSessionLifespans.empty()) {
-        return;
-    }
-
-    PersistableBundle startTimesBundle;
-    PersistableBundle endTimesBundle;
-    for (auto it = mSessionLifespans.begin(); it != mSessionLifespans.end();
-         it++) {
-        String16 key(it->first.c_str(), it->first.size());
-        startTimesBundle.putLong(key, it->second.first);
-        endTimesBundle.putLong(key, it->second.second);
-    }
-    metrics->putPersistableBundle(
-        android::String16("drm.mediadrm.session_start_times_ms"),
-        startTimesBundle);
-    metrics->putPersistableBundle(
-        android::String16("drm.mediadrm.session_end_times_ms"), endTimesBundle);
-}
-
 std::string ToHexString(const android::Vector<uint8_t> &sessionId) {
     std::ostringstream out;
     out << std::hex << std::setfill('0');
@@ -175,31 +44,6 @@
     return out.str();
 }
 
-template <typename CT>
-void SetValue(const String16 &name, DrmMetricGroup::ValueType type,
-              const CT &value, PersistableBundle *bundle) {
-    switch (type) {
-    case DrmMetricGroup::ValueType::INT64_TYPE:
-        bundle->putLong(name, value.int64Value);
-        break;
-    case DrmMetricGroup::ValueType::DOUBLE_TYPE:
-        bundle->putDouble(name, value.doubleValue);
-        break;
-    case DrmMetricGroup::ValueType::STRING_TYPE:
-        bundle->putString(name, String16(value.stringValue.c_str()));
-        break;
-    default:
-        ALOGE("Unexpected value type: %hhu", type);
-    }
-}
-
-inline String16 MakeIndexString(unsigned int index) {
-  std::string str("[");
-  str.append(std::to_string(index));
-  str.append("]");
-  return String16(str.c_str());
-}
-
 } // namespace
 
 namespace android {
@@ -237,23 +81,6 @@
     }
 }
 
-void MediaDrmMetrics::Export(PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    ExportCounterMetric(mOpenSessionCounter, metrics);
-    ExportCounterMetric(mCloseSessionCounter, metrics);
-    ExportEventMetric(mGetKeyRequestTimeUs, metrics);
-    ExportEventMetric(mProvideKeyResponseTimeUs, metrics);
-    ExportCounterMetric(mGetProvisionRequestCounter, metrics);
-    ExportCounterMetric(mProvideProvisionResponseCounter, metrics);
-    ExportCounterMetricWithAttributeNames(mKeyStatusChangeCounter, metrics);
-    ExportCounterMetricWithAttributeNames(mEventCounter, metrics);
-    ExportCounterMetric(mGetDeviceUniqueIdCounter, metrics);
-    ExportSessionLifespans(mSessionLifespans, metrics);
-}
-
 status_t MediaDrmMetrics::GetSerializedMetrics(std::string *serializedMetrics) {
 
     if (!serializedMetrics) {
@@ -361,62 +188,14 @@
     return OK;
 }
 
+std::map<std::string, std::pair<int64_t, int64_t>> MediaDrmMetrics::GetSessionLifespans() const {
+  return mSessionLifespans;
+}
+
 int64_t MediaDrmMetrics::GetCurrentTimeMs() {
     struct timeval tv;
     gettimeofday(&tv, NULL);
     return ((int64_t)tv.tv_sec * 1000) + ((int64_t)tv.tv_usec / 1000);
 }
 
-status_t MediaDrmMetrics::HidlMetricsToBundle(
-    const hidl_vec<DrmMetricGroup> &hidlMetricGroups,
-    PersistableBundle *bundleMetricGroups) {
-    if (bundleMetricGroups == nullptr) {
-        return UNEXPECTED_NULL;
-    }
-    if (hidlMetricGroups.size() == 0) {
-        return OK;
-    }
-
-    int groupIndex = 0;
-    std::map<String16, int> indexMap;
-    for (const auto &hidlMetricGroup : hidlMetricGroups) {
-        PersistableBundle bundleMetricGroup;
-        for (const auto &hidlMetric : hidlMetricGroup.metrics) {
-            String16 metricName(hidlMetric.name.c_str());
-            PersistableBundle bundleMetric;
-            // Add metric component values.
-            for (const auto &value : hidlMetric.values) {
-                SetValue(String16(value.componentName.c_str()), value.type,
-                         value, &bundleMetric);
-            }
-            // Set metric attributes.
-            PersistableBundle bundleMetricAttributes;
-            for (const auto &attribute : hidlMetric.attributes) {
-                SetValue(String16(attribute.name.c_str()), attribute.type,
-                         attribute, &bundleMetricAttributes);
-            }
-            // Add attributes to the bundle metric.
-            bundleMetric.putPersistableBundle(String16("attributes"),
-                                              bundleMetricAttributes);
-            // Add one layer of indirection, allowing for repeated metric names.
-            PersistableBundle repeatedMetrics;
-            bundleMetricGroup.getPersistableBundle(metricName,
-                                                   &repeatedMetrics);
-            int index = indexMap[metricName];
-            repeatedMetrics.putPersistableBundle(MakeIndexString(index),
-                                                 bundleMetric);
-            indexMap[metricName] = ++index;
-
-            // Add the bundle metric to the group of metrics.
-            bundleMetricGroup.putPersistableBundle(metricName,
-                                                   repeatedMetrics);
-        }
-        // Add the bundle metric group to the collection of groups.
-        bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
-                                                 bundleMetricGroup);
-    }
-
-    return OK;
-}
-
 } // namespace android
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
new file mode 100644
index 0000000..b47b4ff
--- /dev/null
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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 "DrmMetricsConsumer"
+
+#include <android-base/macros.h>
+#include <mediadrm/DrmMetricsConsumer.h>
+#include <mediadrm/DrmMetrics.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+using ::android::String16;
+using ::android::String8;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_2::KeyStatusType;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+using ::android::os::PersistableBundle;
+
+namespace {
+
+template <typename T> std::string GetAttributeName(T type);
+
+template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
+    static const char *type_names[] = {"USABLE", "EXPIRED",
+                                       "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
+                                       "INTERNAL_ERROR"};
+    if (((size_t)type) > arraysize(type_names)) {
+        return "UNKNOWN_TYPE";
+    }
+    return type_names[(size_t)type];
+}
+
+template <> std::string GetAttributeName<EventType>(EventType type) {
+    static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
+                                       "KEY_EXPIRED", "VENDOR_DEFINED",
+                                       "SESSION_RECLAIMED"};
+    if (((size_t)type) > arraysize(type_names)) {
+        return "UNKNOWN_TYPE";
+    }
+    return type_names[(size_t)type];
+}
+
+template <typename T>
+void ExportCounterMetric(const android::CounterMetric<T> &counter,
+                         PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+    std::string success_count_name = counter.metric_name() + ".ok.count";
+    std::string error_count_name = counter.metric_name() + ".error.count";
+    std::vector<int64_t> status_values;
+    counter.ExportValues(
+        [&](const android::status_t status, const int64_t value) {
+            if (status == android::OK) {
+                metrics->putLong(android::String16(success_count_name.c_str()),
+                                 value);
+            } else {
+                int64_t total_errors(0);
+                metrics->getLong(android::String16(error_count_name.c_str()),
+                                 &total_errors);
+                metrics->putLong(android::String16(error_count_name.c_str()),
+                                 total_errors + value);
+                status_values.push_back(status);
+            }
+        });
+    if (!status_values.empty()) {
+        std::string error_list_name = counter.metric_name() + ".error.list";
+        metrics->putLongVector(android::String16(error_list_name.c_str()),
+                               status_values);
+    }
+}
+
+template <typename T>
+void ExportCounterMetricWithAttributeNames(
+    const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+    counter.ExportValues([&](const T &attribute, const int64_t value) {
+        std::string name = counter.metric_name() + "." +
+                           GetAttributeName(attribute) + ".count";
+        metrics->putLong(android::String16(name.c_str()), value);
+    });
+}
+
+template <typename T>
+void ExportEventMetric(const android::EventMetric<T> &event,
+                       PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+    std::string success_count_name = event.metric_name() + ".ok.count";
+    std::string error_count_name = event.metric_name() + ".error.count";
+    std::string timing_name = event.metric_name() + ".ok.average_time_micros";
+    std::vector<int64_t> status_values;
+    event.ExportValues([&](const android::status_t &status,
+                           const android::EventStatistics &value) {
+        if (status == android::OK) {
+            metrics->putLong(android::String16(success_count_name.c_str()),
+                             value.count);
+            metrics->putLong(android::String16(timing_name.c_str()),
+                             value.mean);
+        } else {
+            int64_t total_errors(0);
+            metrics->getLong(android::String16(error_count_name.c_str()),
+                             &total_errors);
+            metrics->putLong(android::String16(error_count_name.c_str()),
+                             total_errors + value.count);
+            status_values.push_back(status);
+        }
+    });
+    if (!status_values.empty()) {
+        std::string error_list_name = event.metric_name() + ".error.list";
+        metrics->putLongVector(android::String16(error_list_name.c_str()),
+                               status_values);
+    }
+}
+
+void ExportSessionLifespans(
+    const std::map<std::string, std::pair<int64_t, int64_t>> &sessionLifespans,
+    PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+
+    if (sessionLifespans.empty()) {
+        return;
+    }
+
+    PersistableBundle startTimesBundle;
+    PersistableBundle endTimesBundle;
+    for (auto it = sessionLifespans.begin(); it != sessionLifespans.end();
+         it++) {
+        String16 key(it->first.c_str(), it->first.size());
+        startTimesBundle.putLong(key, it->second.first);
+        endTimesBundle.putLong(key, it->second.second);
+    }
+    metrics->putPersistableBundle(
+        android::String16("drm.mediadrm.session_start_times_ms"),
+        startTimesBundle);
+    metrics->putPersistableBundle(
+        android::String16("drm.mediadrm.session_end_times_ms"), endTimesBundle);
+}
+
+template <typename CT>
+void SetValue(const String16 &name, DrmMetricGroup::ValueType type,
+              const CT &value, PersistableBundle *bundle) {
+    switch (type) {
+    case DrmMetricGroup::ValueType::INT64_TYPE:
+        bundle->putLong(name, value.int64Value);
+        break;
+    case DrmMetricGroup::ValueType::DOUBLE_TYPE:
+        bundle->putDouble(name, value.doubleValue);
+        break;
+    case DrmMetricGroup::ValueType::STRING_TYPE:
+        bundle->putString(name, String16(value.stringValue.c_str()));
+        break;
+    default:
+        ALOGE("Unexpected value type: %hhu", type);
+    }
+}
+
+inline String16 MakeIndexString(unsigned int index) {
+  std::string str("[");
+  str.append(std::to_string(index));
+  str.append("]");
+  return String16(str.c_str());
+}
+
+} // namespace
+
+namespace android {
+
+status_t DrmMetricsConsumer::consumeFrameworkMetrics(const MediaDrmMetrics &metrics) {
+    ExportCounterMetric(metrics.mOpenSessionCounter, mBundle);
+    ExportCounterMetric(metrics.mCloseSessionCounter, mBundle);
+    ExportEventMetric(metrics.mGetKeyRequestTimeUs, mBundle);
+    ExportEventMetric(metrics.mProvideKeyResponseTimeUs, mBundle);
+    ExportCounterMetric(metrics.mGetProvisionRequestCounter, mBundle);
+    ExportCounterMetric(metrics.mProvideProvisionResponseCounter, mBundle);
+    ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, mBundle);
+    ExportCounterMetricWithAttributeNames(metrics.mEventCounter, mBundle);
+    ExportCounterMetric(metrics.mGetDeviceUniqueIdCounter, mBundle);
+    ExportSessionLifespans(metrics.GetSessionLifespans(), mBundle);
+    return android::OK;
+}
+
+status_t DrmMetricsConsumer::consumeHidlMetrics(
+        const String8 &vendor,
+        const hidl_vec<DrmMetricGroup> &pluginMetrics) {
+    PersistableBundle pluginBundle;
+    if (DrmMetricsConsumer::HidlMetricsToBundle(
+            pluginMetrics, &pluginBundle) == OK) {
+        mBundle->putPersistableBundle(String16(vendor), pluginBundle);
+    }
+    return android::OK;
+}
+
+status_t DrmMetricsConsumer::HidlMetricsToBundle(
+    const hidl_vec<DrmMetricGroup> &hidlMetricGroups,
+    PersistableBundle *bundleMetricGroups) {
+    if (bundleMetricGroups == nullptr) {
+        return UNEXPECTED_NULL;
+    }
+    if (hidlMetricGroups.size() == 0) {
+        return OK;
+    }
+
+    int groupIndex = 0;
+    std::map<String16, int> indexMap;
+    for (const auto &hidlMetricGroup : hidlMetricGroups) {
+        PersistableBundle bundleMetricGroup;
+        for (const auto &hidlMetric : hidlMetricGroup.metrics) {
+            String16 metricName(hidlMetric.name.c_str());
+            PersistableBundle bundleMetric;
+            // Add metric component values.
+            for (const auto &value : hidlMetric.values) {
+                SetValue(String16(value.componentName.c_str()), value.type,
+                         value, &bundleMetric);
+            }
+            // Set metric attributes.
+            PersistableBundle bundleMetricAttributes;
+            for (const auto &attribute : hidlMetric.attributes) {
+                SetValue(String16(attribute.name.c_str()), attribute.type,
+                         attribute, &bundleMetricAttributes);
+            }
+            // Add attributes to the bundle metric.
+            bundleMetric.putPersistableBundle(String16("attributes"),
+                                              bundleMetricAttributes);
+            // Add one layer of indirection, allowing for repeated metric names.
+            PersistableBundle repeatedMetrics;
+            bundleMetricGroup.getPersistableBundle(metricName,
+                                                   &repeatedMetrics);
+            int index = indexMap[metricName];
+            repeatedMetrics.putPersistableBundle(MakeIndexString(index),
+                                                 bundleMetric);
+            indexMap[metricName] = ++index;
+
+            // Add the bundle metric to the group of metrics.
+            bundleMetricGroup.putPersistableBundle(metricName,
+                                                   repeatedMetrics);
+        }
+        // Add the bundle metric group to the collection of groups.
+        bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
+                                                 bundleMetricGroup);
+    }
+
+    return OK;
+}
+
+} // namespace android
+
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 165a4d6..7a4e1ae 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -18,13 +18,12 @@
 #define LOG_TAG "DrmSessionManager"
 #include <utils/Log.h>
 
-#include <android/media/IResourceManagerClient.h>
-#include <android/media/IResourceManagerService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IProcessInfoService.h>
-#include <binder/IServiceManager.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <aidl/android/media/MediaResourceParcel.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
 #include <cutils/properties.h>
-#include <media/MediaResource.h>
 #include <mediadrm/DrmUtils.h>
 #include <mediadrm/DrmSessionManager.h>
 #include <unistd.h>
@@ -32,10 +31,18 @@
 
 #include <vector>
 
-#include "ResourceManagerService.h"
-
 namespace android {
-using android::binder::Status;
+
+using aidl::android::media::MediaResourceParcel;
+
+namespace {
+void ResourceManagerServiceDied(void* cookie) {
+    auto thiz = static_cast<DrmSessionManager*>(cookie);
+    thiz->binderDied();
+}
+}
+
+using ::ndk::ScopedAStatus;
 
 static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
     String8 sessionIdStr;
@@ -45,34 +52,28 @@
     return sessionIdStr;
 }
 
-static std::vector<uint8_t> toStdVec(const Vector<uint8_t> &vector) {
-    const uint8_t *v = vector.array();
-    std::vector<uint8_t> vec(v, v + vector.size());
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t> &vector) {
+    auto v = reinterpret_cast<const Byte *>(vector.array());
+    std::vector<Byte> vec(v, v + vector.size());
     return vec;
 }
 
-static uint64_t toClientId(const sp<IResourceManagerClient>& drm) {
-    return reinterpret_cast<int64_t>(drm.get());
-}
-
 static std::vector<MediaResourceParcel> toResourceVec(
         const Vector<uint8_t> &sessionId, int64_t value) {
+    using Type = aidl::android::media::MediaResourceType;
+    using SubType = aidl::android::media::MediaResourceSubType;
     std::vector<MediaResourceParcel> resources;
-    resources.push_back(MediaResource::DrmSessionResource(toStdVec(sessionId), value));
+    MediaResourceParcel resource{
+            Type::kDrmSession, SubType::kUnspecifiedSubType,
+            toStdVec<int8_t>(sessionId), value};
+    resources.push_back(resource);
     return resources;
 }
 
-static sp<IResourceManagerService> getResourceManagerService() {
-    if (DrmUtils::UseDrmService()) {
-        // Create ResourceManagerService object in mediadrmserver process
-        return new android::media::ResourceManagerService();
-    }
-    sp<IServiceManager> sm = defaultServiceManager();
-    if (sm == NULL) {
-        return NULL;
-    }
-    sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
-    return interface_cast<IResourceManagerService>(binder);
+static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
+    ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
+    return IResourceManagerService::fromBinder(binder);
 }
 
 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
@@ -88,7 +89,7 @@
 }
 
 sp<DrmSessionManager> DrmSessionManager::Instance() {
-    static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+    auto drmSessionManager = new DrmSessionManager();
     drmSessionManager->init();
     return drmSessionManager;
 }
@@ -97,9 +98,10 @@
     : DrmSessionManager(getResourceManagerService()) {
 }
 
-DrmSessionManager::DrmSessionManager(const sp<IResourceManagerService> &service)
+DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
     : mService(service),
-      mInitialized(false) {
+      mInitialized(false),
+      mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
     if (mService == NULL) {
         ALOGE("Failed to init ResourceManagerService");
     }
@@ -107,7 +109,7 @@
 
 DrmSessionManager::~DrmSessionManager() {
     if (mService != NULL) {
-        IInterface::asBinder(mService)->unlinkToDeath(this);
+        AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
     }
 }
 
@@ -118,13 +120,13 @@
     }
     mInitialized = true;
     if (mService != NULL) {
-        IInterface::asBinder(mService)->linkToDeath(this);
+        AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
     }
 }
 
 void DrmSessionManager::addSession(int pid,
-        const sp<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
-    uid_t uid = IPCThreadState::self()->getCallingUid();
+        const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
+    uid_t uid = AIBinder_getCallingUid();
     ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
             GetSessionIdString(sessionId).string());
 
@@ -133,9 +135,9 @@
         return;
     }
 
-    int64_t clientId = toClientId(drm);
+    static int64_t clientId = 0;
     mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
-    mService->addResource(pid, uid, clientId, drm, toResourceVec(sessionId, INT64_MAX));
+    mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
 }
 
 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
@@ -170,7 +172,7 @@
 
     // unlock early because reclaimResource might callback into removeSession
     mLock.lock();
-    sp<IResourceManagerService> service(mService);
+    std::shared_ptr<IResourceManagerService> service(mService);
     mLock.unlock();
 
     if (service == NULL) {
@@ -181,7 +183,7 @@
     // we rely on IResourceManagerClient to removeSession in reclaimResource
     Vector<uint8_t> dummy;
     bool success;
-    Status status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+    ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
     return status.isOk() && success;
 }
 
@@ -195,10 +197,10 @@
     return mSessionMap.count(toStdVec(sessionId));
 }
 
-void DrmSessionManager::binderDied(const wp<IBinder>& /*who*/) {
+void DrmSessionManager::binderDied() {
     ALOGW("ResourceManagerService died.");
     Mutex::Autolock lock(mLock);
-    mService.clear();
+    mService.reset();
 }
 
 }  // namespace android
diff --git a/drm/libmediadrm/IMediaDrmService.cpp b/drm/libmediadrm/IMediaDrmService.cpp
deleted file mode 100644
index db67c23..0000000
--- a/drm/libmediadrm/IMediaDrmService.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-**
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <mediadrm/ICrypto.h>
-#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/String8.h>
-
-namespace android {
-
-class BpMediaDrmService: public BpInterface<IMediaDrmService>
-{
-public:
-    explicit BpMediaDrmService(const sp<IBinder>& impl)
-        : BpInterface<IMediaDrmService>(impl)
-    {
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaDrmService, "android.media.IMediaDrmService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaDrmService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/drm/libmediadrm/PluginMetricsReporting.cpp b/drm/libmediadrm/PluginMetricsReporting.cpp
index 098f07b..b0abf83 100644
--- a/drm/libmediadrm/PluginMetricsReporting.cpp
+++ b/drm/libmediadrm/PluginMetricsReporting.cpp
@@ -21,7 +21,7 @@
 
 #include <inttypes.h>
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetrics.h>
 #include <utils/Log.h>
 
 
@@ -33,18 +33,18 @@
 
 status_t reportVendorMetrics(const std::string& metrics,
                              const String8& name,
-                             const String8& appPackageName) {
-    std::unique_ptr<MediaAnalyticsItem> analyticsItem(MediaAnalyticsItem::create(name.c_str()));
-    std::string app_package_name(appPackageName.c_str(), appPackageName.size());
-    analyticsItem->setPkgName(app_package_name);
+                             uid_t appUid) {
+    mediametrics_handle_t analyticsItem(mediametrics_create(name.c_str()));
+    mediametrics_setUid(analyticsItem, appUid);
     if (metrics.size() > 0) {
-        analyticsItem->setCString(kSerializedMetricsField, metrics.c_str());
+        mediametrics_setCString(analyticsItem, kSerializedMetricsField, metrics.c_str());
     }
 
-    if (!analyticsItem->selfrecord()) {
+    if (!mediametrics_selfRecord(analyticsItem)) {
       ALOGE("%s: selfrecord() returned false", __func__);
     }
 
+    mediametrics_delete(analyticsItem);
     return OK;
 }
 
@@ -67,13 +67,13 @@
 status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
                                 const String8& vendor,
                                 const String8& description,
-                                const String8& appPackageName) {
+                                uid_t appUid) {
 
     String8 name = String8::format("drm.vendor.%s.%s",
                                    sanitize(vendor).c_str(),
                                    sanitize(description).c_str());
 
-    return reportVendorMetrics(b64EncodedMetrics, name, appPackageName);
+    return reportVendorMetrics(b64EncodedMetrics, name, appUid);
 }
 
 }  // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 865ca38..c9fda67 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -31,6 +31,9 @@
 using drm::V1_0::ICryptoFactory;
 using drm::V1_0::ICryptoPlugin;
 using drm::V1_0::SharedBuffer;
+using drm::V1_0::DestinationBuffer;
+
+using ::android::hardware::HidlMemory;
 
 class IMemoryHeap;
 
@@ -58,12 +61,12 @@
 
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const ICrypto::SourceBuffer &source, size_t offset,
+            const ::SharedBuffer &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            const ICrypto::DestinationBuffer &destination,
+            const ::DestinationBuffer &destination,
             AString *errorDetailMsg);
 
-    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) {
+    virtual int32_t setHeap(const sp<HidlMemory>& heap) {
         return setHeapBase(heap);
     }
     virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
@@ -83,30 +86,17 @@
      */
     status_t mInitCheck;
 
-    struct HeapBase {
-        HeapBase() : mBufferId(0), mSize(0) {}
-        HeapBase(uint32_t bufferId, size_t size) :
-            mBufferId(bufferId), mSize(size) {}
-
-        uint32_t getBufferId() const {return mBufferId;}
-        size_t getSize() const {return mSize;}
-
-    private:
-        uint32_t mBufferId;
-        size_t mSize;
-    };
-
-    KeyedVector<int32_t, HeapBase> mHeapBases;
+    KeyedVector<int32_t, size_t> mHeapSizes;
     int32_t mHeapSeqNum;
 
     Vector<sp<ICryptoFactory>> makeCryptoFactories();
     sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
             const uint8_t uuid[16], const void *initData, size_t size);
 
-    int32_t setHeapBase(const sp<IMemoryHeap>& heap);
+    int32_t setHeapBase(const sp<HidlMemory>& heap);
     void clearHeapBase(int32_t seqNum);
 
-    status_t toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer);
+    status_t checkSharedBuffer(const ::SharedBuffer& buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
 };
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index 97dd920..6818dd7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -26,11 +26,11 @@
 #include <android/hardware/drm/1.2/IDrmPlugin.h>
 #include <android/hardware/drm/1.2/IDrmPluginListener.h>
 
-#include <media/MediaAnalyticsItem.h>
 #include <mediadrm/DrmMetrics.h>
 #include <mediadrm/DrmSessionManager.h>
 #include <mediadrm/IDrm.h>
 #include <mediadrm/IDrmClient.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
 #include <utils/threads.h>
 
 namespace drm = ::android::hardware::drm;
@@ -137,7 +137,7 @@
     virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
     virtual status_t setPropertyByteArray(String8 const &name,
                                           Vector<uint8_t> const &value ) const;
-    virtual status_t getMetrics(os::PersistableBundle *metrics);
+    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
 
     virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
                                         String8 const &algorithm);
@@ -207,7 +207,7 @@
     // Mutable to allow modification within GetPropertyByteArray.
     mutable MediaDrmMetrics mMetrics;
 
-    Vector<sp<DrmSessionClient>> mOpenSessions;
+    std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
     void closeOpenSessions();
     void cleanup();
 
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetrics.h b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
index 6f132bf..100b8f7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetrics.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
@@ -25,6 +25,7 @@
 #include <binder/PersistableBundle.h>
 #include <media/CounterMetric.h>
 #include <media/EventMetric.h>
+#include <sys/types.h>
 
 namespace android {
 
@@ -71,8 +72,8 @@
   void SetAppPackageName(const String8& appPackageName) { mAppPackageName = appPackageName; }
   const String8& GetAppPackageName() { return mAppPackageName; }
 
-  // Export the metrics to a PersistableBundle.
-  void Export(os::PersistableBundle* metricsBundle);
+  void SetAppUid(uid_t appUid) { mAppUid = appUid; }
+  uid_t GetAppUid() const { return mAppUid; }
 
   // Get the serialized metrics. Metrics are formatted as a serialized
   // DrmFrameworkMetrics proto. If there is a failure serializing the metrics,
@@ -80,46 +81,8 @@
   // caller and must not be null.
   status_t GetSerializedMetrics(std::string* serializedMetrics);
 
-  // Converts the DRM plugin metrics to a PersistableBundle. All of the metrics
-  // found in |pluginMetrics| are added to the |metricsBundle| parameter.
-  // |pluginBundle| is owned by the caller and must not be null.
-  //
-  // Each item in the pluginMetrics vector is added as a new PersistableBundle. E.g.
-  // DrmMetricGroup {
-  //   metrics[0] {
-  //     name: "buf_copy"
-  //     attributes[0] {
-  //       name: "size"
-  //       type: INT64_TYPE
-  //       int64Value: 1024
-  //     }
-  //     values[0] {
-  //       componentName: "operation_count"
-  //       type: INT64_TYPE
-  //       int64Value: 75
-  //     }
-  //     values[1] {
-  //       component_name: "average_time_seconds"
-  //       type: DOUBLE_TYPE
-  //       doubleValue: 0.00000042
-  //     }
-  //   }
-  // }
-  //
-  // becomes
-  //
-  // metricsBundle {
-  //   "0": (PersistableBundle) {
-  //     "attributes" : (PersistableBundle) {
-  //       "size" : (int64) 1024
-  //     }
-  //     "operation_count" : (int64) 75
-  //     "average_time_seconds" : (double) 0.00000042
-  //   }
-  //
-  static status_t HidlMetricsToBundle(
-          const hardware::hidl_vec<hardware::drm::V1_1::DrmMetricGroup>& pluginMetrics,
-          os::PersistableBundle* metricsBundle);
+  // Get copy of session lifetimes.
+  std::map<std::string, std::pair<int64_t, int64_t>> GetSessionLifespans() const;
 
  protected:
   // This is visible for testing only.
@@ -131,6 +94,7 @@
   std::map<std::string, std::pair<int64_t, int64_t>> mSessionLifespans;
 
   String8 mAppPackageName;
+  uid_t mAppUid{~0u};
 };
 
 }  // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsConsumer.h b/drm/libmediadrm/include/mediadrm/DrmMetricsConsumer.h
new file mode 100644
index 0000000..bbbf4b5
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsConsumer.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/PersistableBundle.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/Errors.h>
+
+#ifndef ANDROID_METRICSCONSUMER_H_
+
+#define ANDROID_METRICSCONSUMER_H_
+
+namespace android {
+
+/**
+ * IDrmMetricsConsumer which saves IDrm/ICrypto metrics into a PersistableBundle.
+ *
+ * Example usage:
+ *
+ *   PersistableBundle bundle;
+ *   DrmMetricsConsumer consumer(&bundle);
+ *   drm->exportMetrics(&consumer);
+ *   crypto->exportMetrics(&consumer);
+ *   // bundle now contains metrics from drm/crypto.
+ *
+ */
+struct DrmMetricsConsumer : public IDrmMetricsConsumer {
+    DrmMetricsConsumer(os::PersistableBundle *bundle) : mBundle(bundle) {}
+
+    status_t consumeFrameworkMetrics(const MediaDrmMetrics &) override;
+
+    status_t consumeHidlMetrics(
+            const String8 &/*vendor*/,
+            const hidl_vec<DrmMetricGroup> &/*pluginMetrics*/) override;
+
+    // Converts the DRM plugin metrics to a PersistableBundle. All of the metrics
+    // found in |pluginMetrics| are added to the |metricsBundle| parameter.
+    // |pluginBundle| is owned by the caller and must not be null.
+    //
+    // Each item in the pluginMetrics vector is added as a new PersistableBundle. E.g.
+    // DrmMetricGroup {
+    //   metrics[0] {
+    //     name: "buf_copy"
+    //     attributes[0] {
+    //       name: "size"
+    //       type: INT64_TYPE
+    //       int64Value: 1024
+    //     }
+    //     values[0] {
+    //       componentName: "operation_count"
+    //       type: INT64_TYPE
+    //       int64Value: 75
+    //     }
+    //     values[1] {
+    //       component_name: "average_time_seconds"
+    //       type: DOUBLE_TYPE
+    //       doubleValue: 0.00000042
+    //     }
+    //   }
+    // }
+    //
+    // becomes
+    //
+    // metricsBundle {
+    //   "0": (PersistableBundle) {
+    //     "attributes" : (PersistableBundle) {
+    //       "size" : (int64) 1024
+    //     }
+    //     "operation_count" : (int64) 75
+    //     "average_time_seconds" : (double) 0.00000042
+    //   }
+    //
+    static status_t HidlMetricsToBundle(
+            const hardware::hidl_vec<hardware::drm::V1_1::DrmMetricGroup>& pluginMetrics,
+            os::PersistableBundle* metricsBundle);
+
+private:
+    os::PersistableBundle *mBundle;
+    DISALLOW_EVIL_CONSTRUCTORS(DrmMetricsConsumer);
+};
+
+}  // namespace android
+
+#endif // ANDROID_METRICSCONSUMER_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
index 3258f7a..9e43504 100644
--- a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
+++ b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
@@ -18,7 +18,9 @@
 
 #define DRM_SESSION_MANAGER_H_
 
-#include <binder/IBinder.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <android/binder_auto_utils.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/RefBase.h>
 #include <utils/KeyedVector.h>
@@ -26,6 +28,7 @@
 #include <utils/Vector.h>
 
 #include <map>
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -33,12 +36,8 @@
 
 class DrmSessionManagerTest;
 
-namespace media {
-class IResourceManagerClient;
-class IResourceManagerService;
-}
-using android::media::IResourceManagerClient;
-using android::media::IResourceManagerService;
+using aidl::android::media::IResourceManagerClient;
+using aidl::android::media::IResourceManagerService;
 
 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
 
@@ -50,13 +49,15 @@
 
 typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap;
 
-struct DrmSessionManager : public IBinder::DeathRecipient {
+struct DrmSessionManager : public RefBase {
     static sp<DrmSessionManager> Instance();
 
     DrmSessionManager();
-    explicit DrmSessionManager(const sp<IResourceManagerService> &service);
+    explicit DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service);
 
-    void addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t>& sessionId);
+    void addSession(int pid,
+            const std::shared_ptr<IResourceManagerClient>& drm,
+            const Vector<uint8_t>& sessionId);
     void useSession(const Vector<uint8_t>& sessionId);
     void removeSession(const Vector<uint8_t>& sessionId);
     bool reclaimSession(int callingPid);
@@ -66,7 +67,7 @@
     bool containsSession(const Vector<uint8_t>& sessionId) const;
 
     // implements DeathRecipient
-    virtual void binderDied(const wp<IBinder>& /*who*/);
+    void binderDied();
 
 protected:
     virtual ~DrmSessionManager();
@@ -74,10 +75,11 @@
 private:
     void init();
 
-    sp<IResourceManagerService> mService;
+    std::shared_ptr<IResourceManagerService> mService;
     mutable Mutex mLock;
     SessionInfoMap mSessionMap;
     bool mInitialized;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
 
     DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
 };
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index db79008..48a7170 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -18,8 +18,8 @@
 #include <binder/PersistableBundle.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/drm/DrmAPI.h>
-#include <media/MediaAnalyticsItem.h>
 #include <mediadrm/IDrmClient.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
 
 #ifndef ANDROID_IDRM_H_
 
@@ -108,7 +108,7 @@
     virtual status_t setPropertyByteArray(String8 const &name,
                                           Vector<uint8_t> const &value) const = 0;
 
-    virtual status_t getMetrics(os::PersistableBundle *metrics) = 0;
+    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
 
     virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
                                         String8 const &algorithm) = 0;
diff --git a/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h b/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h
new file mode 100644
index 0000000..aef35c3
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/drm/1.1/types.h>
+#include <hidl/HidlSupport.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#ifndef ANDROID_IDRMMETRICSCONSUMER_H_
+
+#define ANDROID_IDRMMETRICSCONSUMER_H_
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+
+namespace android {
+
+class MediaDrmMetrics;
+class String8;
+
+/**
+ * Interface to consume metrics produced by the IDrm/ICrypto
+ *
+ * To use with IDrm:
+ *   drm->exportMetrics(&consumer);
+ *
+ * IDrmMetricsConsumer::consumeFrameworkMetrics &
+ * IDrmMetricsConsumer::consumeHidlMetrics implementations
+ * would each be invoked once per call to IDrm::exportMetrics.
+ * |consumeFrameworkMetrics| would be called for plugin-agnostic
+ * framework metrics; |consumeHidlMetrics| would be called for
+ * plugin specific metrics.
+ *
+ * ----------------------------------------
+ *
+ * To use with ICrypto:
+ *   crypto->exportMetrics(&consumer);
+ *
+ * IDrmMetricsConsumer::consumeHidlMetrics implementation
+ * would each be invoked once per call to ICrypto::exportMetrics.
+ * ICrypto metrics are plugin agnostic.
+ *
+ * ----------------------------------------
+ *
+ * For an example implementation of IDrmMetricsConsumer, please
+ * see DrmMetricsConsumer. DrmMetricsConsumer consumes IDrm/ICrypto
+ * metrics and saves the metrics to a PersistableBundle.
+ *
+ */
+struct IDrmMetricsConsumer : public RefBase {
+
+    virtual ~IDrmMetricsConsumer() {}
+
+    /**
+     * Consume framework (plugin agnostic) MediaDrmMetrics
+     */
+    virtual status_t consumeFrameworkMetrics(const MediaDrmMetrics &) = 0;
+
+    /**
+     * Consume list of DrmMetricGroup with optional Drm vendor name
+     */
+    virtual status_t consumeHidlMetrics(
+            const String8 &vendor,
+            const hidl_vec<DrmMetricGroup> &pluginMetrics) = 0;
+
+protected:
+    IDrmMetricsConsumer() {}
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(IDrmMetricsConsumer);
+};
+
+}  // namespace android
+
+#endif // ANDROID_IDRMMETRICSCONSUMER_H_
diff --git a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h b/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
deleted file mode 100644
index 715e0e4..0000000
--- a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
+++ /dev/null
@@ -1,50 +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.
- */
-
-#ifndef ANDROID_IMEDIADRMSERVICE_H
-#define ANDROID_IMEDIADRMSERVICE_H
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-struct IDrm;
-
-class IMediaDrmService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(MediaDrmService);
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaDrmService: public BnInterface<IMediaDrmService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIADRMSERVICE_H
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 48a0c44..df980ae 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -25,10 +25,23 @@
 #define ANDROID_ICRYPTO_H_
 
 namespace android {
+namespace hardware {
+class HidlMemory;
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+struct DestinationBuffer;
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::SharedBuffer;
+
+namespace android {
 
 struct AString;
-class IMemory;
-class IMemoryHeap;
 
 struct ICrypto : public RefBase {
 
@@ -50,27 +63,16 @@
 
     virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
 
-    struct SourceBuffer {
-        sp<IMemory> mSharedMemory;
-        int32_t mHeapSeqNum;
-    };
-
     enum DestinationType {
         kDestinationTypeSharedMemory, // non-secure
         kDestinationTypeNativeHandle  // secure
     };
 
-    struct DestinationBuffer {
-        DestinationType mType;
-        native_handle_t *mHandle;
-        sp<IMemory> mSharedMemory;
-    };
-
-    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
-            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const SourceBuffer &source, size_t offset,
-            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
+    virtual ssize_t decrypt(const uint8_t /*key*/[16], const uint8_t /*iv*/[16],
+            CryptoPlugin::Mode /*mode*/, const CryptoPlugin::Pattern &/*pattern*/,
+            const drm::V1_0::SharedBuffer &/*source*/, size_t /*offset*/,
+            const CryptoPlugin::SubSample * /*subSamples*/, size_t /*numSubSamples*/,
+            const drm::V1_0::DestinationBuffer &/*destination*/, AString * /*errorDetailMsg*/) = 0;
 
     /**
      * Declare the heap that the shared memory source buffers passed
@@ -78,7 +80,7 @@
      * that subsequent decrypt calls can use to refer to the heap,
      * with -1 indicating failure.
      */
-    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) = 0;
+    virtual int32_t setHeap(const sp<hardware::HidlMemory>& heap) = 0;
     virtual void unsetHeap(int32_t seqNum) = 0;
 
 protected:
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
index 2e39943..7471e05 100644
--- a/drm/libmediadrm/tests/Android.bp
+++ b/drm/libmediadrm/tests/Android.bp
@@ -24,6 +24,8 @@
       "libbinder",
       "libhidlbase",
       "liblog",
+      "libmediadrm",
+      "libmediadrmmetrics_consumer",
       "libmediadrmmetrics_full",
       "libmediametrics",
       "libprotobuf-cpp-full",
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index 5c8a1b0..f362d60 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "DrmMetricsTest"
 #include "mediadrm/DrmMetrics.h"
+#include "mediadrm/DrmMetricsConsumer.h"
 
 #include <android/hardware/drm/1.0/types.h>
 #include <android/hardware/drm/1.1/types.h>
@@ -58,8 +59,9 @@
 TEST_F(MediaDrmMetricsTest, EmptySuccess) {
   MediaDrmMetrics metrics;
   PersistableBundle bundle;
+  DrmMetricsConsumer consumer(&bundle);
 
-  metrics.Export(&bundle);
+  consumer.consumeFrameworkMetrics(metrics);
   EXPECT_TRUE(bundle.empty());
 }
 
@@ -85,8 +87,9 @@
   metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
 
   PersistableBundle bundle;
+  DrmMetricsConsumer consumer(&bundle);
 
-  metrics.Export(&bundle);
+  consumer.consumeFrameworkMetrics(metrics);
   EXPECT_EQ(11U, bundle.size());
 
   // Verify the list of pairs of int64 metrics.
@@ -174,7 +177,8 @@
   metrics.SetSessionEnd(sessionId1);
 
   PersistableBundle bundle;
-  metrics.Export(&bundle);
+  DrmMetricsConsumer consumer(&bundle);
+  consumer.consumeFrameworkMetrics(metrics);
   EXPECT_EQ(35U, bundle.size());
 
   // Verify the list of pairs of int64 metrics.
@@ -421,7 +425,7 @@
   hidl_vec<DrmMetricGroup> hidlMetricGroups;
   PersistableBundle bundleMetricGroups;
 
-  ASSERT_EQ(OK, MediaDrmMetrics::HidlMetricsToBundle(hidlMetricGroups, &bundleMetricGroups));
+  ASSERT_EQ(OK, DrmMetricsConsumer::HidlMetricsToBundle(hidlMetricGroups, &bundleMetricGroups));
   ASSERT_EQ(0U, bundleMetricGroups.size());
 }
 
@@ -441,7 +445,7 @@
           } } };
 
   PersistableBundle bundleMetricGroups;
-  ASSERT_EQ(OK, MediaDrmMetrics::HidlMetricsToBundle(hidl_vec<DrmMetricGroup>({hidlMetricGroup}),
+  ASSERT_EQ(OK, DrmMetricsConsumer::HidlMetricsToBundle(hidl_vec<DrmMetricGroup>({hidlMetricGroup}),
                                                      &bundleMetricGroups));
   ASSERT_EQ(1U, bundleMetricGroups.size());
   PersistableBundle bundleMetricGroup;
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index b41c271..e3d419c 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -40,7 +40,7 @@
 namespace {
 
 constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
-
+constexpr uint32_t kMinOutBufferSize = 524288;
 void ParseGop(
         const C2StreamGopTuning::output &gop,
         uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
@@ -440,8 +440,7 @@
       mSignalledError(false),
       mCodecCtx(nullptr),
       mOutBlock(nullptr),
-      // TODO: output buffer size
-      mOutBufferSize(524288) {
+      mOutBufferSize(kMinOutBufferSize) {
 
     // If dump is enabled, then open create an empty file
     GENERATE_FILE_NAMES();
@@ -951,6 +950,9 @@
 
     mStride = width;
 
+    // Assume worst case output buffer size to be equal to number of bytes in input
+    mOutBufferSize = std::max(width * height * 3 / 2, kMinOutBufferSize);
+
     // TODO
     mIvVideoColorFormat = IV_YUV_420P;
 
diff --git a/media/codec2/hidl/services/vendor.cpp b/media/codec2/hidl/services/vendor.cpp
index 65bb6f7..81bffeb 100644
--- a/media/codec2/hidl/services/vendor.cpp
+++ b/media/codec2/hidl/services/vendor.cpp
@@ -23,7 +23,9 @@
 #include <hidl/HidlTransportSupport.h>
 #include <minijail.h>
 
+#include <util/C2InterfaceHelper.h>
 #include <C2Component.h>
+#include <C2Config.h>
 
 // This is the absolute on-device path of the prebuild_etc module
 // "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
@@ -37,11 +39,14 @@
         "/vendor/etc/seccomp_policy/"
         "android.hardware.media.c2@1.1-extended-seccomp-policy";
 
-class DummyC2Store : public C2ComponentStore {
+class StoreImpl : public C2ComponentStore {
 public:
-    DummyC2Store() = default;
+    StoreImpl()
+        : mReflectorHelper(std::make_shared<C2ReflectorHelper>()),
+          mInterface(mReflectorHelper) {
+    }
 
-    virtual ~DummyC2Store() override = default;
+    virtual ~StoreImpl() override = default;
 
     virtual C2String getName() const override {
         return "default";
@@ -71,31 +76,69 @@
     }
 
     virtual c2_status_t query_sm(
-        const std::vector<C2Param*>& /* stackParams */,
-        const std::vector<C2Param::Index>& /* heapParamIndices */,
-        std::vector<std::unique_ptr<C2Param>>* const /* heapParams */) const override {
-        return C2_OMITTED;
+        const std::vector<C2Param*>& stackParams,
+        const std::vector<C2Param::Index>& heapParamIndices,
+        std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
+        return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
     }
 
     virtual c2_status_t config_sm(
-            const std::vector<C2Param*>& /* params */,
-            std::vector<std::unique_ptr<C2SettingResult>>* const /* failures */) override {
-        return C2_OMITTED;
+            const std::vector<C2Param*>& params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
+        return mInterface.config(params, C2_MAY_BLOCK, failures);
     }
 
     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override {
-        return nullptr;
+        return mReflectorHelper;
     }
 
     virtual c2_status_t querySupportedParams_nb(
-            std::vector<std::shared_ptr<C2ParamDescriptor>>* const /* params */) const override {
-        return C2_OMITTED;
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override {
+        return mInterface.querySupportedParams(params);
     }
 
     virtual c2_status_t querySupportedValues_sm(
-            std::vector<C2FieldSupportedValuesQuery>& /* fields */) const override {
-        return C2_OMITTED;
+            std::vector<C2FieldSupportedValuesQuery>& fields) const override {
+        return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
     }
+
+private:
+    class Interface : public C2InterfaceHelper {
+    public:
+        Interface(const std::shared_ptr<C2ReflectorHelper> &helper)
+            : C2InterfaceHelper(helper) {
+            setDerivedInstance(this);
+
+            addParameter(
+                DefineParam(mIonUsageInfo, "ion-usage")
+                .withDefault(new C2StoreIonUsageInfo())
+                .withFields({
+                    C2F(mIonUsageInfo, usage).flags(
+                            {C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
+                    C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
+                    C2F(mIonUsageInfo, heapMask).any(),
+                    C2F(mIonUsageInfo, allocFlags).flags({}),
+                    C2F(mIonUsageInfo, minAlignment).equalTo(0)
+                })
+                .withSetter(SetIonUsage)
+                .build());
+        }
+
+        virtual ~Interface() = default;
+
+    private:
+        static C2R SetIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
+            // Vendor's TODO: put appropriate mapping logic
+            me.set().heapMask = ~0;
+            me.set().allocFlags = 0;
+            me.set().minAlignment = 0;
+            return C2R::Ok();
+        }
+
+        std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
+    };
+    std::shared_ptr<C2ReflectorHelper> mReflectorHelper;
+    Interface mInterface;
 };
 
 int main(int /* argc */, char** /* argv */) {
@@ -124,7 +167,7 @@
         //         /* implementation of C2ComponentStore */);
         LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
         store = new utils::ComponentStore(
-                std::make_shared<DummyC2Store>());
+                std::make_shared<StoreImpl>());
 
         if (store == nullptr) {
             LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index e174751..59ac94b 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -27,6 +27,7 @@
 
     shared_libs: [
         "android.hardware.cas.native@1.0",
+        "android.hardware.drm@1.0",
         "android.hardware.media.c2@1.0",
         "android.hardware.media.omx@1.0",
         "libbase",
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index c78cdc1..31e5406 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1524,7 +1524,9 @@
 
     {
         Mutexed<State>::Locked state(mState);
-        state->set(FLUSHED);
+        if (state->get() == FLUSHING) {
+            state->set(FLUSHED);
+        }
     }
     mCallback->onFlushCompleted();
 }
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index d61b751..7b8dac5 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -27,10 +27,12 @@
 #include <C2Debug.h>
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
 #include <android-base/stringprintf.h>
 #include <binder/MemoryDealer.h>
 #include <cutils/properties.h>
 #include <gui/Surface.h>
+#include <hidlmemory/FrameworkUtils.h>
 #include <media/openmax/OMX_Core.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALookup.h>
@@ -52,10 +54,14 @@
 using hardware::hidl_handle;
 using hardware::hidl_string;
 using hardware::hidl_vec;
+using hardware::fromHeap;
+using hardware::HidlMemory;
+
 using namespace hardware::cas::V1_0;
 using namespace hardware::cas::native::V1_0;
 
 using CasStatus = hardware::cas::V1_0::Status;
+using DrmBufferType = hardware::drm::V1_0::BufferType;
 
 namespace {
 
@@ -431,15 +437,16 @@
     ssize_t result = -1;
     ssize_t codecDataOffset = 0;
     if (mCrypto != nullptr) {
-        ICrypto::DestinationBuffer destination;
+        hardware::drm::V1_0::DestinationBuffer destination;
         if (secure) {
-            destination.mType = ICrypto::kDestinationTypeNativeHandle;
-            destination.mHandle = encryptedBuffer->handle();
+            destination.type = DrmBufferType::NATIVE_HANDLE;
+            destination.secureMemory = hidl_handle(encryptedBuffer->handle());
         } else {
-            destination.mType = ICrypto::kDestinationTypeSharedMemory;
-            destination.mSharedMemory = mDecryptDestination;
+            destination.type = DrmBufferType::SHARED_MEMORY;
+            IMemoryToSharedBuffer(
+                    mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
         }
-        ICrypto::SourceBuffer source;
+        hardware::drm::V1_0::SharedBuffer source;
         encryptedBuffer->fillSourceBuffer(&source);
         result = mCrypto->decrypt(
                 key, iv, mode, pattern, source, buffer->offset(),
@@ -447,7 +454,7 @@
         if (result < 0) {
             return result;
         }
-        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+        if (destination.type == DrmBufferType::SHARED_MEMORY) {
             encryptedBuffer->copyDecryptedContent(mDecryptDestination, result);
         }
     } else {
@@ -919,7 +926,8 @@
                     mDecryptDestination = mDealer->allocate((size_t)capacity);
                 }
                 if (mCrypto != nullptr && mHeapSeqNum < 0) {
-                    mHeapSeqNum = mCrypto->setHeap(mDealer->getMemoryHeap());
+                    sp<HidlMemory> heap = fromHeap(mDealer->getMemoryHeap());
+                    mHeapSeqNum = mCrypto->setHeap(heap);
                 } else {
                     mHeapSeqNum = -1;
                 }
@@ -1662,6 +1670,14 @@
     mMetaMode = mode;
 }
 
+void CCodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
+    mCrypto = crypto;
+}
+
+void CCodecBufferChannel::setDescrambler(const sp<IDescrambler> &descrambler) {
+    mDescrambler = descrambler;
+}
+
 status_t toStatusT(c2_status_t c2s, c2_operation_t c2op) {
     // C2_OK is always translated to OK.
     if (c2s == C2_OK) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index c0fa138..82fec18 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -56,6 +56,9 @@
     virtual ~CCodecBufferChannel();
 
     // BufferChannelBase interface
+    void setCrypto(const sp<ICrypto> &crypto) override;
+    void setDescrambler(const sp<IDescrambler> &descrambler) override;
+
     virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
     virtual status_t queueSecureInputBuffer(
             const sp<MediaCodecBuffer> &buffer,
@@ -318,6 +321,9 @@
     std::atomic_bool mInputMetEos;
     std::once_flag mRenderWarningFlag;
 
+    sp<ICrypto> mCrypto;
+    sp<IDescrambler> mDescrambler;
+
     inline bool hasCryptoOrDescrambler() {
         return mCrypto != nullptr || mDescrambler != nullptr;
     }
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index b339a92..b6d18e2 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -20,6 +20,7 @@
 
 #include <hidlmemory/FrameworkUtils.h>
 #include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/CodecBase.h>
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -779,9 +780,8 @@
 }
 
 void EncryptedLinearBlockBuffer::fillSourceBuffer(
-        ICrypto::SourceBuffer *source) {
-    source->mSharedMemory = mMemory;
-    source->mHeapSeqNum = mHeapSeqNum;
+        hardware::drm::V1_0::SharedBuffer *source) {
+    BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
 }
 
 void EncryptedLinearBlockBuffer::fillSourceBuffer(
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 6f87101..9291c52 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -21,6 +21,7 @@
 #include <C2Buffer.h>
 
 #include <android/hardware/cas/native/1.0/types.h>
+#include <android/hardware/drm/1.0/types.h>
 #include <binder/IMemory.h>
 #include <media/hardware/VideoAPI.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -361,7 +362,8 @@
      *
      * \param source  source buffer structure to fill.
      */
-    void fillSourceBuffer(ICrypto::SourceBuffer *source);
+    void fillSourceBuffer(
+            hardware::drm::V1_0::SharedBuffer *source);
     void fillSourceBuffer(
             hardware::cas::native::V1_0::SharedBuffer *source);
 
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 4c529a6..e0b3939 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -16,6 +16,7 @@
     vendor_available: true,
 
     srcs: [
+        "C2AllocatorBlob.cpp",
         "C2AllocatorIon.cpp",
         "C2AllocatorGralloc.cpp",
         "C2Buffer.cpp",
diff --git a/media/codec2/vndk/C2AllocatorBlob.cpp b/media/codec2/vndk/C2AllocatorBlob.cpp
new file mode 100644
index 0000000..50c9e59
--- /dev/null
+++ b/media/codec2/vndk/C2AllocatorBlob.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "C2AllocatorBlob"
+
+#include <C2AllocatorBlob.h>
+#include <C2PlatformSupport.h>
+
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+
+constexpr uint32_t kLinearBufferHeight = 1u;
+constexpr uint32_t kLinearBufferFormat = static_cast<uint32_t>(PixelFormat::BLOB);
+
+namespace {
+
+c2_status_t GetCapacityFromHandle(const C2Handle* const grallocHandle, size_t* capacity) {
+    uint32_t width, height, format, stride, generation, igbp_slot;
+    uint64_t usage, igbp_id;
+    _UnwrapNativeCodec2GrallocMetadata(grallocHandle, &width, &height, &format, &usage, &stride,
+                                       &generation, &igbp_id, &igbp_slot);
+
+    if (height != kLinearBufferHeight || format != kLinearBufferFormat) {
+        return C2_BAD_VALUE;
+    }
+    *capacity = width;
+    return C2_OK;
+}
+
+}  // namespace
+
+// C2AllocationBlob is a wrapper for C2AllocationGralloc allocated by C2AllocatorGralloc.
+// C2AllocationBlob::handle() delegates to the backed C2AllocationGralloc::handle().
+class C2AllocationBlob : public C2LinearAllocation {
+public:
+    C2AllocationBlob(std::shared_ptr<C2GraphicAllocation> graphicAllocation, size_t capacity,
+                     C2Allocator::id_t allocatorId);
+    ~C2AllocationBlob() override;
+    c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence* fence,
+                    void** addr /* nonnull */) override;
+    c2_status_t unmap(void* addr, size_t size, C2Fence* fenceFd) override;
+
+    id_t getAllocatorId() const override { return mAllocatorId; }
+    const C2Handle* handle() const override { return mGraphicAllocation->handle(); }
+    bool equals(const std::shared_ptr<C2LinearAllocation>& other) const override {
+        return other && other->handle() == handle();
+    }
+
+private:
+    const std::shared_ptr<C2GraphicAllocation> mGraphicAllocation;
+    const C2Allocator::id_t mAllocatorId;
+};
+
+C2AllocationBlob::C2AllocationBlob(
+        std::shared_ptr<C2GraphicAllocation> graphicAllocation, size_t capacity,
+        C2Allocator::id_t allocatorId)
+      : C2LinearAllocation(capacity),
+        mGraphicAllocation(std::move(graphicAllocation)),
+        mAllocatorId(allocatorId) {}
+
+C2AllocationBlob::~C2AllocationBlob() {}
+
+c2_status_t C2AllocationBlob::map(size_t offset, size_t size, C2MemoryUsage usage,
+                                  C2Fence* fence, void** addr /* nonnull */) {
+    C2PlanarLayout layout;
+    C2Rect rect = C2Rect(size, kLinearBufferHeight).at(offset, 0u);
+    return mGraphicAllocation->map(rect, usage, fence, &layout, reinterpret_cast<uint8_t**>(addr));
+}
+
+c2_status_t C2AllocationBlob::unmap(void* addr, size_t size, C2Fence* fenceFd) {
+    C2Rect rect(size, kLinearBufferHeight);
+    return mGraphicAllocation->unmap(reinterpret_cast<uint8_t**>(&addr), rect, fenceFd);
+}
+
+/* ====================================== BLOB ALLOCATOR ====================================== */
+C2AllocatorBlob::C2AllocatorBlob(id_t id) {
+    C2MemoryUsage minUsage = {0, 0};
+    C2MemoryUsage maxUsage = {C2MemoryUsage::CPU_READ | C2MemoryUsage::READ_PROTECTED,
+                              C2MemoryUsage::CPU_WRITE};
+    Traits traits = {"android.allocator.blob", id, LINEAR, minUsage, maxUsage};
+    mTraits = std::make_shared<C2Allocator::Traits>(traits);
+    auto allocatorStore = GetCodec2PlatformAllocatorStore();
+    allocatorStore->fetchAllocator(C2PlatformAllocatorStore::GRALLOC, &mC2AllocatorGralloc);
+    if (!mC2AllocatorGralloc) {
+        ALOGE("Failed to obtain C2AllocatorGralloc as backed allocator");
+    }
+}
+
+C2AllocatorBlob::~C2AllocatorBlob() {}
+
+c2_status_t C2AllocatorBlob::newLinearAllocation(
+        uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation>* allocation) {
+    if (allocation == nullptr) {
+        return C2_BAD_VALUE;
+    }
+
+    allocation->reset();
+
+    if (!mC2AllocatorGralloc) {
+        return C2_CORRUPTED;
+    }
+
+    std::shared_ptr<C2GraphicAllocation> graphicAllocation;
+    c2_status_t status = mC2AllocatorGralloc->newGraphicAllocation(
+            capacity, kLinearBufferHeight, kLinearBufferFormat, usage, &graphicAllocation);
+    if (status != C2_OK) {
+        ALOGE("Failed newGraphicAllocation");
+        return status;
+    }
+
+    allocation->reset(new C2AllocationBlob(std::move(graphicAllocation),
+                                           static_cast<size_t>(capacity), mTraits->id));
+    return C2_OK;
+}
+
+c2_status_t C2AllocatorBlob::priorLinearAllocation(
+        const C2Handle* handle, std::shared_ptr<C2LinearAllocation>* allocation) {
+    if (allocation == nullptr) {
+        return C2_BAD_VALUE;
+    }
+
+    allocation->reset();
+
+    if (!mC2AllocatorGralloc) {
+        return C2_CORRUPTED;
+    }
+
+    std::shared_ptr<C2GraphicAllocation> graphicAllocation;
+    c2_status_t status = mC2AllocatorGralloc->priorGraphicAllocation(handle, &graphicAllocation);
+    if (status != C2_OK) {
+        ALOGE("Failed priorGraphicAllocation");
+        return status;
+    }
+
+    const C2Handle* const grallocHandle = graphicAllocation->handle();
+    size_t capacity = 0;
+    status = GetCapacityFromHandle(grallocHandle, &capacity);
+    if (status != C2_OK) {
+        ALOGE("Failed to extract capacity from Handle");
+        return status;
+    }
+
+    allocation->reset(new C2AllocationBlob(std::move(graphicAllocation), capacity, mTraits->id));
+    return C2_OK;
+}
+
+id_t C2AllocatorBlob::getId() const {
+    return mTraits->id;
+}
+
+C2String C2AllocatorBlob::getName() const {
+    return mTraits->name;
+}
+
+std::shared_ptr<const C2Allocator::Traits> C2AllocatorBlob::getTraits() const {
+    return mTraits;
+}
+
+// static
+bool C2AllocatorBlob::isValid(const C2Handle* const o) {
+    size_t capacity;
+    // Distinguish C2Handle purely allocated by C2AllocatorGralloc, or one allocated through
+    // C2AllocatorBlob, by checking the handle's height is 1, and its format is
+    // PixelFormat::BLOB by GetCapacityFromHandle().
+    return C2AllocatorGralloc::isValid(o) && GetCapacityFromHandle(o, &capacity) == C2_OK;
+}
+
+}  // namespace android
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index cd179be..78ac355 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -605,14 +605,11 @@
                           (int32_t)rect.width, (int32_t)rect.height },
                         // TODO: fence
                         hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
+                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
                             err = maperr2error(maperr);
                             if (err == C2_OK) {
                                 pointer = mapPointer;
                             }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
                         }).isOk()) {
                     ALOGE("failed transaction: lock(RGBA_1010102) (@4.0)");
                     return C2_CORRUPTED;
@@ -743,14 +740,11 @@
                           (int32_t)rect.width, (int32_t)rect.height },
                         // TODO: fence
                         hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
+                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
                             err = maperr2error(maperr);
                             if (err == C2_OK) {
                                 pointer = mapPointer;
                             }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
                         }).isOk()) {
                     ALOGE("failed transaction: lock(RGBA_8888) (@4.0)");
                     return C2_CORRUPTED;
@@ -816,6 +810,70 @@
             break;
         }
 
+        case PixelFormat4::BLOB: {
+            void* pointer = nullptr;
+            if (mMapper2) {
+                if (!mMapper2->lock(const_cast<native_handle_t*>(mBuffer), grallocUsage,
+                                    {(int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width,
+                                     (int32_t)rect.height},
+                                    // TODO: fence
+                                    hidl_handle(),
+                                    [&err, &pointer](const auto& maperr, const auto& mapPointer) {
+                                        err = maperr2error(maperr);
+                                        if (err == C2_OK) {
+                                            pointer = mapPointer;
+                                        }
+                                    }).isOk()) {
+                    ALOGE("failed transaction: lock(BLOB)");
+                    return C2_CORRUPTED;
+                }
+            } else if (mMapper3) {
+                if (!mMapper3->lock(
+                        const_cast<native_handle_t*>(mBuffer),
+                        grallocUsage,
+                        { (int32_t)rect.left, (int32_t)rect.top,
+                          (int32_t)rect.width, (int32_t)rect.height },
+                        // TODO: fence
+                        hidl_handle(),
+                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
+                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
+                            err = maperr2error(maperr);
+                            if (err == C2_OK) {
+                                pointer = mapPointer;
+                            }
+                            (void)bytesPerPixel;
+                            (void)bytesPerStride;
+                        }).isOk()) {
+                    ALOGE("failed transaction: lock(BLOB) (@3.0)");
+                    return C2_CORRUPTED;
+                }
+            } else {
+                if (!mMapper4->lock(
+                        const_cast<native_handle_t *>(mBuffer),
+                        grallocUsage,
+                        { (int32_t)rect.left, (int32_t)rect.top,
+                          (int32_t)rect.width, (int32_t)rect.height },
+                        // TODO: fence
+                        hidl_handle(),
+                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
+                            err = maperr2error(maperr);
+                            if (err == C2_OK) {
+                                pointer = mapPointer;
+                            }
+                        }).isOk()) {
+                    ALOGE("failed transaction: lock(BLOB) (@4.0)");
+                    return C2_CORRUPTED;
+                }
+            }
+            if (err != C2_OK) {
+                ALOGD("lock failed: %d", err);
+                return err;
+            }
+
+            *addr = static_cast<uint8_t*>(pointer);
+            break;
+        }
+
         case PixelFormat4::YCBCR_420_888:
             // fall-through
         case PixelFormat4::YV12:
@@ -875,27 +933,14 @@
                     return C2_CORRUPTED;
                 }
             } else {
-                if (!mMapper4->lockYCbCr(
-                        const_cast<native_handle_t *>(mBuffer), grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                ycbcrLayout = YCbCrLayout{
-                                        mapLayout.y,
-                                        mapLayout.cb,
-                                        mapLayout.cr,
-                                        mapLayout.yStride,
-                                        mapLayout.cStride,
-                                        mapLayout.chromaStep};
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lockYCbCr (@4.0)");
-                    return C2_CORRUPTED;
-                }
+                // No device currently supports IMapper 4.0 so it is safe to just return an error
+                // code here.
+                //
+                // This will be supported by a combination of lock and BufferMetadata getters.
+                // We are going to refactor all the IAllocator/IMapper versioning code into a
+                // shared library. We will then add the IMapper 4.0 lockYCbCr support then.
+                ALOGE("failed transaction: lockYCbCr (@4.0)");
+                return C2_CORRUPTED;
             }
             if (err != C2_OK) {
                 ALOGD("lockYCbCr failed: %d", err);
diff --git a/media/codec2/vndk/include/C2AllocatorBlob.h b/media/codec2/vndk/include/C2AllocatorBlob.h
new file mode 100644
index 0000000..89ce949
--- /dev/null
+++ b/media/codec2/vndk/include/C2AllocatorBlob.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
+
+#include <functional>
+
+#include <C2AllocatorGralloc.h>
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorBlob : public C2Allocator {
+public:
+    virtual id_t getId() const override;
+
+    virtual C2String getName() const override;
+
+    virtual std::shared_ptr<const Traits> getTraits() const override;
+
+    virtual c2_status_t newLinearAllocation(
+            uint32_t capacity, C2MemoryUsage usage,
+            std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+    virtual c2_status_t priorLinearAllocation(
+            const C2Handle *handle,
+            std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+    C2AllocatorBlob(id_t id);
+
+    virtual ~C2AllocatorBlob() override;
+
+    static bool isValid(const C2Handle* const o);
+
+private:
+    std::shared_ptr<const Traits> mTraits;
+    // Design as C2AllocatorGralloc-backed to unify Gralloc implementations.
+    std::shared_ptr<C2Allocator> mC2AllocatorGralloc;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 850b1d0..463f606 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -40,6 +40,20 @@
         "libutils",
         "libbinder",
     ],
+
+    sanitize: {
+        integer_overflow: true,
+        misc_undefined: ["bounds"],
+        diag: {
+            integer_overflow: true,
+            misc_undefined: ["bounds"],
+            no_recover: [
+                "bounds",
+                "integer",
+            ],
+        },
+    },
+
 }
 
 cc_library {
@@ -57,7 +71,7 @@
     export_include_dirs: ["."],
     header_libs: [
         "libaaudio_headers",
-        "libmedia_headers"
+        "libmedia_headers",
     ],
     export_header_lib_headers: ["libaaudio_headers"],
 
@@ -116,4 +130,17 @@
         "flowgraph/SourceI16.cpp",
         "flowgraph/SourceI24.cpp",
     ],
+    sanitize: {
+        integer_overflow: true,
+        misc_undefined: ["bounds"],
+        diag: {
+            integer_overflow: true,
+            misc_undefined: ["bounds"],
+            no_recover: [
+                "bounds",
+                "integer",
+            ],
+        },
+    },
+
 }
diff --git a/media/libaaudio/src/fifo/FifoControllerBase.cpp b/media/libaaudio/src/fifo/FifoControllerBase.cpp
index 66e247f..1dece0e 100644
--- a/media/libaaudio/src/fifo/FifoControllerBase.cpp
+++ b/media/libaaudio/src/fifo/FifoControllerBase.cpp
@@ -33,7 +33,9 @@
 }
 
 fifo_frames_t FifoControllerBase::getFullFramesAvailable() {
-    return (fifo_frames_t) (getWriteCounter() - getReadCounter());
+    fifo_frames_t temp = 0;
+    __builtin_sub_overflow(getWriteCounter(), getReadCounter(), &temp);
+    return temp;
 }
 
 fifo_frames_t FifoControllerBase::getReadIndex() {
@@ -42,7 +44,9 @@
 }
 
 void FifoControllerBase::advanceReadIndex(fifo_frames_t numFrames) {
-    setReadCounter(getReadCounter() + numFrames);
+   fifo_counter_t temp = 0;
+    __builtin_add_overflow(getReadCounter(), numFrames, &temp);
+    setReadCounter(temp);
 }
 
 fifo_frames_t FifoControllerBase::getEmptyFramesAvailable() {
@@ -55,7 +59,9 @@
 }
 
 void FifoControllerBase::advanceWriteIndex(fifo_frames_t numFrames) {
-    setWriteCounter(getWriteCounter() + numFrames);
+    fifo_counter_t temp = 0;
+    __builtin_add_overflow(getWriteCounter(), numFrames, &temp);
+    setWriteCounter(temp);
 }
 
 void FifoControllerBase::setThreshold(fifo_frames_t threshold) {
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index 1bfe3f9..31257d5 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -42,6 +42,13 @@
     return audioDeviceOutAllScoSet;
 }
 
+const DeviceTypeSet& getAudioDeviceOutAllUsbSet() {
+    static const DeviceTypeSet audioDeviceOutAllUsbSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_OUT_ALL_USB_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_ALL_USB_ARRAY));
+    return audioDeviceOutAllUsbSet;
+}
+
 const DeviceTypeSet& getAudioDeviceInAllSet() {
     static const DeviceTypeSet audioDeviceInAllSet = DeviceTypeSet(
             std::begin(AUDIO_DEVICE_IN_ALL_ARRAY),
@@ -49,6 +56,13 @@
     return audioDeviceInAllSet;
 }
 
+const DeviceTypeSet& getAudioDeviceInAllUsbSet() {
+    static const DeviceTypeSet audioDeviceInAllUsbSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_IN_ALL_USB_ARRAY),
+            std::end(AUDIO_DEVICE_IN_ALL_USB_ARRAY));
+    return audioDeviceInAllUsbSet;
+}
+
 bool deviceTypesToString(const DeviceTypeSet &deviceTypes, std::string &str) {
     if (deviceTypes.empty()) {
         str = "Empty device types";
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 2a3385b..72fda49 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -37,7 +37,9 @@
 const DeviceTypeSet& getAudioDeviceOutAllSet();
 const DeviceTypeSet& getAudioDeviceOutAllA2dpSet();
 const DeviceTypeSet& getAudioDeviceOutAllScoSet();
+const DeviceTypeSet& getAudioDeviceOutAllUsbSet();
 const DeviceTypeSet& getAudioDeviceInAllSet();
+const DeviceTypeSet& getAudioDeviceInAllUsbSet();
 
 template<typename T>
 static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 8669e2a..e96a68c 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -27,6 +27,7 @@
         "android.hardware.audio.common-util",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libaudiofoundation",
         "libaudiohal_deathhandler",
         "libaudioutils",
         "libbase",
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.cpp b/media/libaudiohal/impl/ConversionHelperHidl.cpp
index 9f8a520..f29b0f3 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperHidl.cpp
@@ -17,6 +17,7 @@
 #include <string.h>
 
 #define LOG_TAG "HalHidl"
+#include <media/AudioContainers.h>
 #include <media/AudioParameter.h>
 #include <utils/Log.h>
 
@@ -109,26 +110,22 @@
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
     memset(halAddress, 0, sizeof(halAddress));
     audio_devices_t halDevice = static_cast<audio_devices_t>(address.device);
-    const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
-        (isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+    if (getAudioDeviceOutAllA2dpSet().count(halDevice) > 0 ||
+        halDevice == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
                  address.address.mac[0], address.address.mac[1], address.address.mac[2],
                  address.address.mac[3], address.address.mac[4], address.address.mac[5]);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_IP || halDevice == AUDIO_DEVICE_IN_IP) {
         snprintf(halAddress, sizeof(halAddress), "%d.%d.%d.%d", address.address.ipv4[0],
                  address.address.ipv4[1], address.address.ipv4[2], address.address.ipv4[3]);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
+    } else if (getAudioDeviceOutAllUsbSet().count(halDevice) > 0 ||
+               getAudioDeviceInAllUsbSet().count(halDevice) > 0) {
         snprintf(halAddress, sizeof(halAddress), "card=%d;device=%d", address.address.alsa.card,
                  address.address.alsa.device);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_BUS || halDevice == AUDIO_DEVICE_IN_BUS) {
         snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+               halDevice == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
         snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
     } else {
         snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 3d3a5eb..d52416c 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -22,6 +22,7 @@
 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
 #include <cutils/native_handle.h>
 #include <hwbinder/IPCThreadState.h>
+#include <media/AudioContainers.h>
 #include <utils/Log.h>
 
 #include <common/all-versions/VersionUtils.h>
@@ -51,42 +52,32 @@
     if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
         return OK;
     }
-    const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
-            || (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+    if (getAudioDeviceOutAllA2dpSet().count(device) > 0
+            || device == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         int status = sscanf(halAddress,
                 "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
                 &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
                 &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
         return status == 6 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0)
-            || (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+    } else if (device == AUDIO_DEVICE_OUT_IP || device == AUDIO_DEVICE_IN_IP) {
         int status = sscanf(halAddress,
                 "%hhu.%hhu.%hhu.%hhu",
                 &address->address.ipv4[0], &address->address.ipv4[1],
                 &address->address.ipv4[2], &address->address.ipv4[3]);
         return status == 4 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0
-            || (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+    } else if (getAudioDeviceOutAllUsbSet().count(device) > 0
+            || getAudioDeviceInAllUsbSet().count(device) > 0) {
         int status = sscanf(halAddress,
                 "card=%d;device=%d",
                 &address->address.alsa.card, &address->address.alsa.device);
         return status == 2 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0)
-            || (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
-        if (halAddress != NULL) {
-            address->busAddress = halAddress;
-            return OK;
-        }
-        return BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
-            || (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
-        if (halAddress != NULL) {
-            address->rSubmixAddress = halAddress;
-            return OK;
-        }
-        return BAD_VALUE;
+    } else if (device == AUDIO_DEVICE_OUT_BUS || device == AUDIO_DEVICE_IN_BUS) {
+        address->busAddress = halAddress;
+        return OK;
+    } else if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+            || device == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+        address->rSubmixAddress = halAddress;
+        return OK;
     }
     return OK;
 }
@@ -100,8 +91,12 @@
 
 DeviceHalHidl::~DeviceHalHidl() {
     if (mDevice != 0) {
+#if MAJOR_VERSION <= 5
         mDevice.clear();
         hardware::IPCThreadState::self()->flushCommands();
+#elif MAJOR_VERSION >= 6
+        mDevice->close();
+#endif
     }
 }
 
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index ac88448..b064f08 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -34,7 +34,6 @@
         "aidl/android/media/MediaResourceParcel.aidl",
         "aidl/android/media/MediaResourcePolicyParcel.aidl",
     ],
-    api_dir: "api/resourcemanager",
     versions: ["1"],
 }
 
diff --git a/media/libmedia/api/resourcemanager/1/.hash b/media/libmedia/aidl_api/resourcemanager_aidl_interface/.hash
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/.hash
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/.hash
diff --git a/media/libmedia/api/resourcemanager/1/android/media/IResourceManagerClient.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerClient.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/IResourceManagerClient.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerClient.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/IResourceManagerService.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerService.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/IResourceManagerService.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerService.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceParcel.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceParcel.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceParcel.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceParcel.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourcePolicyParcel.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourcePolicyParcel.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourcePolicyParcel.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourcePolicyParcel.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceSubType.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceSubType.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceSubType.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceSubType.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceType.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceType.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceType.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceType.aidl
diff --git a/media/libmedia/include/media/PluginMetricsReporting.h b/media/libmedia/include/media/PluginMetricsReporting.h
index e00bd43..f71c52d 100644
--- a/media/libmedia/include/media/PluginMetricsReporting.h
+++ b/media/libmedia/include/media/PluginMetricsReporting.h
@@ -18,6 +18,7 @@
 
 #define PLUGIN_METRICS_REPORTING_H_
 
+#include <sys/types.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 
@@ -26,7 +27,7 @@
 status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
                                 const String8& vendorName,
                                 const String8& description,
-                                const String8& appPackageName);
+                                uid_t appUid);
 
 }  // namespace android
 
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index 8357925..e845c33 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -7,6 +7,7 @@
     shared_libs: [
         "liblog",
         "libbinder",
+        "libbinder_ndk",
         "libmedia",
         "libmediaplayerservice",
         "libmediadrm",
@@ -17,6 +18,10 @@
         "android.hardware.drm@1.2",
     ],
 
+    static_libs: [
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
     include_dirs: [
         "frameworks/av/include",
         "frameworks/av/services/mediaresourcemanager",
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index 262fe32..9a8ed8d 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -16,19 +16,21 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DrmSessionManager_test"
+#include <android/binder_auto_utils.h>
 #include <utils/Log.h>
 
 #include <gtest/gtest.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <aidl/android/media/BnResourceManagerService.h>
 #include <android/media/BnResourceManagerClient.h>
-#include <android/media/IResourceManagerService.h>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/ProcessInfoInterface.h>
-#include <mediadrm/DrmHal.h>
-#include <mediadrm/DrmSessionClientInterface.h>
 #include <mediadrm/DrmSessionManager.h>
 
 #include <algorithm>
+#include <iostream>
 #include <vector>
 
 #include "ResourceManagerService.h"
@@ -36,8 +38,109 @@
 namespace android {
 
 using ::android::binder::Status;
-using ::android::media::BnResourceManagerClient;
 using ::android::media::ResourceManagerService;
+using ::ndk::ScopedAStatus;
+
+using NdkBnResourceManagerClient = ::aidl::android::media::BnResourceManagerClient;
+using NdkBnResourceManagerService = ::aidl::android::media::BnResourceManagerService;
+using NdkMediaResource = ::aidl::android::media::MediaResourceParcel;
+using NdkResourceManagerClient = ::aidl::android::media::IResourceManagerClient;
+
+using FwkBnResourceManagerClient = ::android::media::BnResourceManagerClient;
+using FwkMediaResource = ::android::media::MediaResourceParcel;
+
+namespace {
+
+struct FwkResourceManagerClientImpl : public FwkBnResourceManagerClient {
+    FwkResourceManagerClientImpl(const std::shared_ptr<NdkResourceManagerClient> &client)
+        : mClient(client) {
+    }
+
+    Status reclaimResource(bool* _aidl_return) override {
+        mClient->reclaimResource(_aidl_return);
+        return Status::ok();
+    }
+
+    Status getName(std::string* _aidl_return) override {
+        mClient->getName(_aidl_return);
+        return Status::ok();
+    }
+
+private:
+    std::shared_ptr<NdkResourceManagerClient> mClient;
+};
+
+FwkMediaResource NdkToFwkMediaResource(const NdkMediaResource &in) {
+    FwkMediaResource out{};
+    out.type = static_cast<decltype(out.type)>(in.type);
+    out.subType = static_cast<decltype(out.subType)>(in.subType);
+    auto v(reinterpret_cast<const uint8_t *>(in.id.data()));
+    out.id.assign(v, v + in.id.size());
+    out.value = in.value;
+    return out;
+}
+
+std::vector<FwkMediaResource> NdkToFwkMediaResourceVec(const std::vector<NdkMediaResource> &in) {
+    std::vector<FwkMediaResource> out;
+    for (auto e : in) {
+        out.push_back(NdkToFwkMediaResource(e));
+    }
+    return out;
+}
+
+ScopedAStatus FwkToNdkStatus(Status err) {
+    return ScopedAStatus(AStatus_fromExceptionCode(err.serviceSpecificErrorCode()));
+}
+
+struct NdkResourceManagerServiceImpl : public NdkBnResourceManagerService {
+    using NdkMediaResourcePolicy = ::aidl::android::media::MediaResourcePolicyParcel;
+
+    NdkResourceManagerServiceImpl(const sp<ResourceManagerService> &service)
+        : mService(service) {}
+
+    ScopedAStatus config(const std::vector<NdkMediaResourcePolicy>& in_policies) override {
+        (void)in_policies;
+        return ScopedAStatus::ok();
+    }
+
+    ScopedAStatus addResource(int32_t in_pid, int32_t in_uid, int64_t in_clientId,
+            const std::shared_ptr<NdkResourceManagerClient>& in_client,
+            const std::vector<NdkMediaResource>& in_resources) override {
+        sp<FwkBnResourceManagerClient> client(new FwkResourceManagerClientImpl(in_client));
+        std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+        auto err = mService->addResource(in_pid, in_uid, in_clientId, client, resources);
+        return FwkToNdkStatus(err);
+    }
+
+    ScopedAStatus removeResource(int32_t in_pid, int64_t in_clientId,
+            const std::vector<NdkMediaResource>& in_resources) override {
+        std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+        auto err = mService->removeResource(in_pid, in_clientId, resources);
+        return FwkToNdkStatus(err);
+    }
+
+    ScopedAStatus removeClient(int32_t in_pid, int64_t in_clientId) override{
+        auto err = mService->removeClient(in_pid, in_clientId);
+        return FwkToNdkStatus(err);
+    }
+
+    ScopedAStatus reclaimResource(int32_t in_callingPid,
+            const std::vector<NdkMediaResource>& in_resources, bool* _aidl_return) override {
+        std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+        auto err = mService->reclaimResource(in_callingPid, resources, _aidl_return);
+        return FwkToNdkStatus(err);
+    }
+
+private:
+    sp<ResourceManagerService> mService;
+};
+
+template <typename Impl>
+std::shared_ptr<NdkResourceManagerClient> NdkImplToIface(const Impl &impl) {
+    return std::static_pointer_cast<NdkResourceManagerClient>(impl);
+}
+
+}
 
 static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
     Vector<uint8_t> aVec;
@@ -66,29 +169,27 @@
     DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
 };
 
-struct FakeDrm : public BnResourceManagerClient {
+struct FakeDrm : public NdkBnResourceManagerClient {
     FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
         : mSessionId(toAndroidVector(sessionId)),
           mReclaimed(false),
           mDrmSessionManager(manager) {}
 
-    virtual ~FakeDrm() {}
-
-    Status reclaimResource(bool* _aidl_return) {
+    ScopedAStatus reclaimResource(bool* _aidl_return) {
         mReclaimed = true;
         mDrmSessionManager->removeSession(mSessionId);
         *_aidl_return = true;
-        return Status::ok();
+        return ScopedAStatus::ok();
     }
 
-    Status getName(::std::string* _aidl_return) {
+    ScopedAStatus getName(::std::string* _aidl_return) {
         String8 name("FakeDrm[");
         for (size_t i = 0; i < mSessionId.size(); ++i) {
             name.appendFormat("%02x", mSessionId[i]);
         }
         name.append("]");
         *_aidl_return = name;
-        return Status::ok();
+        return ScopedAStatus::ok();
     }
 
     bool isReclaimed() const {
@@ -137,27 +238,24 @@
 public:
     DrmSessionManagerTest()
         : mService(new ResourceManagerService(new FakeProcessInfo(), new FakeSystemCallback())),
-          mDrmSessionManager(new DrmSessionManager(mService)),
+          mDrmSessionManager(new DrmSessionManager(std::shared_ptr<NdkBnResourceManagerService>(new NdkResourceManagerServiceImpl(mService)))),
           mTestDrm1(new FakeDrm(kTestSessionId1, mDrmSessionManager)),
           mTestDrm2(new FakeDrm(kTestSessionId2, mDrmSessionManager)),
           mTestDrm3(new FakeDrm(kTestSessionId3, mDrmSessionManager)) {
-        DrmSessionManager *ptr = new DrmSessionManager(mService);
-        EXPECT_NE(ptr, nullptr);
-        /* mDrmSessionManager = ptr; */
     }
 
 protected:
     void addSession() {
-        mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+        mDrmSessionManager->addSession(kTestPid1, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
+        mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
+        mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
     }
 
-    sp<IResourceManagerService> mService;
+    sp<ResourceManagerService> mService;
     sp<DrmSessionManager> mDrmSessionManager;
-    sp<FakeDrm> mTestDrm1;
-    sp<FakeDrm> mTestDrm2;
-    sp<FakeDrm> mTestDrm3;
+    std::shared_ptr<FakeDrm> mTestDrm1;
+    std::shared_ptr<FakeDrm> mTestDrm2;
+    std::shared_ptr<FakeDrm> mTestDrm3;
 };
 
 TEST_F(DrmSessionManagerTest, addSession) {
@@ -204,8 +302,8 @@
 
     // add a session from a higher priority process.
     const std::vector<uint8_t> sid{1, 3, 5};
-    sp<FakeDrm> drm = new FakeDrm(sid, mDrmSessionManager);
-    mDrmSessionManager->addSession(15, drm, drm->mSessionId);
+    std::shared_ptr<FakeDrm> drm(new FakeDrm(sid, mDrmSessionManager));
+    mDrmSessionManager->addSession(15, NdkImplToIface(drm), drm->mSessionId);
 
     // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
     mDrmSessionManager->useSession(mTestDrm3->mSessionId);
@@ -225,9 +323,9 @@
     EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
 
     // add sessions from same pid
-    mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
-    mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
-    mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
 
     // use some but not all sessions
     mDrmSessionManager->useSession(mTestDrm1->mSessionId);
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index dd6f7b4..bf8f09c 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -21,6 +21,7 @@
 #include <numeric>
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
 #include <binder/MemoryDealer.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <media/openmax/OMX_Core.h>
@@ -41,6 +42,7 @@
 using hardware::hidl_vec;
 using namespace hardware::cas::V1_0;
 using namespace hardware::cas::native::V1_0;
+using DrmBufferType = hardware::drm::V1_0::BufferType;
 using BufferInfo = ACodecBufferChannel::BufferInfo;
 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
 
@@ -131,18 +133,18 @@
     ssize_t result = -1;
     ssize_t codecDataOffset = 0;
     if (mCrypto != NULL) {
-        ICrypto::DestinationBuffer destination;
+        hardware::drm::V1_0::DestinationBuffer destination;
         if (secure) {
-            destination.mType = ICrypto::kDestinationTypeNativeHandle;
-            destination.mHandle = secureHandle;
+            destination.type = DrmBufferType::NATIVE_HANDLE;
+            destination.secureMemory = hidl_handle(secureHandle);
         } else {
-            destination.mType = ICrypto::kDestinationTypeSharedMemory;
-            destination.mSharedMemory = mDecryptDestination;
+            destination.type = DrmBufferType::SHARED_MEMORY;
+            IMemoryToSharedBuffer(
+                    mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
         }
 
-        ICrypto::SourceBuffer source;
-        source.mSharedMemory = it->mSharedEncryptedBuffer;
-        source.mHeapSeqNum = mHeapSeqNum;
+        hardware::drm::V1_0::SharedBuffer source;
+        IMemoryToSharedBuffer(it->mSharedEncryptedBuffer, mHeapSeqNum, &source);
 
         result = mCrypto->decrypt(key, iv, mode, pattern,
                 source, it->mClientBuffer->offset(),
@@ -152,9 +154,8 @@
             return result;
         }
 
-        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
-            memcpy(it->mCodecBuffer->base(),
-                destination.mSharedMemory->unsecurePointer(), result);
+        if (destination.type == DrmBufferType::SHARED_MEMORY) {
+            memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);
         }
     } else {
         // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
@@ -315,7 +316,8 @@
     }
     dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
     if (mCrypto != nullptr) {
-        int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
+        sp<HidlMemory> hHeap = fromHeap(dealer->getMemoryHeap());
+        int32_t seqNum = mCrypto->setHeap(hHeap);
         if (seqNum >= 0) {
             mHeapSeqNum = seqNum;
             ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
@@ -431,4 +433,12 @@
             it->mClientBuffer);
 }
 
+void ACodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
+    mCrypto = crypto;
+}
+
+void ACodecBufferChannel::setDescrambler(const sp<IDescrambler> &descrambler) {
+    mDescrambler = descrambler;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index afd5017..76eadf7 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -252,6 +252,7 @@
         "libhidlmemory",
         "android.hidl.allocator@1.0",
         "android.hardware.cas.native@1.0",
+        "android.hardware.drm@1.0",
         "android.hardware.media.omx@1.0",
     ],
 
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index 5765883..5b724aa 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -26,14 +26,6 @@
 
 namespace android {
 
-void BufferChannelBase::setCrypto(const sp<ICrypto> &crypto) {
-    mCrypto = crypto;
-}
-
-void BufferChannelBase::setDescrambler(const sp<IDescrambler> &descrambler) {
-    mDescrambler = descrambler;
-}
-
 void BufferChannelBase::IMemoryToSharedBuffer(
         const sp<IMemory> &memory,
         int32_t heapSeqNum,
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 14564c9..b043e31 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -955,37 +955,41 @@
     mCodecInfo.clear();
 
     bool secureCodec = false;
-    AString tmp = name;
-    if (tmp.endsWith(".secure")) {
-        secureCodec = true;
-        tmp.erase(tmp.size() - 7, 7);
-    }
-    const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
-    if (mcl == NULL) {
-        mCodec = NULL;  // remove the codec.
-        return NO_INIT; // if called from Java should raise IOException
-    }
-    for (const AString &codecName : { name, tmp }) {
-        ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
-        if (codecIdx < 0) {
-            continue;
+    const char *owner = "";
+    if (!name.startsWith("android.filter.")) {
+        AString tmp = name;
+        if (tmp.endsWith(".secure")) {
+            secureCodec = true;
+            tmp.erase(tmp.size() - 7, 7);
         }
-        mCodecInfo = mcl->getCodecInfo(codecIdx);
-        Vector<AString> mediaTypes;
-        mCodecInfo->getSupportedMediaTypes(&mediaTypes);
-        for (size_t i = 0; i < mediaTypes.size(); i++) {
-            if (mediaTypes[i].startsWith("video/")) {
-                mIsVideo = true;
-                break;
+        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+        if (mcl == NULL) {
+            mCodec = NULL;  // remove the codec.
+            return NO_INIT; // if called from Java should raise IOException
+        }
+        for (const AString &codecName : { name, tmp }) {
+            ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
+            if (codecIdx < 0) {
+                continue;
             }
+            mCodecInfo = mcl->getCodecInfo(codecIdx);
+            Vector<AString> mediaTypes;
+            mCodecInfo->getSupportedMediaTypes(&mediaTypes);
+            for (size_t i = 0; i < mediaTypes.size(); i++) {
+                if (mediaTypes[i].startsWith("video/")) {
+                    mIsVideo = true;
+                    break;
+                }
+            }
+            break;
         }
-        break;
-    }
-    if (mCodecInfo == nullptr) {
-        return NAME_NOT_FOUND;
+        if (mCodecInfo == nullptr) {
+            return NAME_NOT_FOUND;
+        }
+        owner = mCodecInfo->getOwnerName();
     }
 
-    mCodec = GetCodecBase(name, mCodecInfo->getOwnerName());
+    mCodec = GetCodecBase(name, owner);
     if (mCodec == NULL) {
         return NAME_NOT_FOUND;
     }
@@ -1014,9 +1018,11 @@
                     new BufferCallback(new AMessage(kWhatCodecNotify, this))));
 
     sp<AMessage> msg = new AMessage(kWhatInit, this);
-    msg->setObject("codecInfo", mCodecInfo);
-    // name may be different from mCodecInfo->getCodecName() if we stripped
-    // ".secure"
+    if (mCodecInfo) {
+        msg->setObject("codecInfo", mCodecInfo);
+        // name may be different from mCodecInfo->getCodecName() if we stripped
+        // ".secure"
+    }
     msg->setString("name", name);
 
     if (mMetricsHandle != 0) {
@@ -2070,9 +2076,9 @@
                                                 mComponentName.c_str());
                     }
 
-                    const char *owner = mCodecInfo->getOwnerName();
+                    const char *owner = mCodecInfo ? mCodecInfo->getOwnerName() : "";
                     if (mComponentName.startsWith("OMX.google.")
-                            && (owner == nullptr || strncmp(owner, "default", 8) == 0)) {
+                            && strncmp(owner, "default", 8) == 0) {
                         mFlags |= kFlagUsesSoftwareRenderer;
                     } else {
                         mFlags &= ~kFlagUsesSoftwareRenderer;
@@ -2480,12 +2486,14 @@
             setState(INITIALIZING);
 
             sp<RefBase> codecInfo;
-            CHECK(msg->findObject("codecInfo", &codecInfo));
+            (void)msg->findObject("codecInfo", &codecInfo);
             AString name;
             CHECK(msg->findString("name", &name));
 
             sp<AMessage> format = new AMessage;
-            format->setObject("codecInfo", codecInfo);
+            if (codecInfo) {
+                format->setObject("codecInfo", codecInfo);
+            }
             format->setString("componentName", name);
 
             mCodec->initiateAllocateComponent(format);
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index 777ab5b..c7baa73 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -20,13 +20,12 @@
 #include <inttypes.h>
 #include <utils/Trace.h>
 
-#include <binder/MemoryDealer.h>
-
-#include <media/stagefright/BufferProducerWrapper.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
+#include <media/stagefright/BufferProducerWrapper.h>
+#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaFilter.h>
@@ -42,11 +41,121 @@
 #include "SaturationFilter.h"
 #include "ZeroFilter.h"
 
-#include "../include/ACodecBufferChannel.h"
-#include "../include/SharedMemoryBuffer.h"
-
 namespace android {
 
+class MediaFilter::BufferChannel : public BufferChannelBase {
+public:
+    BufferChannel(const sp<AMessage> &in, const sp<AMessage> &out)
+        : mInputBufferFilled(in), mOutputBufferDrained(out) {
+    }
+
+    ~BufferChannel() override = default;
+
+    // BufferChannelBase
+
+    status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override {
+        sp<AMessage> msg = mInputBufferFilled->dup();
+        msg->setObject("buffer", buffer);
+        msg->post();
+        return OK;
+    }
+
+    status_t queueSecureInputBuffer(
+            const sp<MediaCodecBuffer> &,
+            bool,
+            const uint8_t *,
+            const uint8_t *,
+            CryptoPlugin::Mode,
+            CryptoPlugin::Pattern,
+            const CryptoPlugin::SubSample *,
+            size_t,
+            AString *) override {
+        return INVALID_OPERATION;
+    }
+
+    status_t renderOutputBuffer(
+            const sp<MediaCodecBuffer> &buffer, int64_t /* timestampNs */) override {
+        sp<AMessage> msg = mOutputBufferDrained->dup();
+        msg->setObject("buffer", buffer);
+        msg->post();
+        return OK;
+    }
+
+    status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override {
+        if (FindBufferIndex(&mInputBuffers, buffer) >= 0) {
+            sp<AMessage> msg = mInputBufferFilled->dup();
+            msg->setObject("buffer", buffer);
+            msg->post();
+            return OK;
+        }
+        sp<AMessage> msg = mOutputBufferDrained->dup();
+        msg->setObject("buffer", buffer);
+        msg->post();
+        return OK;
+    }
+
+    void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
+        if (!array) {
+            return;
+        }
+        array->clear();
+        array->appendVector(mInputBuffers);
+    }
+
+    void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
+        if (!array) {
+            return;
+        }
+        array->clear();
+        array->appendVector(mOutputBuffers);
+    }
+
+    // For MediaFilter
+
+    void fillThisBuffer(const sp<MediaCodecBuffer> &buffer) {
+        ssize_t index = FindBufferIndex(&mInputBuffers, buffer);
+        mCallback->onInputBufferAvailable(index, buffer);
+    }
+
+    void drainThisBuffer(const sp<MediaCodecBuffer> &buffer, int flags) {
+        ssize_t index = FindBufferIndex(&mOutputBuffers, buffer);
+        buffer->meta()->setInt32("flags", flags);
+        mCallback->onOutputBufferAvailable(index, buffer);
+    }
+
+    template <class T>
+    void setInputBuffers(T begin, T end) {
+        mInputBuffers.clear();
+        for (T it = begin; it != end; ++it) {
+            mInputBuffers.push_back(it->mData);
+        }
+    }
+
+    template <class T>
+    void setOutputBuffers(T begin, T end) {
+        mOutputBuffers.clear();
+        for (T it = begin; it != end; ++it) {
+            mOutputBuffers.push_back(it->mData);
+        }
+    }
+
+private:
+    sp<AMessage> mInputBufferFilled;
+    sp<AMessage> mOutputBufferDrained;
+    Vector<sp<MediaCodecBuffer>> mInputBuffers;
+    Vector<sp<MediaCodecBuffer>> mOutputBuffers;
+
+    static ssize_t FindBufferIndex(
+            Vector<sp<MediaCodecBuffer>> *array, const sp<MediaCodecBuffer> &buffer) {
+        for (size_t i = 0; i < array->size(); ++i) {
+            if (array->itemAt(i) == buffer) {
+                return i;
+            }
+        }
+        return -1;
+    }
+};
+
 // parameter: number of input and output buffers
 static const size_t kBufferCountActual = 4;
 
@@ -54,9 +163,6 @@
     : mState(UNINITIALIZED),
       mGeneration(0),
       mGraphicBufferListener(NULL) {
-    mBufferChannel = std::make_shared<ACodecBufferChannel>(
-            new AMessage(kWhatInputBufferFilled, this),
-            new AMessage(kWhatOutputBufferDrained, this));
 }
 
 MediaFilter::~MediaFilter() {
@@ -65,6 +171,11 @@
 //////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
 
 std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
+    if (!mBufferChannel) {
+        mBufferChannel = std::make_shared<BufferChannel>(
+                new AMessage(kWhatInputBufferFilled, this),
+                new AMessage(kWhatOutputBufferDrained, this));
+    }
     return mBufferChannel;
 }
 
@@ -212,28 +323,23 @@
     const bool isInput = portIndex == kPortIndexInput;
     const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize;
 
-    CHECK(mDealer[portIndex] == NULL);
     CHECK(mBuffers[portIndex].isEmpty());
 
     ALOGV("Allocating %zu buffers of size %zu on %s port",
             kBufferCountActual, bufferSize,
             isInput ? "input" : "output");
 
-    size_t totalSize = kBufferCountActual * bufferSize;
-
-    mDealer[portIndex] = new MemoryDealer(totalSize, "MediaFilter");
-
+    // trigger output format change
+    sp<AMessage> outputFormat = mOutputFormat->dup();
     for (size_t i = 0; i < kBufferCountActual; ++i) {
-        sp<IMemory> mem = mDealer[portIndex]->allocate(bufferSize);
-        CHECK(mem.get() != NULL);
-
         BufferInfo info;
         info.mStatus = BufferInfo::OWNED_BY_US;
         info.mBufferID = i;
         info.mGeneration = mGeneration;
         info.mOutputFlags = 0;
-        info.mData = new SharedMemoryBuffer(
-                isInput ? mInputFormat : mOutputFormat, mem);
+        info.mData = new MediaCodecBuffer(
+                isInput ? mInputFormat : outputFormat,
+                new ABuffer(bufferSize));
         info.mData->meta()->setInt64("timeUs", 0);
 
         mBuffers[portIndex].push_back(info);
@@ -243,27 +349,24 @@
                     &mBuffers[portIndex].editItemAt(i));
         }
     }
-
-    std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
-    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
-        array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
-    }
-    if (portIndex == kPortIndexInput) {
-        mBufferChannel->setInputBufferArray(array);
+    if (isInput) {
+        mBufferChannel->setInputBuffers(
+                mBuffers[portIndex].begin(), mBuffers[portIndex].end());
     } else {
-        mBufferChannel->setOutputBufferArray(array);
+        mBufferChannel->setOutputBuffers(
+                mBuffers[portIndex].begin(), mBuffers[portIndex].end());
     }
 
     return OK;
 }
 
-MediaFilter::BufferInfo* MediaFilter::findBufferByID(
-        uint32_t portIndex, IOMX::buffer_id bufferID,
+MediaFilter::BufferInfo* MediaFilter::findBuffer(
+        uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
         ssize_t *index) {
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
 
-        if (info->mBufferID == bufferID) {
+        if (info->mData == buffer) {
             if (index != NULL) {
                 *index = i;
             }
@@ -293,7 +396,7 @@
 
     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
 
-    mBufferChannel->fillThisBuffer(info->mBufferID);
+    mBufferChannel->fillThisBuffer(info->mData);
 }
 
 void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
@@ -304,7 +407,7 @@
     sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
     reply->setInt32("buffer-id", info->mBufferID);
 
-    mBufferChannel->drainThisBuffer(info->mBufferID, info->mOutputFlags);
+    mBufferChannel->drainThisBuffer(info->mData, info->mOutputFlags);
 
     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
 }
@@ -359,7 +462,7 @@
     outputInfo->mOutputFlags = 0;
     int32_t eos = 0;
     if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) {
-        outputInfo->mOutputFlags |= OMX_BUFFERFLAG_EOS;
+        outputInfo->mOutputFlags |= BUFFER_FLAG_END_OF_STREAM;
         mPortEOS[kPortIndexOutput] = true;
         outputInfo->mData->meta()->setInt32("eos", eos);
         postEOS();
@@ -400,8 +503,7 @@
         return;
     }
 
-    // HACK - need "OMX.google" to use MediaCodec's software renderer
-    mCallback->onComponentAllocated("OMX.google.MediaFilter");
+    mCallback->onComponentAllocated(mComponentName.c_str());
     mState = INITIALIZED;
     ALOGV("Handled kWhatAllocateComponent.");
 }
@@ -477,6 +579,7 @@
     mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
     mOutputFormat->setInt32("width", mWidth);
     mOutputFormat->setInt32("height", mHeight);
+    mOutputFormat->setInt32("using-sw-renderer", 1);
 
     mCallback->onComponentConfigured(mInputFormat, mOutputFormat);
     mState = CONFIGURED;
@@ -509,9 +612,11 @@
 }
 
 void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
-    IOMX::buffer_id bufferID;
-    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
-    BufferInfo *info = findBufferByID(kPortIndexInput, bufferID);
+    sp<RefBase> obj;
+    CHECK(msg->findObject("buffer", &obj));
+    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+    ssize_t index = -1;
+    BufferInfo *info = findBuffer(kPortIndexInput, buffer, &index);
 
     if (mState != STARTED) {
         // we're not running, so we'll just keep that buffer...
@@ -520,7 +625,7 @@
     }
 
     if (info->mGeneration != mGeneration) {
-        ALOGV("Caught a stale input buffer [ID %d]", bufferID);
+        ALOGV("Caught a stale input buffer [index %zd]", index);
         // buffer is stale (taken before a flush/shutdown) - repost it
         CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
         postFillThisBuffer(info);
@@ -530,30 +635,9 @@
     CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
     info->mStatus = BufferInfo::OWNED_BY_US;
 
-    sp<MediaCodecBuffer> buffer;
     int32_t err = OK;
     bool eos = false;
 
-    sp<RefBase> obj;
-    if (!msg->findObject("buffer", &obj)) {
-        // these are unfilled buffers returned by client
-        CHECK(msg->findInt32("err", &err));
-
-        if (err == OK) {
-            // buffers with no errors are returned on MediaCodec.flush
-            ALOGV("saw unfilled buffer (MediaCodec.flush)");
-            postFillThisBuffer(info);
-            return;
-        } else {
-            ALOGV("saw error %d instead of an input buffer", err);
-            eos = true;
-        }
-
-        buffer.clear();
-    } else {
-        buffer = static_cast<MediaCodecBuffer *>(obj.get());
-    }
-
     int32_t isCSD;
     if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
             && isCSD != 0) {
@@ -577,13 +661,15 @@
         mInputEOSResult = err;
     }
 
-    ALOGV("Handled kWhatInputBufferFilled. [ID %u]", bufferID);
+    ALOGV("Handled kWhatInputBufferFilled. [index %zd]", index);
 }
 
 void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
-    IOMX::buffer_id bufferID;
-    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
-    BufferInfo *info = findBufferByID(kPortIndexOutput, bufferID);
+    sp<RefBase> obj;
+    CHECK(msg->findObject("buffer", &obj));
+    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+    ssize_t index = -1;
+    BufferInfo *info = findBuffer(kPortIndexOutput, buffer, &index);
 
     if (mState != STARTED) {
         // we're not running, so we'll just keep that buffer...
@@ -592,7 +678,7 @@
     }
 
     if (info->mGeneration != mGeneration) {
-        ALOGV("Caught a stale output buffer [ID %d]", bufferID);
+        ALOGV("Caught a stale output buffer [index %zd]", index);
         // buffer is stale (taken before a flush/shutdown) - keep it
         CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
         return;
@@ -605,8 +691,7 @@
 
     processBuffers();
 
-    ALOGV("Handled kWhatOutputBufferDrained. [ID %u]",
-            bufferID);
+    ALOGV("Handled kWhatOutputBufferDrained. [index %zd]", index);
 }
 
 void MediaFilter::onShutdown(const sp<AMessage> &msg) {
@@ -739,7 +824,7 @@
             return;
         }
 
-        eosBuf->mOutputFlags = OMX_BUFFERFLAG_EOS;
+        eosBuf->mOutputFlags = BUFFER_FLAG_END_OF_STREAM;
         eosBuf->mGeneration = mGeneration;
         eosBuf->mData->setRange(0, 0);
         postDrainThisBuffer(eosBuf);
diff --git a/media/libstagefright/foundation/TEST_MAPPING b/media/libstagefright/foundation/TEST_MAPPING
new file mode 100644
index 0000000..3301c4b
--- /dev/null
+++ b/media/libstagefright/foundation/TEST_MAPPING
@@ -0,0 +1,5 @@
+{
+  "presubmit": [
+    { "name": "sf_foundation_test" }
+  ]
+}
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
new file mode 100644
index 0000000..f2157c9
--- /dev/null
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -0,0 +1,27 @@
+cc_test {
+    name: "sf_foundation_test",
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    include_dirs: [
+        "frameworks/av/include",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    srcs: [
+        "AData_test.cpp",
+        "Base64_test.cpp",
+        "Flagged_test.cpp",
+        "TypeTraits_test.cpp",
+        "Utils_test.cpp",
+    ],
+}
diff --git a/media/libstagefright/foundation/tests/Android.mk b/media/libstagefright/foundation/tests/Android.mk
deleted file mode 100644
index a9e3c76..0000000
--- a/media/libstagefright/foundation/tests/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := sf_foundation_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-	AData_test.cpp \
-	Base64_test.cpp \
-	Flagged_test.cpp \
-	TypeTraits_test.cpp \
-	Utils_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libstagefright_foundation \
-	libutils \
-
-LOCAL_C_INCLUDES := \
-	frameworks/av/include \
-
-LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
-
-include $(BUILD_NATIVE_TEST)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 3a087d1..5f65575 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -67,6 +67,9 @@
     virtual ~ACodecBufferChannel();
 
     // BufferChannelBase interface
+    void setCrypto(const sp<ICrypto> &crypto) override;
+    void setDescrambler(const sp<IDescrambler> &descrambler) override;
+
     virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
     virtual status_t queueSecureInputBuffer(
             const sp<MediaCodecBuffer> &buffer,
@@ -135,6 +138,9 @@
 
     sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
 
+    sp<ICrypto> mCrypto;
+    sp<IDescrambler> mDescrambler;
+
     bool hasCryptoOrDescrambler() {
         return mCrypto != NULL || mDescrambler != NULL;
     }
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index e728c00..bc7881c 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -257,15 +257,15 @@
  */
 class BufferChannelBase {
 public:
+    BufferChannelBase() = default;
     virtual ~BufferChannelBase() = default;
 
     inline void setCallback(std::unique_ptr<CodecBase::BufferCallback> &&callback) {
         mCallback = std::move(callback);
     }
 
-    void setCrypto(const sp<ICrypto> &crypto);
-
-    void setDescrambler(const sp<IDescrambler> &descrambler);
+    virtual void setCrypto(const sp<ICrypto> &) {}
+    virtual void setDescrambler(const sp<IDescrambler> &) {}
 
     /**
      * Queue an input buffer into the buffer channel.
@@ -336,8 +336,6 @@
 
 protected:
     std::unique_ptr<CodecBase::BufferCallback> mCallback;
-    sp<ICrypto> mCrypto;
-    sp<IDescrambler> mDescrambler;
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaFilter.h b/media/libstagefright/include/media/stagefright/MediaFilter.h
index a28c49d..1255e0f 100644
--- a/media/libstagefright/include/media/stagefright/MediaFilter.h
+++ b/media/libstagefright/include/media/stagefright/MediaFilter.h
@@ -21,9 +21,7 @@
 
 namespace android {
 
-class ACodecBufferChannel;
 struct GraphicBufferListener;
-class MemoryDealer;
 struct SimpleFilter;
 
 struct MediaFilter : public CodecBase {
@@ -65,6 +63,8 @@
         sp<MediaCodecBuffer> mData;
     };
 
+    class BufferChannel;
+
     enum State {
       UNINITIALIZED,
       INITIALIZED,
@@ -104,7 +104,6 @@
     sp<AMessage> mInputFormat;
     sp<AMessage> mOutputFormat;
 
-    sp<MemoryDealer> mDealer[2];
     Vector<BufferInfo> mBuffers[2];
     Vector<BufferInfo*> mAvailableInputBuffers;
     Vector<BufferInfo*> mAvailableOutputBuffers;
@@ -113,15 +112,15 @@
     sp<SimpleFilter> mFilter;
     sp<GraphicBufferListener> mGraphicBufferListener;
 
-    std::shared_ptr<ACodecBufferChannel> mBufferChannel;
+    std::shared_ptr<BufferChannel> mBufferChannel;
 
     // helper functions
     void signalProcessBuffers();
     void signalError(status_t error);
 
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
-    BufferInfo *findBufferByID(
-            uint32_t portIndex, uint32_t bufferID,
+    BufferInfo *findBuffer(
+            uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
             ssize_t *index = NULL);
     void postFillThisBuffer(BufferInfo *info);
     void postDrainThisBuffer(BufferInfo *info);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index cb1ef7f..53e2dd5 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -168,6 +168,7 @@
                 if (hwDevice != 0) {
                     hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
                 }
+                halHandle = removedPatch.mHalHandle;
             }
             mPatches.erase(iter);
             removeSoftwarePatchFromInsertedModules(*handle);
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 80df7db..5c6c518 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -139,7 +139,9 @@
     mOutputSlots.clear();
     mConsumerBufferCount.clear();
 
-    mConsumer->consumerDisconnect();
+    if (mConsumer.get() != nullptr) {
+        mConsumer->consumerDisconnect();
+    }
 
     if (mBuffers.size() > 0) {
         SP_LOGW("%zu buffers still being tracked", mBuffers.size());
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
deleted file mode 100644
index 72d42ae..0000000
--- a/services/mediadrm/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    MediaDrmService.cpp \
-    main_mediadrmserver.cpp
-
-LOCAL_HEADER_LIBRARIES:= \
-    libmedia_headers \
-    libmediadrm_headers
-
-LOCAL_SHARED_LIBRARIES:= \
-    libbinder \
-    liblog \
-    libmedia \
-    libmediadrm \
-    libutils \
-    libhidlbase \
-    libhidlmemory \
-    android.hardware.drm@1.0 \
-    android.hardware.drm@1.1 \
-    android.hardware.drm@1.2
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-LOCAL_MODULE:= mediadrmserver
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-LOCAL_INIT_RC := mediadrmserver.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
deleted file mode 100644
index 3cee88b..0000000
--- a/services/mediadrm/MediaDrmService.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-**
-** Copyright 2008, 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.
-*/
-
-// Proxy for media player implementations
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaDrmService"
-
-#include "MediaDrmService.h"
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-
-#include <mediadrm/CryptoHal.h>
-#include <mediadrm/DrmHal.h>
-
-namespace android {
-
-void MediaDrmService::instantiate() {
-    defaultServiceManager()->addService(
-            String16("media.drm"), new MediaDrmService());
-}
-
-} // namespace android
diff --git a/services/mediadrm/MediaDrmService.h b/services/mediadrm/MediaDrmService.h
deleted file mode 100644
index 8a11e36..0000000
--- a/services/mediadrm/MediaDrmService.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_MEDIADRMSERVICE_H
-#define ANDROID_MEDIADRMSERVICE_H
-
-#include <arpa/inet.h>
-
-#include <utils/threads.h>
-
-#include <media/Metadata.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <mediadrm/IMediaDrmService.h>
-
-namespace android {
-
-class MediaDrmService : public BnMediaDrmService
-{
-public:
-    static void instantiate();
-
-private:
-    MediaDrmService() {}
-    virtual ~MediaDrmService() {}
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_MEDIADRMSERVICE_H
diff --git a/services/mediadrm/OWNERS b/services/mediadrm/OWNERS
deleted file mode 100644
index 6d3b533..0000000
--- a/services/mediadrm/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jtinker@google.com
-marcone@google.com
diff --git a/services/mediadrm/main_mediadrmserver.cpp b/services/mediadrm/main_mediadrmserver.cpp
deleted file mode 100644
index b767b8c..0000000
--- a/services/mediadrm/main_mediadrmserver.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-**
-** Copyright 2008, 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 "mediaserver"
-//#define LOG_NDEBUG 0
-
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include "MediaDrmService.h"
-
-using namespace android;
-
-int main()
-{
-    signal(SIGPIPE, SIG_IGN);
-
-    sp<ProcessState> proc(ProcessState::self());
-    sp<IServiceManager> sm = defaultServiceManager();
-    ALOGI("ServiceManager: %p", sm.get());
-    MediaDrmService::instantiate();
-    ProcessState::self()->startThreadPool();
-    IPCThreadState::self()->joinThreadPool();
-}
diff --git a/services/mediadrm/mediadrmserver.rc b/services/mediadrm/mediadrmserver.rc
deleted file mode 100644
index 359c2cf..0000000
--- a/services/mediadrm/mediadrmserver.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service mediadrm /system/bin/mediadrmserver
-    class main
-    user media
-    group mediadrm drmrpc
-    ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
diff --git a/tools/OWNERS b/tools/OWNERS
deleted file mode 100644
index f9cb567..0000000
--- a/tools/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-gkasten@google.com
diff --git a/tools/resampler_tools/Android.bp b/tools/resampler_tools/Android.bp
deleted file mode 100644
index 7549359..0000000
--- a/tools/resampler_tools/Android.bp
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2005 The Android Open Source Project
-//
-// Android.mk for resampler_tools
-//
-
-cc_binary_host {
-    name: "fir",
-
-    srcs: ["fir.cpp"],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-}
diff --git a/tools/resampler_tools/OWNERS b/tools/resampler_tools/OWNERS
deleted file mode 100644
index b4a6798..0000000
--- a/tools/resampler_tools/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-hunga@google.com
diff --git a/tools/resampler_tools/fir.cpp b/tools/resampler_tools/fir.cpp
deleted file mode 100644
index fe4d212..0000000
--- a/tools/resampler_tools/fir.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-static inline double sinc(double x) {
-    if (fabs(x) == 0.0f) return 1.0f;
-    return sin(x) / x;
-}
-
-static inline double sqr(double x) {
-    return x*x;
-}
-
-static inline int64_t toint(double x, int64_t maxval) {
-    int64_t v;
-
-    v = static_cast<int64_t>(floor(x * maxval + 0.5));
-    if (v >= maxval) {
-        return maxval - 1; // error!
-    }
-    return v;
-}
-
-static double I0(double x) {
-    // from the Numerical Recipes in C p. 237
-    double ax,ans,y;
-    ax=fabs(x);
-    if (ax < 3.75) {
-        y=x/3.75;
-        y*=y;
-        ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492
-                +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
-    } else {
-        y=3.75/ax;
-        ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1
-                +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2
-                        +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1
-                                +y*0.392377e-2))))))));
-    }
-    return ans;
-}
-
-static double kaiser(int k, int N, double beta) {
-    if (k < 0 || k > N)
-        return 0;
-    return I0(beta * sqrt(1.0 - sqr((2.0*k)/N - 1.0))) / I0(beta);
-}
-
-static void usage(char* name) {
-    fprintf(stderr,
-            "usage: %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
-            " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] [-l lerp]\n"
-            "       %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
-            " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] -p M/N\n"
-            "    -h    this help message\n"
-            "    -d    debug, print comma-separated coefficient table\n"
-            "    -D    generate extra declarations\n"
-            "    -p    generate poly-phase filter coefficients, with sample increment M/N\n"
-            "    -s    sample rate (48000)\n"
-            "    -c    cut-off frequency (20478)\n"
-            "    -n    number of zero-crossings on one side (8)\n"
-            "    -l    number of lerping bits (4)\n"
-            "    -m    number of polyphases (related to -l, default 16)\n"
-            "    -f    output format, can be fixed, fixed16, or float (fixed)\n"
-            "    -b    kaiser window parameter beta (7.865 [-80dB])\n"
-            "    -v    attenuation in dBFS (0)\n",
-            name, name
-    );
-    exit(0);
-}
-
-int main(int argc, char** argv)
-{
-    // nc is the number of bits to store the coefficients
-    int nc = 32;
-    bool polyphase = false;
-    unsigned int polyM = 160;
-    unsigned int polyN = 147;
-    bool debug = false;
-    double Fs = 48000;
-    double Fc = 20478;
-    double atten = 1;
-    int format = 0;     // 0=fixed, 1=float
-    bool declarations = false;
-
-    // in order to keep the errors associated with the linear
-    // interpolation of the coefficients below the quantization error
-    // we must satisfy:
-    //   2^nz >= 2^(nc/2)
-    //
-    // for 16 bit coefficients that would be 256
-    //
-    // note that increasing nz only increases memory requirements,
-    // but doesn't increase the amount of computation to do.
-    //
-    //
-    // see:
-    // Smith, J.O. Digital Audio Resampling Home Page
-    // https://ccrma.stanford.edu/~jos/resample/, 2011-03-29
-    //
-
-    //         | 0.1102*(A - 8.7)                         A > 50
-    //  beta = | 0.5842*(A - 21)^0.4 + 0.07886*(A - 21)   21 <= A <= 50
-    //         | 0                                        A < 21
-    //   with A is the desired stop-band attenuation in dBFS
-    //
-    // for eg:
-    //
-    //    30 dB    2.210
-    //    40 dB    3.384
-    //    50 dB    4.538
-    //    60 dB    5.658
-    //    70 dB    6.764
-    //    80 dB    7.865
-    //    90 dB    8.960
-    //   100 dB   10.056
-    double beta = 7.865;
-
-    // 2*nzc = (A - 8) / (2.285 * dw)
-    //      with dw the transition width = 2*pi*dF/Fs
-    //
-    int nzc = 8;
-
-    /*
-     * Example:
-     * 44.1 KHz to 48 KHz resampling
-     * 100 dB rejection above 28 KHz
-     *   (the spectrum will fold around 24 KHz and we want 100 dB rejection
-     *    at the point where the folding reaches 20 KHz)
-     *  ...___|_____
-     *        |     \|
-     *        | ____/|\____
-     *        |/alias|     \
-     *  ------/------+------\---------> KHz
-     *       20     24     28
-     *
-     * Transition band 8 KHz, or dw = 1.0472
-     *
-     * beta = 10.056
-     * nzc  = 20
-     */
-
-    int M = 1 << 4; // number of phases for interpolation
-    int ch;
-    while ((ch = getopt(argc, argv, ":hds:c:n:f:l:m:b:p:v:z:D")) != -1) {
-        switch (ch) {
-            case 'd':
-                debug = true;
-                break;
-            case 'D':
-                declarations = true;
-                break;
-            case 'p':
-                if (sscanf(optarg, "%u/%u", &polyM, &polyN) != 2) {
-                    usage(argv[0]);
-                }
-                polyphase = true;
-                break;
-            case 's':
-                Fs = atof(optarg);
-                break;
-            case 'c':
-                Fc = atof(optarg);
-                break;
-            case 'n':
-                nzc = atoi(optarg);
-                break;
-            case 'm':
-                M = atoi(optarg);
-                break;
-            case 'l':
-                M = 1 << atoi(optarg);
-                break;
-            case 'f':
-                if (!strcmp(optarg, "fixed")) {
-                    format = 0;
-                }
-                else if (!strcmp(optarg, "fixed16")) {
-                    format = 0;
-                    nc = 16;
-                }
-                else if (!strcmp(optarg, "float")) {
-                    format = 1;
-                }
-                else {
-                    usage(argv[0]);
-                }
-                break;
-            case 'b':
-                beta = atof(optarg);
-                break;
-            case 'v':
-                atten = pow(10, -fabs(atof(optarg))*0.05 );
-                break;
-            case 'h':
-            default:
-                usage(argv[0]);
-                break;
-        }
-    }
-
-    // cut off frequency ratio Fc/Fs
-    double Fcr = Fc / Fs;
-
-    // total number of coefficients (one side)
-
-    const int N = M * nzc;
-
-    // lerp (which is most useful if M is a power of 2)
-
-    int nz = 0; // recalculate nz as the bits needed to represent M
-    for (int i = M-1 ; i; i>>=1, nz++);
-    // generate the right half of the filter
-    if (!debug) {
-        printf("// cmd-line:");
-        for (int i=0 ; i<argc ; i++) {
-            printf(" %s", argv[i]);
-        }
-        printf("\n");
-        if (declarations) {
-            if (!polyphase) {
-                printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", N);
-                printf("const int32_t RESAMPLE_FIR_INT_PHASES     = %d;\n", M);
-                printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", nzc);
-            } else {
-                printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", 2*nzc*polyN);
-                printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", 2*nzc);
-            }
-            if (!format) {
-                printf("const int32_t RESAMPLE_FIR_COEF_BITS      = %d;\n", nc);
-            }
-            printf("\n");
-            printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float");
-        }
-    }
-
-    if (!polyphase) {
-        for (int i=0 ; i<=M ; i++) { // an extra set of coefs for interpolation
-            for (int j=0 ; j<nzc ; j++) {
-                int ix = j*M + i;
-                double x = (2.0 * M_PI * ix * Fcr) / M;
-                double y = kaiser(ix+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;
-                y *= atten;
-
-                if (!debug) {
-                    if (j == 0)
-                        printf("\n    ");
-                }
-                if (!format) {
-                    int64_t yi = toint(y, 1ULL<<(nc-1));
-                    if (nc > 16) {
-                        printf("0x%08x,", int32_t(yi));
-                    } else {
-                        printf("0x%04x,", int32_t(yi)&0xffff);
-                    }
-                } else {
-                    printf("%.9g%s", y, debug ? "," : "f,");
-                }
-                if (j != nzc-1) {
-                    printf(" ");
-                }
-            }
-        }
-    } else {
-        for (unsigned int j=0 ; j<polyN ; j++) {
-            // calculate the phase
-            double p = ((polyM*j) % polyN) / double(polyN);
-            if (!debug) printf("\n    ");
-            else        printf("\n");
-            // generate a FIR per phase
-            for (int i=-nzc ; i<nzc ; i++) {
-                double x = 2.0 * M_PI * Fcr * (i + p);
-                double y = kaiser(i+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;;
-                y *= atten;
-                if (!format) {
-                    int64_t yi = toint(y, 1ULL<<(nc-1));
-                    if (nc > 16) {
-                        printf("0x%08x,", int32_t(yi));
-                    } else {
-                        printf("0x%04x,", int32_t(yi)&0xffff);
-                    }
-                } else {
-                    printf("%.9g%s", y, debug ? "," : "f,");
-                }
-
-                if (i != nzc-1) {
-                    printf(" ");
-                }
-            }
-        }
-    }
-
-    if (!debug && declarations) {
-        printf("\n};");
-    }
-    printf("\n");
-    return 0;
-}
-
-// http://www.csee.umbc.edu/help/sound/AFsp-V2R1/html/audio/ResampAudio.html