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