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