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