Merge "Support multiple codecs per crypto instance"
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f1f3b01..5732613 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -95,17 +95,6 @@
 }
 
 
-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());
 }
@@ -114,7 +103,7 @@
 CryptoHal::CryptoHal()
     : mFactory(makeCryptoFactory()),
       mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT),
-      mHeapBase(NULL) {
+      mNextBufferId(0) {
 }
 
 CryptoHal::~CryptoHal() {
@@ -206,20 +195,45 @@
  * 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;
-        }
+void CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
+    native_handle_t* nativeHandle = native_handle_create(1, 0);
+    if (!nativeHandle) {
+        ALOGE("setSharedBufferBase(), failed to create native handle");
+        return;
     }
+    if (heap == NULL) {
+        ALOGE("setSharedBufferBase(): heap is NULL");
+        return;
+    }
+    int fd = heap->getHeapID();
+    nativeHandle->data[0] = fd;
+    auto hidlHandle = hidl_handle(nativeHandle);
+    auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
+    mHeapBases.add(heap->getBase(), mNextBufferId);
+    Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++);
+    ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
+}
+
+status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::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;
+    }
+
+    if (mHeapBases.indexOfKey(heap->getBase()) < 0) {
+        setHeapBase(heap);
+    }
+
+    buffer->bufferId = mHeapBases.valueFor(heap->getBase());
+    buffer->offset = offset >= 0 ? offset : 0;
+    buffer->size = size;
     return OK;
 }
 
@@ -234,9 +248,6 @@
         return mInitCheck;
     }
 
-    // Establish the base of the shared memory heap
-    setHeapBase(source);
-
     Mode hMode;
     switch(mode) {
     case CryptoPlugin::kMode_Unencrypted:
@@ -272,7 +283,11 @@
     ::DestinationBuffer hDestination;
     if (destination.mType == kDestinationTypeSharedMemory) {
         hDestination.type = BufferType::SHARED_MEMORY;
-        hDestination.nonsecureMemory = toSharedBuffer(destination.mSharedMemory);
+        status_t status = toSharedBuffer(destination.mSharedMemory,
+                &hDestination.nonsecureMemory);
+        if (status != OK) {
+            return status;
+        }
         secure = false;
     } else {
         hDestination.type = BufferType::NATIVE_HANDLE;
@@ -280,12 +295,17 @@
         secure = true;
     }
 
+    ::SharedBuffer hSource;
+    status_t status = toSharedBuffer(source, &hSource);
+    if (status != OK) {
+        return status;
+    }
 
     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,
+            hPattern, hSubSamples, hSource, offset, hDestination,
             [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
                 if (status == Status::OK) {
                     bytesWritten = hBytesWritten;
diff --git a/include/media/CryptoHal.h b/include/media/CryptoHal.h
index 1ace957..9d0c3e4 100644
--- a/include/media/CryptoHal.h
+++ b/include/media/CryptoHal.h
@@ -26,6 +26,8 @@
 
 #include "SharedLibrary.h"
 
+class IMemoryHeap;
+
 namespace android {
 
 struct CryptoHal : public BnCrypto {
@@ -70,7 +72,8 @@
      */
     status_t mInitCheck;
 
-    void *mHeapBase;
+    KeyedVector<void *, uint32_t> mHeapBases;
+    uint32_t mNextBufferId;
 
     sp<::android::hardware::drm::V1_0::ICryptoFactory>
             makeCryptoFactory();
@@ -78,7 +81,10 @@
             makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
                 size_t size);
 
-    status_t setHeapBase(const sp<IMemory> &sharedBuffer);
+    void setHeapBase(const sp<IMemoryHeap>& heap);
+
+    status_t toSharedBuffer(const sp<IMemory>& memory,
+            ::android::hardware::drm::V1_0::SharedBuffer* buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
 };