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