• 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 #include "AMessage.h"
18 
19 #include <ctype.h>
20 
21 #include "AAtomizer.h"
22 #include "ABuffer.h"
23 #include "ADebug.h"
24 #include "ALooperRoster.h"
25 #include "AString.h"
26 
27 #include <binder/Parcel.h>
28 #include <media/stagefright/foundation/hexdump.h>
29 
30 namespace android {
31 
32 extern ALooperRoster gLooperRoster;
33 
AMessage(uint32_t what,ALooper::handler_id target)34 AMessage::AMessage(uint32_t what, ALooper::handler_id target)
35     : mWhat(what),
36       mTarget(target),
37       mNumItems(0) {
38 }
39 
~AMessage()40 AMessage::~AMessage() {
41     clear();
42 }
43 
setWhat(uint32_t what)44 void AMessage::setWhat(uint32_t what) {
45     mWhat = what;
46 }
47 
what() const48 uint32_t AMessage::what() const {
49     return mWhat;
50 }
51 
setTarget(ALooper::handler_id handlerID)52 void AMessage::setTarget(ALooper::handler_id handlerID) {
53     mTarget = handlerID;
54 }
55 
target() const56 ALooper::handler_id AMessage::target() const {
57     return mTarget;
58 }
59 
clear()60 void AMessage::clear() {
61     for (size_t i = 0; i < mNumItems; ++i) {
62         Item *item = &mItems[i];
63         freeItem(item);
64     }
65     mNumItems = 0;
66 }
67 
freeItem(Item * item)68 void AMessage::freeItem(Item *item) {
69     switch (item->mType) {
70         case kTypeString:
71         {
72             delete item->u.stringValue;
73             break;
74         }
75 
76         case kTypeObject:
77         case kTypeMessage:
78         case kTypeBuffer:
79         {
80             if (item->u.refValue != NULL) {
81                 item->u.refValue->decStrong(this);
82             }
83             break;
84         }
85 
86         default:
87             break;
88     }
89 }
90 
allocateItem(const char * name)91 AMessage::Item *AMessage::allocateItem(const char *name) {
92     name = AAtomizer::Atomize(name);
93 
94     size_t i = 0;
95     while (i < mNumItems && mItems[i].mName != name) {
96         ++i;
97     }
98 
99     Item *item;
100 
101     if (i < mNumItems) {
102         item = &mItems[i];
103         freeItem(item);
104     } else {
105         CHECK(mNumItems < kMaxNumItems);
106         i = mNumItems++;
107         item = &mItems[i];
108 
109         item->mName = name;
110     }
111 
112     return item;
113 }
114 
findItem(const char * name,Type type) const115 const AMessage::Item *AMessage::findItem(
116         const char *name, Type type) const {
117     name = AAtomizer::Atomize(name);
118 
119     for (size_t i = 0; i < mNumItems; ++i) {
120         const Item *item = &mItems[i];
121 
122         if (item->mName == name) {
123             return item->mType == type ? item : NULL;
124         }
125     }
126 
127     return NULL;
128 }
129 
130 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
131 void AMessage::set##NAME(const char *name, TYPENAME value) {            \
132     Item *item = allocateItem(name);                                    \
133                                                                         \
134     item->mType = kType##NAME;                                          \
135     item->u.FIELDNAME = value;                                          \
136 }                                                                       \
137                                                                         \
138 bool AMessage::find##NAME(const char *name, TYPENAME *value) const {    \
139     const Item *item = findItem(name, kType##NAME);                     \
140     if (item) {                                                         \
141         *value = item->u.FIELDNAME;                                     \
142         return true;                                                    \
143     }                                                                   \
144     return false;                                                       \
145 }
146 
BASIC_TYPE(Int32,int32Value,int32_t)147 BASIC_TYPE(Int32,int32Value,int32_t)
148 BASIC_TYPE(Int64,int64Value,int64_t)
149 BASIC_TYPE(Size,sizeValue,size_t)
150 BASIC_TYPE(Float,floatValue,float)
151 BASIC_TYPE(Double,doubleValue,double)
152 BASIC_TYPE(Pointer,ptrValue,void *)
153 
154 #undef BASIC_TYPE
155 
156 void AMessage::setString(
157         const char *name, const char *s, ssize_t len) {
158     Item *item = allocateItem(name);
159     item->mType = kTypeString;
160     item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
161 }
162 
setObjectInternal(const char * name,const sp<RefBase> & obj,Type type)163 void AMessage::setObjectInternal(
164         const char *name, const sp<RefBase> &obj, Type type) {
165     Item *item = allocateItem(name);
166     item->mType = type;
167 
168     if (obj != NULL) { obj->incStrong(this); }
169     item->u.refValue = obj.get();
170 }
171 
setObject(const char * name,const sp<RefBase> & obj)172 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
173     setObjectInternal(name, obj, kTypeObject);
174 }
175 
setBuffer(const char * name,const sp<ABuffer> & buffer)176 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
177     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
178 }
179 
setMessage(const char * name,const sp<AMessage> & obj)180 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
181     Item *item = allocateItem(name);
182     item->mType = kTypeMessage;
183 
184     if (obj != NULL) { obj->incStrong(this); }
185     item->u.refValue = obj.get();
186 }
187 
setRect(const char * name,int32_t left,int32_t top,int32_t right,int32_t bottom)188 void AMessage::setRect(
189         const char *name,
190         int32_t left, int32_t top, int32_t right, int32_t bottom) {
191     Item *item = allocateItem(name);
192     item->mType = kTypeRect;
193 
194     item->u.rectValue.mLeft = left;
195     item->u.rectValue.mTop = top;
196     item->u.rectValue.mRight = right;
197     item->u.rectValue.mBottom = bottom;
198 }
199 
findString(const char * name,AString * value) const200 bool AMessage::findString(const char *name, AString *value) const {
201     const Item *item = findItem(name, kTypeString);
202     if (item) {
203         *value = *item->u.stringValue;
204         return true;
205     }
206     return false;
207 }
208 
findObject(const char * name,sp<RefBase> * obj) const209 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
210     const Item *item = findItem(name, kTypeObject);
211     if (item) {
212         *obj = item->u.refValue;
213         return true;
214     }
215     return false;
216 }
217 
findBuffer(const char * name,sp<ABuffer> * buf) const218 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
219     const Item *item = findItem(name, kTypeBuffer);
220     if (item) {
221         *buf = (ABuffer *)(item->u.refValue);
222         return true;
223     }
224     return false;
225 }
226 
findMessage(const char * name,sp<AMessage> * obj) const227 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
228     const Item *item = findItem(name, kTypeMessage);
229     if (item) {
230         *obj = static_cast<AMessage *>(item->u.refValue);
231         return true;
232     }
233     return false;
234 }
235 
findRect(const char * name,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom) const236 bool AMessage::findRect(
237         const char *name,
238         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
239     const Item *item = findItem(name, kTypeRect);
240     if (item == NULL) {
241         return false;
242     }
243 
244     *left = item->u.rectValue.mLeft;
245     *top = item->u.rectValue.mTop;
246     *right = item->u.rectValue.mRight;
247     *bottom = item->u.rectValue.mBottom;
248 
249     return true;
250 }
251 
post(int64_t delayUs)252 void AMessage::post(int64_t delayUs) {
253     gLooperRoster.postMessage(this, delayUs);
254 }
255 
postAndAwaitResponse(sp<AMessage> * response)256 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
257     return gLooperRoster.postAndAwaitResponse(this, response);
258 }
259 
postReply(uint32_t replyID)260 void AMessage::postReply(uint32_t replyID) {
261     gLooperRoster.postReply(replyID, this);
262 }
263 
senderAwaitsResponse(uint32_t * replyID) const264 bool AMessage::senderAwaitsResponse(uint32_t *replyID) const {
265     int32_t tmp;
266     bool found = findInt32("replyID", &tmp);
267 
268     if (!found) {
269         return false;
270     }
271 
272     *replyID = static_cast<uint32_t>(tmp);
273 
274     return true;
275 }
276 
dup() const277 sp<AMessage> AMessage::dup() const {
278     sp<AMessage> msg = new AMessage(mWhat, mTarget);
279     msg->mNumItems = mNumItems;
280 
281     for (size_t i = 0; i < mNumItems; ++i) {
282         const Item *from = &mItems[i];
283         Item *to = &msg->mItems[i];
284 
285         to->mName = from->mName;
286         to->mType = from->mType;
287 
288         switch (from->mType) {
289             case kTypeString:
290             {
291                 to->u.stringValue =
292                     new AString(*from->u.stringValue);
293                 break;
294             }
295 
296             case kTypeObject:
297             case kTypeBuffer:
298             {
299                 to->u.refValue = from->u.refValue;
300                 to->u.refValue->incStrong(msg.get());
301                 break;
302             }
303 
304             case kTypeMessage:
305             {
306                 sp<AMessage> copy =
307                     static_cast<AMessage *>(from->u.refValue)->dup();
308 
309                 to->u.refValue = copy.get();
310                 to->u.refValue->incStrong(msg.get());
311                 break;
312             }
313 
314             default:
315             {
316                 to->u = from->u;
317                 break;
318             }
319         }
320     }
321 
322     return msg;
323 }
324 
appendIndent(AString * s,int32_t indent)325 static void appendIndent(AString *s, int32_t indent) {
326     static const char kWhitespace[] =
327         "                                        "
328         "                                        ";
329 
330     CHECK_LT((size_t)indent, sizeof(kWhitespace));
331 
332     s->append(kWhitespace, indent);
333 }
334 
isFourcc(uint32_t what)335 static bool isFourcc(uint32_t what) {
336     return isprint(what & 0xff)
337         && isprint((what >> 8) & 0xff)
338         && isprint((what >> 16) & 0xff)
339         && isprint((what >> 24) & 0xff);
340 }
341 
debugString(int32_t indent) const342 AString AMessage::debugString(int32_t indent) const {
343     AString s = "AMessage(what = ";
344 
345     AString tmp;
346     if (isFourcc(mWhat)) {
347         tmp = StringPrintf(
348                 "'%c%c%c%c'",
349                 (char)(mWhat >> 24),
350                 (char)((mWhat >> 16) & 0xff),
351                 (char)((mWhat >> 8) & 0xff),
352                 (char)(mWhat & 0xff));
353     } else {
354         tmp = StringPrintf("0x%08x", mWhat);
355     }
356     s.append(tmp);
357 
358     if (mTarget != 0) {
359         tmp = StringPrintf(", target = %d", mTarget);
360         s.append(tmp);
361     }
362     s.append(") = {\n");
363 
364     for (size_t i = 0; i < mNumItems; ++i) {
365         const Item &item = mItems[i];
366 
367         switch (item.mType) {
368             case kTypeInt32:
369                 tmp = StringPrintf(
370                         "int32_t %s = %d", item.mName, item.u.int32Value);
371                 break;
372             case kTypeInt64:
373                 tmp = StringPrintf(
374                         "int64_t %s = %lld", item.mName, item.u.int64Value);
375                 break;
376             case kTypeSize:
377                 tmp = StringPrintf(
378                         "size_t %s = %d", item.mName, item.u.sizeValue);
379                 break;
380             case kTypeFloat:
381                 tmp = StringPrintf(
382                         "float %s = %f", item.mName, item.u.floatValue);
383                 break;
384             case kTypeDouble:
385                 tmp = StringPrintf(
386                         "double %s = %f", item.mName, item.u.doubleValue);
387                 break;
388             case kTypePointer:
389                 tmp = StringPrintf(
390                         "void *%s = %p", item.mName, item.u.ptrValue);
391                 break;
392             case kTypeString:
393                 tmp = StringPrintf(
394                         "string %s = \"%s\"",
395                         item.mName,
396                         item.u.stringValue->c_str());
397                 break;
398             case kTypeObject:
399                 tmp = StringPrintf(
400                         "RefBase *%s = %p", item.mName, item.u.refValue);
401                 break;
402             case kTypeBuffer:
403             {
404                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
405 
406                 if (buffer != NULL && buffer->size() <= 64) {
407                     tmp = StringPrintf("Buffer %s = {\n", item.mName);
408                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
409                     appendIndent(&tmp, indent + 2);
410                     tmp.append("}");
411                 } else {
412                     tmp = StringPrintf(
413                             "Buffer *%s = %p", item.mName, buffer.get());
414                 }
415                 break;
416             }
417             case kTypeMessage:
418                 tmp = StringPrintf(
419                         "AMessage %s = %s",
420                         item.mName,
421                         static_cast<AMessage *>(
422                             item.u.refValue)->debugString(
423                                 indent + strlen(item.mName) + 14).c_str());
424                 break;
425             case kTypeRect:
426                 tmp = StringPrintf(
427                         "Rect %s(%d, %d, %d, %d)",
428                         item.mName,
429                         item.u.rectValue.mLeft,
430                         item.u.rectValue.mTop,
431                         item.u.rectValue.mRight,
432                         item.u.rectValue.mBottom);
433                 break;
434             default:
435                 TRESPASS();
436         }
437 
438         appendIndent(&s, indent);
439         s.append("  ");
440         s.append(tmp);
441         s.append("\n");
442     }
443 
444     appendIndent(&s, indent);
445     s.append("}");
446 
447     return s;
448 }
449 
450 // static
FromParcel(const Parcel & parcel)451 sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
452     int32_t what = parcel.readInt32();
453     sp<AMessage> msg = new AMessage(what);
454 
455     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
456 
457     for (size_t i = 0; i < msg->mNumItems; ++i) {
458         Item *item = &msg->mItems[i];
459 
460         item->mName = AAtomizer::Atomize(parcel.readCString());
461         item->mType = static_cast<Type>(parcel.readInt32());
462 
463         switch (item->mType) {
464             case kTypeInt32:
465             {
466                 item->u.int32Value = parcel.readInt32();
467                 break;
468             }
469 
470             case kTypeInt64:
471             {
472                 item->u.int64Value = parcel.readInt64();
473                 break;
474             }
475 
476             case kTypeSize:
477             {
478                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
479                 break;
480             }
481 
482             case kTypeFloat:
483             {
484                 item->u.floatValue = parcel.readFloat();
485                 break;
486             }
487 
488             case kTypeDouble:
489             {
490                 item->u.doubleValue = parcel.readDouble();
491                 break;
492             }
493 
494             case kTypeString:
495             {
496                 item->u.stringValue = new AString(parcel.readCString());
497                 break;
498             }
499 
500             case kTypeMessage:
501             {
502                 sp<AMessage> subMsg = AMessage::FromParcel(parcel);
503                 subMsg->incStrong(msg.get());
504 
505                 item->u.refValue = subMsg.get();
506                 break;
507             }
508 
509             default:
510             {
511                 ALOGE("This type of object cannot cross process boundaries.");
512                 TRESPASS();
513             }
514         }
515     }
516 
517     return msg;
518 }
519 
writeToParcel(Parcel * parcel) const520 void AMessage::writeToParcel(Parcel *parcel) const {
521     parcel->writeInt32(static_cast<int32_t>(mWhat));
522     parcel->writeInt32(static_cast<int32_t>(mNumItems));
523 
524     for (size_t i = 0; i < mNumItems; ++i) {
525         const Item &item = mItems[i];
526 
527         parcel->writeCString(item.mName);
528         parcel->writeInt32(static_cast<int32_t>(item.mType));
529 
530         switch (item.mType) {
531             case kTypeInt32:
532             {
533                 parcel->writeInt32(item.u.int32Value);
534                 break;
535             }
536 
537             case kTypeInt64:
538             {
539                 parcel->writeInt64(item.u.int64Value);
540                 break;
541             }
542 
543             case kTypeSize:
544             {
545                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
546                 break;
547             }
548 
549             case kTypeFloat:
550             {
551                 parcel->writeFloat(item.u.floatValue);
552                 break;
553             }
554 
555             case kTypeDouble:
556             {
557                 parcel->writeDouble(item.u.doubleValue);
558                 break;
559             }
560 
561             case kTypeString:
562             {
563                 parcel->writeCString(item.u.stringValue->c_str());
564                 break;
565             }
566 
567             case kTypeMessage:
568             {
569                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
570                 break;
571             }
572 
573             default:
574             {
575                 ALOGE("This type of object cannot cross process boundaries.");
576                 TRESPASS();
577             }
578         }
579     }
580 }
581 
countEntries() const582 size_t AMessage::countEntries() const {
583     return mNumItems;
584 }
585 
getEntryNameAt(size_t index,Type * type) const586 const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
587     if (index >= mNumItems) {
588         *type = kTypeInt32;
589 
590         return NULL;
591     }
592 
593     *type = mItems[index].mType;
594 
595     return mItems[index].mName;
596 }
597 
598 }  // namespace android
599