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