• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #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_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 
postAndAwaitResponse(sp<AMessage> * response)433 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
434     sp<ALooper> looper = mLooper.promote();
435     if (looper == NULL) {
436         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
437         return -ENOENT;
438     }
439 
440     sp<AReplyToken> token = looper->createReplyToken();
441     if (token == NULL) {
442         ALOGE("failed to create reply token");
443         return -ENOMEM;
444     }
445     setObject("replyID", token);
446 
447     looper->post(this, 0 /* delayUs */);
448     return looper->awaitResponse(token, response);
449 }
450 
postReply(const sp<AReplyToken> & replyToken)451 status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
452     if (replyToken == NULL) {
453         ALOGW("failed to post reply to a NULL token");
454         return -ENOENT;
455     }
456     sp<ALooper> looper = replyToken->getLooper();
457     if (looper == NULL) {
458         ALOGW("failed to post reply as target looper is gone.");
459         return -ENOENT;
460     }
461     return looper->postReply(replyToken, this);
462 }
463 
senderAwaitsResponse(sp<AReplyToken> * replyToken)464 bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
465     sp<RefBase> tmp;
466     bool found = findObject("replyID", &tmp);
467 
468     if (!found) {
469         return false;
470     }
471 
472     *replyToken = static_cast<AReplyToken *>(tmp.get());
473     tmp.clear();
474     setObject("replyID", tmp);
475     // TODO: delete Object instead of setting it to NULL
476 
477     return *replyToken != NULL;
478 }
479 
dup() const480 sp<AMessage> AMessage::dup() const {
481     sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
482     msg->mItems = mItems;
483 
484 #ifdef DUMP_STATS
485     {
486         Mutex::Autolock _l(gLock);
487         ++gDupCalls;
488         gAverageDupItems += mItems.size();
489         reportStats();
490     }
491 #endif
492 
493     for (size_t i = 0; i < mItems.size(); ++i) {
494         const Item *from = &mItems[i];
495         Item *to = &msg->mItems[i];
496 
497         to->setName(from->mName, from->mNameLength);
498         to->mType = from->mType;
499 
500         switch (from->mType) {
501             case kTypeString:
502             {
503                 to->u.stringValue =
504                     new AString(*from->u.stringValue);
505                 break;
506             }
507 
508             case kTypeObject:
509             case kTypeBuffer:
510             {
511                 to->u.refValue = from->u.refValue;
512                 to->u.refValue->incStrong(msg.get());
513                 break;
514             }
515 
516             case kTypeMessage:
517             {
518                 sp<AMessage> copy =
519                     static_cast<AMessage *>(from->u.refValue)->dup();
520 
521                 to->u.refValue = copy.get();
522                 to->u.refValue->incStrong(msg.get());
523                 break;
524             }
525 
526             default:
527             {
528                 to->u = from->u;
529                 break;
530             }
531         }
532     }
533 
534     return msg;
535 }
536 
appendIndent(AString * s,int32_t indent)537 static void appendIndent(AString *s, int32_t indent) {
538     static const char kWhitespace[] =
539         "                                        "
540         "                                        ";
541 
542     CHECK_LT((size_t)indent, sizeof(kWhitespace));
543 
544     s->append(kWhitespace, indent);
545 }
546 
isFourcc(uint32_t what)547 static bool isFourcc(uint32_t what) {
548     return isprint(what & 0xff)
549         && isprint((what >> 8) & 0xff)
550         && isprint((what >> 16) & 0xff)
551         && isprint((what >> 24) & 0xff);
552 }
553 
debugString(int32_t indent) const554 AString AMessage::debugString(int32_t indent) const {
555     AString s = "AMessage(what = ";
556 
557     AString tmp;
558     if (isFourcc(mWhat)) {
559         tmp = AStringPrintf(
560                 "'%c%c%c%c'",
561                 (char)(mWhat >> 24),
562                 (char)((mWhat >> 16) & 0xff),
563                 (char)((mWhat >> 8) & 0xff),
564                 (char)(mWhat & 0xff));
565     } else {
566         tmp = AStringPrintf("0x%08x", mWhat);
567     }
568     s.append(tmp);
569 
570     if (mTarget != 0) {
571         tmp = AStringPrintf(", target = %d", mTarget);
572         s.append(tmp);
573     }
574     s.append(") = {\n");
575 
576     for (size_t i = 0; i < mItems.size(); ++i) {
577         const Item &item = mItems[i];
578 
579         switch (item.mType) {
580             case kTypeInt32:
581                 tmp = AStringPrintf(
582                         "int32_t %s = %d", item.mName, item.u.int32Value);
583                 break;
584             case kTypeInt64:
585                 tmp = AStringPrintf(
586                         "int64_t %s = %lld", item.mName, item.u.int64Value);
587                 break;
588             case kTypeSize:
589                 tmp = AStringPrintf(
590                         "size_t %s = %d", item.mName, item.u.sizeValue);
591                 break;
592             case kTypeFloat:
593                 tmp = AStringPrintf(
594                         "float %s = %f", item.mName, item.u.floatValue);
595                 break;
596             case kTypeDouble:
597                 tmp = AStringPrintf(
598                         "double %s = %f", item.mName, item.u.doubleValue);
599                 break;
600             case kTypePointer:
601                 tmp = AStringPrintf(
602                         "void *%s = %p", item.mName, item.u.ptrValue);
603                 break;
604             case kTypeString:
605                 tmp = AStringPrintf(
606                         "string %s = \"%s\"",
607                         item.mName,
608                         item.u.stringValue->c_str());
609                 break;
610             case kTypeObject:
611                 tmp = AStringPrintf(
612                         "RefBase *%s = %p", item.mName, item.u.refValue);
613                 break;
614             case kTypeBuffer:
615             {
616                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
617 
618                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
619                     tmp = AStringPrintf("Buffer %s = {\n", item.mName);
620                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
621                     appendIndent(&tmp, indent + 2);
622                     tmp.append("}");
623                 } else {
624                     tmp = AStringPrintf(
625                             "Buffer *%s = %p", item.mName, buffer.get());
626                 }
627                 break;
628             }
629             case kTypeMessage:
630                 tmp = AStringPrintf(
631                         "AMessage %s = %s",
632                         item.mName,
633                         static_cast<AMessage *>(
634                             item.u.refValue)->debugString(
635                                 indent + strlen(item.mName) + 14).c_str());
636                 break;
637             case kTypeRect:
638                 tmp = AStringPrintf(
639                         "Rect %s(%d, %d, %d, %d)",
640                         item.mName,
641                         item.u.rectValue.mLeft,
642                         item.u.rectValue.mTop,
643                         item.u.rectValue.mRight,
644                         item.u.rectValue.mBottom);
645                 break;
646             default:
647                 TRESPASS();
648         }
649 
650         appendIndent(&s, indent);
651         s.append("  ");
652         s.append(tmp);
653         s.append("\n");
654     }
655 
656     appendIndent(&s, indent);
657     s.append("}");
658 
659     return s;
660 }
661 
662 #if !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
663 // static
FromParcel(const Parcel & parcel,size_t maxNestingLevel)664 sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
665     int32_t what = parcel.readInt32();
666     sp<AMessage> msg = new AMessage();
667     msg->setWhat(what);
668 
669     size_t numItems = static_cast<size_t>(parcel.readInt32());
670     if (numItems > kMaxNumItems) {
671         ALOGE("Too large number of items clipped.");
672         numItems = kMaxNumItems;
673     }
674     msg->mItems.resize(numItems);
675 
676     for (size_t i = 0; i < msg->mItems.size(); ++i) {
677         Item *item = &msg->mItems[i];
678 
679         const char *name = parcel.readCString();
680         if (name == NULL) {
681             ALOGE("Failed reading name for an item. Parsing aborted.");
682             msg->mItems.resize(i);
683             break;
684         }
685 
686         item->mType = static_cast<Type>(parcel.readInt32());
687         // setName() happens below so that we don't leak memory when parsing
688         // is aborted in the middle.
689         switch (item->mType) {
690             case kTypeInt32:
691             {
692                 item->u.int32Value = parcel.readInt32();
693                 break;
694             }
695 
696             case kTypeInt64:
697             {
698                 item->u.int64Value = parcel.readInt64();
699                 break;
700             }
701 
702             case kTypeSize:
703             {
704                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
705                 break;
706             }
707 
708             case kTypeFloat:
709             {
710                 item->u.floatValue = parcel.readFloat();
711                 break;
712             }
713 
714             case kTypeDouble:
715             {
716                 item->u.doubleValue = parcel.readDouble();
717                 break;
718             }
719 
720             case kTypeString:
721             {
722                 const char *stringValue = parcel.readCString();
723                 if (stringValue == NULL) {
724                     ALOGE("Failed reading string value from a parcel. "
725                         "Parsing aborted.");
726                     msg->mItems.resize(i);
727                     continue;
728                     // The loop will terminate subsequently.
729                 } else {
730                     item->u.stringValue = new AString(stringValue);
731                 }
732                 break;
733             }
734 
735             case kTypeMessage:
736             {
737                 if (maxNestingLevel == 0) {
738                     ALOGE("Too many levels of AMessage nesting.");
739                     return NULL;
740                 }
741                 sp<AMessage> subMsg = AMessage::FromParcel(
742                         parcel,
743                         maxNestingLevel - 1);
744                 if (subMsg == NULL) {
745                     // This condition will be triggered when there exists an
746                     // object that cannot cross process boundaries or when the
747                     // level of nested AMessage is too deep.
748                     return NULL;
749                 }
750                 subMsg->incStrong(msg.get());
751 
752                 item->u.refValue = subMsg.get();
753                 break;
754             }
755 
756             default:
757             {
758                 ALOGE("This type of object cannot cross process boundaries.");
759                 return NULL;
760             }
761         }
762 
763         item->setName(name, strlen(name));
764     }
765 
766     return msg;
767 }
768 
writeToParcel(Parcel * parcel) const769 void AMessage::writeToParcel(Parcel *parcel) const {
770     parcel->writeInt32(static_cast<int32_t>(mWhat));
771     parcel->writeInt32(static_cast<int32_t>(mItems.size()));
772 
773     for (const Item &item : mItems) {
774         parcel->writeCString(item.mName);
775         parcel->writeInt32(static_cast<int32_t>(item.mType));
776 
777         switch (item.mType) {
778             case kTypeInt32:
779             {
780                 parcel->writeInt32(item.u.int32Value);
781                 break;
782             }
783 
784             case kTypeInt64:
785             {
786                 parcel->writeInt64(item.u.int64Value);
787                 break;
788             }
789 
790             case kTypeSize:
791             {
792                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
793                 break;
794             }
795 
796             case kTypeFloat:
797             {
798                 parcel->writeFloat(item.u.floatValue);
799                 break;
800             }
801 
802             case kTypeDouble:
803             {
804                 parcel->writeDouble(item.u.doubleValue);
805                 break;
806             }
807 
808             case kTypeString:
809             {
810                 parcel->writeCString(item.u.stringValue->c_str());
811                 break;
812             }
813 
814             case kTypeMessage:
815             {
816                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
817                 break;
818             }
819 
820             default:
821             {
822                 ALOGE("This type of object cannot cross process boundaries.");
823                 TRESPASS();
824             }
825         }
826     }
827 }
828 #endif  // !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
829 
changesFrom(const sp<const AMessage> & other,bool deep) const830 sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
831     if (other == NULL) {
832         return const_cast<AMessage*>(this);
833     }
834 
835     sp<AMessage> diff = new AMessage;
836     if (mWhat != other->mWhat) {
837         diff->setWhat(mWhat);
838     }
839     if (mHandler != other->mHandler) {
840         diff->setTarget(mHandler.promote());
841     }
842 
843     for (const Item &item : mItems) {
844         const Item *oitem = other->findItem(item.mName, item.mType);
845         switch (item.mType) {
846             case kTypeInt32:
847                 if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
848                     diff->setInt32(item.mName, item.u.int32Value);
849                 }
850                 break;
851 
852             case kTypeInt64:
853                 if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
854                     diff->setInt64(item.mName, item.u.int64Value);
855                 }
856                 break;
857 
858             case kTypeSize:
859                 if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
860                     diff->setSize(item.mName, item.u.sizeValue);
861                 }
862                 break;
863 
864             case kTypeFloat:
865                 if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
866                     diff->setFloat(item.mName, item.u.sizeValue);
867                 }
868                 break;
869 
870             case kTypeDouble:
871                 if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
872                     diff->setDouble(item.mName, item.u.sizeValue);
873                 }
874                 break;
875 
876             case kTypeString:
877                 if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
878                     diff->setString(item.mName, *item.u.stringValue);
879                 }
880                 break;
881 
882             case kTypeRect:
883                 if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
884                     diff->setRect(
885                             item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
886                             item.u.rectValue.mRight, item.u.rectValue.mBottom);
887                 }
888                 break;
889 
890             case kTypePointer:
891                 if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
892                     diff->setPointer(item.mName, item.u.ptrValue);
893                 }
894                 break;
895 
896             case kTypeBuffer:
897             {
898                 sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
899                 if (myBuf == NULL) {
900                     if (oitem == NULL || oitem->u.refValue != NULL) {
901                         diff->setBuffer(item.mName, NULL);
902                     }
903                     break;
904                 }
905                 sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
906                 if (oBuf == NULL
907                         || myBuf->size() != oBuf->size()
908                         || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
909                         || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
910                     diff->setBuffer(item.mName, myBuf);
911                 }
912                 break;
913             }
914 
915             case kTypeMessage:
916             {
917                 sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
918                 if (myMsg == NULL) {
919                     if (oitem == NULL || oitem->u.refValue != NULL) {
920                         diff->setMessage(item.mName, NULL);
921                     }
922                     break;
923                 }
924                 sp<AMessage> oMsg =
925                     oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
926                 sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
927                 if (changes->countEntries()) {
928                     diff->setMessage(item.mName, deep ? changes : myMsg);
929                 }
930                 break;
931             }
932 
933             case kTypeObject:
934                 if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
935                     diff->setObject(item.mName, item.u.refValue);
936                 }
937                 break;
938 
939             default:
940             {
941                 ALOGE("Unknown type %d", item.mType);
942                 TRESPASS();
943             }
944         }
945     }
946     return diff;
947 }
948 
countEntries() const949 size_t AMessage::countEntries() const {
950     return mItems.size();
951 }
952 
getEntryNameAt(size_t index,Type * type) const953 const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
954     if (index >= mItems.size()) {
955         *type = kTypeInt32;
956 
957         return NULL;
958     }
959 
960     *type = mItems[index].mType;
961 
962     return mItems[index].mName;
963 }
964 
getEntryAt(size_t index) const965 AMessage::ItemData AMessage::getEntryAt(size_t index) const {
966     ItemData it;
967     if (index < mItems.size()) {
968         switch (mItems[index].mType) {
969             case kTypeInt32:    it.set(mItems[index].u.int32Value); break;
970             case kTypeInt64:    it.set(mItems[index].u.int64Value); break;
971             case kTypeSize:     it.set(mItems[index].u.sizeValue); break;
972             case kTypeFloat:    it.set(mItems[index].u.floatValue); break;
973             case kTypeDouble:   it.set(mItems[index].u.doubleValue); break;
974             case kTypePointer:  it.set(mItems[index].u.ptrValue); break;
975             case kTypeRect:     it.set(mItems[index].u.rectValue); break;
976             case kTypeString:   it.set(*mItems[index].u.stringValue); break;
977             case kTypeObject: {
978                 sp<RefBase> obj = mItems[index].u.refValue;
979                 it.set(obj);
980                 break;
981             }
982             case kTypeMessage: {
983                 sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
984                 it.set(msg);
985                 break;
986             }
987             case kTypeBuffer: {
988                 sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
989                 it.set(buf);
990                 break;
991             }
992             default:
993                 break;
994         }
995     }
996     return it;
997 }
998 
setEntryNameAt(size_t index,const char * name)999 status_t AMessage::setEntryNameAt(size_t index, const char *name) {
1000     if (index >= mItems.size()) {
1001         return BAD_INDEX;
1002     }
1003     if (name == nullptr) {
1004         return BAD_VALUE;
1005     }
1006     if (!strcmp(name, mItems[index].mName)) {
1007         return OK; // name has not changed
1008     }
1009     size_t len = strlen(name);
1010     if (findItemIndex(name, len) < mItems.size()) {
1011         return ALREADY_EXISTS;
1012     }
1013     delete[] mItems[index].mName;
1014     mItems[index].mName = nullptr;
1015     mItems[index].setName(name, len);
1016     return OK;
1017 }
1018 
setEntryAt(size_t index,const ItemData & item)1019 status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
1020     AString stringValue;
1021     sp<RefBase> refValue;
1022     sp<AMessage> msgValue;
1023     sp<ABuffer> bufValue;
1024 
1025     if (index >= mItems.size()) {
1026         return BAD_INDEX;
1027     }
1028     if (!item.used()) {
1029         return BAD_VALUE;
1030     }
1031     Item *dst = &mItems[index];
1032     freeItemValue(dst);
1033 
1034     // some values can be directly set with the getter. others need items to be allocated
1035     if (item.find(&dst->u.int32Value)) {
1036         dst->mType = kTypeInt32;
1037     } else if (item.find(&dst->u.int64Value)) {
1038         dst->mType = kTypeInt64;
1039     } else if (item.find(&dst->u.sizeValue)) {
1040         dst->mType = kTypeSize;
1041     } else if (item.find(&dst->u.floatValue)) {
1042         dst->mType = kTypeFloat;
1043     } else if (item.find(&dst->u.doubleValue)) {
1044         dst->mType = kTypeDouble;
1045     } else if (item.find(&dst->u.ptrValue)) {
1046         dst->mType = kTypePointer;
1047     } else if (item.find(&dst->u.rectValue)) {
1048         dst->mType = kTypeRect;
1049     } else if (item.find(&stringValue)) {
1050         dst->u.stringValue = new AString(stringValue);
1051         dst->mType = kTypeString;
1052     } else if (item.find(&refValue)) {
1053         if (refValue != NULL) { refValue->incStrong(this); }
1054         dst->u.refValue = refValue.get();
1055         dst->mType = kTypeObject;
1056     } else if (item.find(&msgValue)) {
1057         if (msgValue != NULL) { msgValue->incStrong(this); }
1058         dst->u.refValue = msgValue.get();
1059         dst->mType = kTypeMessage;
1060     } else if (item.find(&bufValue)) {
1061         if (bufValue != NULL) { bufValue->incStrong(this); }
1062         dst->u.refValue = bufValue.get();
1063         dst->mType = kTypeBuffer;
1064     } else {
1065         // unsupported item - we should not be here.
1066         dst->mType = kTypeInt32;
1067         dst->u.int32Value = 0xDEADDEAD;
1068         return BAD_TYPE;
1069     }
1070     return OK;
1071 }
1072 
removeEntryAt(size_t index)1073 status_t AMessage::removeEntryAt(size_t index) {
1074     if (index >= mItems.size()) {
1075         return BAD_INDEX;
1076     }
1077     // delete entry data and objects
1078     delete[] mItems[index].mName;
1079     mItems[index].mName = nullptr;
1080     freeItemValue(&mItems[index]);
1081 
1082     // swap entry with last entry and clear last entry's data
1083     size_t lastIndex = mItems.size() - 1;
1084     if (index < lastIndex) {
1085         mItems[index] = mItems[lastIndex];
1086         mItems[lastIndex].mName = nullptr;
1087         mItems[lastIndex].mType = kTypeInt32;
1088     }
1089     mItems.pop_back();
1090     return OK;
1091 }
1092 
removeEntryByName(const char * name)1093 status_t AMessage::removeEntryByName(const char *name) {
1094     if (name == nullptr) {
1095         return BAD_VALUE;
1096     }
1097     size_t index = findEntryByName(name);
1098     if (index >= mItems.size()) {
1099         return BAD_INDEX;
1100     }
1101     return removeEntryAt(index);
1102 }
1103 
setItem(const char * name,const ItemData & item)1104 void AMessage::setItem(const char *name, const ItemData &item) {
1105     if (item.used()) {
1106         Item *it = allocateItem(name);
1107         if (it != nullptr) {
1108             setEntryAt(it - &mItems[0], item);
1109         }
1110     }
1111 }
1112 
findItem(const char * name) const1113 AMessage::ItemData AMessage::findItem(const char *name) const {
1114     return getEntryAt(findEntryByName(name));
1115 }
1116 
extend(const sp<AMessage> & other)1117 void AMessage::extend(const sp<AMessage> &other) {
1118     // ignore null messages
1119     if (other == nullptr) {
1120         return;
1121     }
1122 
1123     for (size_t ix = 0; ix < other->mItems.size(); ++ix) {
1124         Item *it = allocateItem(other->mItems[ix].mName);
1125         if (it != nullptr) {
1126             ItemData data = other->getEntryAt(ix);
1127             setEntryAt(it - &mItems[0], data);
1128         }
1129     }
1130 }
1131 
findEntryByName(const char * name) const1132 size_t AMessage::findEntryByName(const char *name) const {
1133     return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
1134 }
1135 
1136 }  // namespace android
1137