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