Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68130d84 authored by Dhananjay Kumar's avatar Dhananjay Kumar Committed by Linux Build Service Account
Browse files

stagefright: add handling for Large metadata across binder

getMetadata can fail at binder interface due to large parcel,
when large metaData like Album art of size as big as 1MB is
included.
Using MemoryBase to pass such large metaData across binder.

CRs-Fixed: 1029437
Change-Id: I79bf4778ed3533cc812e2eab131ad7459c80633e
parent 8ce2c687
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -228,6 +228,14 @@ public:
        TYPE_RECT     = 'rect',
    };

    static const size_t kSharedMemThreshold = 10 * 1024;

    enum ParcelAllocationType {
        NULL_ALLOCATION,
        SHARED_ALLOCATION,
        INLINE_ALLOCATION
    };

    void clear();
    bool remove(uint32_t key);

+49 −5
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@
#include <stdlib.h>
#include <string.h>

#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IPCThreadState.h>

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
@@ -392,6 +396,7 @@ void MetaData::dumpToLog() const {
}

status_t MetaData::writeToParcel(Parcel &parcel) {
    status_t status = OK;
    size_t numItems = mItems.size();
    parcel.writeUint32(uint32_t(numItems));
    for (size_t i = 0; i < numItems; i++) {
@@ -403,12 +408,34 @@ status_t MetaData::writeToParcel(Parcel &parcel) {
        item.getData(&type, &data, &size);
        parcel.writeInt32(key);
        parcel.writeUint32(type);
        if (size < SIZE_MAX && size >= kSharedMemThreshold) {
            sp<MemoryHeapBase> heap =
                    new MemoryHeapBase(size, 0, "Metadata::writeToParcel");
            if (heap == NULL) {
                ALOGE("cannot create HeapBase for shared allocation");
                status = UNKNOWN_ERROR;
                break;
            }
            sp<IMemory>  mem = new MemoryBase(heap, 0, size);
            if (mem == NULL || mem->pointer() == NULL) {
                ALOGE("cannot create MemoryBase for shared allocation");
                status = UNKNOWN_ERROR;
                break;
            }
            parcel.writeInt32(SHARED_ALLOCATION);
            parcel.writeUint32(size);
            memcpy(mem->pointer(), data, size);
            parcel.writeStrongBinder(IInterface::asBinder(mem));
        } else {
            parcel.writeInt32(INLINE_ALLOCATION);
            parcel.writeByteArray(size, (uint8_t*)data);
        }
    return OK;
    }
    return status;
}

status_t MetaData::updateFromParcel(const Parcel &parcel) {
    status_t status = OK;
    uint32_t numItems;
    if (parcel.readUint32(&numItems) == OK) {

@@ -416,17 +443,34 @@ status_t MetaData::updateFromParcel(const Parcel &parcel) {
            int32_t key;
            uint32_t type;
            uint32_t size;
            int32_t allocationType;
            status_t ret = parcel.readInt32(&key);
            ret |= parcel.readUint32(&type);
            ret |= parcel.readInt32(&allocationType);
            ret |= parcel.readUint32(&size);
            if (ret != OK) {
                break;
            }
            if (allocationType == SHARED_ALLOCATION) {
                sp<IBinder> binder = parcel.readStrongBinder();
                sp<IMemory> mem = interface_cast<IMemory>(binder);
                if (mem == NULL || mem->pointer() == NULL) {
                    ALOGE("received NULL IMemory for shared allocation");
                    status = UNKNOWN_ERROR;
                    break;
                }
                setData(key, type, mem->pointer(), size);
            } else if (allocationType == INLINE_ALLOCATION) {
                // copy data directly from Parcel storage, then advance position
                setData(key, type, parcel.readInplace(size), size);
            } else {
                ALOGE("unknown allocation");
                status = UNKNOWN_ERROR;
                break;
            }
         }

        return OK;
        return status;
    }
    ALOGW("no metadata in parcel");
    return UNKNOWN_ERROR;