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