blob: 960212a740e8a83beb0092c5869f30c3169704e0 [file] [log] [blame]
* Copyright (C) 2010 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#ifndef A_MESSAGE_H_
#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>
#include <vector>
namespace android {
struct ABuffer;
struct AHandler;
struct AString;
class Parcel;
struct AReplyToken : public RefBase {
explicit AReplyToken(const sp<ALooper> &looper)
: mLooper(looper),
mReplied(false) {
friend struct AMessage;
friend struct ALooper;
wp<ALooper> mLooper;
sp<AMessage> mReply;
bool mReplied;
sp<ALooper> getLooper() const {
return mLooper.promote();
// if reply is not set, returns false; otherwise, it retrieves the reply and returns true
bool retrieveReply(sp<AMessage> *reply) {
if (mReplied) {
*reply = mReply;
return mReplied;
// sets the reply for this token. returns OK or error
status_t setReply(const sp<AMessage> &reply);
struct AMessage : public RefBase {
AMessage(uint32_t what, const sp<const AHandler> &handler);
#if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
// Construct an AMessage from a parcel.
// nestingAllowed determines how many levels AMessage can be nested inside
// AMessage. The default value here is arbitrarily set to 255.
// FromParcel() returns NULL on error, which occurs when the input parcel
// contains
// - an AMessage nested deeper than maxNestingLevel; or
// - an item whose type is not recognized by this function.
// Types currently recognized by this function are:
// Item types set/find function suffixes
// ==========================================
// int32_t Int32
// int64_t Int64
// size_t Size
// float Float
// double Double
// AString String
// AMessage Message
static sp<AMessage> FromParcel(const Parcel &parcel,
size_t maxNestingLevel = 255);
// Write this AMessage to a parcel.
// All items in the AMessage must have types that are recognized by
// FromParcel(); otherwise, TRESPASS error will occur.
void writeToParcel(Parcel *parcel) const;
#endif // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
void setWhat(uint32_t what);
uint32_t what() const;
void setTarget(const sp<const AHandler> &handler);
// removes all items
void clear();
void setInt32(const char *name, int32_t value);
void setInt64(const char *name, int64_t value);
void setSize(const char *name, size_t value);
void setFloat(const char *name, float value);
void setDouble(const char *name, double value);
void setPointer(const char *name, void *value);
void setString(const char *name, const char *s, ssize_t len = -1);
void setString(const char *name, const AString &s);
void setObject(const char *name, const sp<RefBase> &obj);
void setBuffer(const char *name, const sp<ABuffer> &buffer);
void setMessage(const char *name, const sp<AMessage> &obj);
void setRect(
const char *name,
int32_t left, int32_t top, int32_t right, int32_t bottom);
bool contains(const char *name) const;
bool findInt32(const char *name, int32_t *value) const;
bool findInt64(const char *name, int64_t *value) const;
bool findSize(const char *name, size_t *value) const;
bool findFloat(const char *name, float *value) const;
bool findDouble(const char *name, double *value) const;
bool findPointer(const char *name, void **value) const;
bool findString(const char *name, AString *value) const;
bool findObject(const char *name, sp<RefBase> *obj) const;
bool findBuffer(const char *name, sp<ABuffer> *buffer) const;
bool findMessage(const char *name, sp<AMessage> *obj) const;
// finds signed integer types cast to int64_t
bool findAsInt64(const char *name, int64_t *value) const;
// finds any numeric type cast to a float
bool findAsFloat(const char *name, float *value) const;
bool findRect(
const char *name,
int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
status_t post(int64_t delayUs = 0);
// Posts the message to its target and waits for a response (or error)
// before returning.
status_t postAndAwaitResponse(sp<AMessage> *response);
// If this returns true, the sender of this message is synchronously
// awaiting a response and the reply token is consumed from the message
// and stored into replyID. The reply token must be used to send the response
// using "postReply" below.
bool senderAwaitsResponse(sp<AReplyToken> *replyID);
// Posts the message as a response to a reply token. A reply token can
// only be used once. Returns OK if the response could be posted; otherwise,
// an error.
status_t postReply(const sp<AReplyToken> &replyID);
// Performs a deep-copy of "this", contained messages are in turn "dup'ed".
// Warning: RefBase items, i.e. "objects" are _not_ copied but only have
// 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
// their refcount incremented.
// This is true for AMessages that have no corresponding AMessage equivalent in |other|.
// (E.g. there is no such key or the type is different.) On the other hand, changes in
// the AMessage (or AMessages if deep is |false|) are returned in new objects.
sp<AMessage> changesFrom(const sp<const AMessage> &other, bool deep = false) const;
AString debugString(int32_t indent = 0) const;
enum Type {
struct Rect {
int32_t mLeft, mTop, mRight, mBottom;
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.
* \retval countEntries() if the entry is not found.
size_t findEntryByName(const char *name) const;
* Sets the name of an entry based on index.
* \param index index of the entry
* \param name (new) name of the entry
* \retval OK the name was set successfully
* \retval BAD_INDEX invalid index
* \retval BAD_VALUE name is invalid (null)
* \retval ALREADY_EXISTS name is already used by another entry
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.
* \param index index of the entry
* \retval OK the entry was removed successfully
* \retval BAD_INDEX invalid index
status_t removeEntryAt(size_t index);
* Removes an entry based on name.
* \param name name of the entry
* \retval OK the entry was removed successfully
* \retval BAD_VALUE name is invalid (null)
* \retval BAD_INDEX name not found
status_t removeEntryByName(const char *name);
virtual ~AMessage();
friend struct ALooper; // deliver()
uint32_t mWhat;
// used only for debugging
ALooper::handler_id mTarget;
wp<AHandler> mHandler;
wp<ALooper> mLooper;
struct Item {
union {
int32_t int32Value;
int64_t int64Value;
size_t sizeValue;
float floatValue;
double doubleValue;
void *ptrValue;
RefBase *refValue;
AString *stringValue;
Rect rectValue;
} u;
const char *mName;
size_t mNameLength;
Type mType;
void setName(const char *name, size_t len);
Item() : mName(nullptr), mNameLength(0), mType(kTypeInt32) { }
Item(const char *name, size_t length);
enum {
kMaxNumItems = 256
std::vector<Item> mItems;
* Allocates an item with the given key |name|. If the key already exists, the corresponding
* item value is freed. Otherwise a new item is added.
* This method currently asserts if the number of elements would exceed the max number of
* elements allowed (kMaxNumItems). This is a security precaution to avoid arbitrarily large
* AMessage structures.
* @todo(b/192153245) Either revisit this security precaution, or change the behavior to
* silently ignore keys added after the max number of elements are reached.
* @note All previously returned Item* pointers are deemed invalid after this call. (E.g. from
* allocateItem or findItem)
* @param name the key for the requested item.
* @return Item* a pointer to the item.
Item *allocateItem(const char *name);
/** Frees the value for the item. */
void freeItemValue(Item *item);
/** Finds an item with given key |name| and |type|. Returns nullptr if item is not found. */
const Item *findItem(const char *name, Type type) const;
void setObjectInternal(
const char *name, const sp<RefBase> &obj, Type type);
size_t findItemIndex(const char *name, size_t len) const;
void deliver();
} // namespace android
#endif // A_MESSAGE_H_