• 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     // Post a message uniquely to its target with the given timeout.
145     // This method ensures that there is exactly one message with the same token posted to its
146     // target after the call returns. A null token will result in an EINVAL error status.
147     status_t postUnique(const sp<RefBase> &token, int64_t delayUs = 0);
148 
149     // Posts the message to its target and waits for a response (or error)
150     // before returning.
151     status_t postAndAwaitResponse(sp<AMessage> *response);
152 
153     // If this returns true, the sender of this message is synchronously
154     // awaiting a response and the reply token is consumed from the message
155     // and stored into replyID. The reply token must be used to send the response
156     // using "postReply" below.
157     bool senderAwaitsResponse(sp<AReplyToken> *replyID);
158 
159     // Posts the message as a response to a reply token.  A reply token can
160     // only be used once. Returns OK if the response could be posted; otherwise,
161     // an error.
162     status_t postReply(const sp<AReplyToken> &replyID);
163 
164     // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
165     // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
166     // their refcount incremented.
167     sp<AMessage> dup() const;
168 
169     // Adds all items from other into this.
170     void extend(const sp<AMessage> &other);
171 
172     // Performs a shallow or deep comparison of |this| and |other| and returns
173     // an AMessage with the differences.
174     // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
175     // their refcount incremented.
176     // This is true for AMessages that have no corresponding AMessage equivalent in |other|.
177     // (E.g. there is no such key or the type is different.) On the other hand, changes in
178     // the AMessage (or AMessages if deep is |false|) are returned in new objects.
179     sp<AMessage> changesFrom(const sp<const AMessage> &other, bool deep = false) const;
180 
181     AString debugString(int32_t indent = 0) const;
182 
183     enum Type {
184         kTypeInt32,
185         kTypeInt64,
186         kTypeSize,
187         kTypeFloat,
188         kTypeDouble,
189         kTypePointer,
190         kTypeString,
191         kTypeObject,
192         kTypeMessage,
193         kTypeRect,
194         kTypeBuffer,
195     };
196 
197     struct Rect {
198         int32_t mLeft, mTop, mRight, mBottom;
199     };
200 
201     size_t countEntries() const;
202     static size_t maxAllowedEntries();
203     const char *getEntryNameAt(size_t index, Type *type) const;
204 
205     /**
206      * Retrieves the item at a specific index.
207      */
208     typedef AData<
209         int32_t, int64_t, size_t, float, double, Rect, AString,
210         void *, sp<AMessage>, sp<ABuffer>, sp<RefBase>>::Basic ItemData;
211 
212     /**
213      * Finds an item by name. This can be used if the type is unknown.
214      *
215      * \param name name of the item
216      * Returns an empty item if no item is present with that name.
217      */
218     ItemData findItem(const char *name) const;
219 
220     /**
221      * Sets an item of arbitrary type. Does nothing if the item value is empty.
222      *
223      * \param name name of the item
224      * \param item value of the item
225      */
226     void setItem(const char *name, const ItemData &item);
227 
228     ItemData getEntryAt(size_t index) const;
229 
230     /**
231      * Finds an entry by name and returns its index.
232      *
233      * \retval countEntries() if the entry is not found.
234      */
235     size_t findEntryByName(const char *name) const;
236 
237     /**
238      * Sets the name of an entry based on index.
239      *
240      * \param index index of the entry
241      * \param name (new) name of the entry
242      *
243      * \retval OK the name was set successfully
244      * \retval BAD_INDEX invalid index
245      * \retval BAD_VALUE name is invalid (null)
246      * \retval ALREADY_EXISTS name is already used by another entry
247      */
248     status_t setEntryNameAt(size_t index, const char *name);
249 
250     /**
251      * Sets the item of an entry based on index.
252      *
253      * \param index index of the entry
254      * \param item new item of the entry
255      *
256      * \retval OK the item was set successfully
257      * \retval BAD_INDEX invalid index
258      * \retval BAD_VALUE item is invalid (null)
259      * \retval BAD_TYPE type is unsupported (should not happen)
260      */
261     status_t setEntryAt(size_t index, const ItemData &item);
262 
263     /**
264      * Removes an entry based on index.
265      *
266      * \param index index of the entry
267      *
268      * \retval OK the entry was removed successfully
269      * \retval BAD_INDEX invalid index
270      */
271     status_t removeEntryAt(size_t index);
272 
273     /**
274      * Removes an entry based on name.
275      *
276      * \param name  name of the entry
277      *
278      * \retval OK the entry was removed successfully
279      * \retval BAD_VALUE name is invalid (null)
280      * \retval BAD_INDEX name not found
281      */
282     status_t removeEntryByName(const char *name);
283 
284 protected:
285     virtual ~AMessage();
286 
287 private:
288     friend struct ALooper; // deliver()
289 
290     uint32_t mWhat;
291 
292     // used only for debugging
293     ALooper::handler_id mTarget;
294 
295     wp<AHandler> mHandler;
296     wp<ALooper> mLooper;
297 
298     struct Item {
299         union {
300             int32_t int32Value;
301             int64_t int64Value;
302             size_t sizeValue;
303             float floatValue;
304             double doubleValue;
305             void *ptrValue;
306             RefBase *refValue;
307             AString *stringValue;
308             Rect rectValue;
309         } u;
310         const char *mName;
311         size_t      mNameLength;
312         Type mType;
313         void setName(const char *name, size_t len);
ItemAMessage::Item314         Item() : mName(nullptr), mNameLength(0), mType(kTypeInt32) { }
315         Item(const char *name, size_t length);
316     };
317 
318     enum {
319         kMaxNumItems = 256
320     };
321     std::vector<Item> mItems;
322 
323     /**
324      * Allocates an item with the given key |name|. If the key already exists, the corresponding
325      * item value is freed. Otherwise a new item is added.
326      *
327      * This method currently asserts if the number of elements would exceed the max number of
328      * elements allowed (kMaxNumItems). This is a security precaution to avoid arbitrarily large
329      * AMessage structures.
330      *
331      * @todo(b/192153245) Either revisit this security precaution, or change the behavior to
332      *      silently ignore keys added after the max number of elements are reached.
333      *
334      * @note All previously returned Item* pointers are deemed invalid after this call. (E.g. from
335      *       allocateItem or findItem)
336      *
337      * @param name the key for the requested item.
338      *
339      * @return Item* a pointer to the item.
340      */
341     Item *allocateItem(const char *name);
342 
343     /** Frees the value for the item. */
344     void freeItemValue(Item *item);
345 
346     /** Finds an item with given key |name| and |type|. Returns nullptr if item is not found. */
347     const Item *findItem(const char *name, Type type) const;
348 
349     void setObjectInternal(
350             const char *name, const sp<RefBase> &obj, Type type);
351 
352     size_t findItemIndex(const char *name, size_t len) const;
353 
354     void deliver();
355 
356     DISALLOW_EVIL_CONSTRUCTORS(AMessage);
357 };
358 
359 /*
360  * Helper struct for wrapping any object with RefBase.
361  */
362 template <typename T>
363 struct WrapperObject : public RefBase {
WrapperObjectWrapperObject364     WrapperObject(const T& v) : value(v) {}
WrapperObjectWrapperObject365     WrapperObject(T&& v) : value(std::move(v)) {}
366     T value;
367 };
368 
369 }  // namespace android
370 
371 #endif  // A_MESSAGE_H_
372