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