blob: 7cc7c41729ae6655ba35d01b6176d3327b4dbdbf [file] [log] [blame]
Andreas Huber72961232010-06-07 10:18:57 -07001/*
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
Lajos Molnar7ea42922014-08-27 09:02:47 -070017#define LOG_TAG "AMessage"
18//#define LOG_NDEBUG 0
19//#define DUMP_STATS
Mark Salyzyn60d02072016-09-29 08:48:48 -070020
21#include <ctype.h>
Lajos Molnar7ea42922014-08-27 09:02:47 -070022
Andreas Huber72961232010-06-07 10:18:57 -070023#include "AMessage.h"
24
Mark Salyzyne74bbf12017-01-12 15:10:27 -080025#include <log/log.h>
Andreas Huberbbc2b822010-07-01 14:11:31 -070026
Andreas Huber72961232010-06-07 10:18:57 -070027#include "AAtomizer.h"
Andreas Huber2d8bedd2012-02-21 14:38:23 -080028#include "ABuffer.h"
Andreas Huber72961232010-06-07 10:18:57 -070029#include "ADebug.h"
30#include "ALooperRoster.h"
Lajos Molnar5804a762015-03-04 17:00:10 -080031#include "AHandler.h"
Andreas Huber72961232010-06-07 10:18:57 -070032#include "AString.h"
33
Andreas Huber84066782011-08-16 09:34:26 -070034#include <media/stagefright/foundation/hexdump.h>
Andreas Huber14acc732010-12-06 10:36:06 -080035
Colin Crossf8b5fe22021-12-15 14:59:00 -080036#if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
Dongwon Kang97a21552019-08-28 11:22:33 -070037#include <binder/Parcel.h>
38#endif
39
Andreas Huber72961232010-06-07 10:18:57 -070040namespace android {
41
Andreas Huber5df775d2011-08-25 16:09:06 -070042extern ALooperRoster gLooperRoster;
43
Lajos Molnar3f274362015-03-05 14:35:41 -080044status_t AReplyToken::setReply(const sp<AMessage> &reply) {
45 if (mReplied) {
46 ALOGE("trying to post a duplicate reply");
47 return -EBUSY;
48 }
49 CHECK(mReply == NULL);
50 mReply = reply;
51 mReplied = true;
52 return OK;
53}
54
Lajos Molnar5804a762015-03-04 17:00:10 -080055AMessage::AMessage(void)
56 : mWhat(0),
Lajos Molnar7ba01f72021-06-27 10:11:49 -070057 mTarget(0) {
Lajos Molnar5804a762015-03-04 17:00:10 -080058}
59
Lajos Molnar5804a762015-03-04 17:00:10 -080060AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
Lajos Molnar7ba01f72021-06-27 10:11:49 -070061 : mWhat(what) {
Lajos Molnar5804a762015-03-04 17:00:10 -080062 setTarget(handler);
Andreas Huber72961232010-06-07 10:18:57 -070063}
64
65AMessage::~AMessage() {
66 clear();
67}
68
69void AMessage::setWhat(uint32_t what) {
70 mWhat = what;
71}
72
73uint32_t AMessage::what() const {
74 return mWhat;
75}
76
Lajos Molnar5804a762015-03-04 17:00:10 -080077void AMessage::setTarget(const sp<const AHandler> &handler) {
78 if (handler == NULL) {
79 mTarget = 0;
80 mHandler.clear();
81 mLooper.clear();
82 } else {
83 mTarget = handler->id();
84 mHandler = handler->getHandler();
85 mLooper = handler->getLooper();
86 }
Andreas Huber72961232010-06-07 10:18:57 -070087}
88
89void AMessage::clear() {
Lajos Molnar7ba01f72021-06-27 10:11:49 -070090 // Item needs to be handled delicately
91 for (Item &item : mItems) {
92 delete[] item.mName;
93 item.mName = NULL;
94 freeItemValue(&item);
Andreas Huber72961232010-06-07 10:18:57 -070095 }
Lajos Molnar7ba01f72021-06-27 10:11:49 -070096 mItems.clear();
Andreas Huber72961232010-06-07 10:18:57 -070097}
98
Lajos Molnar7ea42922014-08-27 09:02:47 -070099void AMessage::freeItemValue(Item *item) {
Andreas Huber72961232010-06-07 10:18:57 -0700100 switch (item->mType) {
101 case kTypeString:
102 {
103 delete item->u.stringValue;
104 break;
105 }
106
107 case kTypeObject:
108 case kTypeMessage:
Andreas Huberbdaa29a2012-03-09 14:33:01 -0800109 case kTypeBuffer:
Andreas Huber72961232010-06-07 10:18:57 -0700110 {
111 if (item->u.refValue != NULL) {
112 item->u.refValue->decStrong(this);
113 }
114 break;
115 }
116
117 default:
118 break;
119 }
Lajos Molnarf2854872018-05-15 20:46:09 -0700120 item->mType = kTypeInt32; // clear type
Andreas Huber72961232010-06-07 10:18:57 -0700121}
122
Lajos Molnar7ea42922014-08-27 09:02:47 -0700123#ifdef DUMP_STATS
124#include <utils/Mutex.h>
Andreas Huber72961232010-06-07 10:18:57 -0700125
Lajos Molnar7ea42922014-08-27 09:02:47 -0700126Mutex gLock;
127static int32_t gFindItemCalls = 1;
128static int32_t gDupCalls = 1;
129static int32_t gAverageNumItems = 0;
130static int32_t gAverageNumChecks = 0;
131static int32_t gAverageNumMemChecks = 0;
132static int32_t gAverageDupItems = 0;
133static int32_t gLastChecked = -1;
134
135static void reportStats() {
136 int32_t time = (ALooper::GetNowUs() / 1000);
137 if (time / 1000 != gLastChecked / 1000) {
138 gLastChecked = time;
139 ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)",
140 gFindItemCalls,
141 gAverageNumItems / (float)gFindItemCalls,
142 gAverageNumChecks / (float)gFindItemCalls,
143 gAverageNumMemChecks / (float)gFindItemCalls,
144 gDupCalls,
145 gAverageDupItems / (float)gDupCalls);
146 gFindItemCalls = gDupCalls = 1;
147 gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0;
148 gLastChecked = time;
Andreas Huber72961232010-06-07 10:18:57 -0700149 }
Lajos Molnar7ea42922014-08-27 09:02:47 -0700150}
151#endif
Andreas Huber72961232010-06-07 10:18:57 -0700152
Lajos Molnar7ea42922014-08-27 09:02:47 -0700153inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
154#ifdef DUMP_STATS
155 size_t memchecks = 0;
156#endif
157 size_t i = 0;
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700158 for (; i < mItems.size(); i++) {
Lajos Molnar7ea42922014-08-27 09:02:47 -0700159 if (len != mItems[i].mNameLength) {
160 continue;
161 }
162#ifdef DUMP_STATS
163 ++memchecks;
164#endif
165 if (!memcmp(mItems[i].mName, name, len)) {
166 break;
167 }
168 }
169#ifdef DUMP_STATS
170 {
171 Mutex::Autolock _l(gLock);
172 ++gFindItemCalls;
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700173 gAverageNumItems += mItems.size();
Lajos Molnar7ea42922014-08-27 09:02:47 -0700174 gAverageNumMemChecks += memchecks;
175 gAverageNumChecks += i;
176 reportStats();
177 }
178#endif
179 return i;
180}
181
182// assumes item's name was uninitialized or NULL
183void AMessage::Item::setName(const char *name, size_t len) {
184 mNameLength = len;
185 mName = new char[len + 1];
186 memcpy((void*)mName, name, len + 1);
187}
188
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700189AMessage::Item::Item(const char *name, size_t len)
190 : mType(kTypeInt32) {
191 // mName and mNameLength are initialized by setName
192 setName(name, len);
193}
194
Lajos Molnar7ea42922014-08-27 09:02:47 -0700195AMessage::Item *AMessage::allocateItem(const char *name) {
196 size_t len = strlen(name);
197 size_t i = findItemIndex(name, len);
Andreas Huber72961232010-06-07 10:18:57 -0700198 Item *item;
199
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700200 if (i < mItems.size()) {
Andreas Huber72961232010-06-07 10:18:57 -0700201 item = &mItems[i];
Lajos Molnar7ea42922014-08-27 09:02:47 -0700202 freeItemValue(item);
Andreas Huber72961232010-06-07 10:18:57 -0700203 } else {
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700204 CHECK(mItems.size() < kMaxNumItems);
205 i = mItems.size();
206 // place a 'blank' item at the end - this is of type kTypeInt32
207 mItems.emplace_back(name, len);
Andreas Huber72961232010-06-07 10:18:57 -0700208 item = &mItems[i];
Andreas Huber72961232010-06-07 10:18:57 -0700209 }
210
211 return item;
212}
213
214const AMessage::Item *AMessage::findItem(
215 const char *name, Type type) const {
Lajos Molnar7ea42922014-08-27 09:02:47 -0700216 size_t i = findItemIndex(name, strlen(name));
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700217 if (i < mItems.size()) {
Andreas Huber72961232010-06-07 10:18:57 -0700218 const Item *item = &mItems[i];
Lajos Molnar7ea42922014-08-27 09:02:47 -0700219 return item->mType == type ? item : NULL;
Andreas Huber72961232010-06-07 10:18:57 -0700220
Andreas Huber72961232010-06-07 10:18:57 -0700221 }
Andreas Huber72961232010-06-07 10:18:57 -0700222 return NULL;
223}
224
Lajos Molnar63a4d502016-07-14 18:16:38 -0700225bool AMessage::findAsFloat(const char *name, float *value) const {
226 size_t i = findItemIndex(name, strlen(name));
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700227 if (i < mItems.size()) {
Lajos Molnar63a4d502016-07-14 18:16:38 -0700228 const Item *item = &mItems[i];
229 switch (item->mType) {
230 case kTypeFloat:
231 *value = item->u.floatValue;
232 return true;
233 case kTypeDouble:
234 *value = (float)item->u.doubleValue;
235 return true;
236 case kTypeInt64:
237 *value = (float)item->u.int64Value;
238 return true;
239 case kTypeInt32:
240 *value = (float)item->u.int32Value;
241 return true;
242 case kTypeSize:
243 *value = (float)item->u.sizeValue;
244 return true;
245 default:
246 return false;
247 }
248 }
249 return false;
250}
251
Lajos Molnar01c10f82017-03-17 14:31:33 -0700252bool AMessage::findAsInt64(const char *name, int64_t *value) const {
253 size_t i = findItemIndex(name, strlen(name));
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700254 if (i < mItems.size()) {
Lajos Molnar01c10f82017-03-17 14:31:33 -0700255 const Item *item = &mItems[i];
256 switch (item->mType) {
257 case kTypeInt64:
Lajos Molnar321218a2017-03-24 16:20:51 -0700258 *value = item->u.int64Value;
Lajos Molnar01c10f82017-03-17 14:31:33 -0700259 return true;
260 case kTypeInt32:
Lajos Molnar321218a2017-03-24 16:20:51 -0700261 *value = item->u.int32Value;
Lajos Molnar01c10f82017-03-17 14:31:33 -0700262 return true;
263 default:
264 return false;
265 }
266 }
267 return false;
268}
269
Lajos Molnar513d9672014-07-15 07:57:52 -0700270bool AMessage::contains(const char *name) const {
Lajos Molnar7ea42922014-08-27 09:02:47 -0700271 size_t i = findItemIndex(name, strlen(name));
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700272 return i < mItems.size();
Lajos Molnar513d9672014-07-15 07:57:52 -0700273}
274
Andreas Huber72961232010-06-07 10:18:57 -0700275#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \
276void AMessage::set##NAME(const char *name, TYPENAME value) { \
277 Item *item = allocateItem(name); \
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700278 if (item) { \
279 item->mType = kType##NAME; \
280 item->u.FIELDNAME = value; \
281 } \
Andreas Huber72961232010-06-07 10:18:57 -0700282} \
283 \
Chih-Hung Hsieh183d3872016-05-17 15:37:39 -0700284/* NOLINT added to avoid incorrect warning/fix from clang.tidy */ \
285bool AMessage::find##NAME(const char *name, TYPENAME *value) const { /* NOLINT */ \
Andreas Huber72961232010-06-07 10:18:57 -0700286 const Item *item = findItem(name, kType##NAME); \
287 if (item) { \
288 *value = item->u.FIELDNAME; \
289 return true; \
290 } \
291 return false; \
292}
293
294BASIC_TYPE(Int32,int32Value,int32_t)
295BASIC_TYPE(Int64,int64Value,int64_t)
296BASIC_TYPE(Size,sizeValue,size_t)
297BASIC_TYPE(Float,floatValue,float)
298BASIC_TYPE(Double,doubleValue,double)
299BASIC_TYPE(Pointer,ptrValue,void *)
300
301#undef BASIC_TYPE
302
303void AMessage::setString(
304 const char *name, const char *s, ssize_t len) {
305 Item *item = allocateItem(name);
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700306 if (item) {
307 item->mType = kTypeString;
308 item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
309 }
Andreas Huber72961232010-06-07 10:18:57 -0700310}
311
Lajos Molnar513d9672014-07-15 07:57:52 -0700312void AMessage::setString(
313 const char *name, const AString &s) {
314 setString(name, s.c_str(), s.size());
315}
316
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800317void AMessage::setObjectInternal(
318 const char *name, const sp<RefBase> &obj, Type type) {
Andreas Huber72961232010-06-07 10:18:57 -0700319 Item *item = allocateItem(name);
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700320 if (item) {
321 item->mType = type;
Andreas Huber72961232010-06-07 10:18:57 -0700322
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700323 if (obj != NULL) { obj->incStrong(this); }
324 item->u.refValue = obj.get();
325 }
Andreas Huber72961232010-06-07 10:18:57 -0700326}
327
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800328void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
329 setObjectInternal(name, obj, kTypeObject);
330}
331
332void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
333 setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
334}
335
Andreas Huber72961232010-06-07 10:18:57 -0700336void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
337 Item *item = allocateItem(name);
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700338 if (item) {
339 item->mType = kTypeMessage;
Andreas Huber72961232010-06-07 10:18:57 -0700340
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700341 if (obj != NULL) { obj->incStrong(this); }
342 item->u.refValue = obj.get();
343 }
Andreas Huber72961232010-06-07 10:18:57 -0700344}
345
Andreas Huber31e25082011-01-10 10:38:31 -0800346void AMessage::setRect(
347 const char *name,
348 int32_t left, int32_t top, int32_t right, int32_t bottom) {
349 Item *item = allocateItem(name);
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700350 if (item) {
351 item->mType = kTypeRect;
Andreas Huber31e25082011-01-10 10:38:31 -0800352
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700353 item->u.rectValue.mLeft = left;
354 item->u.rectValue.mTop = top;
355 item->u.rectValue.mRight = right;
356 item->u.rectValue.mBottom = bottom;
357 }
Andreas Huber31e25082011-01-10 10:38:31 -0800358}
359
Andreas Huber72961232010-06-07 10:18:57 -0700360bool AMessage::findString(const char *name, AString *value) const {
361 const Item *item = findItem(name, kTypeString);
362 if (item) {
363 *value = *item->u.stringValue;
364 return true;
365 }
366 return false;
367}
368
369bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
370 const Item *item = findItem(name, kTypeObject);
371 if (item) {
372 *obj = item->u.refValue;
373 return true;
374 }
375 return false;
376}
377
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800378bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
379 const Item *item = findItem(name, kTypeBuffer);
380 if (item) {
381 *buf = (ABuffer *)(item->u.refValue);
382 return true;
383 }
384 return false;
385}
386
Andreas Huber72961232010-06-07 10:18:57 -0700387bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
388 const Item *item = findItem(name, kTypeMessage);
389 if (item) {
390 *obj = static_cast<AMessage *>(item->u.refValue);
391 return true;
392 }
393 return false;
394}
395
Andreas Huber31e25082011-01-10 10:38:31 -0800396bool AMessage::findRect(
397 const char *name,
398 int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
399 const Item *item = findItem(name, kTypeRect);
400 if (item == NULL) {
401 return false;
402 }
403
404 *left = item->u.rectValue.mLeft;
405 *top = item->u.rectValue.mTop;
406 *right = item->u.rectValue.mRight;
407 *bottom = item->u.rectValue.mBottom;
408
409 return true;
410}
411
Lajos Molnar5804a762015-03-04 17:00:10 -0800412void AMessage::deliver() {
413 sp<AHandler> handler = mHandler.promote();
414 if (handler == NULL) {
415 ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
416 return;
417 }
418
419 handler->deliverMessage(this);
420}
421
422status_t AMessage::post(int64_t delayUs) {
423 sp<ALooper> looper = mLooper.promote();
424 if (looper == NULL) {
425 ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
426 return -ENOENT;
427 }
428
429 looper->post(this, delayUs);
430 return OK;
Andreas Huber72961232010-06-07 10:18:57 -0700431}
432
Brian Lindahl352fec52023-01-17 09:45:36 -0700433status_t AMessage::postUnique(const sp<RefBase> &token, int64_t delayUs) {
434 sp<ALooper> looper = mLooper.promote();
435 if (looper == NULL) {
436 ALOGW("failed to post message as target looper for handler %d is gone.",
437 mTarget);
438 return -ENOENT;
439 }
440
441 return looper->postUnique(this, token, delayUs);
442}
443
Andreas Huber5df775d2011-08-25 16:09:06 -0700444status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800445 sp<ALooper> looper = mLooper.promote();
446 if (looper == NULL) {
447 ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
448 return -ENOENT;
449 }
450
451 sp<AReplyToken> token = looper->createReplyToken();
452 if (token == NULL) {
453 ALOGE("failed to create reply token");
454 return -ENOMEM;
455 }
456 setObject("replyID", token);
457
458 looper->post(this, 0 /* delayUs */);
459 return looper->awaitResponse(token, response);
Andreas Huber5df775d2011-08-25 16:09:06 -0700460}
461
Lajos Molnar3f274362015-03-05 14:35:41 -0800462status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
463 if (replyToken == NULL) {
464 ALOGW("failed to post reply to a NULL token");
465 return -ENOENT;
466 }
467 sp<ALooper> looper = replyToken->getLooper();
468 if (looper == NULL) {
469 ALOGW("failed to post reply as target looper is gone.");
470 return -ENOENT;
471 }
472 return looper->postReply(replyToken, this);
Andreas Huber5df775d2011-08-25 16:09:06 -0700473}
474
Lajos Molnar3f274362015-03-05 14:35:41 -0800475bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
476 sp<RefBase> tmp;
477 bool found = findObject("replyID", &tmp);
Andreas Huber5df775d2011-08-25 16:09:06 -0700478
479 if (!found) {
480 return false;
481 }
482
Lajos Molnar3f274362015-03-05 14:35:41 -0800483 *replyToken = static_cast<AReplyToken *>(tmp.get());
484 tmp.clear();
485 setObject("replyID", tmp);
486 // TODO: delete Object instead of setting it to NULL
Andreas Huber5df775d2011-08-25 16:09:06 -0700487
Lajos Molnar3f274362015-03-05 14:35:41 -0800488 return *replyToken != NULL;
Andreas Huber5df775d2011-08-25 16:09:06 -0700489}
490
Andreas Huber72961232010-06-07 10:18:57 -0700491sp<AMessage> AMessage::dup() const {
Lajos Molnar5804a762015-03-04 17:00:10 -0800492 sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700493 msg->mItems = mItems;
Andreas Huber72961232010-06-07 10:18:57 -0700494
Lajos Molnar7ea42922014-08-27 09:02:47 -0700495#ifdef DUMP_STATS
496 {
497 Mutex::Autolock _l(gLock);
498 ++gDupCalls;
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700499 gAverageDupItems += mItems.size();
Lajos Molnar7ea42922014-08-27 09:02:47 -0700500 reportStats();
501 }
502#endif
503
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700504 for (size_t i = 0; i < mItems.size(); ++i) {
Andreas Huber72961232010-06-07 10:18:57 -0700505 const Item *from = &mItems[i];
506 Item *to = &msg->mItems[i];
507
Lajos Molnar7ea42922014-08-27 09:02:47 -0700508 to->setName(from->mName, from->mNameLength);
Andreas Huber72961232010-06-07 10:18:57 -0700509 to->mType = from->mType;
510
511 switch (from->mType) {
512 case kTypeString:
513 {
514 to->u.stringValue =
515 new AString(*from->u.stringValue);
516 break;
517 }
518
519 case kTypeObject:
Andreas Huberbdaa29a2012-03-09 14:33:01 -0800520 case kTypeBuffer:
Andreas Huber72961232010-06-07 10:18:57 -0700521 {
522 to->u.refValue = from->u.refValue;
523 to->u.refValue->incStrong(msg.get());
524 break;
525 }
526
Andreas Huber2c2814b2010-12-15 17:18:20 -0800527 case kTypeMessage:
528 {
529 sp<AMessage> copy =
530 static_cast<AMessage *>(from->u.refValue)->dup();
531
532 to->u.refValue = copy.get();
533 to->u.refValue->incStrong(msg.get());
534 break;
535 }
536
Andreas Huber72961232010-06-07 10:18:57 -0700537 default:
538 {
539 to->u = from->u;
540 break;
541 }
542 }
543 }
544
545 return msg;
546}
547
Andreas Huberbbc2b822010-07-01 14:11:31 -0700548static void appendIndent(AString *s, int32_t indent) {
549 static const char kWhitespace[] =
550 " "
551 " ";
552
553 CHECK_LT((size_t)indent, sizeof(kWhitespace));
554
555 s->append(kWhitespace, indent);
556}
557
558static bool isFourcc(uint32_t what) {
559 return isprint(what & 0xff)
560 && isprint((what >> 8) & 0xff)
561 && isprint((what >> 16) & 0xff)
562 && isprint((what >> 24) & 0xff);
563}
564
565AString AMessage::debugString(int32_t indent) const {
566 AString s = "AMessage(what = ";
567
568 AString tmp;
569 if (isFourcc(mWhat)) {
Elliott Hughesa1e89442015-02-04 11:54:28 -0800570 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700571 "'%c%c%c%c'",
572 (char)(mWhat >> 24),
573 (char)((mWhat >> 16) & 0xff),
574 (char)((mWhat >> 8) & 0xff),
575 (char)(mWhat & 0xff));
576 } else {
Elliott Hughesa1e89442015-02-04 11:54:28 -0800577 tmp = AStringPrintf("0x%08x", mWhat);
Andreas Huberbbc2b822010-07-01 14:11:31 -0700578 }
579 s.append(tmp);
580
581 if (mTarget != 0) {
Elliott Hughesa1e89442015-02-04 11:54:28 -0800582 tmp = AStringPrintf(", target = %d", mTarget);
Andreas Huberbbc2b822010-07-01 14:11:31 -0700583 s.append(tmp);
584 }
585 s.append(") = {\n");
586
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700587 for (size_t i = 0; i < mItems.size(); ++i) {
Andreas Huberbbc2b822010-07-01 14:11:31 -0700588 const Item &item = mItems[i];
589
590 switch (item.mType) {
591 case kTypeInt32:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800592 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700593 "int32_t %s = %d", item.mName, item.u.int32Value);
594 break;
595 case kTypeInt64:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800596 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700597 "int64_t %s = %lld", item.mName, item.u.int64Value);
598 break;
599 case kTypeSize:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800600 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700601 "size_t %s = %d", item.mName, item.u.sizeValue);
602 break;
603 case kTypeFloat:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800604 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700605 "float %s = %f", item.mName, item.u.floatValue);
606 break;
607 case kTypeDouble:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800608 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700609 "double %s = %f", item.mName, item.u.doubleValue);
610 break;
611 case kTypePointer:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800612 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700613 "void *%s = %p", item.mName, item.u.ptrValue);
614 break;
615 case kTypeString:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800616 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700617 "string %s = \"%s\"",
618 item.mName,
619 item.u.stringValue->c_str());
620 break;
621 case kTypeObject:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800622 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700623 "RefBase *%s = %p", item.mName, item.u.refValue);
624 break;
Andreas Huberbdaa29a2012-03-09 14:33:01 -0800625 case kTypeBuffer:
Andreas Huber84066782011-08-16 09:34:26 -0700626 {
627 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
628
Andy Hungcf31f1e2014-09-23 14:59:01 -0700629 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
Elliott Hughesa1e89442015-02-04 11:54:28 -0800630 tmp = AStringPrintf("Buffer %s = {\n", item.mName);
Andreas Huber84066782011-08-16 09:34:26 -0700631 hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
632 appendIndent(&tmp, indent + 2);
633 tmp.append("}");
634 } else {
Elliott Hughesa1e89442015-02-04 11:54:28 -0800635 tmp = AStringPrintf(
Andreas Huber84066782011-08-16 09:34:26 -0700636 "Buffer *%s = %p", item.mName, buffer.get());
637 }
Andreas Huberbdaa29a2012-03-09 14:33:01 -0800638 break;
Andreas Huber84066782011-08-16 09:34:26 -0700639 }
Andreas Huberbbc2b822010-07-01 14:11:31 -0700640 case kTypeMessage:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800641 tmp = AStringPrintf(
Andreas Huberbbc2b822010-07-01 14:11:31 -0700642 "AMessage %s = %s",
643 item.mName,
644 static_cast<AMessage *>(
645 item.u.refValue)->debugString(
646 indent + strlen(item.mName) + 14).c_str());
647 break;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700648 case kTypeRect:
Elliott Hughesa1e89442015-02-04 11:54:28 -0800649 tmp = AStringPrintf(
Andreas Huber078cfcf2011-09-15 12:25:04 -0700650 "Rect %s(%d, %d, %d, %d)",
651 item.mName,
652 item.u.rectValue.mLeft,
653 item.u.rectValue.mTop,
654 item.u.rectValue.mRight,
655 item.u.rectValue.mBottom);
656 break;
Andreas Huberbbc2b822010-07-01 14:11:31 -0700657 default:
658 TRESPASS();
659 }
660
661 appendIndent(&s, indent);
662 s.append(" ");
663 s.append(tmp);
664 s.append("\n");
665 }
666
667 appendIndent(&s, indent);
668 s.append("}");
669
670 return s;
671}
672
Colin Crossf8b5fe22021-12-15 14:59:00 -0800673#if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
Andreas Huber14acc732010-12-06 10:36:06 -0800674// static
Pawin Vongmasa8dab17302016-05-02 16:08:39 -0700675sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
Andreas Huber14acc732010-12-06 10:36:06 -0800676 int32_t what = parcel.readInt32();
Lajos Molnar5804a762015-03-04 17:00:10 -0800677 sp<AMessage> msg = new AMessage();
678 msg->setWhat(what);
Andreas Huber14acc732010-12-06 10:36:06 -0800679
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700680 size_t numItems = static_cast<size_t>(parcel.readInt32());
681 if (numItems > kMaxNumItems) {
Flankerddd346c2015-09-11 19:05:47 +0800682 ALOGE("Too large number of items clipped.");
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700683 numItems = kMaxNumItems;
Flankerddd346c2015-09-11 19:05:47 +0800684 }
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700685 msg->mItems.resize(numItems);
Flankerddd346c2015-09-11 19:05:47 +0800686
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700687 for (size_t i = 0; i < msg->mItems.size(); ++i) {
Andreas Huber14acc732010-12-06 10:36:06 -0800688 Item *item = &msg->mItems[i];
689
Lajos Molnar7ea42922014-08-27 09:02:47 -0700690 const char *name = parcel.readCString();
Flankerddd346c2015-09-11 19:05:47 +0800691 if (name == NULL) {
692 ALOGE("Failed reading name for an item. Parsing aborted.");
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700693 msg->mItems.resize(i);
Flankerddd346c2015-09-11 19:05:47 +0800694 break;
695 }
Andreas Huber14acc732010-12-06 10:36:06 -0800696
Flankerddd346c2015-09-11 19:05:47 +0800697 item->mType = static_cast<Type>(parcel.readInt32());
698 // setName() happens below so that we don't leak memory when parsing
699 // is aborted in the middle.
Andreas Huber14acc732010-12-06 10:36:06 -0800700 switch (item->mType) {
701 case kTypeInt32:
702 {
703 item->u.int32Value = parcel.readInt32();
704 break;
705 }
706
707 case kTypeInt64:
708 {
709 item->u.int64Value = parcel.readInt64();
710 break;
711 }
712
713 case kTypeSize:
714 {
715 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
716 break;
717 }
718
719 case kTypeFloat:
720 {
721 item->u.floatValue = parcel.readFloat();
722 break;
723 }
724
725 case kTypeDouble:
726 {
727 item->u.doubleValue = parcel.readDouble();
728 break;
729 }
730
731 case kTypeString:
732 {
Flankerddd346c2015-09-11 19:05:47 +0800733 const char *stringValue = parcel.readCString();
734 if (stringValue == NULL) {
735 ALOGE("Failed reading string value from a parcel. "
736 "Parsing aborted.");
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700737 msg->mItems.resize(i);
Flankerddd346c2015-09-11 19:05:47 +0800738 continue;
739 // The loop will terminate subsequently.
740 } else {
741 item->u.stringValue = new AString(stringValue);
742 }
Andreas Huber14acc732010-12-06 10:36:06 -0800743 break;
744 }
745
746 case kTypeMessage:
747 {
Pawin Vongmasa8dab17302016-05-02 16:08:39 -0700748 if (maxNestingLevel == 0) {
749 ALOGE("Too many levels of AMessage nesting.");
750 return NULL;
751 }
752 sp<AMessage> subMsg = AMessage::FromParcel(
753 parcel,
754 maxNestingLevel - 1);
755 if (subMsg == NULL) {
756 // This condition will be triggered when there exists an
757 // object that cannot cross process boundaries or when the
758 // level of nested AMessage is too deep.
759 return NULL;
760 }
Andreas Huber14acc732010-12-06 10:36:06 -0800761 subMsg->incStrong(msg.get());
762
763 item->u.refValue = subMsg.get();
764 break;
765 }
766
767 default:
768 {
Steve Block29357bc2012-01-06 19:20:56 +0000769 ALOGE("This type of object cannot cross process boundaries.");
Pawin Vongmasa8dab17302016-05-02 16:08:39 -0700770 return NULL;
Andreas Huber14acc732010-12-06 10:36:06 -0800771 }
772 }
Flankerddd346c2015-09-11 19:05:47 +0800773
774 item->setName(name, strlen(name));
Andreas Huber14acc732010-12-06 10:36:06 -0800775 }
776
777 return msg;
778}
779
780void AMessage::writeToParcel(Parcel *parcel) const {
781 parcel->writeInt32(static_cast<int32_t>(mWhat));
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700782 parcel->writeInt32(static_cast<int32_t>(mItems.size()));
Andreas Huber14acc732010-12-06 10:36:06 -0800783
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700784 for (const Item &item : mItems) {
Andreas Huber14acc732010-12-06 10:36:06 -0800785 parcel->writeCString(item.mName);
786 parcel->writeInt32(static_cast<int32_t>(item.mType));
787
788 switch (item.mType) {
789 case kTypeInt32:
790 {
791 parcel->writeInt32(item.u.int32Value);
792 break;
793 }
794
795 case kTypeInt64:
796 {
797 parcel->writeInt64(item.u.int64Value);
798 break;
799 }
800
801 case kTypeSize:
802 {
803 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
804 break;
805 }
806
807 case kTypeFloat:
808 {
809 parcel->writeFloat(item.u.floatValue);
810 break;
811 }
812
813 case kTypeDouble:
814 {
815 parcel->writeDouble(item.u.doubleValue);
816 break;
817 }
818
819 case kTypeString:
820 {
821 parcel->writeCString(item.u.stringValue->c_str());
822 break;
823 }
824
825 case kTypeMessage:
826 {
827 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
828 break;
829 }
830
831 default:
832 {
Steve Block29357bc2012-01-06 19:20:56 +0000833 ALOGE("This type of object cannot cross process boundaries.");
Andreas Huber14acc732010-12-06 10:36:06 -0800834 TRESPASS();
835 }
836 }
837 }
838}
Colin Crossf8b5fe22021-12-15 14:59:00 -0800839#endif // defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
Andreas Huber14acc732010-12-06 10:36:06 -0800840
Lajos Molnar1734c7d2016-03-23 12:10:22 -0700841sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
842 if (other == NULL) {
843 return const_cast<AMessage*>(this);
844 }
845
846 sp<AMessage> diff = new AMessage;
847 if (mWhat != other->mWhat) {
848 diff->setWhat(mWhat);
849 }
850 if (mHandler != other->mHandler) {
851 diff->setTarget(mHandler.promote());
852 }
853
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700854 for (const Item &item : mItems) {
Lajos Molnar1734c7d2016-03-23 12:10:22 -0700855 const Item *oitem = other->findItem(item.mName, item.mType);
856 switch (item.mType) {
857 case kTypeInt32:
858 if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
859 diff->setInt32(item.mName, item.u.int32Value);
860 }
861 break;
862
863 case kTypeInt64:
864 if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
865 diff->setInt64(item.mName, item.u.int64Value);
866 }
867 break;
868
869 case kTypeSize:
870 if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
871 diff->setSize(item.mName, item.u.sizeValue);
872 }
873 break;
874
875 case kTypeFloat:
876 if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
877 diff->setFloat(item.mName, item.u.sizeValue);
878 }
879 break;
880
881 case kTypeDouble:
882 if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
883 diff->setDouble(item.mName, item.u.sizeValue);
884 }
885 break;
886
887 case kTypeString:
888 if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
889 diff->setString(item.mName, *item.u.stringValue);
890 }
891 break;
892
893 case kTypeRect:
894 if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
895 diff->setRect(
896 item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
897 item.u.rectValue.mRight, item.u.rectValue.mBottom);
898 }
899 break;
900
901 case kTypePointer:
902 if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
903 diff->setPointer(item.mName, item.u.ptrValue);
904 }
905 break;
906
907 case kTypeBuffer:
908 {
909 sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
910 if (myBuf == NULL) {
911 if (oitem == NULL || oitem->u.refValue != NULL) {
912 diff->setBuffer(item.mName, NULL);
913 }
914 break;
915 }
916 sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
917 if (oBuf == NULL
918 || myBuf->size() != oBuf->size()
919 || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
920 || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
921 diff->setBuffer(item.mName, myBuf);
922 }
923 break;
924 }
925
926 case kTypeMessage:
927 {
928 sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
929 if (myMsg == NULL) {
930 if (oitem == NULL || oitem->u.refValue != NULL) {
931 diff->setMessage(item.mName, NULL);
932 }
933 break;
934 }
935 sp<AMessage> oMsg =
936 oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
937 sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
938 if (changes->countEntries()) {
939 diff->setMessage(item.mName, deep ? changes : myMsg);
940 }
941 break;
942 }
943
944 case kTypeObject:
945 if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
946 diff->setObject(item.mName, item.u.refValue);
947 }
948 break;
949
950 default:
951 {
952 ALOGE("Unknown type %d", item.mType);
953 TRESPASS();
954 }
955 }
956 }
957 return diff;
958}
959
Andreas Huber57788222012-02-21 11:47:18 -0800960size_t AMessage::countEntries() const {
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700961 return mItems.size();
Andreas Huber57788222012-02-21 11:47:18 -0800962}
963
Ray Essickbffe0d62023-03-26 09:14:16 -0500964/* static */
965size_t AMessage::maxAllowedEntries() {
966 return kMaxNumItems;
967}
968
Andreas Huber57788222012-02-21 11:47:18 -0800969const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700970 if (index >= mItems.size()) {
Andreas Huber57788222012-02-21 11:47:18 -0800971 *type = kTypeInt32;
972
973 return NULL;
974 }
975
976 *type = mItems[index].mType;
977
978 return mItems[index].mName;
979}
980
Lajos Molnar81fba532018-05-09 16:49:39 -0700981AMessage::ItemData AMessage::getEntryAt(size_t index) const {
982 ItemData it;
Lajos Molnar7ba01f72021-06-27 10:11:49 -0700983 if (index < mItems.size()) {
Lajos Molnar81fba532018-05-09 16:49:39 -0700984 switch (mItems[index].mType) {
985 case kTypeInt32: it.set(mItems[index].u.int32Value); break;
986 case kTypeInt64: it.set(mItems[index].u.int64Value); break;
987 case kTypeSize: it.set(mItems[index].u.sizeValue); break;
988 case kTypeFloat: it.set(mItems[index].u.floatValue); break;
989 case kTypeDouble: it.set(mItems[index].u.doubleValue); break;
990 case kTypePointer: it.set(mItems[index].u.ptrValue); break;
991 case kTypeRect: it.set(mItems[index].u.rectValue); break;
992 case kTypeString: it.set(*mItems[index].u.stringValue); break;
993 case kTypeObject: {
994 sp<RefBase> obj = mItems[index].u.refValue;
995 it.set(obj);
996 break;
997 }
998 case kTypeMessage: {
999 sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
1000 it.set(msg);
1001 break;
1002 }
1003 case kTypeBuffer: {
1004 sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
1005 it.set(buf);
1006 break;
1007 }
1008 default:
1009 break;
1010 }
1011 }
1012 return it;
1013}
1014
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001015status_t AMessage::setEntryNameAt(size_t index, const char *name) {
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001016 if (index >= mItems.size()) {
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001017 return BAD_INDEX;
1018 }
1019 if (name == nullptr) {
1020 return BAD_VALUE;
1021 }
1022 if (!strcmp(name, mItems[index].mName)) {
1023 return OK; // name has not changed
1024 }
1025 size_t len = strlen(name);
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001026 if (findItemIndex(name, len) < mItems.size()) {
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001027 return ALREADY_EXISTS;
1028 }
1029 delete[] mItems[index].mName;
1030 mItems[index].mName = nullptr;
1031 mItems[index].setName(name, len);
1032 return OK;
1033}
1034
Lajos Molnar81fba532018-05-09 16:49:39 -07001035status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
1036 AString stringValue;
1037 sp<RefBase> refValue;
1038 sp<AMessage> msgValue;
1039 sp<ABuffer> bufValue;
1040
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001041 if (index >= mItems.size()) {
Lajos Molnar81fba532018-05-09 16:49:39 -07001042 return BAD_INDEX;
1043 }
1044 if (!item.used()) {
1045 return BAD_VALUE;
1046 }
1047 Item *dst = &mItems[index];
1048 freeItemValue(dst);
1049
1050 // some values can be directly set with the getter. others need items to be allocated
1051 if (item.find(&dst->u.int32Value)) {
1052 dst->mType = kTypeInt32;
1053 } else if (item.find(&dst->u.int64Value)) {
1054 dst->mType = kTypeInt64;
1055 } else if (item.find(&dst->u.sizeValue)) {
1056 dst->mType = kTypeSize;
1057 } else if (item.find(&dst->u.floatValue)) {
1058 dst->mType = kTypeFloat;
1059 } else if (item.find(&dst->u.doubleValue)) {
1060 dst->mType = kTypeDouble;
1061 } else if (item.find(&dst->u.ptrValue)) {
1062 dst->mType = kTypePointer;
1063 } else if (item.find(&dst->u.rectValue)) {
1064 dst->mType = kTypeRect;
1065 } else if (item.find(&stringValue)) {
1066 dst->u.stringValue = new AString(stringValue);
1067 dst->mType = kTypeString;
1068 } else if (item.find(&refValue)) {
1069 if (refValue != NULL) { refValue->incStrong(this); }
1070 dst->u.refValue = refValue.get();
1071 dst->mType = kTypeObject;
1072 } else if (item.find(&msgValue)) {
1073 if (msgValue != NULL) { msgValue->incStrong(this); }
1074 dst->u.refValue = msgValue.get();
1075 dst->mType = kTypeMessage;
1076 } else if (item.find(&bufValue)) {
1077 if (bufValue != NULL) { bufValue->incStrong(this); }
1078 dst->u.refValue = bufValue.get();
1079 dst->mType = kTypeBuffer;
1080 } else {
1081 // unsupported item - we should not be here.
1082 dst->mType = kTypeInt32;
1083 dst->u.int32Value = 0xDEADDEAD;
1084 return BAD_TYPE;
1085 }
1086 return OK;
1087}
1088
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001089status_t AMessage::removeEntryAt(size_t index) {
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001090 if (index >= mItems.size()) {
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001091 return BAD_INDEX;
1092 }
1093 // delete entry data and objects
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001094 delete[] mItems[index].mName;
1095 mItems[index].mName = nullptr;
1096 freeItemValue(&mItems[index]);
1097
1098 // swap entry with last entry and clear last entry's data
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001099 size_t lastIndex = mItems.size() - 1;
1100 if (index < lastIndex) {
1101 mItems[index] = mItems[lastIndex];
1102 mItems[lastIndex].mName = nullptr;
1103 mItems[lastIndex].mType = kTypeInt32;
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001104 }
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001105 mItems.pop_back();
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001106 return OK;
1107}
1108
Ray Essickc77a9622021-03-15 15:07:48 -07001109status_t AMessage::removeEntryByName(const char *name) {
1110 if (name == nullptr) {
1111 return BAD_VALUE;
1112 }
1113 size_t index = findEntryByName(name);
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001114 if (index >= mItems.size()) {
Ray Essickc77a9622021-03-15 15:07:48 -07001115 return BAD_INDEX;
1116 }
1117 return removeEntryAt(index);
1118}
1119
Lajos Molnar81fba532018-05-09 16:49:39 -07001120void AMessage::setItem(const char *name, const ItemData &item) {
1121 if (item.used()) {
1122 Item *it = allocateItem(name);
1123 if (it != nullptr) {
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001124 setEntryAt(it - &mItems[0], item);
Lajos Molnar81fba532018-05-09 16:49:39 -07001125 }
1126 }
1127}
1128
1129AMessage::ItemData AMessage::findItem(const char *name) const {
1130 return getEntryAt(findEntryByName(name));
1131}
1132
1133void AMessage::extend(const sp<AMessage> &other) {
1134 // ignore null messages
1135 if (other == nullptr) {
1136 return;
1137 }
1138
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001139 for (size_t ix = 0; ix < other->mItems.size(); ++ix) {
Lajos Molnar81fba532018-05-09 16:49:39 -07001140 Item *it = allocateItem(other->mItems[ix].mName);
1141 if (it != nullptr) {
1142 ItemData data = other->getEntryAt(ix);
Lajos Molnar7ba01f72021-06-27 10:11:49 -07001143 setEntryAt(it - &mItems[0], data);
Lajos Molnar81fba532018-05-09 16:49:39 -07001144 }
1145 }
1146}
1147
Lajos Molnar1cc95d82018-04-04 16:42:40 -07001148size_t AMessage::findEntryByName(const char *name) const {
1149 return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
1150}
1151
Andreas Huber72961232010-06-07 10:18:57 -07001152} // namespace android