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 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 52 AMessage::AMessage(void) 53 : mWhat(0), 54 mTarget(0), 55 mNumItems(0) { 56 } 57 58 AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler) 59 : mWhat(what), 60 mNumItems(0) { 61 setTarget(handler); 62 } 63 64 AMessage::~AMessage() { 65 clear(); 66 } 67 68 void AMessage::setWhat(uint32_t what) { 69 mWhat = what; 70 } 71 72 uint32_t AMessage::what() const { 73 return mWhat; 74 } 75 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 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 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 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 152 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 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 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 207 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 218 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 245 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 263 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 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 302 void AMessage::setString( 303 const char *name, const AString &s) { 304 setString(name, s.c_str(), s.size()); 305 } 306 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 316 void AMessage::setObject(const char *name, const sp<RefBase> &obj) { 317 setObjectInternal(name, obj, kTypeObject); 318 } 319 320 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) { 321 setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer); 322 } 323 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 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 344 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 353 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 362 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 371 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 380 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 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 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 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 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 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 464 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 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 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 538 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 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 751 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 813 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 933 size_t AMessage::countEntries() const { 934 return mNumItems; 935 } 936 937 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 949 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 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 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 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 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 1085 AMessage::ItemData AMessage::findItem(const char *name) const { 1086 return getEntryAt(findEntryByName(name)); 1087 } 1088 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 1104 size_t AMessage::findEntryByName(const char *name) const { 1105 return name == nullptr ? countEntries() : findItemIndex(name, strlen(name)); 1106 } 1107 1108 } // namespace android 1109