Merge changes from topic 'heapbase'

* changes:
  DRM: more fixes for heap base mapping
  Revert "Revert "Fix decoder instantiation during playback""
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 1466222..25c16da 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -105,7 +105,8 @@
 CryptoHal::CryptoHal()
     : mFactories(makeCryptoFactories()),
       mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
-      mNextBufferId(0) {
+      mNextBufferId(0),
+      mHeapSeqNum(0) {
 }
 
 CryptoHal::~CryptoHal() {
@@ -225,26 +226,37 @@
  * size.  Once the heap base is established, shared memory buffers
  * are sent by providing an offset into the heap and a buffer size.
  */
-void CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
+int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
+    if (heap == NULL) {
+        ALOGE("setHeapBase(): heap is NULL");
+        return -1;
+    }
     native_handle_t* nativeHandle = native_handle_create(1, 0);
     if (!nativeHandle) {
-        ALOGE("setSharedBufferBase(), failed to create native handle");
-        return;
+        ALOGE("setHeapBase(), failed to create native handle");
+        return -1;
     }
-    if (heap == NULL) {
-        ALOGE("setSharedBufferBase(): heap is NULL");
-        return;
-    }
+
+    Mutex::Autolock autoLock(mLock);
+
+    int32_t seqNum = mHeapSeqNum++;
     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);
+    mHeapBases.add(seqNum, mNextBufferId);
     Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++);
     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
+    return seqNum;
 }
 
-status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer) {
+void CryptoHal::clearHeapBase(int32_t seqNum) {
+    Mutex::Autolock autoLock(mLock);
+
+    mHeapBases.removeItem(seqNum);
+}
+
+status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
     ssize_t offset;
     size_t size;
 
@@ -257,11 +269,10 @@
         return UNEXPECTED_NULL;
     }
 
-    if (mHeapBases.indexOfKey(heap->getBase()) < 0) {
-        setHeapBase(heap);
-    }
+    // memory must be in the declared heap
+    CHECK(mHeapBases.indexOfKey(seqNum) >= 0);
 
-    buffer->bufferId = mHeapBases.valueFor(heap->getBase());
+    buffer->bufferId = mHeapBases.valueFor(seqNum);
     buffer->offset = offset >= 0 ? offset : 0;
     buffer->size = size;
     return OK;
@@ -269,7 +280,7 @@
 
 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 ICrypto::SourceBuffer &source, size_t offset,
         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
         const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
     Mutex::Autolock autoLock(mLock);
@@ -309,11 +320,12 @@
     }
     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,
+        status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum,
                 &hDestination.nonsecureMemory);
         if (status != OK) {
             return status;
@@ -326,7 +338,7 @@
     }
 
     ::SharedBuffer hSource;
-    status_t status = toSharedBuffer(source, &hSource);
+    status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource);
     if (status != OK) {
         return status;
     }
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
index 92c9548..8506d95 100644
--- a/drm/libmediadrm/ICrypto.cpp
+++ b/drm/libmediadrm/ICrypto.cpp
@@ -36,6 +36,8 @@
     DECRYPT,
     NOTIFY_RESOLUTION,
     SET_MEDIADRM_SESSION,
+    SET_HEAP,
+    UNSET_HEAP,
 };
 
 struct BpCrypto : public BpInterface<ICrypto> {
@@ -96,7 +98,7 @@
 
     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 SourceBuffer &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
             const DestinationBuffer &destination, AString *errorDetailMsg) {
         Parcel data, reply;
@@ -125,7 +127,8 @@
         }
 
         data.writeInt32(totalSize);
-        data.writeStrongBinder(IInterface::asBinder(source));
+        data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
+        data.writeInt32(source.mHeapSeqNum);
         data.writeInt32(offset);
 
         data.writeInt32(numSubSamples);
@@ -177,6 +180,30 @@
         return reply.readInt32();
     }
 
+    virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(heap));
+        status_t err = remote()->transact(SET_HEAP, data, &reply);
+        if (err != NO_ERROR) {
+            return -1;
+        }
+        int32_t seqNum;
+        if (reply.readInt32(&seqNum) != NO_ERROR) {
+            return -1;
+        }
+        return seqNum;
+    }
+
+    virtual void unsetHeap(int32_t seqNum) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+        data.writeInt32(seqNum);
+        remote()->transact(UNSET_HEAP, data, &reply);
+        return;
+    }
+
+
 private:
     void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
         uint32_t size = reply.readInt32();
@@ -295,12 +322,17 @@
             data.read(iv, sizeof(iv));
 
             size_t totalSize = data.readInt32();
-            sp<IMemory> source =
+
+            SourceBuffer source;
+
+            source.mSharedMemory =
                 interface_cast<IMemory>(data.readStrongBinder());
-            if (source == NULL) {
+            if (source.mSharedMemory == NULL) {
                 reply->writeInt32(BAD_VALUE);
                 return OK;
             }
+            source.mHeapSeqNum = data.readInt32();
+
             int32_t offset = data.readInt32();
 
             int32_t numSubSamples = data.readInt32();
@@ -353,9 +385,9 @@
 
             if (overflow || sumSubsampleSizes != totalSize) {
                 result = -EINVAL;
-            } else if (totalSize > source->size()) {
+            } else if (totalSize > source.mSharedMemory->size()) {
                 result = -EINVAL;
-            } else if ((size_t)offset > source->size() - totalSize) {
+            } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
                 result = -EINVAL;
             } else {
                 result = decrypt(key, iv, mode, pattern, source, offset,
@@ -404,6 +436,23 @@
             return OK;
         }
 
+        case SET_HEAP:
+        {
+            CHECK_INTERFACE(ICrypto, data, reply);
+            sp<IMemoryHeap> heap =
+                interface_cast<IMemoryHeap>(data.readStrongBinder());
+            reply->writeInt32(setHeap(heap));
+            return OK;
+        }
+
+        case UNSET_HEAP:
+        {
+            CHECK_INTERFACE(ICrypto, data, reply);
+            int32_t seqNum = data.readInt32();
+            unsetHeap(seqNum);
+            return OK;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/include/Crypto.h b/media/libmedia/include/Crypto.h
index ce08f98..b68413d 100644
--- a/media/libmedia/include/Crypto.h
+++ b/media/libmedia/include/Crypto.h
@@ -55,6 +55,9 @@
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
             const DestinationBuffer &destination, AString *errorDetailMsg);
 
+    virtual void setHeap(const sp<IMemoryHeap>&) {}
+    virtual void unsetHeap(const sp<IMemoryHeap>&) {}
+
 private:
     mutable Mutex mLock;
 
diff --git a/media/libmedia/include/CryptoHal.h b/media/libmedia/include/CryptoHal.h
index 28ade20..a5d8b43 100644
--- a/media/libmedia/include/CryptoHal.h
+++ b/media/libmedia/include/CryptoHal.h
@@ -55,11 +55,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> &source, size_t offset,
+            const ICrypto::SourceBuffer &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
             const ICrypto::DestinationBuffer &destination,
             AString *errorDetailMsg);
 
+    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) {
+        return setHeapBase(heap);
+    }
+    virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
+
 private:
     mutable Mutex mLock;
 
@@ -74,16 +79,18 @@
      */
     status_t mInitCheck;
 
-    KeyedVector<void *, uint32_t> mHeapBases;
+    KeyedVector<int32_t, uint32_t> mHeapBases;
     uint32_t mNextBufferId;
+    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);
 
-    void setHeapBase(const sp<IMemoryHeap>& heap);
+    int32_t setHeapBase(const sp<IMemoryHeap>& heap);
+    void clearHeapBase(int32_t seqNum);
 
-    status_t toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer);
+    status_t toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
 };
diff --git a/media/libmedia/include/ICrypto.h b/media/libmedia/include/ICrypto.h
index 8990f4b..6d896b8 100644
--- a/media/libmedia/include/ICrypto.h
+++ b/media/libmedia/include/ICrypto.h
@@ -27,6 +27,7 @@
 
 struct AString;
 class IMemory;
+class IMemoryHeap;
 
 struct ICrypto : public IInterface {
     DECLARE_META_INTERFACE(Crypto);
@@ -47,6 +48,11 @@
 
     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
@@ -60,10 +66,19 @@
 
     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 SourceBuffer &source, size_t offset,
             const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
             const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
 
+    /**
+     * Declare the heap that the shared memory source buffers passed
+     * to decrypt will be allocated from. Returns a sequence number
+     * 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 void unsetHeap(int32_t seqNum) = 0;
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
 };
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index ecbbd03..40ac986 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -39,6 +39,12 @@
 using BufferInfo = ACodecBufferChannel::BufferInfo;
 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
 
+ACodecBufferChannel::~ACodecBufferChannel() {
+    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
+        mCrypto->unsetHeap(mHeapSeqNum);
+    }
+}
+
 static BufferInfoIterator findClientBuffer(
         const std::shared_ptr<const std::vector<const BufferInfo>> &array,
         const sp<MediaCodecBuffer> &buffer) {
@@ -71,7 +77,8 @@
 ACodecBufferChannel::ACodecBufferChannel(
         const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
     : mInputBufferFilled(inputBufferFilled),
-      mOutputBufferDrained(outputBufferDrained) {
+      mOutputBufferDrained(outputBufferDrained),
+      mHeapSeqNum(-1) {
 }
 
 status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
@@ -122,11 +129,15 @@
         destination.mSharedMemory = mDecryptDestination;
     }
 
+    ICrypto::SourceBuffer source;
+    source.mSharedMemory = it->mSharedEncryptedBuffer;
+    source.mHeapSeqNum = mHeapSeqNum;
+
     ssize_t result = -1;
     if (mCrypto != NULL) {
         result = mCrypto->decrypt(key, iv, mode, pattern,
-                    it->mSharedEncryptedBuffer, it->mClientBuffer->offset(),
-                    subSamples, numSubSamples, destination, errorDetailMsg);
+                source, it->mClientBuffer->offset(),
+                subSamples, numSubSamples, destination, errorDetailMsg);
     } else {
         DescrambleInfo descrambleInfo;
         descrambleInfo.dstType = destination.mType ==
@@ -254,6 +265,25 @@
     }
 }
 
+sp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
+    sp<MemoryDealer> dealer;
+    if (mDealer != nullptr && mCrypto != nullptr && mHeapSeqNum >= 0) {
+        mCrypto->unsetHeap(mHeapSeqNum);
+    }
+    dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
+    if (mCrypto != nullptr) {
+        int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
+        if (seqNum >= 0) {
+            mHeapSeqNum = seqNum;
+            ALOGD("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
+        } else {
+            mHeapSeqNum = -1;
+            ALOGD("setHeap failed, setting mHeapSeqNum=-1");
+        }
+    }
+    return dealer;
+}
+
 void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
     if (hasCryptoOrDescrambler()) {
         size_t totalSize = std::accumulate(
@@ -268,8 +298,10 @@
                 (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);
+        size_t destinationBufferSize = maxSize;
+        size_t heapSize = totalSize + destinationBufferSize;
+        mDealer = makeMemoryDealer(heapSize);
+        mDecryptDestination = mDealer->allocate(destinationBufferSize);
     }
     std::vector<const BufferInfo> inputBuffers;
     for (const BufferAndId &elem : array) {
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 02468c1..0da2e81 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -60,7 +60,7 @@
 
     ACodecBufferChannel(
             const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained);
-    virtual ~ACodecBufferChannel() = default;
+    virtual ~ACodecBufferChannel();
 
     // BufferChannelBase interface
     virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
@@ -116,6 +116,7 @@
 
     sp<MemoryDealer> mDealer;
     sp<IMemory> mDecryptDestination;
+    int32_t mHeapSeqNum;
 
     // These should only be accessed via std::atomic_* functions.
     //
@@ -127,6 +128,8 @@
     std::shared_ptr<const std::vector<const BufferInfo>> mInputBuffers;
     std::shared_ptr<const std::vector<const BufferInfo>> mOutputBuffers;
 
+    sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
+
     bool hasCryptoOrDescrambler() {
         return mCrypto != NULL || mDescrambler != NULL;
     }