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