DRM: more fixes for heap base mapping -- DO NOT MERGE
Heap base for the same heap could be mapped to different values
after they go across binder to CryptoHal. So we can't use heapbase
to index the heaps.
Since each ACodec instance allocates all its shared memory buffers
from the same memory dealer, we let CryptoHal assign a sequence
number to the ACodec when it calls setHeap. In subsequent calls
to CryptoHal::decrypt, reference the heap by the seq num, and ignore
the heap base address.
Bug: 36479980
Bug: 36209723
Bug: 36660223
Test: the above bugs don't repro
Change-Id: I2f519a689a5891447385d1bf9d6e668bb3b4dbe2
(cherry-picked from bf628da1e231e2e4d6bf61f9884e120bae3f9156)
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 9f41403..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,30 +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("setHeapBase(), failed to create native handle");
- return;
+ return -1;
}
- if (heap == NULL) {
- ALOGE("setHeapBase(): 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;
}
-void CryptoHal::clearHeapBase(const sp<IMemoryHeap>& heap) {
- mHeapBases.removeItem(heap->getBase());
+void CryptoHal::clearHeapBase(int32_t seqNum) {
+ Mutex::Autolock autoLock(mLock);
+
+ mHeapBases.removeItem(seqNum);
}
-status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer) {
+status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
ssize_t offset;
size_t size;
@@ -262,9 +270,9 @@
}
// memory must be in the declared heap
- CHECK(mHeapBases.indexOfKey(heap->getBase()) >= 0);
+ 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;
@@ -272,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);
@@ -312,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;
@@ -329,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 7b70205..8506d95 100644
--- a/drm/libmediadrm/ICrypto.cpp
+++ b/drm/libmediadrm/ICrypto.cpp
@@ -98,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;
@@ -127,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);
@@ -179,18 +180,25 @@
return reply.readInt32();
}
- virtual void setHeap(const sp<IMemoryHeap> &heap) {
+ virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(heap));
- remote()->transact(SET_HEAP, data, &reply);
- return;
+ 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(const sp<IMemoryHeap>& heap) {
+ virtual void unsetHeap(int32_t seqNum) {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(heap));
+ data.writeInt32(seqNum);
remote()->transact(UNSET_HEAP, data, &reply);
return;
}
@@ -314,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();
@@ -372,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,
@@ -428,16 +441,15 @@
CHECK_INTERFACE(ICrypto, data, reply);
sp<IMemoryHeap> heap =
interface_cast<IMemoryHeap>(data.readStrongBinder());
- setHeap(heap);
+ reply->writeInt32(setHeap(heap));
return OK;
}
case UNSET_HEAP:
{
CHECK_INTERFACE(ICrypto, data, reply);
- sp<IMemoryHeap> heap =
- interface_cast<IMemoryHeap>(data.readStrongBinder());
- unsetHeap(heap);
+ int32_t seqNum = data.readInt32();
+ unsetHeap(seqNum);
return OK;
}