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::contains(const char *name) const { 216 size_t i = findItemIndex(name, strlen(name)); 217 return i < mNumItems; 218 } 219 220 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ 221 void AMessage::set##NAME(const char *name, TYPENAME value) { \ 222 Item *item = allocateItem(name); \ 223 \ 224 item->mType = kType##NAME; \ 225 item->u.FIELDNAME = value; \ 226 } \ 227 \ 228 bool AMessage::find##NAME(const char *name, TYPENAME *value) const { \ 229 const Item *item = findItem(name, kType##NAME); \ 230 if (item) { \ 231 *value = item->u.FIELDNAME; \ 232 return true; \ 233 } \ 234 return false; \ 235 } 236 237 BASIC_TYPE(Int32,int32Value,int32_t) 238 BASIC_TYPE(Int64,int64Value,int64_t) 239 BASIC_TYPE(Size,sizeValue,size_t) 240 BASIC_TYPE(Float,floatValue,float) 241 BASIC_TYPE(Double,doubleValue,double) 242 BASIC_TYPE(Pointer,ptrValue,void *) 243 244 #undef BASIC_TYPE 245 246 void AMessage::setString( 247 const char *name, const char *s, ssize_t len) { 248 Item *item = allocateItem(name); 249 item->mType = kTypeString; 250 item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); 251 } 252 253 void AMessage::setString( 254 const char *name, const AString &s) { 255 setString(name, s.c_str(), s.size()); 256 } 257 258 void AMessage::setObjectInternal( 259 const char *name, const sp<RefBase> &obj, Type type) { 260 Item *item = allocateItem(name); 261 item->mType = type; 262 263 if (obj != NULL) { obj->incStrong(this); } 264 item->u.refValue = obj.get(); 265 } 266 267 void AMessage::setObject(const char *name, const sp<RefBase> &obj) { 268 setObjectInternal(name, obj, kTypeObject); 269 } 270 271 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) { 272 setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer); 273 } 274 275 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { 276 Item *item = allocateItem(name); 277 item->mType = kTypeMessage; 278 279 if (obj != NULL) { obj->incStrong(this); } 280 item->u.refValue = obj.get(); 281 } 282 283 void AMessage::setRect( 284 const char *name, 285 int32_t left, int32_t top, int32_t right, int32_t bottom) { 286 Item *item = allocateItem(name); 287 item->mType = kTypeRect; 288 289 item->u.rectValue.mLeft = left; 290 item->u.rectValue.mTop = top; 291 item->u.rectValue.mRight = right; 292 item->u.rectValue.mBottom = bottom; 293 } 294 295 bool AMessage::findString(const char *name, AString *value) const { 296 const Item *item = findItem(name, kTypeString); 297 if (item) { 298 *value = *item->u.stringValue; 299 return true; 300 } 301 return false; 302 } 303 304 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const { 305 const Item *item = findItem(name, kTypeObject); 306 if (item) { 307 *obj = item->u.refValue; 308 return true; 309 } 310 return false; 311 } 312 313 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const { 314 const Item *item = findItem(name, kTypeBuffer); 315 if (item) { 316 *buf = (ABuffer *)(item->u.refValue); 317 return true; 318 } 319 return false; 320 } 321 322 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const { 323 const Item *item = findItem(name, kTypeMessage); 324 if (item) { 325 *obj = static_cast<AMessage *>(item->u.refValue); 326 return true; 327 } 328 return false; 329 } 330 331 bool AMessage::findRect( 332 const char *name, 333 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const { 334 const Item *item = findItem(name, kTypeRect); 335 if (item == NULL) { 336 return false; 337 } 338 339 *left = item->u.rectValue.mLeft; 340 *top = item->u.rectValue.mTop; 341 *right = item->u.rectValue.mRight; 342 *bottom = item->u.rectValue.mBottom; 343 344 return true; 345 } 346 347 void AMessage::deliver() { 348 sp<AHandler> handler = mHandler.promote(); 349 if (handler == NULL) { 350 ALOGW("failed to deliver message as target handler %d is gone.", mTarget); 351 return; 352 } 353 354 handler->deliverMessage(this); 355 } 356 357 status_t AMessage::post(int64_t delayUs) { 358 sp<ALooper> looper = mLooper.promote(); 359 if (looper == NULL) { 360 ALOGW("failed to post message as target looper for handler %d is gone.", mTarget); 361 return -ENOENT; 362 } 363 364 looper->post(this, delayUs); 365 return OK; 366 } 367 368 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) { 369 sp<ALooper> looper = mLooper.promote(); 370 if (looper == NULL) { 371 ALOGW("failed to post message as target looper for handler %d is gone.", mTarget); 372 return -ENOENT; 373 } 374 375 sp<AReplyToken> token = looper->createReplyToken(); 376 if (token == NULL) { 377 ALOGE("failed to create reply token"); 378 return -ENOMEM; 379 } 380 setObject("replyID", token); 381 382 looper->post(this, 0 /* delayUs */); 383 return looper->awaitResponse(token, response); 384 } 385 386 status_t AMessage::postReply(const sp<AReplyToken> &replyToken) { 387 if (replyToken == NULL) { 388 ALOGW("failed to post reply to a NULL token"); 389 return -ENOENT; 390 } 391 sp<ALooper> looper = replyToken->getLooper(); 392 if (looper == NULL) { 393 ALOGW("failed to post reply as target looper is gone."); 394 return -ENOENT; 395 } 396 return looper->postReply(replyToken, this); 397 } 398 399 bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) { 400 sp<RefBase> tmp; 401 bool found = findObject("replyID", &tmp); 402 403 if (!found) { 404 return false; 405 } 406 407 *replyToken = static_cast<AReplyToken *>(tmp.get()); 408 tmp.clear(); 409 setObject("replyID", tmp); 410 // TODO: delete Object instead of setting it to NULL 411 412 return *replyToken != NULL; 413 } 414 415 sp<AMessage> AMessage::dup() const { 416 sp<AMessage> msg = new AMessage(mWhat, mHandler.promote()); 417 msg->mNumItems = mNumItems; 418 419 #ifdef DUMP_STATS 420 { 421 Mutex::Autolock _l(gLock); 422 ++gDupCalls; 423 gAverageDupItems += mNumItems; 424 reportStats(); 425 } 426 #endif 427 428 for (size_t i = 0; i < mNumItems; ++i) { 429 const Item *from = &mItems[i]; 430 Item *to = &msg->mItems[i]; 431 432 to->setName(from->mName, from->mNameLength); 433 to->mType = from->mType; 434 435 switch (from->mType) { 436 case kTypeString: 437 { 438 to->u.stringValue = 439 new AString(*from->u.stringValue); 440 break; 441 } 442 443 case kTypeObject: 444 case kTypeBuffer: 445 { 446 to->u.refValue = from->u.refValue; 447 to->u.refValue->incStrong(msg.get()); 448 break; 449 } 450 451 case kTypeMessage: 452 { 453 sp<AMessage> copy = 454 static_cast<AMessage *>(from->u.refValue)->dup(); 455 456 to->u.refValue = copy.get(); 457 to->u.refValue->incStrong(msg.get()); 458 break; 459 } 460 461 default: 462 { 463 to->u = from->u; 464 break; 465 } 466 } 467 } 468 469 return msg; 470 } 471 472 static void appendIndent(AString *s, int32_t indent) { 473 static const char kWhitespace[] = 474 " " 475 " "; 476 477 CHECK_LT((size_t)indent, sizeof(kWhitespace)); 478 479 s->append(kWhitespace, indent); 480 } 481 482 static bool isFourcc(uint32_t what) { 483 return isprint(what & 0xff) 484 && isprint((what >> 8) & 0xff) 485 && isprint((what >> 16) & 0xff) 486 && isprint((what >> 24) & 0xff); 487 } 488 489 AString AMessage::debugString(int32_t indent) const { 490 AString s = "AMessage(what = "; 491 492 AString tmp; 493 if (isFourcc(mWhat)) { 494 tmp = AStringPrintf( 495 "'%c%c%c%c'", 496 (char)(mWhat >> 24), 497 (char)((mWhat >> 16) & 0xff), 498 (char)((mWhat >> 8) & 0xff), 499 (char)(mWhat & 0xff)); 500 } else { 501 tmp = AStringPrintf("0x%08x", mWhat); 502 } 503 s.append(tmp); 504 505 if (mTarget != 0) { 506 tmp = AStringPrintf(", target = %d", mTarget); 507 s.append(tmp); 508 } 509 s.append(") = {\n"); 510 511 for (size_t i = 0; i < mNumItems; ++i) { 512 const Item &item = mItems[i]; 513 514 switch (item.mType) { 515 case kTypeInt32: 516 tmp = AStringPrintf( 517 "int32_t %s = %d", item.mName, item.u.int32Value); 518 break; 519 case kTypeInt64: 520 tmp = AStringPrintf( 521 "int64_t %s = %lld", item.mName, item.u.int64Value); 522 break; 523 case kTypeSize: 524 tmp = AStringPrintf( 525 "size_t %s = %d", item.mName, item.u.sizeValue); 526 break; 527 case kTypeFloat: 528 tmp = AStringPrintf( 529 "float %s = %f", item.mName, item.u.floatValue); 530 break; 531 case kTypeDouble: 532 tmp = AStringPrintf( 533 "double %s = %f", item.mName, item.u.doubleValue); 534 break; 535 case kTypePointer: 536 tmp = AStringPrintf( 537 "void *%s = %p", item.mName, item.u.ptrValue); 538 break; 539 case kTypeString: 540 tmp = AStringPrintf( 541 "string %s = \"%s\"", 542 item.mName, 543 item.u.stringValue->c_str()); 544 break; 545 case kTypeObject: 546 tmp = AStringPrintf( 547 "RefBase *%s = %p", item.mName, item.u.refValue); 548 break; 549 case kTypeBuffer: 550 { 551 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue); 552 553 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) { 554 tmp = AStringPrintf("Buffer %s = {\n", item.mName); 555 hexdump(buffer->data(), buffer->size(), indent + 4, &tmp); 556 appendIndent(&tmp, indent + 2); 557 tmp.append("}"); 558 } else { 559 tmp = AStringPrintf( 560 "Buffer *%s = %p", item.mName, buffer.get()); 561 } 562 break; 563 } 564 case kTypeMessage: 565 tmp = AStringPrintf( 566 "AMessage %s = %s", 567 item.mName, 568 static_cast<AMessage *>( 569 item.u.refValue)->debugString( 570 indent + strlen(item.mName) + 14).c_str()); 571 break; 572 case kTypeRect: 573 tmp = AStringPrintf( 574 "Rect %s(%d, %d, %d, %d)", 575 item.mName, 576 item.u.rectValue.mLeft, 577 item.u.rectValue.mTop, 578 item.u.rectValue.mRight, 579 item.u.rectValue.mBottom); 580 break; 581 default: 582 TRESPASS(); 583 } 584 585 appendIndent(&s, indent); 586 s.append(" "); 587 s.append(tmp); 588 s.append("\n"); 589 } 590 591 appendIndent(&s, indent); 592 s.append("}"); 593 594 return s; 595 } 596 597 // static 598 sp<AMessage> AMessage::FromParcel(const Parcel &parcel) { 599 int32_t what = parcel.readInt32(); 600 sp<AMessage> msg = new AMessage(); 601 msg->setWhat(what); 602 603 msg->mNumItems = static_cast<size_t>(parcel.readInt32()); 604 for (size_t i = 0; i < msg->mNumItems; ++i) { 605 Item *item = &msg->mItems[i]; 606 607 const char *name = parcel.readCString(); 608 item->setName(name, strlen(name)); 609 item->mType = static_cast<Type>(parcel.readInt32()); 610 611 switch (item->mType) { 612 case kTypeInt32: 613 { 614 item->u.int32Value = parcel.readInt32(); 615 break; 616 } 617 618 case kTypeInt64: 619 { 620 item->u.int64Value = parcel.readInt64(); 621 break; 622 } 623 624 case kTypeSize: 625 { 626 item->u.sizeValue = static_cast<size_t>(parcel.readInt32()); 627 break; 628 } 629 630 case kTypeFloat: 631 { 632 item->u.floatValue = parcel.readFloat(); 633 break; 634 } 635 636 case kTypeDouble: 637 { 638 item->u.doubleValue = parcel.readDouble(); 639 break; 640 } 641 642 case kTypeString: 643 { 644 item->u.stringValue = new AString(parcel.readCString()); 645 break; 646 } 647 648 case kTypeMessage: 649 { 650 sp<AMessage> subMsg = AMessage::FromParcel(parcel); 651 subMsg->incStrong(msg.get()); 652 653 item->u.refValue = subMsg.get(); 654 break; 655 } 656 657 default: 658 { 659 ALOGE("This type of object cannot cross process boundaries."); 660 TRESPASS(); 661 } 662 } 663 } 664 665 return msg; 666 } 667 668 void AMessage::writeToParcel(Parcel *parcel) const { 669 parcel->writeInt32(static_cast<int32_t>(mWhat)); 670 parcel->writeInt32(static_cast<int32_t>(mNumItems)); 671 672 for (size_t i = 0; i < mNumItems; ++i) { 673 const Item &item = mItems[i]; 674 675 parcel->writeCString(item.mName); 676 parcel->writeInt32(static_cast<int32_t>(item.mType)); 677 678 switch (item.mType) { 679 case kTypeInt32: 680 { 681 parcel->writeInt32(item.u.int32Value); 682 break; 683 } 684 685 case kTypeInt64: 686 { 687 parcel->writeInt64(item.u.int64Value); 688 break; 689 } 690 691 case kTypeSize: 692 { 693 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue)); 694 break; 695 } 696 697 case kTypeFloat: 698 { 699 parcel->writeFloat(item.u.floatValue); 700 break; 701 } 702 703 case kTypeDouble: 704 { 705 parcel->writeDouble(item.u.doubleValue); 706 break; 707 } 708 709 case kTypeString: 710 { 711 parcel->writeCString(item.u.stringValue->c_str()); 712 break; 713 } 714 715 case kTypeMessage: 716 { 717 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel); 718 break; 719 } 720 721 default: 722 { 723 ALOGE("This type of object cannot cross process boundaries."); 724 TRESPASS(); 725 } 726 } 727 } 728 } 729 730 size_t AMessage::countEntries() const { 731 return mNumItems; 732 } 733 734 const char *AMessage::getEntryNameAt(size_t index, Type *type) const { 735 if (index >= mNumItems) { 736 *type = kTypeInt32; 737 738 return NULL; 739 } 740 741 *type = mItems[index].mType; 742 743 return mItems[index].mName; 744 } 745 746 } // namespace android 747