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
AMessage(uint32_t what,ALooper::handler_id target)34 AMessage::AMessage(uint32_t what, ALooper::handler_id target)
35 : mWhat(what),
36 mTarget(target),
37 mNumItems(0) {
38 }
39
~AMessage()40 AMessage::~AMessage() {
41 clear();
42 }
43
setWhat(uint32_t what)44 void AMessage::setWhat(uint32_t what) {
45 mWhat = what;
46 }
47
what() const48 uint32_t AMessage::what() const {
49 return mWhat;
50 }
51
setTarget(ALooper::handler_id handlerID)52 void AMessage::setTarget(ALooper::handler_id handlerID) {
53 mTarget = handlerID;
54 }
55
target() const56 ALooper::handler_id AMessage::target() const {
57 return mTarget;
58 }
59
clear()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
freeItem(Item * item)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
allocateItem(const char * name)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
findItem(const char * name,Type type) const115 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
BASIC_TYPE(Int32,int32Value,int32_t)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
setObjectInternal(const char * name,const sp<RefBase> & obj,Type type)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
setObject(const char * name,const sp<RefBase> & obj)172 void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
173 setObjectInternal(name, obj, kTypeObject);
174 }
175
setBuffer(const char * name,const sp<ABuffer> & buffer)176 void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
177 setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
178 }
179
setMessage(const char * name,const sp<AMessage> & obj)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
setRect(const char * name,int32_t left,int32_t top,int32_t right,int32_t bottom)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
findString(const char * name,AString * value) const200 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
findObject(const char * name,sp<RefBase> * obj) const209 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
findBuffer(const char * name,sp<ABuffer> * buf) const218 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
findMessage(const char * name,sp<AMessage> * obj) const227 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
findRect(const char * name,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom) const236 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
post(int64_t delayUs)252 void AMessage::post(int64_t delayUs) {
253 gLooperRoster.postMessage(this, delayUs);
254 }
255
postAndAwaitResponse(sp<AMessage> * response)256 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
257 return gLooperRoster.postAndAwaitResponse(this, response);
258 }
259
postReply(uint32_t replyID)260 void AMessage::postReply(uint32_t replyID) {
261 gLooperRoster.postReply(replyID, this);
262 }
263
senderAwaitsResponse(uint32_t * replyID) const264 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
dup() const277 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
appendIndent(AString * s,int32_t indent)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
isFourcc(uint32_t what)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
debugString(int32_t indent) const342 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
FromParcel(const Parcel & parcel)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
writeToParcel(Parcel * parcel) const520 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
countEntries() const582 size_t AMessage::countEntries() const {
583 return mNumItems;
584 }
585
getEntryNameAt(size_t index,Type * type) const586 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