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