Merge changes from topic 'OMX Treble 2'

* changes:
  Split Treble conversion module into two sides: impl and utils.
  Use HIDL's memory in CodecBuffer and add wrapper classes for IOmxBufferProducer and IOmxProducerListener.
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index ab99e38..c0da592 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -278,6 +278,7 @@
         case ACAMERA_CONTROL_SCENE_MODE:
         case ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE:
         case ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST:
+        case ACAMERA_CONTROL_ENABLE_ZSL:
         case ACAMERA_EDGE_MODE:
         case ACAMERA_FLASH_MODE:
         case ACAMERA_HOT_PIXEL_MODE:
diff --git a/drm/libmediadrm/Android.mk b/drm/libmediadrm/Android.mk
index 3f0e663..7e77aac 100644
--- a/drm/libmediadrm/Android.mk
+++ b/drm/libmediadrm/Android.mk
@@ -7,14 +7,21 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    Crypto.cpp \
-    Drm.cpp \
     DrmSessionManager.cpp \
     ICrypto.cpp \
     IDrm.cpp \
     IDrmClient.cpp \
     IMediaDrmService.cpp \
     SharedLibrary.cpp
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_SRC_FILES += \
+    DrmHal.cpp \
+    CryptoHal.cpp
+else
+LOCAL_SRC_FILES += \
+    Drm.cpp \
+    Crypto.cpp
+endif
 
 LOCAL_SHARED_LIBRARIES := \
     libbinder \
@@ -24,6 +31,13 @@
     libmediautils \
     libstagefright_foundation \
     libutils
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_SHARED_LIBRARIES += \
+    android.hidl.base@1.0 \
+    android.hardware.drm@1.0 \
+    libhidlbase \
+    libhidlmemory
+endif
 
 LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
 
diff --git a/drm/libmediadrm/Crypto.cpp b/drm/libmediadrm/Crypto.cpp
index 79633cb..d93dad6 100644
--- a/drm/libmediadrm/Crypto.cpp
+++ b/drm/libmediadrm/Crypto.cpp
@@ -233,16 +233,12 @@
     return mPlugin->requiresSecureDecoderComponent(mime);
 }
 
-ssize_t Crypto::decrypt(
-        DestinationType dstType,
-        const uint8_t key[16],
-        const uint8_t iv[16],
-        CryptoPlugin::Mode mode,
-        const CryptoPlugin::Pattern &pattern,
-        const sp<IMemory> &sharedBuffer, size_t offset,
+ssize_t Crypto::decrypt(const uint8_t key[16], const uint8_t iv[16],
+        CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+        const sp<IMemory> &source, size_t offset,
         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-        void *dstPtr,
-        AString *errorDetailMsg) {
+        const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -253,12 +249,21 @@
         return -EINVAL;
     }
 
-    const void *srcPtr = static_cast<uint8_t *>(sharedBuffer->pointer()) + offset;
+    const void *srcPtr = static_cast<uint8_t *>(source->pointer()) + offset;
 
-    return mPlugin->decrypt(
-            dstType != kDestinationTypeVmPointer,
-            key, iv, mode, pattern, srcPtr, subSamples, numSubSamples, dstPtr,
-            errorDetailMsg);
+    void *destPtr;
+    bool secure = false;
+    if (destination.mType == kDestinationTypeNativeHandle) {
+        destPtr = static_cast<void *>(destination.mHandle);
+        secure = true;
+    } else {
+        destPtr = destination.mSharedMemory->pointer();
+    }
+
+    ssize_t result = mPlugin->decrypt(secure, key, iv, mode, pattern, srcPtr, subSamples,
+            numSubSamples, destPtr, errorDetailMsg);
+
+    return result;
 }
 
 void Crypto::notifyResolution(uint32_t width, uint32_t height) {
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
new file mode 100644
index 0000000..f1f3b01
--- /dev/null
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CryptoHal"
+#include <utils/Log.h>
+#include <dirent.h>
+#include <dlfcn.h>
+
+#include <android/hardware/drm/1.0/types.h>
+
+#include <binder/IMemory.h>
+#include <cutils/native_handle.h>
+#include <media/CryptoHal.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaErrors.h>
+
+using ::android::hardware::drm::V1_0::BufferType;
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SharedBuffer;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+
+namespace android {
+
+static status_t toStatusT(Status status) {
+    switch (status) {
+    case Status::OK:
+        return OK;
+    case Status::ERROR_DRM_NO_LICENSE:
+        return ERROR_DRM_NO_LICENSE;
+    case Status::ERROR_DRM_LICENSE_EXPIRED:
+        return ERROR_DRM_LICENSE_EXPIRED;
+    case Status::ERROR_DRM_RESOURCE_BUSY:
+        return ERROR_DRM_RESOURCE_BUSY;
+    case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+    case Status::ERROR_DRM_SESSION_NOT_OPENED:
+        return ERROR_DRM_SESSION_NOT_OPENED;
+    case Status::ERROR_DRM_CANNOT_HANDLE:
+        return ERROR_DRM_CANNOT_HANDLE;
+    default:
+        return UNKNOWN_ERROR;
+    }
+}
+
+
+static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
+    hidl_vec<uint8_t> vec;
+    vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
+    return vec;
+}
+
+static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
+    hidl_vec<uint8_t> vec;
+    vec.resize(size);
+    memcpy(vec.data(), ptr, size);
+    return vec;
+}
+
+static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
+    if (!ptr) {
+        return hidl_array<uint8_t, 16>();
+    }
+    return hidl_array<uint8_t, 16>(ptr);
+}
+
+
+static ::SharedBuffer toSharedBuffer(const sp<IMemory>& sharedBuffer) {
+    ssize_t offset;
+    size_t size;
+    sharedBuffer->getMemory(&offset, &size);
+
+    ::SharedBuffer buffer;
+    buffer.offset = offset >= 0 ? offset : 0;
+    buffer.size = size;
+    return buffer;
+}
+
+static String8 toString8(hidl_string hString) {
+    return String8(hString.c_str());
+}
+
+
+CryptoHal::CryptoHal()
+    : mFactory(makeCryptoFactory()),
+      mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT),
+      mHeapBase(NULL) {
+}
+
+CryptoHal::~CryptoHal() {
+}
+
+
+sp<ICryptoFactory> CryptoHal::makeCryptoFactory() {
+    sp<ICryptoFactory> factory = ICryptoFactory::getService("crypto");
+    if (factory == NULL) {
+        ALOGE("Failed to make crypto factory");
+    }
+    return factory;
+}
+
+sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const uint8_t uuid[16],
+        const void *initData, size_t initDataSize) {
+    if (mFactory == NULL){
+        return NULL;
+    }
+
+    sp<ICryptoPlugin> plugin;
+    Return<void> hResult = mFactory->createPlugin(toHidlArray16(uuid),
+            toHidlVec(initData, initDataSize),
+            [&](Status status, const sp<ICryptoPlugin>& hPlugin) {
+                if (status != Status::OK) {
+                    ALOGE("Failed to make crypto plugin");
+                    return;
+                }
+                plugin = hPlugin;
+            }
+        );
+    return plugin;
+}
+
+
+status_t CryptoHal::initCheck() const {
+    return mInitCheck;
+}
+
+
+bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+    Mutex::Autolock autoLock(mLock);
+    if (mFactory != NULL) {
+        return mFactory->isCryptoSchemeSupported(uuid);
+    }
+    return false;
+}
+
+status_t CryptoHal::createPlugin(
+        const uint8_t uuid[16], const void *data, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    mPlugin = makeCryptoPlugin(uuid, data, size);
+
+    if (mPlugin == NULL) {
+        mInitCheck = ERROR_UNSUPPORTED;
+    } else {
+        mInitCheck = OK;
+    }
+
+    return mInitCheck;
+}
+
+status_t CryptoHal::destroyPlugin() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    mPlugin.clear();
+    return OK;
+}
+
+bool CryptoHal::requiresSecureDecoderComponent(const char *mime) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    return mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
+}
+
+
+/**
+ * If the heap base isn't set, get the heap base from the IMemory
+ * and send it to the HAL so it can map a remote heap of the same
+ * size.  Once the heap base is established, shared memory buffers
+ * are sent by providing an offset into the heap and a buffer size.
+ */
+status_t CryptoHal::setHeapBase(const sp<IMemory>& sharedBuffer) {
+    sp<IMemoryHeap> heap = sharedBuffer->getMemory(NULL, NULL);
+    if (mHeapBase != heap->getBase()) {
+        int fd = heap->getHeapID();
+        native_handle_t* nativeHandle = native_handle_create(1, 0);
+        nativeHandle->data[0] = fd;
+        auto hidlHandle = hidl_handle(nativeHandle);
+        auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
+        mHeapBase = heap->getBase();
+        Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory);
+        if (!hResult.isOk()) {
+            return DEAD_OBJECT;
+        }
+    }
+    return OK;
+}
+
+ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
+        CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+        const sp<IMemory> &source, size_t offset,
+        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+        const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    // Establish the base of the shared memory heap
+    setHeapBase(source);
+
+    Mode hMode;
+    switch(mode) {
+    case CryptoPlugin::kMode_Unencrypted:
+        hMode = Mode::UNENCRYPTED ;
+        break;
+    case CryptoPlugin::kMode_AES_CTR:
+        hMode = Mode::AES_CTR;
+        break;
+    case CryptoPlugin::kMode_AES_WV:
+        hMode = Mode::AES_CBC_CTS;
+        break;
+    case CryptoPlugin::kMode_AES_CBC:
+        hMode = Mode::AES_CBC;
+        break;
+    default:
+        return UNKNOWN_ERROR;
+    }
+
+    Pattern hPattern;
+    hPattern.encryptBlocks = pattern.mEncryptBlocks;
+    hPattern.skipBlocks = pattern.mSkipBlocks;
+
+    std::vector<SubSample> stdSubSamples;
+    for (size_t i = 0; i < numSubSamples; i++) {
+        SubSample subSample;
+        subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
+        subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
+        stdSubSamples.push_back(subSample);
+    }
+    auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
+
+    bool secure;
+    ::DestinationBuffer hDestination;
+    if (destination.mType == kDestinationTypeSharedMemory) {
+        hDestination.type = BufferType::SHARED_MEMORY;
+        hDestination.nonsecureMemory = toSharedBuffer(destination.mSharedMemory);
+        secure = false;
+    } else {
+        hDestination.type = BufferType::NATIVE_HANDLE;
+        hDestination.secureMemory = hidl_handle(destination.mHandle);
+        secure = true;
+    }
+
+
+    status_t err = UNKNOWN_ERROR;
+    uint32_t bytesWritten = 0;
+
+    Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode,
+            hPattern, hSubSamples, toSharedBuffer(source), offset, hDestination,
+            [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+                if (status == Status::OK) {
+                    bytesWritten = hBytesWritten;
+                    *errorDetailMsg = toString8(hDetailedError);
+                }
+                err = toStatusT(status);
+            }
+        );
+
+    if (!hResult.isOk()) {
+        err = DEAD_OBJECT;
+    }
+
+    if (err == OK) {
+        return bytesWritten;
+    }
+    return err;
+}
+
+void CryptoHal::notifyResolution(uint32_t width, uint32_t height) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return;
+    }
+
+    mPlugin->notifyResolution(width, height);
+}
+
+status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t> &sessionId) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    return toStatusT(mPlugin->setMediaDrmSession(toHidlVec(sessionId)));
+}
+
+}  // namespace android
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
new file mode 100644
index 0000000..304cdaf
--- /dev/null
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -0,0 +1,950 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "DrmHal"
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <dirent.h>
+#include <dlfcn.h>
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/types.h>
+
+#include <media/DrmHal.h>
+#include <media/DrmSessionClientInterface.h>
+#include <media/DrmSessionManager.h>
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaErrors.h>
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::KeyedVector;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyStatusType;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+namespace android {
+
+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());
+    return *const_cast<const Vector<uint8_t> *>(&vector);
+}
+
+static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
+    hidl_vec<uint8_t> vec;
+    vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
+    return vec;
+}
+
+static String8 toString8(const hidl_string &string) {
+    return String8(string.c_str());
+}
+
+static hidl_string toHidlString(const String8& string) {
+    return hidl_string(string.string());
+}
+
+
+static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
+        keyedVector) {
+    std::vector<KeyValue> stdKeyedVector;
+    for (size_t i = 0; i < keyedVector.size(); i++) {
+        KeyValue keyValue;
+        keyValue.key = toHidlString(keyedVector.keyAt(i));
+        keyValue.value = toHidlString(keyedVector.valueAt(i));
+        stdKeyedVector.push_back(keyValue);
+    }
+    return ::KeyedVector(stdKeyedVector);
+}
+
+static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
+        hKeyedVector) {
+    KeyedVector<String8, String8> keyedVector;
+    for (size_t i = 0; i < hKeyedVector.size(); i++) {
+        keyedVector.add(toString8(hKeyedVector[i].key),
+                toString8(hKeyedVector[i].value));
+    }
+    return keyedVector;
+}
+
+static List<Vector<uint8_t> > toSecureStops(const hidl_vec<SecureStop>&
+        hSecureStops) {
+    List<Vector<uint8_t> > secureStops;
+    for (size_t i = 0; i < hSecureStops.size(); i++) {
+        secureStops.push_back(toVector(hSecureStops[i].opaqueData));
+    }
+    return secureStops;
+}
+
+static status_t toStatusT(Status status) {
+    switch (status) {
+    case Status::OK:
+        return OK;
+        break;
+    case Status::ERROR_DRM_NO_LICENSE:
+        return ERROR_DRM_NO_LICENSE;
+        break;
+    case Status::ERROR_DRM_LICENSE_EXPIRED:
+        return ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case Status::ERROR_DRM_SESSION_NOT_OPENED:
+        return ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+    case Status::ERROR_DRM_CANNOT_HANDLE:
+        return ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case Status::ERROR_DRM_INVALID_STATE:
+        return ERROR_DRM_TAMPER_DETECTED;
+        break;
+    case Status::BAD_VALUE:
+        return BAD_VALUE;
+        break;
+    case Status::ERROR_DRM_NOT_PROVISIONED:
+        return ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case Status::ERROR_DRM_RESOURCE_BUSY:
+        return ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case Status::ERROR_DRM_DEVICE_REVOKED:
+        return ERROR_DRM_DEVICE_REVOKED;
+        break;
+    case Status::ERROR_DRM_UNKNOWN:
+    default:
+        return ERROR_DRM_UNKNOWN;
+        break;
+    }
+}
+
+
+Mutex DrmHal::mLock;
+
+struct DrmSessionClient : public DrmSessionClientInterface {
+    explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
+
+    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
+        sp<DrmHal> drm = mDrm.promote();
+        if (drm == NULL) {
+            return true;
+        }
+        status_t err = drm->closeSession(sessionId);
+        if (err != OK) {
+            return false;
+        }
+        drm->sendEvent(EventType::SESSION_RECLAIMED,
+                toHidlVec(sessionId), hidl_vec<uint8_t>());
+        return true;
+    }
+
+protected:
+    virtual ~DrmSessionClient() {}
+
+private:
+    wp<DrmHal> mDrm;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
+DrmHal::DrmHal()
+   : mDrmSessionClient(new DrmSessionClient(this)),
+     mFactory(makeDrmFactory()),
+     mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT) {
+}
+
+DrmHal::~DrmHal() {
+    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
+}
+
+sp<IDrmFactory> DrmHal::makeDrmFactory() {
+    sp<IDrmFactory> factory = IDrmFactory::getService("drm");
+    if (factory == NULL) {
+        ALOGE("Failed to make drm factory");
+    }
+    return factory;
+}
+
+sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16]) {
+    if (mFactory == NULL){
+        return NULL;
+    }
+
+    sp<IDrmPlugin> plugin;
+    Return<void> hResult = mFactory->createPlugin(uuid,
+            [&](Status status, const sp<IDrmPlugin>& hPlugin) {
+                if (status != Status::OK) {
+                    ALOGD("Failed to make drm plugin");
+                    return;
+                }
+                plugin = hPlugin;
+            }
+        );
+    return plugin;
+}
+
+status_t DrmHal::initCheck() const {
+    return mInitCheck;
+}
+
+status_t DrmHal::setListener(const sp<IDrmClient>& listener)
+{
+    Mutex::Autolock lock(mEventLock);
+    if (mListener != NULL){
+        IInterface::asBinder(mListener)->unlinkToDeath(this);
+    }
+    if (listener != NULL) {
+        IInterface::asBinder(listener)->linkToDeath(this);
+    }
+    mListener = listener;
+    return NO_ERROR;
+}
+
+Return<void> DrmHal::sendEvent(EventType hEventType,
+        const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+
+    mEventLock.lock();
+    sp<IDrmClient> listener = mListener;
+    mEventLock.unlock();
+
+    if (listener != NULL) {
+        Parcel obj;
+        writeByteArray(obj, sessionId);
+        writeByteArray(obj, data);
+
+        Mutex::Autolock lock(mNotifyLock);
+        DrmPlugin::EventType eventType;
+        switch(hEventType) {
+        case EventType::PROVISION_REQUIRED:
+            eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
+            break;
+        case EventType::KEY_NEEDED:
+            eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
+            break;
+        case EventType::KEY_EXPIRED:
+            eventType = DrmPlugin::kDrmPluginEventKeyExpired;
+            break;
+        case EventType::VENDOR_DEFINED:
+            eventType = DrmPlugin::kDrmPluginEventVendorDefined;
+            break;
+        default:
+            return Void();
+        }
+        listener->notify(eventType, 0, &obj);
+    }
+    return Void();
+}
+
+Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+        int64_t expiryTimeInMS) {
+
+    mEventLock.lock();
+    sp<IDrmClient> listener = mListener;
+    mEventLock.unlock();
+
+    if (listener != NULL) {
+        Parcel obj;
+        writeByteArray(obj, sessionId);
+        obj.writeInt64(expiryTimeInMS);
+
+        Mutex::Autolock lock(mNotifyLock);
+        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+    }
+    return Void();
+}
+
+Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+        const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+
+    mEventLock.lock();
+    sp<IDrmClient> listener = mListener;
+    mEventLock.unlock();
+
+    if (listener != NULL) {
+        Parcel obj;
+        writeByteArray(obj, sessionId);
+
+        size_t nKeys = keyStatusList.size();
+        obj.writeInt32(nKeys);
+        for (size_t i = 0; i < nKeys; ++i) {
+            const KeyStatus &keyStatus = keyStatusList[i];
+            writeByteArray(obj, keyStatus.keyId);
+            uint32_t type;
+            switch(keyStatus.type) {
+            case KeyStatusType::USABLE:
+                type = DrmPlugin::kKeyStatusType_Usable;
+                break;
+            case KeyStatusType::EXPIRED:
+                type = DrmPlugin::kKeyStatusType_Expired;
+                break;
+            case KeyStatusType::OUTPUTNOTALLOWED:
+                type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
+                break;
+            case KeyStatusType::STATUSPENDING:
+                type = DrmPlugin::kKeyStatusType_StatusPending;
+                break;
+            case KeyStatusType::INTERNALERROR:
+            default:
+                type = DrmPlugin::kKeyStatusType_InternalError;
+                break;
+            }
+            obj.writeInt32(type);
+        }
+        obj.writeInt32(hasNewUsableKey);
+
+        Mutex::Autolock lock(mNotifyLock);
+        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+    }
+    return Void();
+}
+
+bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
+    Mutex::Autolock autoLock(mLock);
+    bool result = false;
+
+    if (mFactory != NULL && mFactory->isCryptoSchemeSupported(uuid)) {
+        if (mimeType != "") {
+            result = mFactory->isContentTypeSupported(mimeType.string());
+        }
+    }
+    return result;
+}
+
+status_t DrmHal::createPlugin(const uint8_t uuid[16]) {
+    Mutex::Autolock autoLock(mLock);
+
+    mPlugin = makeDrmPlugin(uuid);
+
+    if (mPlugin == NULL) {
+        mInitCheck = ERROR_UNSUPPORTED;
+    } else {
+        mInitCheck = OK;
+        mPlugin->setListener(this);
+    }
+
+    return mInitCheck;
+}
+
+status_t DrmHal::destroyPlugin() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    setListener(NULL);
+    mPlugin.clear();
+
+    return OK;
+}
+
+status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t  err = UNKNOWN_ERROR;
+
+    bool retry = true;
+    do {
+        hidl_vec<uint8_t> hSessionId;
+
+        Return<void> hResult = mPlugin->openSession(
+                [&](Status status, const hidl_vec<uint8_t>& id) {
+                    if (status == Status::OK) {
+                        sessionId = toVector(id);
+                    }
+                    err = toStatusT(status);
+                }
+            );
+
+        if (!hResult.isOk()) {
+            err = DEAD_OBJECT;
+        }
+
+        if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
+            mLock.unlock();
+            // 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());
+            mLock.lock();
+        } else {
+            retry = false;
+        }
+    } while (retry);
+
+    if (err == OK) {
+        DrmSessionManager::Instance()->addSession(getCallingPid(),
+                mDrmSessionClient, sessionId);
+    }
+    return err;
+}
+
+status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    Status status = mPlugin->closeSession(toHidlVec(sessionId));
+    if (status == Status::OK) {
+        DrmSessionManager::Instance()->removeSession(sessionId);
+    }
+    return toStatusT(status);
+}
+
+status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
+        Vector<uint8_t> const &initData, String8 const &mimeType,
+        DrmPlugin::KeyType keyType, KeyedVector<String8,
+        String8> const &optionalParameters, Vector<uint8_t> &request,
+        String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    KeyType hKeyType;
+    if (keyType == DrmPlugin::kKeyType_Streaming) {
+        hKeyType = KeyType::STREAMING;
+    } else if (keyType == DrmPlugin::kKeyType_Offline) {
+        hKeyType = KeyType::OFFLINE;
+    } else if (keyType == DrmPlugin::kKeyType_Release) {
+        hKeyType = KeyType::RELEASE;
+    } else {
+        return BAD_VALUE;
+    }
+
+    ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
+            toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
+            [&](Status status, const hidl_vec<uint8_t>& hRequest,
+                    KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
+
+                if (status == Status::OK) {
+                    request = toVector(hRequest);
+                    defaultUrl = toString8(hDefaultUrl);
+
+                    switch (hKeyRequestType) {
+                    case KeyRequestType::INITIAL:
+                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
+                        break;
+                    case KeyRequestType::RENEWAL:
+                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
+                        break;
+                    case KeyRequestType::RELEASE:
+                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
+                        break;
+                    default:
+                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
+                        break;
+                    }
+                    err = toStatusT(status);
+                }
+            });
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
+        Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
+            toHidlVec(response),
+            [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
+                if (status == Status::OK) {
+                    keySetId = toVector(hKeySetId);
+                }
+                err = toStatusT(status);
+            }
+        );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
+}
+
+status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
+        Vector<uint8_t> const &keySetId) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
+                    toHidlVec(keySetId)));
+}
+
+status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
+        KeyedVector<String8, String8> &infoMap) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    ::KeyedVector hInfoMap;
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
+            [&](Status status, const hidl_vec<KeyValue>& map) {
+                if (status == Status::OK) {
+                    infoMap = toKeyedVector(map);
+                }
+                err = toStatusT(status);
+            }
+        );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::getProvisionRequest(String8 const &certType,
+        String8 const &certAuthority, Vector<uint8_t> &request,
+        String8 &defaultUrl) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->getProvisionRequest(
+            toHidlString(certType), toHidlString(certAuthority),
+            [&](Status status, const hidl_vec<uint8_t>& hRequest,
+                    const hidl_string& hDefaultUrl) {
+                if (status == Status::OK) {
+                    request = toVector(hRequest);
+                    defaultUrl = toString8(hDefaultUrl);
+                }
+                err = toStatusT(status);
+            }
+        );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
+                                       Vector<uint8_t> &certificate,
+                                       Vector<uint8_t> &wrappedKey) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
+            [&](Status status, const hidl_vec<uint8_t>& hCertificate,
+                    const hidl_vec<uint8_t>& hWrappedKey) {
+                if (status == Status::OK) {
+                    certificate = toVector(hCertificate);
+                    wrappedKey = toVector(hWrappedKey);
+                }
+                err = toStatusT(status);
+            }
+        );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::getSecureStops(List<Vector<uint8_t> > &secureStops) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
+                if (status == Status::OK) {
+                    secureStops = toSecureStops(hSecureStops);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+
+status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
+            [&](Status status, const SecureStop& hSecureStop) {
+                if (status == Status::OK) {
+                    secureStop = toVector(hSecureStop.opaqueData);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
+}
+
+status_t DrmHal::releaseAllSecureStops() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    return toStatusT(mPlugin->releaseAllSecureStops());
+}
+
+status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
+            [&](Status status, const hidl_string& hValue) {
+                if (status == Status::OK) {
+                    value = toString8(hValue);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
+            [&](Status status, const hidl_vec<uint8_t>& hValue) {
+                if (status == Status::OK) {
+                    value = toVector(hValue);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    Status status =  mPlugin->setPropertyString(toHidlString(name),
+            toHidlString(value));
+    return toStatusT(status);
+}
+
+status_t DrmHal::setPropertyByteArray(String8 const &name,
+                                   Vector<uint8_t> const &value ) const {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    Status status = mPlugin->setPropertyByteArray(toHidlString(name),
+            toHidlVec(value));
+    return toStatusT(status);
+}
+
+
+status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                 String8 const &algorithm) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
+            toHidlString(algorithm));
+    return toStatusT(status);
+}
+
+status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                              String8 const &algorithm) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
+            toHidlString(algorithm));
+    return toStatusT(status);
+}
+
+status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
+                      Vector<uint8_t> const &keyId,
+                      Vector<uint8_t> const &input,
+                      Vector<uint8_t> const &iv,
+                      Vector<uint8_t> &output) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
+            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
+            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
+                if (status == Status::OK) {
+                    output = toVector(hOutput);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
+                      Vector<uint8_t> const &keyId,
+                      Vector<uint8_t> const &input,
+                      Vector<uint8_t> const &iv,
+                      Vector<uint8_t> &output) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    status_t  err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
+            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
+            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
+                if (status == Status::OK) {
+                    output = toVector(hOutput);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
+                   Vector<uint8_t> const &keyId,
+                   Vector<uint8_t> const &message,
+                   Vector<uint8_t> &signature) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
+            toHidlVec(keyId), toHidlVec(message),
+            [&](Status status, const hidl_vec<uint8_t>& hSignature)  {
+                if (status == Status::OK) {
+                    signature = toVector(hSignature);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
+                     Vector<uint8_t> const &keyId,
+                     Vector<uint8_t> const &message,
+                     Vector<uint8_t> const &signature,
+                     bool &match) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
+            toHidlVec(message), toHidlVec(signature),
+            [&](Status status, bool hMatch) {
+                if (status == Status::OK) {
+                    match = hMatch;
+                } else {
+                    match = false;
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
+                      String8 const &algorithm,
+                      Vector<uint8_t> const &message,
+                      Vector<uint8_t> const &wrappedKey,
+                      Vector<uint8_t> &signature) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
+        return -EPERM;
+    }
+
+    DrmSessionManager::Instance()->useSession(sessionId);
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
+            toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
+            [&](Status status, const hidl_vec<uint8_t>& hSignature) {
+                if (status == Status::OK) {
+                    signature = toVector(hSignature);
+                }
+                err = toStatusT(status);
+            }
+        );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
+{
+    mEventLock.lock();
+    mListener.clear();
+    mEventLock.unlock();
+
+    Mutex::Autolock autoLock(mLock);
+    mPlugin.clear();
+}
+
+void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
+{
+    if (vec.size()) {
+        obj.writeInt32(vec.size());
+        obj.write(vec.data(), vec.size());
+    } else {
+        obj.writeInt32(0);
+    }
+}
+
+}  // namespace android
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
index 8ba80c6..10e6bc3 100644
--- a/drm/libmediadrm/ICrypto.cpp
+++ b/drm/libmediadrm/ICrypto.cpp
@@ -94,18 +94,13 @@
         return reply.readInt32() != 0;
     }
 
-    virtual ssize_t decrypt(
-            DestinationType dstType,
-            const uint8_t key[16],
-            const uint8_t iv[16],
+    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const sp<IMemory> &sharedBuffer, size_t offset,
+            const sp<IMemory> &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            void *dstPtr,
-            AString *errorDetailMsg) {
+            const DestinationBuffer &destination, AString *errorDetailMsg) {
         Parcel data, reply;
         data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32((int32_t)dstType);
         data.writeInt32(mode);
         data.writeInt32(pattern.mEncryptBlocks);
         data.writeInt32(pattern.mSkipBlocks);
@@ -130,18 +125,23 @@
         }
 
         data.writeInt32(totalSize);
-        data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
+        data.writeStrongBinder(IInterface::asBinder(source));
         data.writeInt32(offset);
 
         data.writeInt32(numSubSamples);
         data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
 
-        if (dstType == kDestinationTypeNativeHandle) {
-            data.writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
-        } else if (dstType == kDestinationTypeOpaqueHandle) {
-            data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
+        data.writeInt32((int32_t)destination.mType);
+        if (destination.mType == kDestinationTypeNativeHandle) {
+            if (destination.mHandle == NULL) {
+                return BAD_VALUE;
+            }
+            data.writeNativeHandle(destination.mHandle);
         } else {
-            dstType = kDestinationTypeVmPointer;
+            if (destination.mSharedMemory == NULL) {
+                return BAD_VALUE;
+            }
+            data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
         }
 
         remote()->transact(DECRYPT, data, &reply);
@@ -150,10 +150,6 @@
 
         if (isCryptoError(result)) {
             errorDetailMsg->setTo(reply.readCString());
-        } else if (dstType == kDestinationTypeVmPointer) {
-            // For the non-secure case, copy the decrypted
-            // data from shared memory to its final destination
-            memcpy(dstPtr, sharedBuffer->pointer(), result);
         }
 
         return result;
@@ -280,7 +276,6 @@
         {
             CHECK_INTERFACE(ICrypto, data, reply);
 
-            DestinationType dstType = (DestinationType)data.readInt32();
             CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
             CryptoPlugin::Pattern pattern;
             pattern.mEncryptBlocks = data.readInt32();
@@ -293,9 +288,9 @@
             data.read(iv, sizeof(iv));
 
             size_t totalSize = data.readInt32();
-            sp<IMemory> sharedBuffer =
+            sp<IMemory> source =
                 interface_cast<IMemory>(data.readStrongBinder());
-            if (sharedBuffer == NULL) {
+            if (source == NULL) {
                 reply->writeInt32(BAD_VALUE);
                 return OK;
             }
@@ -308,23 +303,26 @@
             }
 
             CryptoPlugin::SubSample *subSamples =
-                new CryptoPlugin::SubSample[numSubSamples];
+                    new CryptoPlugin::SubSample[numSubSamples];
 
-            data.read(
-                    subSamples,
+            data.read(subSamples,
                     sizeof(CryptoPlugin::SubSample) * numSubSamples);
 
-            native_handle_t *nativeHandle = NULL;
-            void *secureBufferId = NULL, *dstPtr;
-            if (dstType == kDestinationTypeNativeHandle) {
-                nativeHandle = data.readNativeHandle();
-                dstPtr = static_cast<void *>(nativeHandle);
-            } else if (dstType == kDestinationTypeOpaqueHandle) {
-                secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
-                dstPtr = secureBufferId;
-            } else {
-                dstType = kDestinationTypeVmPointer;
-                dstPtr = malloc(totalSize);
+            DestinationBuffer destination;
+            destination.mType = (DestinationType)data.readInt32();
+            if (destination.mType == kDestinationTypeNativeHandle) {
+                destination.mHandle = data.readNativeHandle();
+                if (destination.mHandle == NULL) {
+                    reply->writeInt32(BAD_VALUE);
+                    return OK;
+                }
+            } else if (destination.mType == kDestinationTypeSharedMemory) {
+                destination.mSharedMemory =
+                        interface_cast<IMemory>(data.readStrongBinder());
+                if (destination.mSharedMemory == NULL) {
+                    reply->writeInt32(BAD_VALUE);
+                    return OK;
+                }
             }
 
             AString errorDetailMsg;
@@ -348,20 +346,13 @@
 
             if (overflow || sumSubsampleSizes != totalSize) {
                 result = -EINVAL;
-            } else if (totalSize > sharedBuffer->size()) {
+            } else if (totalSize > source->size()) {
                 result = -EINVAL;
-            } else if ((size_t)offset > sharedBuffer->size() - totalSize) {
+            } else if ((size_t)offset > source->size() - totalSize) {
                 result = -EINVAL;
             } else {
-                result = decrypt(
-                    dstType,
-                    key,
-                    iv,
-                    mode, pattern,
-                    sharedBuffer, offset,
-                    subSamples, numSubSamples,
-                    dstPtr,
-                    &errorDetailMsg);
+                result = decrypt(key, iv, mode, pattern, source, offset,
+                        subSamples, numSubSamples, destination, &errorDetailMsg);
             }
 
             reply->writeInt32(result);
@@ -370,23 +361,12 @@
                 reply->writeCString(errorDetailMsg.c_str());
             }
 
-            if (dstType == kDestinationTypeVmPointer) {
-                if (result >= 0) {
-                    CHECK_LE(result, static_cast<ssize_t>(totalSize));
-                    // For the non-secure case, pass the decrypted
-                    // data back via the shared buffer rather than
-                    // copying it separately over binder to avoid
-                    // binder's 1MB limit.
-                    memcpy(sharedBuffer->pointer(), dstPtr, result);
-                }
-                free(dstPtr);
-                dstPtr = NULL;
-            } else if (dstType == kDestinationTypeNativeHandle) {
+            if (destination.mType == kDestinationTypeNativeHandle) {
                 int err;
-                if ((err = native_handle_close(nativeHandle)) < 0) {
+                if ((err = native_handle_close(destination.mHandle)) < 0) {
                     ALOGW("secure buffer native_handle_close failed: %d", err);
                 }
-                if ((err = native_handle_delete(nativeHandle)) < 0) {
+                if ((err = native_handle_delete(destination.mHandle)) < 0) {
                     ALOGW("secure buffer native_handle_delete failed: %d", err);
                 }
             }
diff --git a/include/camera/ndk/NdkCameraMetadataTags.h b/include/camera/ndk/NdkCameraMetadataTags.h
index 0fec983..ced6034 100644
--- a/include/camera/ndk/NdkCameraMetadataTags.h
+++ b/include/camera/ndk/NdkCameraMetadataTags.h
@@ -1515,6 +1515,40 @@
      */
     ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST =                // int32
             ACAMERA_CONTROL_START + 40,
+    /**
+     * <p>Allow camera device to enable zero-shutter-lag mode for requests with
+     * ACAMERA_CONTROL_CAPTURE_INTENT == STILL_CAPTURE.</p>
+     *
+     * @see ACAMERA_CONTROL_CAPTURE_INTENT
+     *
+     * <p>This tag may appear in:</p>
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     *   <li>ACaptureRequest</li>
+     * </ul>
+     *
+     * <p>If enableZsl is <code>true</code>, the camera device may enable zero-shutter-lag mode for requests with
+     * STILL_CAPTURE capture intent. The camera device may use images captured in the past to
+     * produce output images for a zero-shutter-lag request. The result metadata including the
+     * ACAMERA_SENSOR_TIMESTAMP reflects the source frames used to produce output images.
+     * Therefore, the contents of the output images and the result metadata may be out of order
+     * compared to previous regular requests. enableZsl does not affect requests with other
+     * capture intents.</p>
+     * <p>For example, when requests are submitted in the following order:
+     *   Request A: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
+     *   Request B: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
+     * <p>The output images for request B may have contents captured before the output images for
+     * request A, and the result metadata for request B may be older than the result metadata for
+     * request A.</p>
+     * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the
+     * past for requests with STILL_CAPTURE capture intent.</p>
+     * <p>The value of enableZsl in capture templates is always <code>false</code> if present.</p>
+     *
+     * @see ACAMERA_CONTROL_CAPTURE_INTENT
+     * @see ACAMERA_SENSOR_TIMESTAMP
+     */
+    ACAMERA_CONTROL_ENABLE_ZSL =                                // byte (enum)
+            ACAMERA_CONTROL_START + 41,
     ACAMERA_CONTROL_END,
 
     /**
@@ -5762,6 +5796,26 @@
 
 } acamera_metadata_enum_android_control_awb_lock_available_t;
 
+// ACAMERA_CONTROL_ENABLE_ZSL
+typedef enum acamera_metadata_enum_acamera_control_enable_zsl {
+    /**
+     * <p>Requests with ACAMERA_CONTROL_CAPTURE_INTENT == STILL_CAPTURE must be captured
+     * after previous requests.</p>
+     *
+     * @see ACAMERA_CONTROL_CAPTURE_INTENT
+     */
+    ACAMERA_CONTROL_ENABLE_ZSL_FALSE                                 = 0,
+
+    /**
+     * <p>Requests with ACAMERA_CONTROL_CAPTURE_INTENT == STILL_CAPTURE may or may not be
+     * captured before previous requests.</p>
+     *
+     * @see ACAMERA_CONTROL_CAPTURE_INTENT
+     */
+    ACAMERA_CONTROL_ENABLE_ZSL_TRUE                                  = 1,
+
+} acamera_metadata_enum_android_control_enable_zsl_t;
+
 
 
 // ACAMERA_EDGE_MODE
diff --git a/include/media/Crypto.h b/include/media/Crypto.h
index 7d181d3..ce08f98 100644
--- a/include/media/Crypto.h
+++ b/include/media/Crypto.h
@@ -49,16 +49,11 @@
 
     virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
 
-    virtual ssize_t decrypt(
-            DestinationType dstType,
-            const uint8_t key[16],
-            const uint8_t iv[16],
-            CryptoPlugin::Mode mode,
-            const CryptoPlugin::Pattern &pattern,
-            const sp<IMemory> &sharedBuffer, size_t offset,
+    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+            const sp<IMemory> &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            void *dstPtr,
-            AString *errorDetailMsg);
+            const DestinationBuffer &destination, AString *errorDetailMsg);
 
 private:
     mutable Mutex mLock;
diff --git a/include/media/CryptoHal.h b/include/media/CryptoHal.h
new file mode 100644
index 0000000..1ace957
--- /dev/null
+++ b/include/media/CryptoHal.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CRYPTO_HAL_H_
+
+#define CRYPTO_HAL_H_
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <media/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+#include "SharedLibrary.h"
+
+namespace android {
+
+struct CryptoHal : public BnCrypto {
+    CryptoHal();
+    virtual ~CryptoHal();
+
+    virtual status_t initCheck() const;
+
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+
+    virtual status_t createPlugin(
+            const uint8_t uuid[16], const void *data, size_t size);
+
+    virtual status_t destroyPlugin();
+
+    virtual bool requiresSecureDecoderComponent(
+            const char *mime) const;
+
+    virtual void notifyResolution(uint32_t width, uint32_t height);
+
+    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+
+    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+            const sp<IMemory> &source, size_t offset,
+            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+            const ICrypto::DestinationBuffer &destination,
+            AString *errorDetailMsg);
+
+private:
+    mutable Mutex mLock;
+
+    sp<SharedLibrary> mLibrary;
+    sp<::android::hardware::drm::V1_0::ICryptoFactory> mFactory;
+    sp<::android::hardware::drm::V1_0::ICryptoPlugin> mPlugin;
+
+    /**
+     * mInitCheck is:
+     *   NO_INIT if a plugin hasn't been created yet
+     *   ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+     *   OK after a plugin has been created and mPlugin is valid
+     */
+    status_t mInitCheck;
+
+    void *mHeapBase;
+
+    sp<::android::hardware::drm::V1_0::ICryptoFactory>
+            makeCryptoFactory();
+    sp<::android::hardware::drm::V1_0::ICryptoPlugin>
+            makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
+                size_t size);
+
+    status_t setHeapBase(const sp<IMemory> &sharedBuffer);
+
+    DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
+};
+
+}  // namespace android
+
+#endif  // CRYPTO_HAL_H_
diff --git a/include/media/DrmHal.h b/include/media/DrmHal.h
new file mode 100644
index 0000000..aaea2c9
--- /dev/null
+++ b/include/media/DrmHal.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_HAL_H_
+
+#define DRM_HAL_H_
+
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+
+#include <media/IDrm.h>
+#include <media/IDrmClient.h>
+#include <utils/threads.h>
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+namespace android {
+
+struct DrmSessionClientInterface;
+
+struct DrmHal : public BnDrm,
+             public IBinder::DeathRecipient,
+             public IDrmPluginListener {
+    DrmHal();
+    virtual ~DrmHal();
+
+    virtual status_t initCheck() const;
+
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
+
+    virtual status_t createPlugin(const uint8_t uuid[16]);
+
+    virtual status_t destroyPlugin();
+
+    virtual status_t openSession(Vector<uint8_t> &sessionId);
+
+    virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+
+    virtual status_t
+        getKeyRequest(Vector<uint8_t> const &sessionId,
+                      Vector<uint8_t> const &initData,
+                      String8 const &mimeType, DrmPlugin::KeyType keyType,
+                      KeyedVector<String8, String8> const &optionalParameters,
+                      Vector<uint8_t> &request, String8 &defaultUrl,
+                      DrmPlugin::KeyRequestType *keyRequestType);
+
+    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                        Vector<uint8_t> const &response,
+                                        Vector<uint8_t> &keySetId);
+
+    virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+
+    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+                                 Vector<uint8_t> const &keySetId);
+
+    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
+                                    KeyedVector<String8, String8> &infoMap) const;
+
+    virtual status_t getProvisionRequest(String8 const &certType,
+                                         String8 const &certAuthority,
+                                         Vector<uint8_t> &request,
+                                         String8 &defaulUrl);
+
+    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                              Vector<uint8_t> &certificate,
+                                              Vector<uint8_t> &wrappedKey);
+
+    virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+
+    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+    virtual status_t releaseAllSecureStops();
+
+    virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+    virtual status_t getPropertyByteArray(String8 const &name,
+                                          Vector<uint8_t> &value ) const;
+    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 setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                        String8 const &algorithm);
+
+    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                     String8 const &algorithm);
+
+    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+                             Vector<uint8_t> const &keyId,
+                             Vector<uint8_t> const &input,
+                             Vector<uint8_t> const &iv,
+                             Vector<uint8_t> &output);
+
+    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+                             Vector<uint8_t> const &keyId,
+                             Vector<uint8_t> const &input,
+                             Vector<uint8_t> const &iv,
+                             Vector<uint8_t> &output);
+
+    virtual status_t sign(Vector<uint8_t> const &sessionId,
+                          Vector<uint8_t> const &keyId,
+                          Vector<uint8_t> const &message,
+                          Vector<uint8_t> &signature);
+
+    virtual status_t verify(Vector<uint8_t> const &sessionId,
+                            Vector<uint8_t> const &keyId,
+                            Vector<uint8_t> const &message,
+                            Vector<uint8_t> const &signature,
+                            bool &match);
+
+    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                             String8 const &algorithm,
+                             Vector<uint8_t> const &message,
+                             Vector<uint8_t> const &wrappedKey,
+                             Vector<uint8_t> &signature);
+
+    virtual status_t setListener(const sp<IDrmClient>& listener);
+
+    // Methods of IDrmPluginListener
+    Return<void> sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS);
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
+
+    virtual void binderDied(const wp<IBinder> &the_late_who);
+
+private:
+    static Mutex mLock;
+
+    sp<DrmSessionClientInterface> mDrmSessionClient;
+
+    sp<IDrmClient> mListener;
+    mutable Mutex mEventLock;
+    mutable Mutex mNotifyLock;
+
+    sp<IDrmFactory> mFactory;
+    sp<IDrmPlugin> mPlugin;
+
+    /**
+     * mInitCheck is:
+     *   NO_INIT if a plugin hasn't been created yet
+     *   ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+     *   OK after a plugin has been created and mPlugin is valid
+     */
+    status_t mInitCheck;
+
+    sp<IDrmFactory> makeDrmFactory();
+    sp<IDrmPlugin> makeDrmPlugin(const uint8_t uuid[16]);
+
+    void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
+};
+
+}  // namespace android
+
+#endif  // DRM_HAL_H_
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index a4bfaf8..8990f4b 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -15,8 +15,9 @@
  */
 
 #include <binder/IInterface.h>
-#include <media/stagefright/foundation/ABase.h>
+#include <cutils/native_handle.h>
 #include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ABase.h>
 
 #ifndef ANDROID_ICRYPTO_H_
 
@@ -47,21 +48,21 @@
     virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
 
     enum DestinationType {
-        kDestinationTypeVmPointer,    // non-secure
-        kDestinationTypeOpaqueHandle, // secure
+        kDestinationTypeSharedMemory, // non-secure
         kDestinationTypeNativeHandle  // secure
     };
 
-    virtual ssize_t decrypt(
-            DestinationType dstType,
-            const uint8_t key[16],
-            const uint8_t iv[16],
-            CryptoPlugin::Mode mode,
-            const CryptoPlugin::Pattern &pattern,
-            const sp<IMemory> &sharedBuffer, size_t offset,
+    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 sp<IMemory> &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            void *dstPtr,
-            AString *errorDetailMsg) = 0;
+            const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
 
 private:
     DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
diff --git a/include/media/PluginLoader.h b/include/media/PluginLoader.h
index 360af2d..a626e16 100644
--- a/include/media/PluginLoader.h
+++ b/include/media/PluginLoader.h
@@ -60,7 +60,10 @@
         }
     }
 
-    T *getFactory(size_t i) const {return factories[i];}
+    T *getFactory(size_t i) const {
+        return factories[i];
+    }
+
     size_t factoryCount() const {return factories.size();}
 
   private:
@@ -74,12 +77,11 @@
             CreateFactoryFunc createFactoryFunc =
                     (CreateFactoryFunc)library->lookup(entry);
             if (createFactoryFunc) {
+                ALOGV("Found plugin factory entry %s in %s", entry, path);
                 libraries.push(library);
-                return createFactoryFunc();
-            } else {
-                ALOGE("Failed to create plugin factory from %s at entry %s: %s",
-                        path, entry, library->lastError());
-            }
+                T* result = createFactoryFunc();
+                return  result;
+           }
         }
         return NULL;
     }
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index f9ab208..0de3559 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -383,6 +383,10 @@
         if ((mAttributes.flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
             flags = (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_FAST);
         }
+        // check deep buffer after flags have been modified above
+        if (flags == AUDIO_OUTPUT_FLAG_NONE && (mAttributes.flags & AUDIO_FLAG_DEEP_BUFFER) != 0) {
+            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+        }
     }
 
     // these below should probably come from the audioFlinger too...
diff --git a/media/libmedia/MediaAnalyticsItem.cpp b/media/libmedia/MediaAnalyticsItem.cpp
index 375d1d5..229e747 100644
--- a/media/libmedia/MediaAnalyticsItem.cpp
+++ b/media/libmedia/MediaAnalyticsItem.cpp
@@ -51,7 +51,7 @@
 
 const char * const MediaAnalyticsItem::EnabledProperty  = "media.metrics.enabled";
 const char * const MediaAnalyticsItem::EnabledPropertyPersist  = "persist.media.metrics.enabled";
-const int MediaAnalyticsItem::EnabledProperty_default  = 0;
+const int MediaAnalyticsItem::EnabledProperty_default  = 1;
 
 
 // access functions for the class
diff --git a/media/libmediaplayerservice/tests/Android.mk b/media/libmediaplayerservice/tests/Android.mk
index c0b3265..dc761ec 100644
--- a/media/libmediaplayerservice/tests/Android.mk
+++ b/media/libmediaplayerservice/tests/Android.mk
@@ -14,6 +14,8 @@
 	libmediaplayerservice \
 	libmediadrm \
 	libutils \
+	android.hidl.base@1.0 \
+	android.hardware.drm@1.0 \
 
 LOCAL_C_INCLUDES := \
 	frameworks/av/include \
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 1db7ab0..296394b 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -88,14 +88,9 @@
 }
 
 status_t ACodecBufferChannel::queueSecureInputBuffer(
-        const sp<MediaCodecBuffer> &buffer,
-        bool secure,
-        const uint8_t *key,
-        const uint8_t *iv,
-        CryptoPlugin::Mode mode,
-        CryptoPlugin::Pattern pattern,
-        const CryptoPlugin::SubSample *subSamples,
-        size_t numSubSamples,
+        const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
+        const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
+        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
         AString *errorDetailMsg) {
     if (mCrypto == nullptr) {
         return -ENOSYS;
@@ -107,35 +102,32 @@
         return -ENOENT;
     }
 
-    void *dst_pointer = nullptr;
-    ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
-
+    ICrypto::DestinationBuffer destination;
     if (secure) {
-        sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(it->mCodecBuffer.get());
-        dst_pointer = secureData->getDestinationPointer();
-        dst_type = secureData->getDestinationType();
+        sp<SecureBuffer> secureData =
+                static_cast<SecureBuffer *>(it->mCodecBuffer.get());
+        destination.mType = secureData->getDestinationType();
+        if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
+            return BAD_VALUE;
+        }
+        destination.mHandle =
+                static_cast<native_handle_t *>(secureData->getDestinationPointer());
     } else {
-        dst_pointer = it->mCodecBuffer->base();
-        dst_type = ICrypto::kDestinationTypeVmPointer;
+        destination.mType = ICrypto::kDestinationTypeSharedMemory;
+        destination.mSharedMemory = mDecryptDestination;
     }
-
-    ssize_t result = mCrypto->decrypt(
-            dst_type,
-            key,
-            iv,
-            mode,
-            pattern,
-            it->mSharedEncryptedBuffer,
-            it->mClientBuffer->offset(),
-            subSamples,
-            numSubSamples,
-            dst_pointer,
-            errorDetailMsg);
+    ssize_t result = mCrypto->decrypt(key, iv, mode, pattern,
+            it->mSharedEncryptedBuffer, it->mClientBuffer->offset(),
+            subSamples, numSubSamples, destination, errorDetailMsg);
 
     if (result < 0) {
         return result;
     }
 
+    if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+        memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
+    }
+
     it->mCodecBuffer->setRange(0, result);
 
     // Copy metadata from client to codec buffer.
@@ -228,7 +220,14 @@
                 (size_t sum, const BufferAndId& elem) {
                     return sum + align(elem.mBuffer->capacity(), alignment);
                 });
-        mDealer = new MemoryDealer(totalSize, "ACodecBufferChannel");
+        size_t maxSize = std::accumulate(
+                array.begin(), array.end(), 0u,
+                [alignment = MemoryDealer::getAllocationAlignment()]
+                (size_t max, const BufferAndId& elem) {
+                    return std::max(max, align(elem.mBuffer->capacity(), alignment));
+                });
+        mDealer = new MemoryDealer(totalSize + maxSize, "ACodecBufferChannel");
+        mDecryptDestination = mDealer->allocate(maxSize);
     }
     std::vector<const BufferInfo> inputBuffers;
     for (const BufferAndId &elem : array) {
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
index 37a40ec..40eb942 100644
--- a/media/libstagefright/BufferImpl.cpp
+++ b/media/libstagefright/BufferImpl.cpp
@@ -51,8 +51,7 @@
 }
 
 ICrypto::DestinationType SecureBuffer::getDestinationType() {
-    return mHandle == nullptr ? ICrypto::kDestinationTypeOpaqueHandle
-                              : ICrypto::kDestinationTypeNativeHandle;
+    return ICrypto::kDestinationTypeNativeHandle;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index d52ce53..ce9bd3c 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -115,6 +115,7 @@
     const sp<AMessage> mOutputBufferDrained;
 
     sp<MemoryDealer> mDealer;
+    sp<IMemory> mDecryptDestination;
 
     // These should only be accessed via std::atomic_* functions.
     //
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 5445413..b169bac 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -57,7 +57,7 @@
     void clearPreemptedSessions();
     bool isActive() const;
     bool isSourceActive(audio_source_t source) const;
-    audio_source_t inputSource() const;
+    audio_source_t inputSource(bool activeOnly = false) const;
     bool isSoundTrigger() const;
     status_t addAudioSession(audio_session_t session,
                              const sp<AudioSession>& audioSession);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 44f9637..2492ed6 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -63,11 +63,9 @@
     return mId;
 }
 
-audio_source_t AudioInputDescriptor::inputSource() const
+audio_source_t AudioInputDescriptor::inputSource(bool activeOnly) const
 {
-    // TODO: return highest priority input source
-    return mSessions.size() > 0 ? mSessions.valueAt(0)->inputSource() :
-                       AUDIO_SOURCE_DEFAULT;
+    return getHighestPrioritySource(activeOnly);
 }
 
 void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e71bb01..eb61ec4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1651,13 +1651,15 @@
             } else if (isSoundTrigger) {
                 break;
             }
+
             // force close input if current source is now the highest priority request on this input
             // and current input properties are not exactly as requested.
-            if ((desc->mSamplingRate != samplingRate ||
+            if (!isConcurrentSource(inputSource) && !isConcurrentSource(desc->inputSource()) &&
+                    ((desc->mSamplingRate != samplingRate ||
                     desc->mChannelMask != channelMask ||
                     !audio_formats_match(desc->mFormat, format)) &&
                     (source_priority(desc->getHighestPrioritySource(false /*activeOnly*/)) <
-                     source_priority(inputSource))) {
+                     source_priority(inputSource)))) {
                 ALOGV("%s: ", __FUNCTION__);
                 AudioSessionCollection sessions = desc->getAudioSessions(false /*activeOnly*/);
                 for (size_t j = 0; j < sessions.size(); j++) {
@@ -1715,6 +1717,14 @@
     return input;
 }
 
+//static
+bool AudioPolicyManager::isConcurrentSource(audio_source_t source)
+{
+    return (source == AUDIO_SOURCE_HOTWORD) ||
+            (source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
+            (source == AUDIO_SOURCE_FM_TUNER);
+}
+
 bool AudioPolicyManager::isConcurentCaptureAllowed(const sp<AudioInputDescriptor>& inputDesc,
         const sp<AudioSession>& audioSession)
 {
@@ -1734,16 +1744,14 @@
     // 3) All other active captures are either for re-routing or HOTWORD
 
     if (is_virtual_input_device(inputDesc->mDevice) ||
-            audioSession->inputSource() == AUDIO_SOURCE_HOTWORD ||
-            audioSession->inputSource() == AUDIO_SOURCE_FM_TUNER) {
+            isConcurrentSource(audioSession->inputSource())) {
         return true;
     }
 
     Vector< sp<AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
     for (size_t i = 0; i <  activeInputs.size(); i++) {
         sp<AudioInputDescriptor> activeInput = activeInputs[i];
-        if ((activeInput->inputSource() != AUDIO_SOURCE_HOTWORD) &&
-                (activeInput->inputSource() != AUDIO_SOURCE_FM_TUNER) &&
+        if (!isConcurrentSource(activeInput->inputSource(true)) &&
                 !is_virtual_input_device(activeInput->mDevice)) {
             return false;
         }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 3c5ed3a..cea3f54 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -507,6 +507,8 @@
 
         void clearAudioSources(uid_t uid);
 
+        static bool isConcurrentSource(audio_source_t source);
+
         bool isConcurentCaptureAllowed(const sp<AudioInputDescriptor>& inputDesc,
                 const sp<AudioSession>& audioSession);
 
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 73109e1..f667068 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -16,7 +16,6 @@
 
 include $(CLEAR_VARS)
 
-
 LOCAL_SRC_FILES:= \
     MediaDrmService.cpp \
     main_mediadrmserver.cpp
@@ -26,8 +25,19 @@
     liblog \
     libmediadrm \
     libutils \
+    libandroidfw
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_SHARED_LIBRARIES += \
+    libhidlbase \
+    libhidlmemory \
+    android.hidl.base@1.0 \
+    android.hardware.drm@1.0
+endif
 
 LOCAL_CFLAGS += -Wall -Wextra -Werror
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_CFLAGS += -DENABLE_TREBLE_DRM=1
+endif
 
 LOCAL_MODULE:= mediadrmserver
 LOCAL_32_BIT_ONLY := true
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
index 331c568..c709b5e 100644
--- a/services/mediadrm/MediaDrmService.cpp
+++ b/services/mediadrm/MediaDrmService.cpp
@@ -21,11 +21,16 @@
 #define LOG_TAG "MediaDrmService"
 
 #include "MediaDrmService.h"
-
 #include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#ifdef ENABLE_TREBLE_DRM
+#include <media/CryptoHal.h>
+#include <media/DrmHal.h>
+#else
 #include <media/Crypto.h>
 #include <media/Drm.h>
-#include <utils/Log.h>
+#endif
 
 namespace android {
 
@@ -35,11 +40,19 @@
 }
 
 sp<ICrypto> MediaDrmService::makeCrypto() {
+#ifdef ENABLE_TREBLE_DRM
+    return new CryptoHal;
+#else
     return new Crypto;
+#endif
 }
 
 sp<IDrm> MediaDrmService::makeDrm() {
+#ifdef ENABLE_TREBLE_DRM
+    return new DrmHal;
+#else
     return new Drm;
+#endif
 }
 
 } // namespace android