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

Commit 81fba534 authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright/foundation: add entry getter/setters to AMessage

Also add ability to set/find items regardless of type. This is much
more efficient than trying findXYZ() for all types using the current
API.

Bug: 79494020
Change-Id: I6f4fd4f4554e3b0de1e6dc7a20f053e39650acf9
parent 4def1327
Loading
Loading
Loading
Loading
+116 −0
Original line number Diff line number Diff line
@@ -944,6 +944,40 @@ const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
    return mItems[index].mName;
}

AMessage::ItemData AMessage::getEntryAt(size_t index) const {
    ItemData it;
    if (index < mNumItems) {
        switch (mItems[index].mType) {
            case kTypeInt32:    it.set(mItems[index].u.int32Value); break;
            case kTypeInt64:    it.set(mItems[index].u.int64Value); break;
            case kTypeSize:     it.set(mItems[index].u.sizeValue); break;
            case kTypeFloat:    it.set(mItems[index].u.floatValue); break;
            case kTypeDouble:   it.set(mItems[index].u.doubleValue); break;
            case kTypePointer:  it.set(mItems[index].u.ptrValue); break;
            case kTypeRect:     it.set(mItems[index].u.rectValue); break;
            case kTypeString:   it.set(*mItems[index].u.stringValue); break;
            case kTypeObject: {
                sp<RefBase> obj = mItems[index].u.refValue;
                it.set(obj);
                break;
            }
            case kTypeMessage: {
                sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
                it.set(msg);
                break;
            }
            case kTypeBuffer: {
                sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
                it.set(buf);
                break;
            }
            default:
                break;
        }
    }
    return it;
}

status_t AMessage::setEntryNameAt(size_t index, const char *name) {
    if (index >= mNumItems) {
        return BAD_INDEX;
@@ -964,6 +998,60 @@ status_t AMessage::setEntryNameAt(size_t index, const char *name) {
    return OK;
}

status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
    AString stringValue;
    sp<RefBase> refValue;
    sp<AMessage> msgValue;
    sp<ABuffer> bufValue;

    if (index >= mNumItems) {
        return BAD_INDEX;
    }
    if (!item.used()) {
        return BAD_VALUE;
    }
    Item *dst = &mItems[index];
    freeItemValue(dst);

    // some values can be directly set with the getter. others need items to be allocated
    if (item.find(&dst->u.int32Value)) {
        dst->mType = kTypeInt32;
    } else if (item.find(&dst->u.int64Value)) {
        dst->mType = kTypeInt64;
    } else if (item.find(&dst->u.sizeValue)) {
        dst->mType = kTypeSize;
    } else if (item.find(&dst->u.floatValue)) {
        dst->mType = kTypeFloat;
    } else if (item.find(&dst->u.doubleValue)) {
        dst->mType = kTypeDouble;
    } else if (item.find(&dst->u.ptrValue)) {
        dst->mType = kTypePointer;
    } else if (item.find(&dst->u.rectValue)) {
        dst->mType = kTypeRect;
    } else if (item.find(&stringValue)) {
        dst->u.stringValue = new AString(stringValue);
        dst->mType = kTypeString;
    } else if (item.find(&refValue)) {
        if (refValue != NULL) { refValue->incStrong(this); }
        dst->u.refValue = refValue.get();
        dst->mType = kTypeObject;
    } else if (item.find(&msgValue)) {
        if (msgValue != NULL) { msgValue->incStrong(this); }
        dst->u.refValue = msgValue.get();
        dst->mType = kTypeMessage;
    } else if (item.find(&bufValue)) {
        if (bufValue != NULL) { bufValue->incStrong(this); }
        dst->u.refValue = bufValue.get();
        dst->mType = kTypeBuffer;
    } else {
        // unsupported item - we should not be here.
        dst->mType = kTypeInt32;
        dst->u.int32Value = 0xDEADDEAD;
        return BAD_TYPE;
    }
    return OK;
}

status_t AMessage::removeEntryAt(size_t index) {
    if (index >= mNumItems) {
        return BAD_INDEX;
@@ -983,6 +1071,34 @@ status_t AMessage::removeEntryAt(size_t index) {
    return OK;
}

void AMessage::setItem(const char *name, const ItemData &item) {
    if (item.used()) {
        Item *it = allocateItem(name);
        if (it != nullptr) {
            setEntryAt(it - mItems, item);
        }
    }
}

AMessage::ItemData AMessage::findItem(const char *name) const {
    return getEntryAt(findEntryByName(name));
}

void AMessage::extend(const sp<AMessage> &other) {
    // ignore null messages
    if (other == nullptr) {
        return;
    }

    for (size_t ix = 0; ix < other->mNumItems; ++ix) {
        Item *it = allocateItem(other->mItems[ix].mName);
        if (it != nullptr) {
            ItemData data = other->getEntryAt(ix);
            setEntryAt(it - mItems, data);
        }
    }
}

size_t AMessage::findEntryByName(const char *name) const {
    return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
}
+42 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define A_MESSAGE_H_

#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AData.h>
#include <media/stagefright/foundation/ALooper.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -155,6 +156,9 @@ struct AMessage : public RefBase {
    // their refcount incremented.
    sp<AMessage> dup() const;

    // Adds all items from other into this.
    void extend(const sp<AMessage> &other);

    // Performs a shallow or deep comparison of |this| and |other| and returns
    // an AMessage with the differences.
    // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
@@ -187,6 +191,31 @@ struct AMessage : public RefBase {
    size_t countEntries() const;
    const char *getEntryNameAt(size_t index, Type *type) const;

    /**
     * Retrieves the item at a specific index.
     */
    typedef AData<
        int32_t, int64_t, size_t, float, double, Rect, AString,
        void *, sp<AMessage>, sp<ABuffer>, sp<RefBase>>::Basic ItemData;

    /**
     * Finds an item by name. This can be used if the type is unknown.
     *
     * \param name name of the item
     * Returns an empty item if no item is present with that name.
     */
    ItemData findItem(const char *name) const;

    /**
     * Sets an item of arbitrary type. Does nothing if the item value is empty.
     *
     * \param name name of the item
     * \param item value of the item
     */
    void setItem(const char *name, const ItemData &item);

    ItemData getEntryAt(size_t index) const;

    /**
     * Finds an entry by name and returns its index.
     *
@@ -207,6 +236,19 @@ struct AMessage : public RefBase {
     */
    status_t setEntryNameAt(size_t index, const char *name);

    /**
     * Sets the item of an entry based on index.
     *
     * \param index index of the entry
     * \param item new item of the entry
     *
     * \retval OK the item was set successfully
     * \retval BAD_INDEX invalid index
     * \retval BAD_VALUE item is invalid (null)
     * \retval BAD_TYPE type is unsupported (should not happen)
     */
    status_t setEntryAt(size_t index, const ItemData &item);

    /**
     * Removes an entry based on index.
     *