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