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 }
    120 
    121 #ifdef DUMP_STATS
    122 #include <utils/Mutex.h>
    123 
    124 Mutex gLock;
    125 static int32_t gFindItemCalls = 1;
    126 static int32_t gDupCalls = 1;
    127 static int32_t gAverageNumItems = 0;
    128 static int32_t gAverageNumChecks = 0;
    129 static int32_t gAverageNumMemChecks = 0;
    130 static int32_t gAverageDupItems = 0;
    131 static int32_t gLastChecked = -1;
    132 
    133 static void reportStats() {
    134     int32_t time = (ALooper::GetNowUs() / 1000);
    135     if (time / 1000 != gLastChecked / 1000) {
    136         gLastChecked = time;
    137         ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)",
    138                 gFindItemCalls,
    139                 gAverageNumItems / (float)gFindItemCalls,
    140                 gAverageNumChecks / (float)gFindItemCalls,
    141                 gAverageNumMemChecks / (float)gFindItemCalls,
    142                 gDupCalls,
    143                 gAverageDupItems / (float)gDupCalls);
    144         gFindItemCalls = gDupCalls = 1;
    145         gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0;
    146         gLastChecked = time;
    147     }
    148 }
    149 #endif
    150 
    151 inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
    152 #ifdef DUMP_STATS
    153     size_t memchecks = 0;
    154 #endif
    155     size_t i = 0;
    156     for (; i < mNumItems; i++) {
    157         if (len != mItems[i].mNameLength) {
    158             continue;
    159         }
    160 #ifdef DUMP_STATS
    161         ++memchecks;
    162 #endif
    163         if (!memcmp(mItems[i].mName, name, len)) {
    164             break;
    165         }
    166     }
    167 #ifdef DUMP_STATS
    168     {
    169         Mutex::Autolock _l(gLock);
    170         ++gFindItemCalls;
    171         gAverageNumItems += mNumItems;
    172         gAverageNumMemChecks += memchecks;
    173         gAverageNumChecks += i;
    174         reportStats();
    175     }
    176 #endif
    177     return i;
    178 }
    179 
    180 // assumes item's name was uninitialized or NULL
    181 void AMessage::Item::setName(const char *name, size_t len) {
    182     mNameLength = len;
    183     mName = new char[len + 1];
    184     memcpy((void*)mName, name, len + 1);
    185 }
    186 
    187 AMessage::Item *AMessage::allocateItem(const char *name) {
    188     size_t len = strlen(name);
    189     size_t i = findItemIndex(name, len);
    190     Item *item;
    191 
    192     if (i < mNumItems) {
    193         item = &mItems[i];
    194         freeItemValue(item);
    195     } else {
    196         CHECK(mNumItems < kMaxNumItems);
    197         i = mNumItems++;
    198         item = &mItems[i];
    199         item->setName(name, len);
    200     }
    201 
    202     return item;
    203 }
    204 
    205 const AMessage::Item *AMessage::findItem(
    206         const char *name, Type type) const {
    207     size_t i = findItemIndex(name, strlen(name));
    208     if (i < mNumItems) {
    209         const Item *item = &mItems[i];
    210         return item->mType == type ? item : NULL;
    211 
    212     }
    213     return NULL;
    214 }
    215 
    216 bool AMessage::findAsFloat(const char *name, float *value) const {
    217     size_t i = findItemIndex(name, strlen(name));
    218     if (i < mNumItems) {
    219         const Item *item = &mItems[i];
    220         switch (item->mType) {
    221             case kTypeFloat:
    222                 *value = item->u.floatValue;
    223                 return true;
    224             case kTypeDouble:
    225                 *value = (float)item->u.doubleValue;
    226                 return true;
    227             case kTypeInt64:
    228                 *value = (float)item->u.int64Value;
    229                 return true;
    230             case kTypeInt32:
    231                 *value = (float)item->u.int32Value;
    232                 return true;
    233             case kTypeSize:
    234                 *value = (float)item->u.sizeValue;
    235                 return true;
    236             default:
    237                 return false;
    238         }
    239     }
    240     return false;
    241 }
    242 
    243 bool AMessage::findAsInt64(const char *name, int64_t *value) const {
    244     size_t i = findItemIndex(name, strlen(name));
    245     if (i < mNumItems) {
    246         const Item *item = &mItems[i];
    247         switch (item->mType) {
    248             case kTypeInt64:
    249                 *value = item->u.int64Value;
    250                 return true;
    251             case kTypeInt32:
    252                 *value = item->u.int32Value;
    253                 return true;
    254             default:
    255                 return false;
    256         }
    257     }
    258     return false;
    259 }
    260 
    261 bool AMessage::contains(const char *name) const {
    262     size_t i = findItemIndex(name, strlen(name));
    263     return i < mNumItems;
    264 }
    265 
    266 #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
    267 void AMessage::set##NAME(const char *name, TYPENAME value) {            \
    268     Item *item = allocateItem(name);                                    \
    269                                                                         \
    270     item->mType = kType##NAME;                                          \
    271     item->u.FIELDNAME = value;                                          \
    272 }                                                                       \
    273                                                                         \
    274 /* NOLINT added to avoid incorrect warning/fix from clang.tidy */       \
    275 bool AMessage::find##NAME(const char *name, TYPENAME *value) const {  /* NOLINT */ \
    276     const Item *item = findItem(name, kType##NAME);                     \
    277     if (item) {                                                         \
    278         *value = item->u.FIELDNAME;                                     \
    279         return true;                                                    \
    280     }                                                                   \
    281     return false;                                                       \
    282 }
    283 
    284 BASIC_TYPE(Int32,int32Value,int32_t)
    285 BASIC_TYPE(Int64,int64Value,int64_t)
    286 BASIC_TYPE(Size,sizeValue,size_t)
    287 BASIC_TYPE(Float,floatValue,float)
    288 BASIC_TYPE(Double,doubleValue,double)
    289 BASIC_TYPE(Pointer,ptrValue,void *)
    290 
    291 #undef BASIC_TYPE
    292 
    293 void AMessage::setString(
    294         const char *name, const char *s, ssize_t len) {
    295     Item *item = allocateItem(name);
    296     item->mType = kTypeString;
    297     item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
    298 }
    299 
    300 void AMessage::setString(
    301         const char *name, const AString &s) {
    302     setString(name, s.c_str(), s.size());
    303 }
    304 
    305 void AMessage::setObjectInternal(
    306         const char *name, const sp<RefBase> &obj, Type type) {
    307     Item *item = allocateItem(name);
    308     item->mType = type;
    309 
    310     if (obj != NULL) { obj->incStrong(this); }
    311     item->u.refValue = obj.get();
    312 }
    313 
    314 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
    315     setObjectInternal(name, obj, kTypeObject);
    316 }
    317 
    318 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
    319     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
    320 }
    321 
    322 void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
    323     Item *item = allocateItem(name);
    324     item->mType = kTypeMessage;
    325 
    326     if (obj != NULL) { obj->incStrong(this); }
    327     item->u.refValue = obj.get();
    328 }
    329 
    330 void AMessage::setRect(
    331         const char *name,
    332         int32_t left, int32_t top, int32_t right, int32_t bottom) {
    333     Item *item = allocateItem(name);
    334     item->mType = kTypeRect;
    335 
    336     item->u.rectValue.mLeft = left;
    337     item->u.rectValue.mTop = top;
    338     item->u.rectValue.mRight = right;
    339     item->u.rectValue.mBottom = bottom;
    340 }
    341 
    342 bool AMessage::findString(const char *name, AString *value) const {
    343     const Item *item = findItem(name, kTypeString);
    344     if (item) {
    345         *value = *item->u.stringValue;
    346         return true;
    347     }
    348     return false;
    349 }
    350 
    351 bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
    352     const Item *item = findItem(name, kTypeObject);
    353     if (item) {
    354         *obj = item->u.refValue;
    355         return true;
    356     }
    357     return false;
    358 }
    359 
    360 bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
    361     const Item *item = findItem(name, kTypeBuffer);
    362     if (item) {
    363         *buf = (ABuffer *)(item->u.refValue);
    364         return true;
    365     }
    366     return false;
    367 }
    368 
    369 bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
    370     const Item *item = findItem(name, kTypeMessage);
    371     if (item) {
    372         *obj = static_cast<AMessage *>(item->u.refValue);
    373         return true;
    374     }
    375     return false;
    376 }
    377 
    378 bool AMessage::findRect(
    379         const char *name,
    380         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
    381     const Item *item = findItem(name, kTypeRect);
    382     if (item == NULL) {
    383         return false;
    384     }
    385 
    386     *left = item->u.rectValue.mLeft;
    387     *top = item->u.rectValue.mTop;
    388     *right = item->u.rectValue.mRight;
    389     *bottom = item->u.rectValue.mBottom;
    390 
    391     return true;
    392 }
    393 
    394 void AMessage::deliver() {
    395     sp<AHandler> handler = mHandler.promote();
    396     if (handler == NULL) {
    397         ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
    398         return;
    399     }
    400 
    401     handler->deliverMessage(this);
    402 }
    403 
    404 status_t AMessage::post(int64_t delayUs) {
    405     sp<ALooper> looper = mLooper.promote();
    406     if (looper == NULL) {
    407         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
    408         return -ENOENT;
    409     }
    410 
    411     looper->post(this, delayUs);
    412     return OK;
    413 }
    414 
    415 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
    416     sp<ALooper> looper = mLooper.promote();
    417     if (looper == NULL) {
    418         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
    419         return -ENOENT;
    420     }
    421 
    422     sp<AReplyToken> token = looper->createReplyToken();
    423     if (token == NULL) {
    424         ALOGE("failed to create reply token");
    425         return -ENOMEM;
    426     }
    427     setObject("replyID", token);
    428 
    429     looper->post(this, 0 /* delayUs */);
    430     return looper->awaitResponse(token, response);
    431 }
    432 
    433 status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
    434     if (replyToken == NULL) {
    435         ALOGW("failed to post reply to a NULL token");
    436         return -ENOENT;
    437     }
    438     sp<ALooper> looper = replyToken->getLooper();
    439     if (looper == NULL) {
    440         ALOGW("failed to post reply as target looper is gone.");
    441         return -ENOENT;
    442     }
    443     return looper->postReply(replyToken, this);
    444 }
    445 
    446 bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
    447     sp<RefBase> tmp;
    448     bool found = findObject("replyID", &tmp);
    449 
    450     if (!found) {
    451         return false;
    452     }
    453 
    454     *replyToken = static_cast<AReplyToken *>(tmp.get());
    455     tmp.clear();
    456     setObject("replyID", tmp);
    457     // TODO: delete Object instead of setting it to NULL
    458 
    459     return *replyToken != NULL;
    460 }
    461 
    462 sp<AMessage> AMessage::dup() const {
    463     sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
    464     msg->mNumItems = mNumItems;
    465 
    466 #ifdef DUMP_STATS
    467     {
    468         Mutex::Autolock _l(gLock);
    469         ++gDupCalls;
    470         gAverageDupItems += mNumItems;
    471         reportStats();
    472     }
    473 #endif
    474 
    475     for (size_t i = 0; i < mNumItems; ++i) {
    476         const Item *from = &mItems[i];
    477         Item *to = &msg->mItems[i];
    478 
    479         to->setName(from->mName, from->mNameLength);
    480         to->mType = from->mType;
    481 
    482         switch (from->mType) {
    483             case kTypeString:
    484             {
    485                 to->u.stringValue =
    486                     new AString(*from->u.stringValue);
    487                 break;
    488             }
    489 
    490             case kTypeObject:
    491             case kTypeBuffer:
    492             {
    493                 to->u.refValue = from->u.refValue;
    494                 to->u.refValue->incStrong(msg.get());
    495                 break;
    496             }
    497 
    498             case kTypeMessage:
    499             {
    500                 sp<AMessage> copy =
    501                     static_cast<AMessage *>(from->u.refValue)->dup();
    502 
    503                 to->u.refValue = copy.get();
    504                 to->u.refValue->incStrong(msg.get());
    505                 break;
    506             }
    507 
    508             default:
    509             {
    510                 to->u = from->u;
    511                 break;
    512             }
    513         }
    514     }
    515 
    516     return msg;
    517 }
    518 
    519 static void appendIndent(AString *s, int32_t indent) {
    520     static const char kWhitespace[] =
    521         "                                        "
    522         "                                        ";
    523 
    524     CHECK_LT((size_t)indent, sizeof(kWhitespace));
    525 
    526     s->append(kWhitespace, indent);
    527 }
    528 
    529 static bool isFourcc(uint32_t what) {
    530     return isprint(what & 0xff)
    531         && isprint((what >> 8) & 0xff)
    532         && isprint((what >> 16) & 0xff)
    533         && isprint((what >> 24) & 0xff);
    534 }
    535 
    536 AString AMessage::debugString(int32_t indent) const {
    537     AString s = "AMessage(what = ";
    538 
    539     AString tmp;
    540     if (isFourcc(mWhat)) {
    541         tmp = AStringPrintf(
    542                 "'%c%c%c%c'",
    543                 (char)(mWhat >> 24),
    544                 (char)((mWhat >> 16) & 0xff),
    545                 (char)((mWhat >> 8) & 0xff),
    546                 (char)(mWhat & 0xff));
    547     } else {
    548         tmp = AStringPrintf("0x%08x", mWhat);
    549     }
    550     s.append(tmp);
    551 
    552     if (mTarget != 0) {
    553         tmp = AStringPrintf(", target = %d", mTarget);
    554         s.append(tmp);
    555     }
    556     s.append(") = {\n");
    557 
    558     for (size_t i = 0; i < mNumItems; ++i) {
    559         const Item &item = mItems[i];
    560 
    561         switch (item.mType) {
    562             case kTypeInt32:
    563                 tmp = AStringPrintf(
    564                         "int32_t %s = %d", item.mName, item.u.int32Value);
    565                 break;
    566             case kTypeInt64:
    567                 tmp = AStringPrintf(
    568                         "int64_t %s = %lld", item.mName, item.u.int64Value);
    569                 break;
    570             case kTypeSize:
    571                 tmp = AStringPrintf(
    572                         "size_t %s = %d", item.mName, item.u.sizeValue);
    573                 break;
    574             case kTypeFloat:
    575                 tmp = AStringPrintf(
    576                         "float %s = %f", item.mName, item.u.floatValue);
    577                 break;
    578             case kTypeDouble:
    579                 tmp = AStringPrintf(
    580                         "double %s = %f", item.mName, item.u.doubleValue);
    581                 break;
    582             case kTypePointer:
    583                 tmp = AStringPrintf(
    584                         "void *%s = %p", item.mName, item.u.ptrValue);
    585                 break;
    586             case kTypeString:
    587                 tmp = AStringPrintf(
    588                         "string %s = \"%s\"",
    589                         item.mName,
    590                         item.u.stringValue->c_str());
    591                 break;
    592             case kTypeObject:
    593                 tmp = AStringPrintf(
    594                         "RefBase *%s = %p", item.mName, item.u.refValue);
    595                 break;
    596             case kTypeBuffer:
    597             {
    598                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
    599 
    600                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
    601                     tmp = AStringPrintf("Buffer %s = {\n", item.mName);
    602                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
    603                     appendIndent(&tmp, indent + 2);
    604                     tmp.append("}");
    605                 } else {
    606                     tmp = AStringPrintf(
    607                             "Buffer *%s = %p", item.mName, buffer.get());
    608                 }
    609                 break;
    610             }
    611             case kTypeMessage:
    612                 tmp = AStringPrintf(
    613                         "AMessage %s = %s",
    614                         item.mName,
    615                         static_cast<AMessage *>(
    616                             item.u.refValue)->debugString(
    617                                 indent + strlen(item.mName) + 14).c_str());
    618                 break;
    619             case kTypeRect:
    620                 tmp = AStringPrintf(
    621                         "Rect %s(%d, %d, %d, %d)",
    622                         item.mName,
    623                         item.u.rectValue.mLeft,
    624                         item.u.rectValue.mTop,
    625                         item.u.rectValue.mRight,
    626                         item.u.rectValue.mBottom);
    627                 break;
    628             default:
    629                 TRESPASS();
    630         }
    631 
    632         appendIndent(&s, indent);
    633         s.append("  ");
    634         s.append(tmp);
    635         s.append("\n");
    636     }
    637 
    638     appendIndent(&s, indent);
    639     s.append("}");
    640 
    641     return s;
    642 }
    643 
    644 // static
    645 sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
    646     int32_t what = parcel.readInt32();
    647     sp<AMessage> msg = new AMessage();
    648     msg->setWhat(what);
    649 
    650     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
    651     if (msg->mNumItems > kMaxNumItems) {
    652         ALOGE("Too large number of items clipped.");
    653         msg->mNumItems = kMaxNumItems;
    654     }
    655 
    656     for (size_t i = 0; i < msg->mNumItems; ++i) {
    657         Item *item = &msg->mItems[i];
    658 
    659         const char *name = parcel.readCString();
    660         if (name == NULL) {
    661             ALOGE("Failed reading name for an item. Parsing aborted.");
    662             msg->mNumItems = i;
    663             break;
    664         }
    665 
    666         item->mType = static_cast<Type>(parcel.readInt32());
    667         // setName() happens below so that we don't leak memory when parsing
    668         // is aborted in the middle.
    669         switch (item->mType) {
    670             case kTypeInt32:
    671             {
    672                 item->u.int32Value = parcel.readInt32();
    673                 break;
    674             }
    675 
    676             case kTypeInt64:
    677             {
    678                 item->u.int64Value = parcel.readInt64();
    679                 break;
    680             }
    681 
    682             case kTypeSize:
    683             {
    684                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
    685                 break;
    686             }
    687 
    688             case kTypeFloat:
    689             {
    690                 item->u.floatValue = parcel.readFloat();
    691                 break;
    692             }
    693 
    694             case kTypeDouble:
    695             {
    696                 item->u.doubleValue = parcel.readDouble();
    697                 break;
    698             }
    699 
    700             case kTypeString:
    701             {
    702                 const char *stringValue = parcel.readCString();
    703                 if (stringValue == NULL) {
    704                     ALOGE("Failed reading string value from a parcel. "
    705                         "Parsing aborted.");
    706                     msg->mNumItems = i;
    707                     continue;
    708                     // The loop will terminate subsequently.
    709                 } else {
    710                     item->u.stringValue = new AString(stringValue);
    711                 }
    712                 break;
    713             }
    714 
    715             case kTypeMessage:
    716             {
    717                 if (maxNestingLevel == 0) {
    718                     ALOGE("Too many levels of AMessage nesting.");
    719                     return NULL;
    720                 }
    721                 sp<AMessage> subMsg = AMessage::FromParcel(
    722                         parcel,
    723                         maxNestingLevel - 1);
    724                 if (subMsg == NULL) {
    725                     // This condition will be triggered when there exists an
    726                     // object that cannot cross process boundaries or when the
    727                     // level of nested AMessage is too deep.
    728                     return NULL;
    729                 }
    730                 subMsg->incStrong(msg.get());
    731 
    732                 item->u.refValue = subMsg.get();
    733                 break;
    734             }
    735 
    736             default:
    737             {
    738                 ALOGE("This type of object cannot cross process boundaries.");
    739                 return NULL;
    740             }
    741         }
    742 
    743         item->setName(name, strlen(name));
    744     }
    745 
    746     return msg;
    747 }
    748 
    749 void AMessage::writeToParcel(Parcel *parcel) const {
    750     parcel->writeInt32(static_cast<int32_t>(mWhat));
    751     parcel->writeInt32(static_cast<int32_t>(mNumItems));
    752 
    753     for (size_t i = 0; i < mNumItems; ++i) {
    754         const Item &item = mItems[i];
    755 
    756         parcel->writeCString(item.mName);
    757         parcel->writeInt32(static_cast<int32_t>(item.mType));
    758 
    759         switch (item.mType) {
    760             case kTypeInt32:
    761             {
    762                 parcel->writeInt32(item.u.int32Value);
    763                 break;
    764             }
    765 
    766             case kTypeInt64:
    767             {
    768                 parcel->writeInt64(item.u.int64Value);
    769                 break;
    770             }
    771 
    772             case kTypeSize:
    773             {
    774                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
    775                 break;
    776             }
    777 
    778             case kTypeFloat:
    779             {
    780                 parcel->writeFloat(item.u.floatValue);
    781                 break;
    782             }
    783 
    784             case kTypeDouble:
    785             {
    786                 parcel->writeDouble(item.u.doubleValue);
    787                 break;
    788             }
    789 
    790             case kTypeString:
    791             {
    792                 parcel->writeCString(item.u.stringValue->c_str());
    793                 break;
    794             }
    795 
    796             case kTypeMessage:
    797             {
    798                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
    799                 break;
    800             }
    801 
    802             default:
    803             {
    804                 ALOGE("This type of object cannot cross process boundaries.");
    805                 TRESPASS();
    806             }
    807         }
    808     }
    809 }
    810 
    811 sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
    812     if (other == NULL) {
    813         return const_cast<AMessage*>(this);
    814     }
    815 
    816     sp<AMessage> diff = new AMessage;
    817     if (mWhat != other->mWhat) {
    818         diff->setWhat(mWhat);
    819     }
    820     if (mHandler != other->mHandler) {
    821         diff->setTarget(mHandler.promote());
    822     }
    823 
    824     for (size_t i = 0; i < mNumItems; ++i) {
    825         const Item &item = mItems[i];
    826         const Item *oitem = other->findItem(item.mName, item.mType);
    827         switch (item.mType) {
    828             case kTypeInt32:
    829                 if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
    830                     diff->setInt32(item.mName, item.u.int32Value);
    831                 }
    832                 break;
    833 
    834             case kTypeInt64:
    835                 if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
    836                     diff->setInt64(item.mName, item.u.int64Value);
    837                 }
    838                 break;
    839 
    840             case kTypeSize:
    841                 if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
    842                     diff->setSize(item.mName, item.u.sizeValue);
    843                 }
    844                 break;
    845 
    846             case kTypeFloat:
    847                 if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
    848                     diff->setFloat(item.mName, item.u.sizeValue);
    849                 }
    850                 break;
    851 
    852             case kTypeDouble:
    853                 if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
    854                     diff->setDouble(item.mName, item.u.sizeValue);
    855                 }
    856                 break;
    857 
    858             case kTypeString:
    859                 if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
    860                     diff->setString(item.mName, *item.u.stringValue);
    861                 }
    862                 break;
    863 
    864             case kTypeRect:
    865                 if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
    866                     diff->setRect(
    867                             item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
    868                             item.u.rectValue.mRight, item.u.rectValue.mBottom);
    869                 }
    870                 break;
    871 
    872             case kTypePointer:
    873                 if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
    874                     diff->setPointer(item.mName, item.u.ptrValue);
    875                 }
    876                 break;
    877 
    878             case kTypeBuffer:
    879             {
    880                 sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
    881                 if (myBuf == NULL) {
    882                     if (oitem == NULL || oitem->u.refValue != NULL) {
    883                         diff->setBuffer(item.mName, NULL);
    884                     }
    885                     break;
    886                 }
    887                 sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
    888                 if (oBuf == NULL
    889                         || myBuf->size() != oBuf->size()
    890                         || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
    891                         || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
    892                     diff->setBuffer(item.mName, myBuf);
    893                 }
    894                 break;
    895             }
    896 
    897             case kTypeMessage:
    898             {
    899                 sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
    900                 if (myMsg == NULL) {
    901                     if (oitem == NULL || oitem->u.refValue != NULL) {
    902                         diff->setMessage(item.mName, NULL);
    903                     }
    904                     break;
    905                 }
    906                 sp<AMessage> oMsg =
    907                     oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
    908                 sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
    909                 if (changes->countEntries()) {
    910                     diff->setMessage(item.mName, deep ? changes : myMsg);
    911                 }
    912                 break;
    913             }
    914 
    915             case kTypeObject:
    916                 if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
    917                     diff->setObject(item.mName, item.u.refValue);
    918                 }
    919                 break;
    920 
    921             default:
    922             {
    923                 ALOGE("Unknown type %d", item.mType);
    924                 TRESPASS();
    925             }
    926         }
    927     }
    928     return diff;
    929 }
    930 
    931 size_t AMessage::countEntries() const {
    932     return mNumItems;
    933 }
    934 
    935 const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
    936     if (index >= mNumItems) {
    937         *type = kTypeInt32;
    938 
    939         return NULL;
    940     }
    941 
    942     *type = mItems[index].mType;
    943 
    944     return mItems[index].mName;
    945 }
    946 
    947 }  // namespace android
    948