Support multiple codecs per crypto instance

The initial drm hidl hal implementation assumed one
codec per crypto instance, but in fact there can be
multiple codecs per crypto instance. This change
extends the drm hal to allow multiple memory heaps
per crypto plugin. It fixes the issue of mapping
memory frequently during playback.

bug:35275191

Test: manual verification with Play Movies on angler
in passthrough mode and on marlin in binderized mode.

Change-Id: Icada005f515483d7bc214b08caf6eea46ca354a7
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;