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 #define LOG_TAG "AMessage"
18 //#define LOG_NDEBUG 0
19 //#define DUMP_STATS
20 #include <cutils/log.h>
21 
22 #include "AMessage.h"
23 
24 #include <ctype.h>
25 
26 #include "AAtomizer.h"
27 #include "ABuffer.h"
28 #include "ADebug.h"
29 #include "ALooperRoster.h"
30 #include "AHandler.h"
31 #include "AString.h"
32 
33 #include <binder/Parcel.h>
34 #include <media/stagefright/foundation/hexdump.h>
35 
36 namespace android {
37 
38 extern ALooperRoster gLooperRoster;
39 
setReply(const sp<AMessage> & reply)40 status_t AReplyToken::setReply(const sp<AMessage> &reply) {
41     if (mReplied) {
42         ALOGE("trying to post a duplicate reply");
43         return -EBUSY;
44     }
45     CHECK(mReply == NULL);
46     mReply = reply;
47     mReplied = true;
48     return OK;
49 }
50 
AMessage(void)51 AMessage::AMessage(void)
52     : mWhat(0),
53       mTarget(0),
54       mNumItems(0) {
55 }
56 
AMessage(uint32_t what,const sp<const AHandler> & handler)57 AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
58     : mWhat(what),
59       mNumItems(0) {
60     setTarget(handler);
61 }
62 
~AMessage()63 AMessage::~AMessage() {
64     clear();
65 }
66 
setWhat(uint32_t what)67 void AMessage::setWhat(uint32_t what) {
68     mWhat = what;
69 }
70 
what() const71 uint32_t AMessage::what() const {
72     return mWhat;
73 }
74 
setTarget(const sp<const AHandler> & handler)75 void AMessage::setTarget(const sp<const AHandler> &handler) {
76     if (handler == NULL) {
77         mTarget = 0;
78         mHandler.clear();
79         mLooper.clear();
80     } else {
81         mTarget = handler->id();
82         mHandler = handler->getHandler();
83         mLooper = handler->getLooper();
84     }
85 }
86 
clear()87 void AMessage::clear() {
88     for (size_t i = 0; i < mNumItems; ++i) {
89         Item *item = &mItems[i];
90         delete[] item->mName;
91         item->mName = NULL;
92         freeItemValue(item);
93     }
94     mNumItems = 0;
95 }
96 
freeItemValue(Item * item)97 void AMessage::freeItemValue(Item *item) {
98     switch (item->mType) {
99         case kTypeString:
100         {
101             delete item->u.stringValue;
102             break;
103         }
104 
105         case kTypeObject:
106         case kTypeMessage:
107         case kTypeBuffer:
108         {
109             if (item->u.refValue != NULL) {
110                 item->u.refValue->decStrong(this);
111             }
112             break;
113         }
114 
115         default:
116             break;
117     }
118 }
119 
120 #ifdef DUMP_STATS
121 #include <utils/Mutex.h>
122 
123 Mutex gLock;
124 static int32_t gFindItemCalls = 1;
125 static int32_t gDupCalls = 1;
126 static int32_t gAverageNumItems = 0;
127 static int32_t gAverageNumChecks = 0;
128 static int32_t gAverageNumMemChecks = 0;
129 static int32_t gAverageDupItems = 0;
130 static int32_t gLastChecked = -1;
131 
reportStats()132 static void reportStats() {
133     int32_t time = (ALooper::GetNowUs() / 1000);
134     if (time / 1000 != gLastChecked / 1000) {
135         gLastChecked = time;
136         ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)",
137                 gFindItemCalls,
138                 gAverageNumItems / (float)gFindItemCalls,
139                 gAverageNumChecks / (float)gFindItemCalls,
140                 gAverageNumMemChecks / (float)gFindItemCalls,
141                 gDupCalls,
142                 gAverageDupItems / (float)gDupCalls);
143         gFindItemCalls = gDupCalls = 1;
144         gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0;
145         gLastChecked = time;
146     }
147 }
148 #endif
149 
findItemIndex(const char * name,size_t len) const150 inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
151 #ifdef DUMP_STATS
152     size_t memchecks = 0;
153 #endif
154     size_t i = 0;
155     for (; i < mNumItems; i++) {
156         if (len != mItems[i].mNameLength) {
157             continue;
158         }
159 #ifdef DUMP_STATS
160         ++memchecks;
161 #endif
162         if (!memcmp(mItems[i].mName, name, len)) {
163             break;
164         }
165     }
166 #ifdef DUMP_STATS
167     {
168         Mutex::Autolock _l(gLock);
169         ++gFindItemCalls;
170         gAverageNumItems += mNumItems;
171         gAverageNumMemChecks += memchecks;
172         gAverageNumChecks += i;
173         reportStats();
174     }
175 #endif
176     return i;
177 }
178 
179 // assumes item's name was uninitialized or NULL
setName(const char * name,size_t len)180 void AMessage::Item::setName(const char *name, size_t len) {
181     mNameLength = len;
182     mName = new char[len + 1];
183     memcpy((void*)mName, name, len + 1);
184 }
185 
allocateItem(const char * name)186 AMessage::Item *AMessage::allocateItem(const char *name) {
187     size_t len = strlen(name);
188     size_t i = findItemIndex(name, len);
189     Item *item;
190 
191     if (i < mNumItems) {
192         item = &mItems[i];
193         freeItemValue(item);
194     } else {
195         CHECK(mNumItems < kMaxNumItems);
196         i = mNumItems++;
197         item = &mItems[i];
198         item->setName(name, len);
199     }
200 
201     return item;
202 }
203 
findItem(const char * name,Type type) const204 const AMessage::Item *AMessage::findItem(
205         const char *name, Type type) const {
206     size_t i = findItemIndex(name, strlen(name));
207     if (i < mNumItems) {
208         const Item *item = &mItems[i];
209         return item->mType == type ? item : NULL;
210 
211     }
212     return NULL;
213 }
214 
contains(const char * name) const215 bool AMessage::contains(const char *name) const {
216     size_t i = findItemIndex(name, strlen(name));
217     return i < mNumItems;
218 }
219 
220 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
221 void AMessage::set##NAME(const char *name, TYPENAME value) {            \
222     Item *item = allocateItem(name);                                    \
223                                                                         \
224     item->mType = kType##NAME;                                          \
225     item->u.FIELDNAME = value;                                          \
226 }                                                                       \
227                                                                         \
228 bool AMessage::find##NAME(const char *name, TYPENAME *value) const {    \
229     const Item *item = findItem(name, kType##NAME);                     \
230     if (item) {                                                         \
231         *value = item->u.FIELDNAME;                                     \
232         return true;                                                    \
233     }                                                                   \
234     return false;                                                       \
235 }
236 
BASIC_TYPE(Int32,int32Value,int32_t)237 BASIC_TYPE(Int32,int32Value,int32_t)
238 BASIC_TYPE(Int64,int64Value,int64_t)
239 BASIC_TYPE(Size,sizeValue,size_t)
240 BASIC_TYPE(Float,floatValue,float)
241 BASIC_TYPE(Double,doubleValue,double)
242 BASIC_TYPE(Pointer,ptrValue,void *)
243 
244 #undef BASIC_TYPE
245 
246 void AMessage::setString(
247         const char *name, const char *s, ssize_t len) {
248     Item *item = allocateItem(name);
249     item->mType = kTypeString;
250     item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
251 }
252 
setString(const char * name,const AString & s)253 void AMessage::setString(
254         const char *name, const AString &s) {
255     setString(name, s.c_str(), s.size());
256 }
257 
setObjectInternal(const char * name,const sp<RefBase> & obj,Type type)258 void AMessage::setObjectInternal(
259         const char *name, const sp<RefBase> &obj, Type type) {
260     Item *item = allocateItem(name);
261     item->mType = type;
262 
263     if (obj != NULL) { obj->incStrong(this); }
264     item->u.refValue = obj.get();
265 }
266 
setObject(const char * name,const sp<RefBase> & obj)267 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
268     setObjectInternal(name, obj, kTypeObject);
269 }
270 
setBuffer(const char * name,const sp<ABuffer> & buffer)271 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
272     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
273 }
274 
setMessage(const char * name,const sp<AMessage> & obj)275 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
276     Item *item = allocateItem(name);
277     item->mType = kTypeMessage;
278 
279     if (obj != NULL) { obj->incStrong(this); }
280     item->u.refValue = obj.get();
281 }
282 
setRect(const char * name,int32_t left,int32_t top,int32_t right,int32_t bottom)283 void AMessage::setRect(
284         const char *name,
285         int32_t left, int32_t top, int32_t right, int32_t bottom) {
286     Item *item = allocateItem(name);
287     item->mType = kTypeRect;
288 
289     item->u.rectValue.mLeft = left;
290     item->u.rectValue.mTop = top;
291     item->u.rectValue.mRight = right;
292     item->u.rectValue.mBottom = bottom;
293 }
294 
findString(const char * name,AString * value) const295 bool AMessage::findString(const char *name, AString *value) const {
296     const Item *item = findItem(name, kTypeString);
297     if (item) {
298         *value = *item->u.stringValue;
299         return true;
300     }
301     return false;
302 }
303 
findObject(const char * name,sp<RefBase> * obj) const304 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
305     const Item *item = findItem(name, kTypeObject);
306     if (item) {
307         *obj = item->u.refValue;
308         return true;
309     }
310     return false;
311 }
312 
findBuffer(const char * name,sp<ABuffer> * buf) const313 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
314     const Item *item = findItem(name, kTypeBuffer);
315     if (item) {
316         *buf = (ABuffer *)(item->u.refValue);
317         return true;
318     }
319     return false;
320 }
321 
findMessage(const char * name,sp<AMessage> * obj) const322 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
323     const Item *item = findItem(name, kTypeMessage);
324     if (item) {
325         *obj = static_cast<AMessage *>(item->u.refValue);
326         return true;
327     }
328     return false;
329 }
330 
findRect(const char * name,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom) const331 bool AMessage::findRect(
332         const char *name,
333         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
334     const Item *item = findItem(name, kTypeRect);
335     if (item == NULL) {
336         return false;
337     }
338 
339     *left = item->u.rectValue.mLeft;
340     *top = item->u.rectValue.mTop;
341     *right = item->u.rectValue.mRight;
342     *bottom = item->u.rectValue.mBottom;
343 
344     return true;
345 }
346 
deliver()347 void AMessage::deliver() {
348     sp<AHandler> handler = mHandler.promote();
349     if (handler == NULL) {
350         ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
351         return;
352     }
353 
354     handler->deliverMessage(this);
355 }
356 
post(int64_t delayUs)357 status_t AMessage::post(int64_t delayUs) {
358     sp<ALooper> looper = mLooper.promote();
359     if (looper == NULL) {
360         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
361         return -ENOENT;
362     }
363 
364     looper->post(this, delayUs);
365     return OK;
366 }
367 
postAndAwaitResponse(sp<AMessage> * response)368 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
369     sp<ALooper> looper = mLooper.promote();
370     if (looper == NULL) {
371         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
372         return -ENOENT;
373     }
374 
375     sp<AReplyToken> token = looper->createReplyToken();
376     if (token == NULL) {
377         ALOGE("failed to create reply token");
378         return -ENOMEM;
379     }
380     setObject("replyID", token);
381 
382     looper->post(this, 0 /* delayUs */);
383     return looper->awaitResponse(token, response);
384 }
385 
postReply(const sp<AReplyToken> & replyToken)386 status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
387     if (replyToken == NULL) {
388         ALOGW("failed to post reply to a NULL token");
389         return -ENOENT;
390     }
391     sp<ALooper> looper = replyToken->getLooper();
392     if (looper == NULL) {
393         ALOGW("failed to post reply as target looper is gone.");
394         return -ENOENT;
395     }
396     return looper->postReply(replyToken, this);
397 }
398 
senderAwaitsResponse(sp<AReplyToken> * replyToken)399 bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
400     sp<RefBase> tmp;
401     bool found = findObject("replyID", &tmp);
402 
403     if (!found) {
404         return false;
405     }
406 
407     *replyToken = static_cast<AReplyToken *>(tmp.get());
408     tmp.clear();
409     setObject("replyID", tmp);
410     // TODO: delete Object instead of setting it to NULL
411 
412     return *replyToken != NULL;
413 }
414 
dup() const415 sp<AMessage> AMessage::dup() const {
416     sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
417     msg->mNumItems = mNumItems;
418 
419 #ifdef DUMP_STATS
420     {
421         Mutex::Autolock _l(gLock);
422         ++gDupCalls;
423         gAverageDupItems += mNumItems;
424         reportStats();
425     }
426 #endif
427 
428     for (size_t i = 0; i < mNumItems; ++i) {
429         const Item *from = &mItems[i];
430         Item *to = &msg->mItems[i];
431 
432         to->setName(from->mName, from->mNameLength);
433         to->mType = from->mType;
434 
435         switch (from->mType) {
436             case kTypeString:
437             {
438                 to->u.stringValue =
439                     new AString(*from->u.stringValue);
440                 break;
441             }
442 
443             case kTypeObject:
444             case kTypeBuffer:
445             {
446                 to->u.refValue = from->u.refValue;
447                 to->u.refValue->incStrong(msg.get());
448                 break;
449             }
450 
451             case kTypeMessage:
452             {
453                 sp<AMessage> copy =
454                     static_cast<AMessage *>(from->u.refValue)->dup();
455 
456                 to->u.refValue = copy.get();
457                 to->u.refValue->incStrong(msg.get());
458                 break;
459             }
460 
461             default:
462             {
463                 to->u = from->u;
464                 break;
465             }
466         }
467     }
468 
469     return msg;
470 }
471 
appendIndent(AString * s,int32_t indent)472 static void appendIndent(AString *s, int32_t indent) {
473     static const char kWhitespace[] =
474         "                                        "
475         "                                        ";
476 
477     CHECK_LT((size_t)indent, sizeof(kWhitespace));
478 
479     s->append(kWhitespace, indent);
480 }
481 
isFourcc(uint32_t what)482 static bool isFourcc(uint32_t what) {
483     return isprint(what & 0xff)
484         && isprint((what >> 8) & 0xff)
485         && isprint((what >> 16) & 0xff)
486         && isprint((what >> 24) & 0xff);
487 }
488 
debugString(int32_t indent) const489 AString AMessage::debugString(int32_t indent) const {
490     AString s = "AMessage(what = ";
491 
492     AString tmp;
493     if (isFourcc(mWhat)) {
494         tmp = AStringPrintf(
495                 "'%c%c%c%c'",
496                 (char)(mWhat >> 24),
497                 (char)((mWhat >> 16) & 0xff),
498                 (char)((mWhat >> 8) & 0xff),
499                 (char)(mWhat & 0xff));
500     } else {
501         tmp = AStringPrintf("0x%08x", mWhat);
502     }
503     s.append(tmp);
504 
505     if (mTarget != 0) {
506         tmp = AStringPrintf(", target = %d", mTarget);
507         s.append(tmp);
508     }
509     s.append(") = {\n");
510 
511     for (size_t i = 0; i < mNumItems; ++i) {
512         const Item &item = mItems[i];
513 
514         switch (item.mType) {
515             case kTypeInt32:
516                 tmp = AStringPrintf(
517                         "int32_t %s = %d", item.mName, item.u.int32Value);
518                 break;
519             case kTypeInt64:
520                 tmp = AStringPrintf(
521                         "int64_t %s = %lld", item.mName, item.u.int64Value);
522                 break;
523             case kTypeSize:
524                 tmp = AStringPrintf(
525                         "size_t %s = %d", item.mName, item.u.sizeValue);
526                 break;
527             case kTypeFloat:
528                 tmp = AStringPrintf(
529                         "float %s = %f", item.mName, item.u.floatValue);
530                 break;
531             case kTypeDouble:
532                 tmp = AStringPrintf(
533                         "double %s = %f", item.mName, item.u.doubleValue);
534                 break;
535             case kTypePointer:
536                 tmp = AStringPrintf(
537                         "void *%s = %p", item.mName, item.u.ptrValue);
538                 break;
539             case kTypeString:
540                 tmp = AStringPrintf(
541                         "string %s = \"%s\"",
542                         item.mName,
543                         item.u.stringValue->c_str());
544                 break;
545             case kTypeObject:
546                 tmp = AStringPrintf(
547                         "RefBase *%s = %p", item.mName, item.u.refValue);
548                 break;
549             case kTypeBuffer:
550             {
551                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
552 
553                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
554                     tmp = AStringPrintf("Buffer %s = {\n", item.mName);
555                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
556                     appendIndent(&tmp, indent + 2);
557                     tmp.append("}");
558                 } else {
559                     tmp = AStringPrintf(
560                             "Buffer *%s = %p", item.mName, buffer.get());
561                 }
562                 break;
563             }
564             case kTypeMessage:
565                 tmp = AStringPrintf(
566                         "AMessage %s = %s",
567                         item.mName,
568                         static_cast<AMessage *>(
569                             item.u.refValue)->debugString(
570                                 indent + strlen(item.mName) + 14).c_str());
571                 break;
572             case kTypeRect:
573                 tmp = AStringPrintf(
574                         "Rect %s(%d, %d, %d, %d)",
575                         item.mName,
576                         item.u.rectValue.mLeft,
577                         item.u.rectValue.mTop,
578                         item.u.rectValue.mRight,
579                         item.u.rectValue.mBottom);
580                 break;
581             default:
582                 TRESPASS();
583         }
584 
585         appendIndent(&s, indent);
586         s.append("  ");
587         s.append(tmp);
588         s.append("\n");
589     }
590 
591     appendIndent(&s, indent);
592     s.append("}");
593 
594     return s;
595 }
596 
597 // static
FromParcel(const Parcel & parcel)598 sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
599     int32_t what = parcel.readInt32();
600     sp<AMessage> msg = new AMessage();
601     msg->setWhat(what);
602 
603     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
604     for (size_t i = 0; i < msg->mNumItems; ++i) {
605         Item *item = &msg->mItems[i];
606 
607         const char *name = parcel.readCString();
608         item->setName(name, strlen(name));
609         item->mType = static_cast<Type>(parcel.readInt32());
610 
611         switch (item->mType) {
612             case kTypeInt32:
613             {
614                 item->u.int32Value = parcel.readInt32();
615                 break;
616             }
617 
618             case kTypeInt64:
619             {
620                 item->u.int64Value = parcel.readInt64();
621                 break;
622             }
623 
624             case kTypeSize:
625             {
626                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
627                 break;
628             }
629 
630             case kTypeFloat:
631             {
632                 item->u.floatValue = parcel.readFloat();
633                 break;
634             }
635 
636             case kTypeDouble:
637             {
638                 item->u.doubleValue = parcel.readDouble();
639                 break;
640             }
641 
642             case kTypeString:
643             {
644                 item->u.stringValue = new AString(parcel.readCString());
645                 break;
646             }
647 
648             case kTypeMessage:
649             {
650                 sp<AMessage> subMsg = AMessage::FromParcel(parcel);
651                 subMsg->incStrong(msg.get());
652 
653                 item->u.refValue = subMsg.get();
654                 break;
655             }
656 
657             default:
658             {
659                 ALOGE("This type of object cannot cross process boundaries.");
660                 TRESPASS();
661             }
662         }
663     }
664 
665     return msg;
666 }
667 
writeToParcel(Parcel * parcel) const668 void AMessage::writeToParcel(Parcel *parcel) const {
669     parcel->writeInt32(static_cast<int32_t>(mWhat));
670     parcel->writeInt32(static_cast<int32_t>(mNumItems));
671 
672     for (size_t i = 0; i < mNumItems; ++i) {
673         const Item &item = mItems[i];
674 
675         parcel->writeCString(item.mName);
676         parcel->writeInt32(static_cast<int32_t>(item.mType));
677 
678         switch (item.mType) {
679             case kTypeInt32:
680             {
681                 parcel->writeInt32(item.u.int32Value);
682                 break;
683             }
684 
685             case kTypeInt64:
686             {
687                 parcel->writeInt64(item.u.int64Value);
688                 break;
689             }
690 
691             case kTypeSize:
692             {
693                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
694                 break;
695             }
696 
697             case kTypeFloat:
698             {
699                 parcel->writeFloat(item.u.floatValue);
700                 break;
701             }
702 
703             case kTypeDouble:
704             {
705                 parcel->writeDouble(item.u.doubleValue);
706                 break;
707             }
708 
709             case kTypeString:
710             {
711                 parcel->writeCString(item.u.stringValue->c_str());
712                 break;
713             }
714 
715             case kTypeMessage:
716             {
717                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
718                 break;
719             }
720 
721             default:
722             {
723                 ALOGE("This type of object cannot cross process boundaries.");
724                 TRESPASS();
725             }
726         }
727     }
728 }
729 
countEntries() const730 size_t AMessage::countEntries() const {
731     return mNumItems;
732 }
733 
getEntryNameAt(size_t index,Type * type) const734 const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
735     if (index >= mNumItems) {
736         *type = kTypeInt32;
737 
738         return NULL;
739     }
740 
741     *type = mItems[index].mType;
742 
743     return mItems[index].mName;
744 }
745 
746 }  // namespace android
747