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 #include "AMessage.h" 18 19 #include <ctype.h> 20 21 #include "AAtomizer.h" 22 #include "ABuffer.h" 23 #include "ADebug.h" 24 #include "ALooperRoster.h" 25 #include "AString.h" 26 27 #include <binder/Parcel.h> 28 #include <media/stagefright/foundation/hexdump.h> 29 30 namespace android { 31 32 extern ALooperRoster gLooperRoster; 33 34 AMessage::AMessage(uint32_t what, ALooper::handler_id target) 35 : mWhat(what), 36 mTarget(target), 37 mNumItems(0) { 38 } 39 40 AMessage::~AMessage() { 41 clear(); 42 } 43 44 void AMessage::setWhat(uint32_t what) { 45 mWhat = what; 46 } 47 48 uint32_t AMessage::what() const { 49 return mWhat; 50 } 51 52 void AMessage::setTarget(ALooper::handler_id handlerID) { 53 mTarget = handlerID; 54 } 55 56 ALooper::handler_id AMessage::target() const { 57 return mTarget; 58 } 59 60 void AMessage::clear() { 61 for (size_t i = 0; i < mNumItems; ++i) { 62 Item *item = &mItems[i]; 63 freeItem(item); 64 } 65 mNumItems = 0; 66 } 67 68 void AMessage::freeItem(Item *item) { 69 switch (item->mType) { 70 case kTypeString: 71 { 72 delete item->u.stringValue; 73 break; 74 } 75 76 case kTypeObject: 77 case kTypeMessage: 78 case kTypeBuffer: 79 { 80 if (item->u.refValue != NULL) { 81 item->u.refValue->decStrong(this); 82 } 83 break; 84 } 85 86 default: 87 break; 88 } 89 } 90 91 AMessage::Item *AMessage::allocateItem(const char *name) { 92 name = AAtomizer::Atomize(name); 93 94 size_t i = 0; 95 while (i < mNumItems && mItems[i].mName != name) { 96 ++i; 97 } 98 99 Item *item; 100 101 if (i < mNumItems) { 102 item = &mItems[i]; 103 freeItem(item); 104 } else { 105 CHECK(mNumItems < kMaxNumItems); 106 i = mNumItems++; 107 item = &mItems[i]; 108 109 item->mName = name; 110 } 111 112 return item; 113 } 114 115 const AMessage::Item *AMessage::findItem( 116 const char *name, Type type) const { 117 name = AAtomizer::Atomize(name); 118 119 for (size_t i = 0; i < mNumItems; ++i) { 120 const Item *item = &mItems[i]; 121 122 if (item->mName == name) { 123 return item->mType == type ? item : NULL; 124 } 125 } 126 127 return NULL; 128 } 129 130 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ 131 void AMessage::set##NAME(const char *name, TYPENAME value) { \ 132 Item *item = allocateItem(name); \ 133 \ 134 item->mType = kType##NAME; \ 135 item->u.FIELDNAME = value; \ 136 } \ 137 \ 138 bool AMessage::find##NAME(const char *name, TYPENAME *value) const { \ 139 const Item *item = findItem(name, kType##NAME); \ 140 if (item) { \ 141 *value = item->u.FIELDNAME; \ 142 return true; \ 143 } \ 144 return false; \ 145 } 146 147 BASIC_TYPE(Int32,int32Value,int32_t) 148 BASIC_TYPE(Int64,int64Value,int64_t) 149 BASIC_TYPE(Size,sizeValue,size_t) 150 BASIC_TYPE(Float,floatValue,float) 151 BASIC_TYPE(Double,doubleValue,double) 152 BASIC_TYPE(Pointer,ptrValue,void *) 153 154 #undef BASIC_TYPE 155 156 void AMessage::setString( 157 const char *name, const char *s, ssize_t len) { 158 Item *item = allocateItem(name); 159 item->mType = kTypeString; 160 item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); 161 } 162 163 void AMessage::setObjectInternal( 164 const char *name, const sp<RefBase> &obj, Type type) { 165 Item *item = allocateItem(name); 166 item->mType = type; 167 168 if (obj != NULL) { obj->incStrong(this); } 169 item->u.refValue = obj.get(); 170 } 171 172 void AMessage::setObject(const char *name, const sp<RefBase> &obj) { 173 setObjectInternal(name, obj, kTypeObject); 174 } 175 176 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) { 177 setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer); 178 } 179 180 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { 181 Item *item = allocateItem(name); 182 item->mType = kTypeMessage; 183 184 if (obj != NULL) { obj->incStrong(this); } 185 item->u.refValue = obj.get(); 186 } 187 188 void AMessage::setRect( 189 const char *name, 190 int32_t left, int32_t top, int32_t right, int32_t bottom) { 191 Item *item = allocateItem(name); 192 item->mType = kTypeRect; 193 194 item->u.rectValue.mLeft = left; 195 item->u.rectValue.mTop = top; 196 item->u.rectValue.mRight = right; 197 item->u.rectValue.mBottom = bottom; 198 } 199 200 bool AMessage::findString(const char *name, AString *value) const { 201 const Item *item = findItem(name, kTypeString); 202 if (item) { 203 *value = *item->u.stringValue; 204 return true; 205 } 206 return false; 207 } 208 209 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const { 210 const Item *item = findItem(name, kTypeObject); 211 if (item) { 212 *obj = item->u.refValue; 213 return true; 214 } 215 return false; 216 } 217 218 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const { 219 const Item *item = findItem(name, kTypeBuffer); 220 if (item) { 221 *buf = (ABuffer *)(item->u.refValue); 222 return true; 223 } 224 return false; 225 } 226 227 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const { 228 const Item *item = findItem(name, kTypeMessage); 229 if (item) { 230 *obj = static_cast<AMessage *>(item->u.refValue); 231 return true; 232 } 233 return false; 234 } 235 236 bool AMessage::findRect( 237 const char *name, 238 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const { 239 const Item *item = findItem(name, kTypeRect); 240 if (item == NULL) { 241 return false; 242 } 243 244 *left = item->u.rectValue.mLeft; 245 *top = item->u.rectValue.mTop; 246 *right = item->u.rectValue.mRight; 247 *bottom = item->u.rectValue.mBottom; 248 249 return true; 250 } 251 252 void AMessage::post(int64_t delayUs) { 253 gLooperRoster.postMessage(this, delayUs); 254 } 255 256 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) { 257 return gLooperRoster.postAndAwaitResponse(this, response); 258 } 259 260 void AMessage::postReply(uint32_t replyID) { 261 gLooperRoster.postReply(replyID, this); 262 } 263 264 bool AMessage::senderAwaitsResponse(uint32_t *replyID) const { 265 int32_t tmp; 266 bool found = findInt32("replyID", &tmp); 267 268 if (!found) { 269 return false; 270 } 271 272 *replyID = static_cast<uint32_t>(tmp); 273 274 return true; 275 } 276 277 sp<AMessage> AMessage::dup() const { 278 sp<AMessage> msg = new AMessage(mWhat, mTarget); 279 msg->mNumItems = mNumItems; 280 281 for (size_t i = 0; i < mNumItems; ++i) { 282 const Item *from = &mItems[i]; 283 Item *to = &msg->mItems[i]; 284 285 to->mName = from->mName; 286 to->mType = from->mType; 287 288 switch (from->mType) { 289 case kTypeString: 290 { 291 to->u.stringValue = 292 new AString(*from->u.stringValue); 293 break; 294 } 295 296 case kTypeObject: 297 case kTypeBuffer: 298 { 299 to->u.refValue = from->u.refValue; 300 to->u.refValue->incStrong(msg.get()); 301 break; 302 } 303 304 case kTypeMessage: 305 { 306 sp<AMessage> copy = 307 static_cast<AMessage *>(from->u.refValue)->dup(); 308 309 to->u.refValue = copy.get(); 310 to->u.refValue->incStrong(msg.get()); 311 break; 312 } 313 314 default: 315 { 316 to->u = from->u; 317 break; 318 } 319 } 320 } 321 322 return msg; 323 } 324 325 static void appendIndent(AString *s, int32_t indent) { 326 static const char kWhitespace[] = 327 " " 328 " "; 329 330 CHECK_LT((size_t)indent, sizeof(kWhitespace)); 331 332 s->append(kWhitespace, indent); 333 } 334 335 static bool isFourcc(uint32_t what) { 336 return isprint(what & 0xff) 337 && isprint((what >> 8) & 0xff) 338 && isprint((what >> 16) & 0xff) 339 && isprint((what >> 24) & 0xff); 340 } 341 342 AString AMessage::debugString(int32_t indent) const { 343 AString s = "AMessage(what = "; 344 345 AString tmp; 346 if (isFourcc(mWhat)) { 347 tmp = StringPrintf( 348 "'%c%c%c%c'", 349 (char)(mWhat >> 24), 350 (char)((mWhat >> 16) & 0xff), 351 (char)((mWhat >> 8) & 0xff), 352 (char)(mWhat & 0xff)); 353 } else { 354 tmp = StringPrintf("0x%08x", mWhat); 355 } 356 s.append(tmp); 357 358 if (mTarget != 0) { 359 tmp = StringPrintf(", target = %d", mTarget); 360 s.append(tmp); 361 } 362 s.append(") = {\n"); 363 364 for (size_t i = 0; i < mNumItems; ++i) { 365 const Item &item = mItems[i]; 366 367 switch (item.mType) { 368 case kTypeInt32: 369 tmp = StringPrintf( 370 "int32_t %s = %d", item.mName, item.u.int32Value); 371 break; 372 case kTypeInt64: 373 tmp = StringPrintf( 374 "int64_t %s = %lld", item.mName, item.u.int64Value); 375 break; 376 case kTypeSize: 377 tmp = StringPrintf( 378 "size_t %s = %d", item.mName, item.u.sizeValue); 379 break; 380 case kTypeFloat: 381 tmp = StringPrintf( 382 "float %s = %f", item.mName, item.u.floatValue); 383 break; 384 case kTypeDouble: 385 tmp = StringPrintf( 386 "double %s = %f", item.mName, item.u.doubleValue); 387 break; 388 case kTypePointer: 389 tmp = StringPrintf( 390 "void *%s = %p", item.mName, item.u.ptrValue); 391 break; 392 case kTypeString: 393 tmp = StringPrintf( 394 "string %s = \"%s\"", 395 item.mName, 396 item.u.stringValue->c_str()); 397 break; 398 case kTypeObject: 399 tmp = StringPrintf( 400 "RefBase *%s = %p", item.mName, item.u.refValue); 401 break; 402 case kTypeBuffer: 403 { 404 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue); 405 406 if (buffer != NULL && buffer->size() <= 64) { 407 tmp = StringPrintf("Buffer %s = {\n", item.mName); 408 hexdump(buffer->data(), buffer->size(), indent + 4, &tmp); 409 appendIndent(&tmp, indent + 2); 410 tmp.append("}"); 411 } else { 412 tmp = StringPrintf( 413 "Buffer *%s = %p", item.mName, buffer.get()); 414 } 415 break; 416 } 417 case kTypeMessage: 418 tmp = StringPrintf( 419 "AMessage %s = %s", 420 item.mName, 421 static_cast<AMessage *>( 422 item.u.refValue)->debugString( 423 indent + strlen(item.mName) + 14).c_str()); 424 break; 425 case kTypeRect: 426 tmp = StringPrintf( 427 "Rect %s(%d, %d, %d, %d)", 428 item.mName, 429 item.u.rectValue.mLeft, 430 item.u.rectValue.mTop, 431 item.u.rectValue.mRight, 432 item.u.rectValue.mBottom); 433 break; 434 default: 435 TRESPASS(); 436 } 437 438 appendIndent(&s, indent); 439 s.append(" "); 440 s.append(tmp); 441 s.append("\n"); 442 } 443 444 appendIndent(&s, indent); 445 s.append("}"); 446 447 return s; 448 } 449 450 // static 451 sp<AMessage> AMessage::FromParcel(const Parcel &parcel) { 452 int32_t what = parcel.readInt32(); 453 sp<AMessage> msg = new AMessage(what); 454 455 msg->mNumItems = static_cast<size_t>(parcel.readInt32()); 456 457 for (size_t i = 0; i < msg->mNumItems; ++i) { 458 Item *item = &msg->mItems[i]; 459 460 item->mName = AAtomizer::Atomize(parcel.readCString()); 461 item->mType = static_cast<Type>(parcel.readInt32()); 462 463 switch (item->mType) { 464 case kTypeInt32: 465 { 466 item->u.int32Value = parcel.readInt32(); 467 break; 468 } 469 470 case kTypeInt64: 471 { 472 item->u.int64Value = parcel.readInt64(); 473 break; 474 } 475 476 case kTypeSize: 477 { 478 item->u.sizeValue = static_cast<size_t>(parcel.readInt32()); 479 break; 480 } 481 482 case kTypeFloat: 483 { 484 item->u.floatValue = parcel.readFloat(); 485 break; 486 } 487 488 case kTypeDouble: 489 { 490 item->u.doubleValue = parcel.readDouble(); 491 break; 492 } 493 494 case kTypeString: 495 { 496 item->u.stringValue = new AString(parcel.readCString()); 497 break; 498 } 499 500 case kTypeMessage: 501 { 502 sp<AMessage> subMsg = AMessage::FromParcel(parcel); 503 subMsg->incStrong(msg.get()); 504 505 item->u.refValue = subMsg.get(); 506 break; 507 } 508 509 default: 510 { 511 ALOGE("This type of object cannot cross process boundaries."); 512 TRESPASS(); 513 } 514 } 515 } 516 517 return msg; 518 } 519 520 void AMessage::writeToParcel(Parcel *parcel) const { 521 parcel->writeInt32(static_cast<int32_t>(mWhat)); 522 parcel->writeInt32(static_cast<int32_t>(mNumItems)); 523 524 for (size_t i = 0; i < mNumItems; ++i) { 525 const Item &item = mItems[i]; 526 527 parcel->writeCString(item.mName); 528 parcel->writeInt32(static_cast<int32_t>(item.mType)); 529 530 switch (item.mType) { 531 case kTypeInt32: 532 { 533 parcel->writeInt32(item.u.int32Value); 534 break; 535 } 536 537 case kTypeInt64: 538 { 539 parcel->writeInt64(item.u.int64Value); 540 break; 541 } 542 543 case kTypeSize: 544 { 545 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue)); 546 break; 547 } 548 549 case kTypeFloat: 550 { 551 parcel->writeFloat(item.u.floatValue); 552 break; 553 } 554 555 case kTypeDouble: 556 { 557 parcel->writeDouble(item.u.doubleValue); 558 break; 559 } 560 561 case kTypeString: 562 { 563 parcel->writeCString(item.u.stringValue->c_str()); 564 break; 565 } 566 567 case kTypeMessage: 568 { 569 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel); 570 break; 571 } 572 573 default: 574 { 575 ALOGE("This type of object cannot cross process boundaries."); 576 TRESPASS(); 577 } 578 } 579 } 580 } 581 582 size_t AMessage::countEntries() const { 583 return mNumItems; 584 } 585 586 const char *AMessage::getEntryNameAt(size_t index, Type *type) const { 587 if (index >= mNumItems) { 588 *type = kTypeInt32; 589 590 return NULL; 591 } 592 593 *type = mItems[index].mType; 594 595 return mItems[index].mName; 596 } 597 598 } // namespace android 599