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