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