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