1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef A_MESSAGE_H_
18
19#define A_MESSAGE_H_
20
21#include <media/stagefright/foundation/ABase.h>
22#include <media/stagefright/foundation/AData.h>
23#include <media/stagefright/foundation/ALooper.h>
24#include <utils/KeyedVector.h>
25#include <utils/RefBase.h>
26
27namespace android {
28
29struct ABuffer;
30struct AHandler;
31struct AString;
32class Parcel;
33
34struct AReplyToken : public RefBase {
35    explicit AReplyToken(const sp<ALooper> &looper)
36        : mLooper(looper),
37          mReplied(false) {
38    }
39
40private:
41    friend struct AMessage;
42    friend struct ALooper;
43    wp<ALooper> mLooper;
44    sp<AMessage> mReply;
45    bool mReplied;
46
47    sp<ALooper> getLooper() const {
48        return mLooper.promote();
49    }
50    // if reply is not set, returns false; otherwise, it retrieves the reply and returns true
51    bool retrieveReply(sp<AMessage> *reply) {
52        if (mReplied) {
53            *reply = mReply;
54            mReply.clear();
55        }
56        return mReplied;
57    }
58    // sets the reply for this token. returns OK or error
59    status_t setReply(const sp<AMessage> &reply);
60};
61
62struct AMessage : public RefBase {
63    AMessage();
64    AMessage(uint32_t what, const sp<const AHandler> &handler);
65
66    // Construct an AMessage from a parcel.
67    // nestingAllowed determines how many levels AMessage can be nested inside
68    // AMessage. The default value here is arbitrarily set to 255.
69    // FromParcel() returns NULL on error, which occurs when the input parcel
70    // contains
71    // - an AMessage nested deeper than maxNestingLevel; or
72    // - an item whose type is not recognized by this function.
73    // Types currently recognized by this function are:
74    //   Item types      set/find function suffixes
75    //   ==========================================
76    //     int32_t                Int32
77    //     int64_t                Int64
78    //     size_t                 Size
79    //     float                  Float
80    //     double                 Double
81    //     AString                String
82    //     AMessage               Message
83    static sp<AMessage> FromParcel(const Parcel &parcel,
84                                   size_t maxNestingLevel = 255);
85
86    // Write this AMessage to a parcel.
87    // All items in the AMessage must have types that are recognized by
88    // FromParcel(); otherwise, TRESPASS error will occur.
89    void writeToParcel(Parcel *parcel) const;
90
91    void setWhat(uint32_t what);
92    uint32_t what() const;
93
94    void setTarget(const sp<const AHandler> &handler);
95
96    void clear();
97
98    void setInt32(const char *name, int32_t value);
99    void setInt64(const char *name, int64_t value);
100    void setSize(const char *name, size_t value);
101    void setFloat(const char *name, float value);
102    void setDouble(const char *name, double value);
103    void setPointer(const char *name, void *value);
104    void setString(const char *name, const char *s, ssize_t len = -1);
105    void setString(const char *name, const AString &s);
106    void setObject(const char *name, const sp<RefBase> &obj);
107    void setBuffer(const char *name, const sp<ABuffer> &buffer);
108    void setMessage(const char *name, const sp<AMessage> &obj);
109
110    void setRect(
111            const char *name,
112            int32_t left, int32_t top, int32_t right, int32_t bottom);
113
114    bool contains(const char *name) const;
115
116    bool findInt32(const char *name, int32_t *value) const;
117    bool findInt64(const char *name, int64_t *value) const;
118    bool findSize(const char *name, size_t *value) const;
119    bool findFloat(const char *name, float *value) const;
120    bool findDouble(const char *name, double *value) const;
121    bool findPointer(const char *name, void **value) const;
122    bool findString(const char *name, AString *value) const;
123    bool findObject(const char *name, sp<RefBase> *obj) const;
124    bool findBuffer(const char *name, sp<ABuffer> *buffer) const;
125    bool findMessage(const char *name, sp<AMessage> *obj) const;
126
127    // finds signed integer types cast to int64_t
128    bool findAsInt64(const char *name, int64_t *value) const;
129
130    // finds any numeric type cast to a float
131    bool findAsFloat(const char *name, float *value) const;
132
133    bool findRect(
134            const char *name,
135            int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
136
137    status_t post(int64_t delayUs = 0);
138
139    // Posts the message to its target and waits for a response (or error)
140    // before returning.
141    status_t postAndAwaitResponse(sp<AMessage> *response);
142
143    // If this returns true, the sender of this message is synchronously
144    // awaiting a response and the reply token is consumed from the message
145    // and stored into replyID. The reply token must be used to send the response
146    // using "postReply" below.
147    bool senderAwaitsResponse(sp<AReplyToken> *replyID);
148
149    // Posts the message as a response to a reply token.  A reply token can
150    // only be used once. Returns OK if the response could be posted; otherwise,
151    // an error.
152    status_t postReply(const sp<AReplyToken> &replyID);
153
154    // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
155    // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
156    // their refcount incremented.
157    sp<AMessage> dup() const;
158
159    // Adds all items from other into this.
160    void extend(const sp<AMessage> &other);
161
162    // Performs a shallow or deep comparison of |this| and |other| and returns
163    // an AMessage with the differences.
164    // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
165    // their refcount incremented.
166    // This is true for AMessages that have no corresponding AMessage equivalent in |other|.
167    // (E.g. there is no such key or the type is different.) On the other hand, changes in
168    // the AMessage (or AMessages if deep is |false|) are returned in new objects.
169    sp<AMessage> changesFrom(const sp<const AMessage> &other, bool deep = false) const;
170
171    AString debugString(int32_t indent = 0) const;
172
173    enum Type {
174        kTypeInt32,
175        kTypeInt64,
176        kTypeSize,
177        kTypeFloat,
178        kTypeDouble,
179        kTypePointer,
180        kTypeString,
181        kTypeObject,
182        kTypeMessage,
183        kTypeRect,
184        kTypeBuffer,
185    };
186
187    struct Rect {
188        int32_t mLeft, mTop, mRight, mBottom;
189    };
190
191    size_t countEntries() const;
192    const char *getEntryNameAt(size_t index, Type *type) const;
193
194    /**
195     * Retrieves the item at a specific index.
196     */
197    typedef AData<
198        int32_t, int64_t, size_t, float, double, Rect, AString,
199        void *, sp<AMessage>, sp<ABuffer>, sp<RefBase>>::Basic ItemData;
200
201    /**
202     * Finds an item by name. This can be used if the type is unknown.
203     *
204     * \param name name of the item
205     * Returns an empty item if no item is present with that name.
206     */
207    ItemData findItem(const char *name) const;
208
209    /**
210     * Sets an item of arbitrary type. Does nothing if the item value is empty.
211     *
212     * \param name name of the item
213     * \param item value of the item
214     */
215    void setItem(const char *name, const ItemData &item);
216
217    ItemData getEntryAt(size_t index) const;
218
219    /**
220     * Finds an entry by name and returns its index.
221     *
222     * \retval countEntries() if the entry is not found.
223     */
224    size_t findEntryByName(const char *name) const;
225
226    /**
227     * Sets the name of an entry based on index.
228     *
229     * \param index index of the entry
230     * \param name (new) name of the entry
231     *
232     * \retval OK the name was set successfully
233     * \retval BAD_INDEX invalid index
234     * \retval BAD_VALUE name is invalid (null)
235     * \retval ALREADY_EXISTS name is already used by another entry
236     */
237    status_t setEntryNameAt(size_t index, const char *name);
238
239    /**
240     * Sets the item of an entry based on index.
241     *
242     * \param index index of the entry
243     * \param item new item of the entry
244     *
245     * \retval OK the item was set successfully
246     * \retval BAD_INDEX invalid index
247     * \retval BAD_VALUE item is invalid (null)
248     * \retval BAD_TYPE type is unsupported (should not happen)
249     */
250    status_t setEntryAt(size_t index, const ItemData &item);
251
252    /**
253     * Removes an entry based on index.
254     *
255     * \param index index of the entry
256     *
257     * \retval OK the entry was removed successfully
258     * \retval BAD_INDEX invalid index
259     */
260    status_t removeEntryAt(size_t index);
261
262protected:
263    virtual ~AMessage();
264
265private:
266    friend struct ALooper; // deliver()
267
268    uint32_t mWhat;
269
270    // used only for debugging
271    ALooper::handler_id mTarget;
272
273    wp<AHandler> mHandler;
274    wp<ALooper> mLooper;
275
276    struct Item {
277        union {
278            int32_t int32Value;
279            int64_t int64Value;
280            size_t sizeValue;
281            float floatValue;
282            double doubleValue;
283            void *ptrValue;
284            RefBase *refValue;
285            AString *stringValue;
286            Rect rectValue;
287        } u;
288        const char *mName;
289        size_t      mNameLength;
290        Type mType;
291        void setName(const char *name, size_t len);
292    };
293
294    enum {
295        kMaxNumItems = 64
296    };
297    Item mItems[kMaxNumItems];
298    size_t mNumItems;
299
300    Item *allocateItem(const char *name);
301    void freeItemValue(Item *item);
302    const Item *findItem(const char *name, Type type) const;
303
304    void setObjectInternal(
305            const char *name, const sp<RefBase> &obj, Type type);
306
307    size_t findItemIndex(const char *name, size_t len) const;
308
309    void deliver();
310
311    DISALLOW_EVIL_CONSTRUCTORS(AMessage);
312};
313
314}  // namespace android
315
316#endif  // A_MESSAGE_H_
317