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 
21 #include <ctype.h>
22 
23 #include "AMessage.h"
24 
25 #include <binder/Parcel.h>
26 #include <log/log.h>
27 
28 #include "AAtomizer.h"
29 #include "ABuffer.h"
30 #include "ADebug.h"
31 #include "ALooperRoster.h"
32 #include "AHandler.h"
33 #include "AString.h"
34 
35 #include <media/stagefright/foundation/hexdump.h>
36 
37 namespace android {
38 
39 extern ALooperRoster gLooperRoster;
40 
setReply(const sp<AMessage> & reply)41 status_t AReplyToken::setReply(const sp<AMessage> &reply) {
42     if (mReplied) {
43         ALOGE("trying to post a duplicate reply");
44         return -EBUSY;
45     }
46     CHECK(mReply == NULL);
47     mReply = reply;
48     mReplied = true;
49     return OK;
50 }
51 
AMessage(void)52 AMessage::AMessage(void)
53     : mWhat(0),
54       mTarget(0),
55       mNumItems(0) {
56 }
57 
AMessage(uint32_t what,const sp<const AHandler> & handler)58 AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
59     : mWhat(what),
60       mNumItems(0) {
61     setTarget(handler);
62 }
63 
~AMessage()64 AMessage::~AMessage() {
65     clear();
66 }
67 
setWhat(uint32_t what)68 void AMessage::setWhat(uint32_t what) {
69     mWhat = what;
70 }
71 
what() const72 uint32_t AMessage::what() const {
73     return mWhat;
74 }
75 
setTarget(const sp<const AHandler> & handler)76 void AMessage::setTarget(const sp<const AHandler> &handler) {
77     if (handler == NULL) {
78         mTarget = 0;
79         mHandler.clear();
80         mLooper.clear();
81     } else {
82         mTarget = handler->id();
83         mHandler = handler->getHandler();
84         mLooper = handler->getLooper();
85     }
86 }
87 
clear()88 void AMessage::clear() {
89     for (size_t i = 0; i < mNumItems; ++i) {
90         Item *item = &mItems[i];
91         delete[] item->mName;
92         item->mName = NULL;
93         freeItemValue(item);
94     }
95     mNumItems = 0;
96 }
97 
freeItemValue(Item * item)98 void AMessage::freeItemValue(Item *item) {
99     switch (item->mType) {
100         case kTypeString:
101         {
102             delete item->u.stringValue;
103             break;
104         }
105 
106         case kTypeObject:
107         case kTypeMessage:
108         case kTypeBuffer:
109         {
110             if (item->u.refValue != NULL) {
111                 item->u.refValue->decStrong(this);
112             }
113             break;
114         }
115 
116         default:
117             break;
118     }
119     item->mType = kTypeInt32; // clear type
120 }
121 
122 #ifdef DUMP_STATS
123 #include <utils/Mutex.h>
124 
125 Mutex gLock;
126 static int32_t gFindItemCalls = 1;
127 static int32_t gDupCalls = 1;
128 static int32_t gAverageNumItems = 0;
129 static int32_t gAverageNumChecks = 0;
130 static int32_t gAverageNumMemChecks = 0;
131 static int32_t gAverageDupItems = 0;
132 static int32_t gLastChecked = -1;
133 
reportStats()134 static void reportStats() {
135     int32_t time = (ALooper::GetNowUs() / 1000);
136     if (time / 1000 != gLastChecked / 1000) {
137         gLastChecked = time;
138         ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)",
139                 gFindItemCalls,
140                 gAverageNumItems / (float)gFindItemCalls,
141                 gAverageNumChecks / (float)gFindItemCalls,
142                 gAverageNumMemChecks / (float)gFindItemCalls,
143                 gDupCalls,
144                 gAverageDupItems / (float)gDupCalls);
145         gFindItemCalls = gDupCalls = 1;
146         gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0;
147         gLastChecked = time;
148     }
149 }
150 #endif
151 
findItemIndex(const char * name,size_t len) const152 inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
153 #ifdef DUMP_STATS
154     size_t memchecks = 0;
155 #endif
156     size_t i = 0;
157     for (; i < mNumItems; i++) {
158         if (len != mItems[i].mNameLength) {
159             continue;
160         }
161 #ifdef DUMP_STATS
162         ++memchecks;
163 #endif
164         if (!memcmp(mItems[i].mName, name, len)) {
165             break;
166         }
167     }
168 #ifdef DUMP_STATS
169     {
170         Mutex::Autolock _l(gLock);
171         ++gFindItemCalls;
172         gAverageNumItems += mNumItems;
173         gAverageNumMemChecks += memchecks;
174         gAverageNumChecks += i;
175         reportStats();
176     }
177 #endif
178     return i;
179 }
180 
181 // assumes item's name was uninitialized or NULL
setName(const char * name,size_t len)182 void AMessage::Item::setName(const char *name, size_t len) {
183     mNameLength = len;
184     mName = new char[len + 1];
185     memcpy((void*)mName, name, len + 1);
186 }
187 
allocateItem(const char * name)188 AMessage::Item *AMessage::allocateItem(const char *name) {
189     size_t len = strlen(name);
190     size_t i = findItemIndex(name, len);
191     Item *item;
192 
193     if (i < mNumItems) {
194         item = &mItems[i];
195         freeItemValue(item);
196     } else {
197         CHECK(mNumItems < kMaxNumItems);
198         i = mNumItems++;
199         item = &mItems[i];
200         item->mType = kTypeInt32;
201         item->setName(name, len);
202     }
203 
204     return item;
205 }
206 
findItem(const char * name,Type type) const207 const AMessage::Item *AMessage::findItem(
208         const char *name, Type type) const {
209     size_t i = findItemIndex(name, strlen(name));
210     if (i < mNumItems) {
211         const Item *item = &mItems[i];
212         return item->mType == type ? item : NULL;
213 
214     }
215     return NULL;
216 }
217 
findAsFloat(const char * name,float * value) const218 bool AMessage::findAsFloat(const char *name, float *value) const {
219     size_t i = findItemIndex(name, strlen(name));
220     if (i < mNumItems) {
221         const Item *item = &mItems[i];
222         switch (item->mType) {
223             case kTypeFloat:
224                 *value = item->u.floatValue;
225                 return true;
226             case kTypeDouble:
227                 *value = (float)item->u.doubleValue;
228                 return true;
229             case kTypeInt64:
230                 *value = (float)item->u.int64Value;
231                 return true;
232             case kTypeInt32:
233                 *value = (float)item->u.int32Value;
234                 return true;
235             case kTypeSize:
236                 *value = (float)item->u.sizeValue;
237                 return true;
238             default:
239                 return false;
240         }
241     }
242     return false;
243 }
244 
findAsInt64(const char * name,int64_t * value) const245 bool AMessage::findAsInt64(const char *name, int64_t *value) const {
246     size_t i = findItemIndex(name, strlen(name));
247     if (i < mNumItems) {
248         const Item *item = &mItems[i];
249         switch (item->mType) {
250             case kTypeInt64:
251                 *value = item->u.int64Value;
252                 return true;
253             case kTypeInt32:
254                 *value = item->u.int32Value;
255                 return true;
256             default:
257                 return false;
258         }
259     }
260     return false;
261 }
262 
contains(const char * name) const263 bool AMessage::contains(const char *name) const {
264     size_t i = findItemIndex(name, strlen(name));
265     return i < mNumItems;
266 }
267 
268 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
269 void AMessage::set##NAME(const char *name, TYPENAME value) {            \
270     Item *item = allocateItem(name);                                    \
271                                                                         \
272     item->mType = kType##NAME;                                          \
273     item->u.FIELDNAME = value;                                          \
274 }                                                                       \
275                                                                         \
276 /* NOLINT added to avoid incorrect warning/fix from clang.tidy */       \
277 bool AMessage::find##NAME(const char *name, TYPENAME *value) const {  /* NOLINT */ \
278     const Item *item = findItem(name, kType##NAME);                     \
279     if (item) {                                                         \
280         *value = item->u.FIELDNAME;                                     \
281         return true;                                                    \
282     }                                                                   \
283     return false;                                                       \
284 }
285 
BASIC_TYPE(Int32,int32Value,int32_t)286 BASIC_TYPE(Int32,int32Value,int32_t)
287 BASIC_TYPE(Int64,int64Value,int64_t)
288 BASIC_TYPE(Size,sizeValue,size_t)
289 BASIC_TYPE(Float,floatValue,float)
290 BASIC_TYPE(Double,doubleValue,double)
291 BASIC_TYPE(Pointer,ptrValue,void *)
292 
293 #undef BASIC_TYPE
294 
295 void AMessage::setString(
296         const char *name, const char *s, ssize_t len) {
297     Item *item = allocateItem(name);
298     item->mType = kTypeString;
299     item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
300 }
301 
setString(const char * name,const AString & s)302 void AMessage::setString(
303         const char *name, const AString &s) {
304     setString(name, s.c_str(), s.size());
305 }
306 
setObjectInternal(const char * name,const sp<RefBase> & obj,Type type)307 void AMessage::setObjectInternal(
308         const char *name, const sp<RefBase> &obj, Type type) {
309     Item *item = allocateItem(name);
310     item->mType = type;
311 
312     if (obj != NULL) { obj->incStrong(this); }
313     item->u.refValue = obj.get();
314 }
315 
setObject(const char * name,const sp<RefBase> & obj)316 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
317     setObjectInternal(name, obj, kTypeObject);
318 }
319 
setBuffer(const char * name,const sp<ABuffer> & buffer)320 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
321     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
322 }
323 
setMessage(const char * name,const sp<AMessage> & obj)324 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
325     Item *item = allocateItem(name);
326     item->mType = kTypeMessage;
327 
328     if (obj != NULL) { obj->incStrong(this); }
329     item->u.refValue = obj.get();
330 }
331 
setRect(const char * name,int32_t left,int32_t top,int32_t right,int32_t bottom)332 void AMessage::setRect(
333         const char *name,
334         int32_t left, int32_t top, int32_t right, int32_t bottom) {
335     Item *item = allocateItem(name);
336     item->mType = kTypeRect;
337 
338     item->u.rectValue.mLeft = left;
339     item->u.rectValue.mTop = top;
340     item->u.rectValue.mRight = right;
341     item->u.rectValue.mBottom = bottom;
342 }
343 
findString(const char * name,AString * value) const344 bool AMessage::findString(const char *name, AString *value) const {
345     const Item *item = findItem(name, kTypeString);
346     if (item) {
347         *value = *item->u.stringValue;
348         return true;
349     }
350     return false;
351 }
352 
findObject(const char * name,sp<RefBase> * obj) const353 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
354     const Item *item = findItem(name, kTypeObject);
355     if (item) {
356         *obj = item->u.refValue;
357         return true;
358     }
359     return false;
360 }
361 
findBuffer(const char * name,sp<ABuffer> * buf) const362 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
363     const Item *item = findItem(name, kTypeBuffer);
364     if (item) {
365         *buf = (ABuffer *)(item->u.refValue);
366         return true;
367     }
368     return false;
369 }
370 
findMessage(const char * name,sp<AMessage> * obj) const371 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
372     const Item *item = findItem(name, kTypeMessage);
373     if (item) {
374         *obj = static_cast<AMessage *>(item->u.refValue);
375         return true;
376     }
377     return false;
378 }
379 
findRect(const char * name,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom) const380 bool AMessage::findRect(
381         const char *name,
382         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
383     const Item *item = findItem(name, kTypeRect);
384     if (item == NULL) {
385         return false;
386     }
387 
388     *left = item->u.rectValue.mLeft;
389     *top = item->u.rectValue.mTop;
390     *right = item->u.rectValue.mRight;
391     *bottom = item->u.rectValue.mBottom;
392 
393     return true;
394 }
395 
deliver()396 void AMessage::deliver() {
397     sp<AHandler> handler = mHandler.promote();
398     if (handler == NULL) {
399         ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
400         return;
401     }
402 
403     handler->deliverMessage(this);
404 }
405 
post(int64_t delayUs)406 status_t AMessage::post(int64_t delayUs) {
407     sp<ALooper> looper = mLooper.promote();
408     if (looper == NULL) {
409         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
410         return -ENOENT;
411     }
412 
413     looper->post(this, delayUs);
414     return OK;
415 }
416 
postAndAwaitResponse(sp<AMessage> * response)417 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
418     sp<ALooper> looper = mLooper.promote();
419     if (looper == NULL) {
420         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
421         return -ENOENT;
422     }
423 
424     sp<AReplyToken> token = looper->createReplyToken();
425     if (token == NULL) {
426         ALOGE("failed to create reply token");
427         return -ENOMEM;
428     }
429     setObject("replyID", token);
430 
431     looper->post(this, 0 /* delayUs */);
432     return looper->awaitResponse(token, response);
433 }
434 
postReply(const sp<AReplyToken> & replyToken)435 status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
436     if (replyToken == NULL) {
437         ALOGW("failed to post reply to a NULL token");
438         return -ENOENT;
439     }
440     sp<ALooper> looper = replyToken->getLooper();
441     if (looper == NULL) {
442         ALOGW("failed to post reply as target looper is gone.");
443         return -ENOENT;
444     }
445     return looper->postReply(replyToken, this);
446 }
447 
senderAwaitsResponse(sp<AReplyToken> * replyToken)448 bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
449     sp<RefBase> tmp;
450     bool found = findObject("replyID", &tmp);
451 
452     if (!found) {
453         return false;
454     }
455 
456     *replyToken = static_cast<AReplyToken *>(tmp.get());
457     tmp.clear();
458     setObject("replyID", tmp);
459     // TODO: delete Object instead of setting it to NULL
460 
461     return *replyToken != NULL;
462 }
463 
dup() const464 sp<AMessage> AMessage::dup() const {
465     sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
466     msg->mNumItems = mNumItems;
467 
468 #ifdef DUMP_STATS
469     {
470         Mutex::Autolock _l(gLock);
471         ++gDupCalls;
472         gAverageDupItems += mNumItems;
473         reportStats();
474     }
475 #endif
476 
477     for (size_t i = 0; i < mNumItems; ++i) {
478         const Item *from = &mItems[i];
479         Item *to = &msg->mItems[i];
480 
481         to->setName(from->mName, from->mNameLength);
482         to->mType = from->mType;
483 
484         switch (from->mType) {
485             case kTypeString:
486             {
487                 to->u.stringValue =
488                     new AString(*from->u.stringValue);
489                 break;
490             }
491 
492             case kTypeObject:
493             case kTypeBuffer:
494             {
495                 to->u.refValue = from->u.refValue;
496                 to->u.refValue->incStrong(msg.get());
497                 break;
498             }
499 
500             case kTypeMessage:
501             {
502                 sp<AMessage> copy =
503                     static_cast<AMessage *>(from->u.refValue)->dup();
504 
505                 to->u.refValue = copy.get();
506                 to->u.refValue->incStrong(msg.get());
507                 break;
508             }
509 
510             default:
511             {
512                 to->u = from->u;
513                 break;
514             }
515         }
516     }
517 
518     return msg;
519 }
520 
appendIndent(AString * s,int32_t indent)521 static void appendIndent(AString *s, int32_t indent) {
522     static const char kWhitespace[] =
523         "                                        "
524         "                                        ";
525 
526     CHECK_LT((size_t)indent, sizeof(kWhitespace));
527 
528     s->append(kWhitespace, indent);
529 }
530 
isFourcc(uint32_t what)531 static bool isFourcc(uint32_t what) {
532     return isprint(what & 0xff)
533         && isprint((what >> 8) & 0xff)
534         && isprint((what >> 16) & 0xff)
535         && isprint((what >> 24) & 0xff);
536 }
537 
debugString(int32_t indent) const538 AString AMessage::debugString(int32_t indent) const {
539     AString s = "AMessage(what = ";
540 
541     AString tmp;
542     if (isFourcc(mWhat)) {
543         tmp = AStringPrintf(
544                 "'%c%c%c%c'",
545                 (char)(mWhat >> 24),
546                 (char)((mWhat >> 16) & 0xff),
547                 (char)((mWhat >> 8) & 0xff),
548                 (char)(mWhat & 0xff));
549     } else {
550         tmp = AStringPrintf("0x%08x", mWhat);
551     }
552     s.append(tmp);
553 
554     if (mTarget != 0) {
555         tmp = AStringPrintf(", target = %d", mTarget);
556         s.append(tmp);
557     }
558     s.append(") = {\n");
559 
560     for (size_t i = 0; i < mNumItems; ++i) {
561         const Item &item = mItems[i];
562 
563         switch (item.mType) {
564             case kTypeInt32:
565                 tmp = AStringPrintf(
566                         "int32_t %s = %d", item.mName, item.u.int32Value);
567                 break;
568             case kTypeInt64:
569                 tmp = AStringPrintf(
570                         "int64_t %s = %lld", item.mName, item.u.int64Value);
571                 break;
572             case kTypeSize:
573                 tmp = AStringPrintf(
574                         "size_t %s = %d", item.mName, item.u.sizeValue);
575                 break;
576             case kTypeFloat:
577                 tmp = AStringPrintf(
578                         "float %s = %f", item.mName, item.u.floatValue);
579                 break;
580             case kTypeDouble:
581                 tmp = AStringPrintf(
582                         "double %s = %f", item.mName, item.u.doubleValue);
583                 break;
584             case kTypePointer:
585                 tmp = AStringPrintf(
586                         "void *%s = %p", item.mName, item.u.ptrValue);
587                 break;
588             case kTypeString:
589                 tmp = AStringPrintf(
590                         "string %s = \"%s\"",
591                         item.mName,
592                         item.u.stringValue->c_str());
593                 break;
594             case kTypeObject:
595                 tmp = AStringPrintf(
596                         "RefBase *%s = %p", item.mName, item.u.refValue);
597                 break;
598             case kTypeBuffer:
599             {
600                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
601 
602                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
603                     tmp = AStringPrintf("Buffer %s = {\n", item.mName);
604                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
605                     appendIndent(&tmp, indent + 2);
606                     tmp.append("}");
607                 } else {
608                     tmp = AStringPrintf(
609                             "Buffer *%s = %p", item.mName, buffer.get());
610                 }
611                 break;
612             }
613             case kTypeMessage:
614                 tmp = AStringPrintf(
615                         "AMessage %s = %s",
616                         item.mName,
617                         static_cast<AMessage *>(
618                             item.u.refValue)->debugString(
619                                 indent + strlen(item.mName) + 14).c_str());
620                 break;
621             case kTypeRect:
622                 tmp = AStringPrintf(
623                         "Rect %s(%d, %d, %d, %d)",
624                         item.mName,
625                         item.u.rectValue.mLeft,
626                         item.u.rectValue.mTop,
627                         item.u.rectValue.mRight,
628                         item.u.rectValue.mBottom);
629                 break;
630             default:
631                 TRESPASS();
632         }
633 
634         appendIndent(&s, indent);
635         s.append("  ");
636         s.append(tmp);
637         s.append("\n");
638     }
639 
640     appendIndent(&s, indent);
641     s.append("}");
642 
643     return s;
644 }
645 
646 // static
FromParcel(const Parcel & parcel,size_t maxNestingLevel)647 sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
648     int32_t what = parcel.readInt32();
649     sp<AMessage> msg = new AMessage();
650     msg->setWhat(what);
651 
652     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
653     if (msg->mNumItems > kMaxNumItems) {
654         ALOGE("Too large number of items clipped.");
655         msg->mNumItems = kMaxNumItems;
656     }
657 
658     for (size_t i = 0; i < msg->mNumItems; ++i) {
659         Item *item = &msg->mItems[i];
660 
661         const char *name = parcel.readCString();
662         if (name == NULL) {
663             ALOGE("Failed reading name for an item. Parsing aborted.");
664             msg->mNumItems = i;
665             break;
666         }
667 
668         item->mType = static_cast<Type>(parcel.readInt32());
669         // setName() happens below so that we don't leak memory when parsing
670         // is aborted in the middle.
671         switch (item->mType) {
672             case kTypeInt32:
673             {
674                 item->u.int32Value = parcel.readInt32();
675                 break;
676             }
677 
678             case kTypeInt64:
679             {
680                 item->u.int64Value = parcel.readInt64();
681                 break;
682             }
683 
684             case kTypeSize:
685             {
686                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
687                 break;
688             }
689 
690             case kTypeFloat:
691             {
692                 item->u.floatValue = parcel.readFloat();
693                 break;
694             }
695 
696             case kTypeDouble:
697             {
698                 item->u.doubleValue = parcel.readDouble();
699                 break;
700             }
701 
702             case kTypeString:
703             {
704                 const char *stringValue = parcel.readCString();
705                 if (stringValue == NULL) {
706                     ALOGE("Failed reading string value from a parcel. "
707                         "Parsing aborted.");
708                     msg->mNumItems = i;
709                     continue;
710                     // The loop will terminate subsequently.
711                 } else {
712                     item->u.stringValue = new AString(stringValue);
713                 }
714                 break;
715             }
716 
717             case kTypeMessage:
718             {
719                 if (maxNestingLevel == 0) {
720                     ALOGE("Too many levels of AMessage nesting.");
721                     return NULL;
722                 }
723                 sp<AMessage> subMsg = AMessage::FromParcel(
724                         parcel,
725                         maxNestingLevel - 1);
726                 if (subMsg == NULL) {
727                     // This condition will be triggered when there exists an
728                     // object that cannot cross process boundaries or when the
729                     // level of nested AMessage is too deep.
730                     return NULL;
731                 }
732                 subMsg->incStrong(msg.get());
733 
734                 item->u.refValue = subMsg.get();
735                 break;
736             }
737 
738             default:
739             {
740                 ALOGE("This type of object cannot cross process boundaries.");
741                 return NULL;
742             }
743         }
744 
745         item->setName(name, strlen(name));
746     }
747 
748     return msg;
749 }
750 
writeToParcel(Parcel * parcel) const751 void AMessage::writeToParcel(Parcel *parcel) const {
752     parcel->writeInt32(static_cast<int32_t>(mWhat));
753     parcel->writeInt32(static_cast<int32_t>(mNumItems));
754 
755     for (size_t i = 0; i < mNumItems; ++i) {
756         const Item &item = mItems[i];
757 
758         parcel->writeCString(item.mName);
759         parcel->writeInt32(static_cast<int32_t>(item.mType));
760 
761         switch (item.mType) {
762             case kTypeInt32:
763             {
764                 parcel->writeInt32(item.u.int32Value);
765                 break;
766             }
767 
768             case kTypeInt64:
769             {
770                 parcel->writeInt64(item.u.int64Value);
771                 break;
772             }
773 
774             case kTypeSize:
775             {
776                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
777                 break;
778             }
779 
780             case kTypeFloat:
781             {
782                 parcel->writeFloat(item.u.floatValue);
783                 break;
784             }
785 
786             case kTypeDouble:
787             {
788                 parcel->writeDouble(item.u.doubleValue);
789                 break;
790             }
791 
792             case kTypeString:
793             {
794                 parcel->writeCString(item.u.stringValue->c_str());
795                 break;
796             }
797 
798             case kTypeMessage:
799             {
800                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
801                 break;
802             }
803 
804             default:
805             {
806                 ALOGE("This type of object cannot cross process boundaries.");
807                 TRESPASS();
808             }
809         }
810     }
811 }
812 
changesFrom(const sp<const AMessage> & other,bool deep) const813 sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
814     if (other == NULL) {
815         return const_cast<AMessage*>(this);
816     }
817 
818     sp<AMessage> diff = new AMessage;
819     if (mWhat != other->mWhat) {
820         diff->setWhat(mWhat);
821     }
822     if (mHandler != other->mHandler) {
823         diff->setTarget(mHandler.promote());
824     }
825 
826     for (size_t i = 0; i < mNumItems; ++i) {
827         const Item &item = mItems[i];
828         const Item *oitem = other->findItem(item.mName, item.mType);
829         switch (item.mType) {
830             case kTypeInt32:
831                 if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
832                     diff->setInt32(item.mName, item.u.int32Value);
833                 }
834                 break;
835 
836             case kTypeInt64:
837                 if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
838                     diff->setInt64(item.mName, item.u.int64Value);
839                 }
840                 break;
841 
842             case kTypeSize:
843                 if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
844                     diff->setSize(item.mName, item.u.sizeValue);
845                 }
846                 break;
847 
848             case kTypeFloat:
849                 if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
850                     diff->setFloat(item.mName, item.u.sizeValue);
851                 }
852                 break;
853 
854             case kTypeDouble:
855                 if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
856                     diff->setDouble(item.mName, item.u.sizeValue);
857                 }
858                 break;
859 
860             case kTypeString:
861                 if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
862                     diff->setString(item.mName, *item.u.stringValue);
863                 }
864                 break;
865 
866             case kTypeRect:
867                 if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
868                     diff->setRect(
869                             item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
870                             item.u.rectValue.mRight, item.u.rectValue.mBottom);
871                 }
872                 break;
873 
874             case kTypePointer:
875                 if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
876                     diff->setPointer(item.mName, item.u.ptrValue);
877                 }
878                 break;
879 
880             case kTypeBuffer:
881             {
882                 sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
883                 if (myBuf == NULL) {
884                     if (oitem == NULL || oitem->u.refValue != NULL) {
885                         diff->setBuffer(item.mName, NULL);
886                     }
887                     break;
888                 }
889                 sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
890                 if (oBuf == NULL
891                         || myBuf->size() != oBuf->size()
892                         || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
893                         || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
894                     diff->setBuffer(item.mName, myBuf);
895                 }
896                 break;
897             }
898 
899             case kTypeMessage:
900             {
901                 sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
902                 if (myMsg == NULL) {
903                     if (oitem == NULL || oitem->u.refValue != NULL) {
904                         diff->setMessage(item.mName, NULL);
905                     }
906                     break;
907                 }
908                 sp<AMessage> oMsg =
909                     oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
910                 sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
911                 if (changes->countEntries()) {
912                     diff->setMessage(item.mName, deep ? changes : myMsg);
913                 }
914                 break;
915             }
916 
917             case kTypeObject:
918                 if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
919                     diff->setObject(item.mName, item.u.refValue);
920                 }
921                 break;
922 
923             default:
924             {
925                 ALOGE("Unknown type %d", item.mType);
926                 TRESPASS();
927             }
928         }
929     }
930     return diff;
931 }
932 
countEntries() const933 size_t AMessage::countEntries() const {
934     return mNumItems;
935 }
936 
getEntryNameAt(size_t index,Type * type) const937 const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
938     if (index >= mNumItems) {
939         *type = kTypeInt32;
940 
941         return NULL;
942     }
943 
944     *type = mItems[index].mType;
945 
946     return mItems[index].mName;
947 }
948 
getEntryAt(size_t index) const949 AMessage::ItemData AMessage::getEntryAt(size_t index) const {
950     ItemData it;
951     if (index < mNumItems) {
952         switch (mItems[index].mType) {
953             case kTypeInt32:    it.set(mItems[index].u.int32Value); break;
954             case kTypeInt64:    it.set(mItems[index].u.int64Value); break;
955             case kTypeSize:     it.set(mItems[index].u.sizeValue); break;
956             case kTypeFloat:    it.set(mItems[index].u.floatValue); break;
957             case kTypeDouble:   it.set(mItems[index].u.doubleValue); break;
958             case kTypePointer:  it.set(mItems[index].u.ptrValue); break;
959             case kTypeRect:     it.set(mItems[index].u.rectValue); break;
960             case kTypeString:   it.set(*mItems[index].u.stringValue); break;
961             case kTypeObject: {
962                 sp<RefBase> obj = mItems[index].u.refValue;
963                 it.set(obj);
964                 break;
965             }
966             case kTypeMessage: {
967                 sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
968                 it.set(msg);
969                 break;
970             }
971             case kTypeBuffer: {
972                 sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
973                 it.set(buf);
974                 break;
975             }
976             default:
977                 break;
978         }
979     }
980     return it;
981 }
982 
setEntryNameAt(size_t index,const char * name)983 status_t AMessage::setEntryNameAt(size_t index, const char *name) {
984     if (index >= mNumItems) {
985         return BAD_INDEX;
986     }
987     if (name == nullptr) {
988         return BAD_VALUE;
989     }
990     if (!strcmp(name, mItems[index].mName)) {
991         return OK; // name has not changed
992     }
993     size_t len = strlen(name);
994     if (findItemIndex(name, len) < mNumItems) {
995         return ALREADY_EXISTS;
996     }
997     delete[] mItems[index].mName;
998     mItems[index].mName = nullptr;
999     mItems[index].setName(name, len);
1000     return OK;
1001 }
1002 
setEntryAt(size_t index,const ItemData & item)1003 status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
1004     AString stringValue;
1005     sp<RefBase> refValue;
1006     sp<AMessage> msgValue;
1007     sp<ABuffer> bufValue;
1008 
1009     if (index >= mNumItems) {
1010         return BAD_INDEX;
1011     }
1012     if (!item.used()) {
1013         return BAD_VALUE;
1014     }
1015     Item *dst = &mItems[index];
1016     freeItemValue(dst);
1017 
1018     // some values can be directly set with the getter. others need items to be allocated
1019     if (item.find(&dst->u.int32Value)) {
1020         dst->mType = kTypeInt32;
1021     } else if (item.find(&dst->u.int64Value)) {
1022         dst->mType = kTypeInt64;
1023     } else if (item.find(&dst->u.sizeValue)) {
1024         dst->mType = kTypeSize;
1025     } else if (item.find(&dst->u.floatValue)) {
1026         dst->mType = kTypeFloat;
1027     } else if (item.find(&dst->u.doubleValue)) {
1028         dst->mType = kTypeDouble;
1029     } else if (item.find(&dst->u.ptrValue)) {
1030         dst->mType = kTypePointer;
1031     } else if (item.find(&dst->u.rectValue)) {
1032         dst->mType = kTypeRect;
1033     } else if (item.find(&stringValue)) {
1034         dst->u.stringValue = new AString(stringValue);
1035         dst->mType = kTypeString;
1036     } else if (item.find(&refValue)) {
1037         if (refValue != NULL) { refValue->incStrong(this); }
1038         dst->u.refValue = refValue.get();
1039         dst->mType = kTypeObject;
1040     } else if (item.find(&msgValue)) {
1041         if (msgValue != NULL) { msgValue->incStrong(this); }
1042         dst->u.refValue = msgValue.get();
1043         dst->mType = kTypeMessage;
1044     } else if (item.find(&bufValue)) {
1045         if (bufValue != NULL) { bufValue->incStrong(this); }
1046         dst->u.refValue = bufValue.get();
1047         dst->mType = kTypeBuffer;
1048     } else {
1049         // unsupported item - we should not be here.
1050         dst->mType = kTypeInt32;
1051         dst->u.int32Value = 0xDEADDEAD;
1052         return BAD_TYPE;
1053     }
1054     return OK;
1055 }
1056 
removeEntryAt(size_t index)1057 status_t AMessage::removeEntryAt(size_t index) {
1058     if (index >= mNumItems) {
1059         return BAD_INDEX;
1060     }
1061     // delete entry data and objects
1062     --mNumItems;
1063     delete[] mItems[index].mName;
1064     mItems[index].mName = nullptr;
1065     freeItemValue(&mItems[index]);
1066 
1067     // swap entry with last entry and clear last entry's data
1068     if (index < mNumItems) {
1069         mItems[index] = mItems[mNumItems];
1070         mItems[mNumItems].mName = nullptr;
1071         mItems[mNumItems].mType = kTypeInt32;
1072     }
1073     return OK;
1074 }
1075 
setItem(const char * name,const ItemData & item)1076 void AMessage::setItem(const char *name, const ItemData &item) {
1077     if (item.used()) {
1078         Item *it = allocateItem(name);
1079         if (it != nullptr) {
1080             setEntryAt(it - mItems, item);
1081         }
1082     }
1083 }
1084 
findItem(const char * name) const1085 AMessage::ItemData AMessage::findItem(const char *name) const {
1086     return getEntryAt(findEntryByName(name));
1087 }
1088 
extend(const sp<AMessage> & other)1089 void AMessage::extend(const sp<AMessage> &other) {
1090     // ignore null messages
1091     if (other == nullptr) {
1092         return;
1093     }
1094 
1095     for (size_t ix = 0; ix < other->mNumItems; ++ix) {
1096         Item *it = allocateItem(other->mItems[ix].mName);
1097         if (it != nullptr) {
1098             ItemData data = other->getEntryAt(ix);
1099             setEntryAt(it - mItems, data);
1100         }
1101     }
1102 }
1103 
findEntryByName(const char * name) const1104 size_t AMessage::findEntryByName(const char *name) const {
1105     return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
1106 }
1107 
1108 }  // namespace android
1109