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