• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AMessage(uint32_t what,ALooper::handler_id target)33 AMessage::AMessage(uint32_t what, ALooper::handler_id target)
34     : mWhat(what),
35       mTarget(target),
36       mNumItems(0) {
37 }
38 
~AMessage()39 AMessage::~AMessage() {
40     clear();
41 }
42 
setWhat(uint32_t what)43 void AMessage::setWhat(uint32_t what) {
44     mWhat = what;
45 }
46 
what() const47 uint32_t AMessage::what() const {
48     return mWhat;
49 }
50 
setTarget(ALooper::handler_id handlerID)51 void AMessage::setTarget(ALooper::handler_id handlerID) {
52     mTarget = handlerID;
53 }
54 
target() const55 ALooper::handler_id AMessage::target() const {
56     return mTarget;
57 }
58 
clear()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 
freeItem(Item * item)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 
allocateItem(const char * name)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 
findItem(const char * name,Type type) const114 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 
BASIC_TYPE(Int32,int32Value,int32_t)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 
setObjectInternal(const char * name,const sp<RefBase> & obj,Type type)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 
setObject(const char * name,const sp<RefBase> & obj)171 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
172     setObjectInternal(name, obj, kTypeObject);
173 }
174 
setBuffer(const char * name,const sp<ABuffer> & buffer)175 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
176     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
177 }
178 
setMessage(const char * name,const sp<AMessage> & obj)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 
setRect(const char * name,int32_t left,int32_t top,int32_t right,int32_t bottom)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 
findString(const char * name,AString * value) const199 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 
findObject(const char * name,sp<RefBase> * obj) const208 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 
findBuffer(const char * name,sp<ABuffer> * buf) const217 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 
findMessage(const char * name,sp<AMessage> * obj) const226 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 
findRect(const char * name,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom) const235 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 
post(int64_t delayUs)251 void AMessage::post(int64_t delayUs) {
252     gLooperRoster.postMessage(this, delayUs);
253 }
254 
postAndAwaitResponse(sp<AMessage> * response)255 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
256     return gLooperRoster.postAndAwaitResponse(this, response);
257 }
258 
postReply(uint32_t replyID)259 void AMessage::postReply(uint32_t replyID) {
260     gLooperRoster.postReply(replyID, this);
261 }
262 
senderAwaitsResponse(uint32_t * replyID) const263 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 
dup() const276 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 
appendIndent(AString * s,int32_t indent)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 
isFourcc(uint32_t what)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 
debugString(int32_t indent) const341 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
FromParcel(const Parcel & parcel)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 
writeToParcel(Parcel * parcel) const508 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 
countEntries() const570 size_t AMessage::countEntries() const {
571     return mNumItems;
572 }
573 
getEntryNameAt(size_t index,Type * type) const574 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