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