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