Home | History | Annotate | Download | only in foundation
      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 
     21 #include <ctype.h>
     22 
     23 #include "AMessage.h"
     24 
     25 #include <binder/Parcel.h>
     26 #include <log/log.h>
     27 
     28 #include "AAtomizer.h"
     29 #include "ABuffer.h"
     30 #include "ADebug.h"
     31 #include "ALooperRoster.h"
     32 #include "AHandler.h"
     33 #include "AString.h"
     34 
     35 #include <media/stagefright/foundation/hexdump.h>
     36 
     37 namespace android {
     38 
     39 extern ALooperRoster gLooperRoster;
     40 
     41 status_t AReplyToken::setReply(const sp<AMessage> &reply) {
     42     if (mReplied) {
     43         ALOGE("trying to post a duplicate reply");
     44         return -EBUSY;
     45     }
     46     CHECK(mReply == NULL);
     47     mReply = reply;
     48     mReplied = true;
     49     return OK;
     50 }
     51 
     52 AMessage::AMessage(void)
     53     : mWhat(0),
     54       mTarget(0),
     55       mNumItems(0) {
     56 }
     57 
     58 AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
     59     : mWhat(what),
     60       mNumItems(0) {
     61     setTarget(handler);
     62 }
     63 
     64 AMessage::~AMessage() {
     65     clear();
     66 }
     67 
     68 void AMessage::setWhat(uint32_t what) {
     69     mWhat = what;
     70 }
     71 
     72 uint32_t AMessage::what() const {
     73     return mWhat;
     74 }
     75 
     76 void AMessage::setTarget(const sp<const AHandler> &handler) {
     77     if (handler == NULL) {
     78         mTarget = 0;
     79         mHandler.clear();
     80         mLooper.clear();
     81     } else {
     82         mTarget = handler->id();
     83         mHandler = handler->getHandler();
     84         mLooper = handler->getLooper();
     85     }
     86 }
     87 
     88 void AMessage::clear() {
     89     for (size_t i = 0; i < mNumItems; ++i) {
     90         Item *item = &mItems[i];
     91         delete[] item->mName;
     92         item->mName = NULL;
     93         freeItemValue(item);
     94     }
     95     mNumItems = 0;
     96 }
     97 
     98 void AMessage::freeItemValue(Item *item) {
     99     switch (item->mType) {
    100         case kTypeString:
    101         {
    102             delete item->u.stringValue;
    103             break;
    104         }
    105 
    106         case kTypeObject:
    107         case kTypeMessage:
    108         case kTypeBuffer:
    109         {
    110             if (item->u.refValue != NULL) {
    111                 item->u.refValue->decStrong(this);
    112             }
    113             break;
    114         }
    115 
    116         default:
    117             break;
    118     }
    119     item->mType = kTypeInt32; // clear type
    120 }
    121 
    122 #ifdef DUMP_STATS
    123 #include <utils/Mutex.h>
    124 
    125 Mutex gLock;
    126 static int32_t gFindItemCalls = 1;
    127 static int32_t gDupCalls = 1;
    128 static int32_t gAverageNumItems = 0;
    129 static int32_t gAverageNumChecks = 0;
    130 static int32_t gAverageNumMemChecks = 0;
    131 static int32_t gAverageDupItems = 0;
    132 static int32_t gLastChecked = -1;
    133 
    134 static void reportStats() {
    135     int32_t time = (ALooper::GetNowUs() / 1000);
    136     if (time / 1000 != gLastChecked / 1000) {
    137         gLastChecked = time;
    138         ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)",
    139                 gFindItemCalls,
    140                 gAverageNumItems / (float)gFindItemCalls,
    141                 gAverageNumChecks / (float)gFindItemCalls,
    142                 gAverageNumMemChecks / (float)gFindItemCalls,
    143                 gDupCalls,
    144                 gAverageDupItems / (float)gDupCalls);
    145         gFindItemCalls = gDupCalls = 1;
    146         gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0;
    147         gLastChecked = time;
    148     }
    149 }
    150 #endif
    151 
    152 inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
    153 #ifdef DUMP_STATS
    154     size_t memchecks = 0;
    155 #endif
    156     size_t i = 0;
    157     for (; i < mNumItems; i++) {
    158         if (len != mItems[i].mNameLength) {
    159             continue;
    160         }
    161 #ifdef DUMP_STATS
    162         ++memchecks;
    163 #endif
    164         if (!memcmp(mItems[i].mName, name, len)) {
    165             break;
    166         }
    167     }
    168 #ifdef DUMP_STATS
    169     {
    170         Mutex::Autolock _l(gLock);
    171         ++gFindItemCalls;
    172         gAverageNumItems += mNumItems;
    173         gAverageNumMemChecks += memchecks;
    174         gAverageNumChecks += i;
    175         reportStats();
    176     }
    177 #endif
    178     return i;
    179 }
    180 
    181 // assumes item's name was uninitialized or NULL
    182 void AMessage::Item::setName(const char *name, size_t len) {
    183     mNameLength = len;
    184     mName = new char[len + 1];
    185     memcpy((void*)mName, name, len + 1);
    186 }
    187 
    188 AMessage::Item *AMessage::allocateItem(const char *name) {
    189     size_t len = strlen(name);
    190     size_t i = findItemIndex(name, len);
    191     Item *item;
    192 
    193     if (i < mNumItems) {
    194         item = &mItems[i];
    195         freeItemValue(item);
    196     } else {
    197         CHECK(mNumItems < kMaxNumItems);
    198         i = mNumItems++;
    199         item = &mItems[i];
    200         item->mType = kTypeInt32;
    201         item->setName(name, len);
    202     }
    203 
    204     return item;
    205 }
    206 
    207 const AMessage::Item *AMessage::findItem(
    208         const char *name, Type type) const {
    209     size_t i = findItemIndex(name, strlen(name));
    210     if (i < mNumItems) {
    211         const Item *item = &mItems[i];
    212         return item->mType == type ? item : NULL;
    213 
    214     }
    215     return NULL;
    216 }
    217 
    218 bool AMessage::findAsFloat(const char *name, float *value) const {
    219     size_t i = findItemIndex(name, strlen(name));
    220     if (i < mNumItems) {
    221         const Item *item = &mItems[i];
    222         switch (item->mType) {
    223             case kTypeFloat:
    224                 *value = item->u.floatValue;
    225                 return true;
    226             case kTypeDouble:
    227                 *value = (float)item->u.doubleValue;
    228                 return true;
    229             case kTypeInt64:
    230                 *value = (float)item->u.int64Value;
    231                 return true;
    232             case kTypeInt32:
    233                 *value = (float)item->u.int32Value;
    234                 return true;
    235             case kTypeSize:
    236                 *value = (float)item->u.sizeValue;
    237                 return true;
    238             default:
    239                 return false;
    240         }
    241     }
    242     return false;
    243 }
    244 
    245 bool AMessage::findAsInt64(const char *name, int64_t *value) const {
    246     size_t i = findItemIndex(name, strlen(name));
    247     if (i < mNumItems) {
    248         const Item *item = &mItems[i];
    249         switch (item->mType) {
    250             case kTypeInt64:
    251                 *value = item->u.int64Value;
    252                 return true;
    253             case kTypeInt32:
    254                 *value = item->u.int32Value;
    255                 return true;
    256             default:
    257                 return false;
    258         }
    259     }
    260     return false;
    261 }
    262 
    263 bool AMessage::contains(const char *name) const {
    264     size_t i = findItemIndex(name, strlen(name));
    265     return i < mNumItems;
    266 }
    267 
    268 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
    269 void AMessage::set##NAME(const char *name, TYPENAME value) {            \
    270     Item *item = allocateItem(name);                                    \
    271                                                                         \
    272     item->mType = kType##NAME;                                          \
    273     item->u.FIELDNAME = value;                                          \
    274 }                                                                       \
    275                                                                         \
    276 /* NOLINT added to avoid incorrect warning/fix from clang.tidy */       \
    277 bool AMessage::find##NAME(const char *name, TYPENAME *value) const {  /* NOLINT */ \
    278     const Item *item = findItem(name, kType##NAME);                     \
    279     if (item) {                                                         \
    280         *value = item->u.FIELDNAME;                                     \
    281         return true;                                                    \
    282     }                                                                   \
    283     return false;                                                       \
    284 }
    285 
    286 BASIC_TYPE(Int32,int32Value,int32_t)
    287 BASIC_TYPE(Int64,int64Value,int64_t)
    288 BASIC_TYPE(Size,sizeValue,size_t)
    289 BASIC_TYPE(Float,floatValue,float)
    290 BASIC_TYPE(Double,doubleValue,double)
    291 BASIC_TYPE(Pointer,ptrValue,void *)
    292 
    293 #undef BASIC_TYPE
    294 
    295 void AMessage::setString(
    296         const char *name, const char *s, ssize_t len) {
    297     Item *item = allocateItem(name);
    298     item->mType = kTypeString;
    299     item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
    300 }
    301 
    302 void AMessage::setString(
    303         const char *name, const AString &s) {
    304     setString(name, s.c_str(), s.size());
    305 }
    306 
    307 void AMessage::setObjectInternal(
    308         const char *name, const sp<RefBase> &obj, Type type) {
    309     Item *item = allocateItem(name);
    310     item->mType = type;
    311 
    312     if (obj != NULL) { obj->incStrong(this); }
    313     item->u.refValue = obj.get();
    314 }
    315 
    316 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
    317     setObjectInternal(name, obj, kTypeObject);
    318 }
    319 
    320 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
    321     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
    322 }
    323 
    324 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
    325     Item *item = allocateItem(name);
    326     item->mType = kTypeMessage;
    327 
    328     if (obj != NULL) { obj->incStrong(this); }
    329     item->u.refValue = obj.get();
    330 }
    331 
    332 void AMessage::setRect(
    333         const char *name,
    334         int32_t left, int32_t top, int32_t right, int32_t bottom) {
    335     Item *item = allocateItem(name);
    336     item->mType = kTypeRect;
    337 
    338     item->u.rectValue.mLeft = left;
    339     item->u.rectValue.mTop = top;
    340     item->u.rectValue.mRight = right;
    341     item->u.rectValue.mBottom = bottom;
    342 }
    343 
    344 bool AMessage::findString(const char *name, AString *value) const {
    345     const Item *item = findItem(name, kTypeString);
    346     if (item) {
    347         *value = *item->u.stringValue;
    348         return true;
    349     }
    350     return false;
    351 }
    352 
    353 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
    354     const Item *item = findItem(name, kTypeObject);
    355     if (item) {
    356         *obj = item->u.refValue;
    357         return true;
    358     }
    359     return false;
    360 }
    361 
    362 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
    363     const Item *item = findItem(name, kTypeBuffer);
    364     if (item) {
    365         *buf = (ABuffer *)(item->u.refValue);
    366         return true;
    367     }
    368     return false;
    369 }
    370 
    371 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
    372     const Item *item = findItem(name, kTypeMessage);
    373     if (item) {
    374         *obj = static_cast<AMessage *>(item->u.refValue);
    375         return true;
    376     }
    377     return false;
    378 }
    379 
    380 bool AMessage::findRect(
    381         const char *name,
    382         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
    383     const Item *item = findItem(name, kTypeRect);
    384     if (item == NULL) {
    385         return false;
    386     }
    387 
    388     *left = item->u.rectValue.mLeft;
    389     *top = item->u.rectValue.mTop;
    390     *right = item->u.rectValue.mRight;
    391     *bottom = item->u.rectValue.mBottom;
    392 
    393     return true;
    394 }
    395 
    396 void AMessage::deliver() {
    397     sp<AHandler> handler = mHandler.promote();
    398     if (handler == NULL) {
    399         ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
    400         return;
    401     }
    402 
    403     handler->deliverMessage(this);
    404 }
    405 
    406 status_t AMessage::post(int64_t delayUs) {
    407     sp<ALooper> looper = mLooper.promote();
    408     if (looper == NULL) {
    409         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
    410         return -ENOENT;
    411     }
    412 
    413     looper->post(this, delayUs);
    414     return OK;
    415 }
    416 
    417 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
    418     sp<ALooper> looper = mLooper.promote();
    419     if (looper == NULL) {
    420         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
    421         return -ENOENT;
    422     }
    423 
    424     sp<AReplyToken> token = looper->createReplyToken();
    425     if (token == NULL) {
    426         ALOGE("failed to create reply token");
    427         return -ENOMEM;
    428     }
    429     setObject("replyID", token);
    430 
    431     looper->post(this, 0 /* delayUs */);
    432     return looper->awaitResponse(token, response);
    433 }
    434 
    435 status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
    436     if (replyToken == NULL) {
    437         ALOGW("failed to post reply to a NULL token");
    438         return -ENOENT;
    439     }
    440     sp<ALooper> looper = replyToken->getLooper();
    441     if (looper == NULL) {
    442         ALOGW("failed to post reply as target looper is gone.");
    443         return -ENOENT;
    444     }
    445     return looper->postReply(replyToken, this);
    446 }
    447 
    448 bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
    449     sp<RefBase> tmp;
    450     bool found = findObject("replyID", &tmp);
    451 
    452     if (!found) {
    453         return false;
    454     }
    455 
    456     *replyToken = static_cast<AReplyToken *>(tmp.get());
    457     tmp.clear();
    458     setObject("replyID", tmp);
    459     // TODO: delete Object instead of setting it to NULL
    460 
    461     return *replyToken != NULL;
    462 }
    463 
    464 sp<AMessage> AMessage::dup() const {
    465     sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
    466     msg->mNumItems = mNumItems;
    467 
    468 #ifdef DUMP_STATS
    469     {
    470         Mutex::Autolock _l(gLock);
    471         ++gDupCalls;
    472         gAverageDupItems += mNumItems;
    473         reportStats();
    474     }
    475 #endif
    476 
    477     for (size_t i = 0; i < mNumItems; ++i) {
    478         const Item *from = &mItems[i];
    479         Item *to = &msg->mItems[i];
    480 
    481         to->setName(from->mName, from->mNameLength);
    482         to->mType = from->mType;
    483 
    484         switch (from->mType) {
    485             case kTypeString:
    486             {
    487                 to->u.stringValue =
    488                     new AString(*from->u.stringValue);
    489                 break;
    490             }
    491 
    492             case kTypeObject:
    493             case kTypeBuffer:
    494             {
    495                 to->u.refValue = from->u.refValue;
    496                 to->u.refValue->incStrong(msg.get());
    497                 break;
    498             }
    499 
    500             case kTypeMessage:
    501             {
    502                 sp<AMessage> copy =
    503                     static_cast<AMessage *>(from->u.refValue)->dup();
    504 
    505                 to->u.refValue = copy.get();
    506                 to->u.refValue->incStrong(msg.get());
    507                 break;
    508             }
    509 
    510             default:
    511             {
    512                 to->u = from->u;
    513                 break;
    514             }
    515         }
    516     }
    517 
    518     return msg;
    519 }
    520 
    521 static void appendIndent(AString *s, int32_t indent) {
    522     static const char kWhitespace[] =
    523         "                                        "
    524         "                                        ";
    525 
    526     CHECK_LT((size_t)indent, sizeof(kWhitespace));
    527 
    528     s->append(kWhitespace, indent);
    529 }
    530 
    531 static bool isFourcc(uint32_t what) {
    532     return isprint(what & 0xff)
    533         && isprint((what >> 8) & 0xff)
    534         && isprint((what >> 16) & 0xff)
    535         && isprint((what >> 24) & 0xff);
    536 }
    537 
    538 AString AMessage::debugString(int32_t indent) const {
    539     AString s = "AMessage(what = ";
    540 
    541     AString tmp;
    542     if (isFourcc(mWhat)) {
    543         tmp = AStringPrintf(
    544                 "'%c%c%c%c'",
    545                 (char)(mWhat >> 24),
    546                 (char)((mWhat >> 16) & 0xff),
    547                 (char)((mWhat >> 8) & 0xff),
    548                 (char)(mWhat & 0xff));
    549     } else {
    550         tmp = AStringPrintf("0x%08x", mWhat);
    551     }
    552     s.append(tmp);
    553 
    554     if (mTarget != 0) {
    555         tmp = AStringPrintf(", target = %d", mTarget);
    556         s.append(tmp);
    557     }
    558     s.append(") = {\n");
    559 
    560     for (size_t i = 0; i < mNumItems; ++i) {
    561         const Item &item = mItems[i];
    562 
    563         switch (item.mType) {
    564             case kTypeInt32:
    565                 tmp = AStringPrintf(
    566                         "int32_t %s = %d", item.mName, item.u.int32Value);
    567                 break;
    568             case kTypeInt64:
    569                 tmp = AStringPrintf(
    570                         "int64_t %s = %lld", item.mName, item.u.int64Value);
    571                 break;
    572             case kTypeSize:
    573                 tmp = AStringPrintf(
    574                         "size_t %s = %d", item.mName, item.u.sizeValue);
    575                 break;
    576             case kTypeFloat:
    577                 tmp = AStringPrintf(
    578                         "float %s = %f", item.mName, item.u.floatValue);
    579                 break;
    580             case kTypeDouble:
    581                 tmp = AStringPrintf(
    582                         "double %s = %f", item.mName, item.u.doubleValue);
    583                 break;
    584             case kTypePointer:
    585                 tmp = AStringPrintf(
    586                         "void *%s = %p", item.mName, item.u.ptrValue);
    587                 break;
    588             case kTypeString:
    589                 tmp = AStringPrintf(
    590                         "string %s = \"%s\"",
    591                         item.mName,
    592                         item.u.stringValue->c_str());
    593                 break;
    594             case kTypeObject:
    595                 tmp = AStringPrintf(
    596                         "RefBase *%s = %p", item.mName, item.u.refValue);
    597                 break;
    598             case kTypeBuffer:
    599             {
    600                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
    601 
    602                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
    603                     tmp = AStringPrintf("Buffer %s = {\n", item.mName);
    604                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
    605                     appendIndent(&tmp, indent + 2);
    606                     tmp.append("}");
    607                 } else {
    608                     tmp = AStringPrintf(
    609                             "Buffer *%s = %p", item.mName, buffer.get());
    610                 }
    611                 break;
    612             }
    613             case kTypeMessage:
    614                 tmp = AStringPrintf(
    615                         "AMessage %s = %s",
    616                         item.mName,
    617                         static_cast<AMessage *>(
    618                             item.u.refValue)->debugString(
    619                                 indent + strlen(item.mName) + 14).c_str());
    620                 break;
    621             case kTypeRect:
    622                 tmp = AStringPrintf(
    623                         "Rect %s(%d, %d, %d, %d)",
    624                         item.mName,
    625                         item.u.rectValue.mLeft,
    626                         item.u.rectValue.mTop,
    627                         item.u.rectValue.mRight,
    628                         item.u.rectValue.mBottom);
    629                 break;
    630             default:
    631                 TRESPASS();
    632         }
    633 
    634         appendIndent(&s, indent);
    635         s.append("  ");
    636         s.append(tmp);
    637         s.append("\n");
    638     }
    639 
    640     appendIndent(&s, indent);
    641     s.append("}");
    642 
    643     return s;
    644 }
    645 
    646 // static
    647 sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
    648     int32_t what = parcel.readInt32();
    649     sp<AMessage> msg = new AMessage();
    650     msg->setWhat(what);
    651 
    652     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
    653     if (msg->mNumItems > kMaxNumItems) {
    654         ALOGE("Too large number of items clipped.");
    655         msg->mNumItems = kMaxNumItems;
    656     }
    657 
    658     for (size_t i = 0; i < msg->mNumItems; ++i) {
    659         Item *item = &msg->mItems[i];
    660 
    661         const char *name = parcel.readCString();
    662         if (name == NULL) {
    663             ALOGE("Failed reading name for an item. Parsing aborted.");
    664             msg->mNumItems = i;
    665             break;
    666         }
    667 
    668         item->mType = static_cast<Type>(parcel.readInt32());
    669         // setName() happens below so that we don't leak memory when parsing
    670         // is aborted in the middle.
    671         switch (item->mType) {
    672             case kTypeInt32:
    673             {
    674                 item->u.int32Value = parcel.readInt32();
    675                 break;
    676             }
    677 
    678             case kTypeInt64:
    679             {
    680                 item->u.int64Value = parcel.readInt64();
    681                 break;
    682             }
    683 
    684             case kTypeSize:
    685             {
    686                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
    687                 break;
    688             }
    689 
    690             case kTypeFloat:
    691             {
    692                 item->u.floatValue = parcel.readFloat();
    693                 break;
    694             }
    695 
    696             case kTypeDouble:
    697             {
    698                 item->u.doubleValue = parcel.readDouble();
    699                 break;
    700             }
    701 
    702             case kTypeString:
    703             {
    704                 const char *stringValue = parcel.readCString();
    705                 if (stringValue == NULL) {
    706                     ALOGE("Failed reading string value from a parcel. "
    707                         "Parsing aborted.");
    708                     msg->mNumItems = i;
    709                     continue;
    710                     // The loop will terminate subsequently.
    711                 } else {
    712                     item->u.stringValue = new AString(stringValue);
    713                 }
    714                 break;
    715             }
    716 
    717             case kTypeMessage:
    718             {
    719                 if (maxNestingLevel == 0) {
    720                     ALOGE("Too many levels of AMessage nesting.");
    721                     return NULL;
    722                 }
    723                 sp<AMessage> subMsg = AMessage::FromParcel(
    724                         parcel,
    725                         maxNestingLevel - 1);
    726                 if (subMsg == NULL) {
    727                     // This condition will be triggered when there exists an
    728                     // object that cannot cross process boundaries or when the
    729                     // level of nested AMessage is too deep.
    730                     return NULL;
    731                 }
    732                 subMsg->incStrong(msg.get());
    733 
    734                 item->u.refValue = subMsg.get();
    735                 break;
    736             }
    737 
    738             default:
    739             {
    740                 ALOGE("This type of object cannot cross process boundaries.");
    741                 return NULL;
    742             }
    743         }
    744 
    745         item->setName(name, strlen(name));
    746     }
    747 
    748     return msg;
    749 }
    750 
    751 void AMessage::writeToParcel(Parcel *parcel) const {
    752     parcel->writeInt32(static_cast<int32_t>(mWhat));
    753     parcel->writeInt32(static_cast<int32_t>(mNumItems));
    754 
    755     for (size_t i = 0; i < mNumItems; ++i) {
    756         const Item &item = mItems[i];
    757 
    758         parcel->writeCString(item.mName);
    759         parcel->writeInt32(static_cast<int32_t>(item.mType));
    760 
    761         switch (item.mType) {
    762             case kTypeInt32:
    763             {
    764                 parcel->writeInt32(item.u.int32Value);
    765                 break;
    766             }
    767 
    768             case kTypeInt64:
    769             {
    770                 parcel->writeInt64(item.u.int64Value);
    771                 break;
    772             }
    773 
    774             case kTypeSize:
    775             {
    776                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
    777                 break;
    778             }
    779 
    780             case kTypeFloat:
    781             {
    782                 parcel->writeFloat(item.u.floatValue);
    783                 break;
    784             }
    785 
    786             case kTypeDouble:
    787             {
    788                 parcel->writeDouble(item.u.doubleValue);
    789                 break;
    790             }
    791 
    792             case kTypeString:
    793             {
    794                 parcel->writeCString(item.u.stringValue->c_str());
    795                 break;
    796             }
    797 
    798             case kTypeMessage:
    799             {
    800                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
    801                 break;
    802             }
    803 
    804             default:
    805             {
    806                 ALOGE("This type of object cannot cross process boundaries.");
    807                 TRESPASS();
    808             }
    809         }
    810     }
    811 }
    812 
    813 sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
    814     if (other == NULL) {
    815         return const_cast<AMessage*>(this);
    816     }
    817 
    818     sp<AMessage> diff = new AMessage;
    819     if (mWhat != other->mWhat) {
    820         diff->setWhat(mWhat);
    821     }
    822     if (mHandler != other->mHandler) {
    823         diff->setTarget(mHandler.promote());
    824     }
    825 
    826     for (size_t i = 0; i < mNumItems; ++i) {
    827         const Item &item = mItems[i];
    828         const Item *oitem = other->findItem(item.mName, item.mType);
    829         switch (item.mType) {
    830             case kTypeInt32:
    831                 if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
    832                     diff->setInt32(item.mName, item.u.int32Value);
    833                 }
    834                 break;
    835 
    836             case kTypeInt64:
    837                 if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
    838                     diff->setInt64(item.mName, item.u.int64Value);
    839                 }
    840                 break;
    841 
    842             case kTypeSize:
    843                 if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
    844                     diff->setSize(item.mName, item.u.sizeValue);
    845                 }
    846                 break;
    847 
    848             case kTypeFloat:
    849                 if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
    850                     diff->setFloat(item.mName, item.u.sizeValue);
    851                 }
    852                 break;
    853 
    854             case kTypeDouble:
    855                 if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
    856                     diff->setDouble(item.mName, item.u.sizeValue);
    857                 }
    858                 break;
    859 
    860             case kTypeString:
    861                 if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
    862                     diff->setString(item.mName, *item.u.stringValue);
    863                 }
    864                 break;
    865 
    866             case kTypeRect:
    867                 if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
    868                     diff->setRect(
    869                             item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
    870                             item.u.rectValue.mRight, item.u.rectValue.mBottom);
    871                 }
    872                 break;
    873 
    874             case kTypePointer:
    875                 if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
    876                     diff->setPointer(item.mName, item.u.ptrValue);
    877                 }
    878                 break;
    879 
    880             case kTypeBuffer:
    881             {
    882                 sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
    883                 if (myBuf == NULL) {
    884                     if (oitem == NULL || oitem->u.refValue != NULL) {
    885                         diff->setBuffer(item.mName, NULL);
    886                     }
    887                     break;
    888                 }
    889                 sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
    890                 if (oBuf == NULL
    891                         || myBuf->size() != oBuf->size()
    892                         || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
    893                         || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
    894                     diff->setBuffer(item.mName, myBuf);
    895                 }
    896                 break;
    897             }
    898 
    899             case kTypeMessage:
    900             {
    901                 sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
    902                 if (myMsg == NULL) {
    903                     if (oitem == NULL || oitem->u.refValue != NULL) {
    904                         diff->setMessage(item.mName, NULL);
    905                     }
    906                     break;
    907                 }
    908                 sp<AMessage> oMsg =
    909                     oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
    910                 sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
    911                 if (changes->countEntries()) {
    912                     diff->setMessage(item.mName, deep ? changes : myMsg);
    913                 }
    914                 break;
    915             }
    916 
    917             case kTypeObject:
    918                 if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
    919                     diff->setObject(item.mName, item.u.refValue);
    920                 }
    921                 break;
    922 
    923             default:
    924             {
    925                 ALOGE("Unknown type %d", item.mType);
    926                 TRESPASS();
    927             }
    928         }
    929     }
    930     return diff;
    931 }
    932 
    933 size_t AMessage::countEntries() const {
    934     return mNumItems;
    935 }
    936 
    937 const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
    938     if (index >= mNumItems) {
    939         *type = kTypeInt32;
    940 
    941         return NULL;
    942     }
    943 
    944     *type = mItems[index].mType;
    945 
    946     return mItems[index].mName;
    947 }
    948 
    949 AMessage::ItemData AMessage::getEntryAt(size_t index) const {
    950     ItemData it;
    951     if (index < mNumItems) {
    952         switch (mItems[index].mType) {
    953             case kTypeInt32:    it.set(mItems[index].u.int32Value); break;
    954             case kTypeInt64:    it.set(mItems[index].u.int64Value); break;
    955             case kTypeSize:     it.set(mItems[index].u.sizeValue); break;
    956             case kTypeFloat:    it.set(mItems[index].u.floatValue); break;
    957             case kTypeDouble:   it.set(mItems[index].u.doubleValue); break;
    958             case kTypePointer:  it.set(mItems[index].u.ptrValue); break;
    959             case kTypeRect:     it.set(mItems[index].u.rectValue); break;
    960             case kTypeString:   it.set(*mItems[index].u.stringValue); break;
    961             case kTypeObject: {
    962                 sp<RefBase> obj = mItems[index].u.refValue;
    963                 it.set(obj);
    964                 break;
    965             }
    966             case kTypeMessage: {
    967                 sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
    968                 it.set(msg);
    969                 break;
    970             }
    971             case kTypeBuffer: {
    972                 sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
    973                 it.set(buf);
    974                 break;
    975             }
    976             default:
    977                 break;
    978         }
    979     }
    980     return it;
    981 }
    982 
    983 status_t AMessage::setEntryNameAt(size_t index, const char *name) {
    984     if (index >= mNumItems) {
    985         return BAD_INDEX;
    986     }
    987     if (name == nullptr) {
    988         return BAD_VALUE;
    989     }
    990     if (!strcmp(name, mItems[index].mName)) {
    991         return OK; // name has not changed
    992     }
    993     size_t len = strlen(name);
    994     if (findItemIndex(name, len) < mNumItems) {
    995         return ALREADY_EXISTS;
    996     }
    997     delete[] mItems[index].mName;
    998     mItems[index].mName = nullptr;
    999     mItems[index].setName(name, len);
   1000     return OK;
   1001 }
   1002 
   1003 status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
   1004     AString stringValue;
   1005     sp<RefBase> refValue;
   1006     sp<AMessage> msgValue;
   1007     sp<ABuffer> bufValue;
   1008 
   1009     if (index >= mNumItems) {
   1010         return BAD_INDEX;
   1011     }
   1012     if (!item.used()) {
   1013         return BAD_VALUE;
   1014     }
   1015     Item *dst = &mItems[index];
   1016     freeItemValue(dst);
   1017 
   1018     // some values can be directly set with the getter. others need items to be allocated
   1019     if (item.find(&dst->u.int32Value)) {
   1020         dst->mType = kTypeInt32;
   1021     } else if (item.find(&dst->u.int64Value)) {
   1022         dst->mType = kTypeInt64;
   1023     } else if (item.find(&dst->u.sizeValue)) {
   1024         dst->mType = kTypeSize;
   1025     } else if (item.find(&dst->u.floatValue)) {
   1026         dst->mType = kTypeFloat;
   1027     } else if (item.find(&dst->u.doubleValue)) {
   1028         dst->mType = kTypeDouble;
   1029     } else if (item.find(&dst->u.ptrValue)) {
   1030         dst->mType = kTypePointer;
   1031     } else if (item.find(&dst->u.rectValue)) {
   1032         dst->mType = kTypeRect;
   1033     } else if (item.find(&stringValue)) {
   1034         dst->u.stringValue = new AString(stringValue);
   1035         dst->mType = kTypeString;
   1036     } else if (item.find(&refValue)) {
   1037         if (refValue != NULL) { refValue->incStrong(this); }
   1038         dst->u.refValue = refValue.get();
   1039         dst->mType = kTypeObject;
   1040     } else if (item.find(&msgValue)) {
   1041         if (msgValue != NULL) { msgValue->incStrong(this); }
   1042         dst->u.refValue = msgValue.get();
   1043         dst->mType = kTypeMessage;
   1044     } else if (item.find(&bufValue)) {
   1045         if (bufValue != NULL) { bufValue->incStrong(this); }
   1046         dst->u.refValue = bufValue.get();
   1047         dst->mType = kTypeBuffer;
   1048     } else {
   1049         // unsupported item - we should not be here.
   1050         dst->mType = kTypeInt32;
   1051         dst->u.int32Value = 0xDEADDEAD;
   1052         return BAD_TYPE;
   1053     }
   1054     return OK;
   1055 }
   1056 
   1057 status_t AMessage::removeEntryAt(size_t index) {
   1058     if (index >= mNumItems) {
   1059         return BAD_INDEX;
   1060     }
   1061     // delete entry data and objects
   1062     --mNumItems;
   1063     delete[] mItems[index].mName;
   1064     mItems[index].mName = nullptr;
   1065     freeItemValue(&mItems[index]);
   1066 
   1067     // swap entry with last entry and clear last entry's data
   1068     if (index < mNumItems) {
   1069         mItems[index] = mItems[mNumItems];
   1070         mItems[mNumItems].mName = nullptr;
   1071         mItems[mNumItems].mType = kTypeInt32;
   1072     }
   1073     return OK;
   1074 }
   1075 
   1076 void AMessage::setItem(const char *name, const ItemData &item) {
   1077     if (item.used()) {
   1078         Item *it = allocateItem(name);
   1079         if (it != nullptr) {
   1080             setEntryAt(it - mItems, item);
   1081         }
   1082     }
   1083 }
   1084 
   1085 AMessage::ItemData AMessage::findItem(const char *name) const {
   1086     return getEntryAt(findEntryByName(name));
   1087 }
   1088 
   1089 void AMessage::extend(const sp<AMessage> &other) {
   1090     // ignore null messages
   1091     if (other == nullptr) {
   1092         return;
   1093     }
   1094 
   1095     for (size_t ix = 0; ix < other->mNumItems; ++ix) {
   1096         Item *it = allocateItem(other->mItems[ix].mName);
   1097         if (it != nullptr) {
   1098             ItemData data = other->getEntryAt(ix);
   1099             setEntryAt(it - mItems, data);
   1100         }
   1101     }
   1102 }
   1103 
   1104 size_t AMessage::findEntryByName(const char *name) const {
   1105     return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
   1106 }
   1107 
   1108 }  // namespace android
   1109