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