xref: /aosp_15_r20/frameworks/av/media/module/foundation/AMessage.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AMessage"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker //#define DUMP_STATS
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <ctype.h>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include "AMessage.h"
24*ec779b8eSAndroid Build Coastguard Worker 
25*ec779b8eSAndroid Build Coastguard Worker #include <log/log.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker #include "AAtomizer.h"
28*ec779b8eSAndroid Build Coastguard Worker #include "ABuffer.h"
29*ec779b8eSAndroid Build Coastguard Worker #include "ADebug.h"
30*ec779b8eSAndroid Build Coastguard Worker #include "ALooperRoster.h"
31*ec779b8eSAndroid Build Coastguard Worker #include "AHandler.h"
32*ec779b8eSAndroid Build Coastguard Worker #include "AString.h"
33*ec779b8eSAndroid Build Coastguard Worker 
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/hexdump.h>
35*ec779b8eSAndroid Build Coastguard Worker 
36*ec779b8eSAndroid Build Coastguard Worker #if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
37*ec779b8eSAndroid Build Coastguard Worker #include <binder/Parcel.h>
38*ec779b8eSAndroid Build Coastguard Worker #endif
39*ec779b8eSAndroid Build Coastguard Worker 
40*ec779b8eSAndroid Build Coastguard Worker namespace android {
41*ec779b8eSAndroid Build Coastguard Worker 
42*ec779b8eSAndroid Build Coastguard Worker extern ALooperRoster gLooperRoster;
43*ec779b8eSAndroid Build Coastguard Worker 
setReply(const sp<AMessage> & reply)44*ec779b8eSAndroid Build Coastguard Worker status_t AReplyToken::setReply(const sp<AMessage> &reply) {
45*ec779b8eSAndroid Build Coastguard Worker     if (mReplied) {
46*ec779b8eSAndroid Build Coastguard Worker         ALOGE("trying to post a duplicate reply");
47*ec779b8eSAndroid Build Coastguard Worker         return -EBUSY;
48*ec779b8eSAndroid Build Coastguard Worker     }
49*ec779b8eSAndroid Build Coastguard Worker     CHECK(mReply == NULL);
50*ec779b8eSAndroid Build Coastguard Worker     mReply = reply;
51*ec779b8eSAndroid Build Coastguard Worker     mReplied = true;
52*ec779b8eSAndroid Build Coastguard Worker     return OK;
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker 
AMessage(void)55*ec779b8eSAndroid Build Coastguard Worker AMessage::AMessage(void)
56*ec779b8eSAndroid Build Coastguard Worker     : mWhat(0),
57*ec779b8eSAndroid Build Coastguard Worker       mTarget(0) {
58*ec779b8eSAndroid Build Coastguard Worker }
59*ec779b8eSAndroid Build Coastguard Worker 
AMessage(uint32_t what,const sp<const AHandler> & handler)60*ec779b8eSAndroid Build Coastguard Worker AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
61*ec779b8eSAndroid Build Coastguard Worker     : mWhat(what) {
62*ec779b8eSAndroid Build Coastguard Worker     setTarget(handler);
63*ec779b8eSAndroid Build Coastguard Worker }
64*ec779b8eSAndroid Build Coastguard Worker 
~AMessage()65*ec779b8eSAndroid Build Coastguard Worker AMessage::~AMessage() {
66*ec779b8eSAndroid Build Coastguard Worker     clear();
67*ec779b8eSAndroid Build Coastguard Worker }
68*ec779b8eSAndroid Build Coastguard Worker 
setWhat(uint32_t what)69*ec779b8eSAndroid Build Coastguard Worker void AMessage::setWhat(uint32_t what) {
70*ec779b8eSAndroid Build Coastguard Worker     mWhat = what;
71*ec779b8eSAndroid Build Coastguard Worker }
72*ec779b8eSAndroid Build Coastguard Worker 
what() const73*ec779b8eSAndroid Build Coastguard Worker uint32_t AMessage::what() const {
74*ec779b8eSAndroid Build Coastguard Worker     return mWhat;
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker 
setTarget(const sp<const AHandler> & handler)77*ec779b8eSAndroid Build Coastguard Worker void AMessage::setTarget(const sp<const AHandler> &handler) {
78*ec779b8eSAndroid Build Coastguard Worker     if (handler == NULL) {
79*ec779b8eSAndroid Build Coastguard Worker         mTarget = 0;
80*ec779b8eSAndroid Build Coastguard Worker         mHandler.clear();
81*ec779b8eSAndroid Build Coastguard Worker         mLooper.clear();
82*ec779b8eSAndroid Build Coastguard Worker     } else {
83*ec779b8eSAndroid Build Coastguard Worker         mTarget = handler->id();
84*ec779b8eSAndroid Build Coastguard Worker         mHandler = handler->getHandler();
85*ec779b8eSAndroid Build Coastguard Worker         mLooper = handler->getLooper();
86*ec779b8eSAndroid Build Coastguard Worker     }
87*ec779b8eSAndroid Build Coastguard Worker }
88*ec779b8eSAndroid Build Coastguard Worker 
clear()89*ec779b8eSAndroid Build Coastguard Worker void AMessage::clear() {
90*ec779b8eSAndroid Build Coastguard Worker     // Item needs to be handled delicately
91*ec779b8eSAndroid Build Coastguard Worker     for (Item &item : mItems) {
92*ec779b8eSAndroid Build Coastguard Worker         delete[] item.mName;
93*ec779b8eSAndroid Build Coastguard Worker         item.mName = NULL;
94*ec779b8eSAndroid Build Coastguard Worker         freeItemValue(&item);
95*ec779b8eSAndroid Build Coastguard Worker     }
96*ec779b8eSAndroid Build Coastguard Worker     mItems.clear();
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker 
freeItemValue(Item * item)99*ec779b8eSAndroid Build Coastguard Worker void AMessage::freeItemValue(Item *item) {
100*ec779b8eSAndroid Build Coastguard Worker     switch (item->mType) {
101*ec779b8eSAndroid Build Coastguard Worker         case kTypeString:
102*ec779b8eSAndroid Build Coastguard Worker         {
103*ec779b8eSAndroid Build Coastguard Worker             delete item->u.stringValue;
104*ec779b8eSAndroid Build Coastguard Worker             break;
105*ec779b8eSAndroid Build Coastguard Worker         }
106*ec779b8eSAndroid Build Coastguard Worker 
107*ec779b8eSAndroid Build Coastguard Worker         case kTypeObject:
108*ec779b8eSAndroid Build Coastguard Worker         case kTypeMessage:
109*ec779b8eSAndroid Build Coastguard Worker         case kTypeBuffer:
110*ec779b8eSAndroid Build Coastguard Worker         {
111*ec779b8eSAndroid Build Coastguard Worker             if (item->u.refValue != NULL) {
112*ec779b8eSAndroid Build Coastguard Worker                 item->u.refValue->decStrong(this);
113*ec779b8eSAndroid Build Coastguard Worker             }
114*ec779b8eSAndroid Build Coastguard Worker             break;
115*ec779b8eSAndroid Build Coastguard Worker         }
116*ec779b8eSAndroid Build Coastguard Worker 
117*ec779b8eSAndroid Build Coastguard Worker         default:
118*ec779b8eSAndroid Build Coastguard Worker             break;
119*ec779b8eSAndroid Build Coastguard Worker     }
120*ec779b8eSAndroid Build Coastguard Worker     item->mType = kTypeInt32; // clear type
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker 
123*ec779b8eSAndroid Build Coastguard Worker #ifdef DUMP_STATS
124*ec779b8eSAndroid Build Coastguard Worker #include <utils/Mutex.h>
125*ec779b8eSAndroid Build Coastguard Worker 
126*ec779b8eSAndroid Build Coastguard Worker Mutex gLock;
127*ec779b8eSAndroid Build Coastguard Worker static int32_t gFindItemCalls = 1;
128*ec779b8eSAndroid Build Coastguard Worker static int32_t gDupCalls = 1;
129*ec779b8eSAndroid Build Coastguard Worker static int32_t gAverageNumItems = 0;
130*ec779b8eSAndroid Build Coastguard Worker static int32_t gAverageNumChecks = 0;
131*ec779b8eSAndroid Build Coastguard Worker static int32_t gAverageNumMemChecks = 0;
132*ec779b8eSAndroid Build Coastguard Worker static int32_t gAverageDupItems = 0;
133*ec779b8eSAndroid Build Coastguard Worker static int32_t gLastChecked = -1;
134*ec779b8eSAndroid Build Coastguard Worker 
reportStats()135*ec779b8eSAndroid Build Coastguard Worker static void reportStats() {
136*ec779b8eSAndroid Build Coastguard Worker     int32_t time = (ALooper::GetNowUs() / 1000);
137*ec779b8eSAndroid Build Coastguard Worker     if (time / 1000 != gLastChecked / 1000) {
138*ec779b8eSAndroid Build Coastguard Worker         gLastChecked = time;
139*ec779b8eSAndroid Build Coastguard Worker         ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)",
140*ec779b8eSAndroid Build Coastguard Worker                 gFindItemCalls,
141*ec779b8eSAndroid Build Coastguard Worker                 gAverageNumItems / (float)gFindItemCalls,
142*ec779b8eSAndroid Build Coastguard Worker                 gAverageNumChecks / (float)gFindItemCalls,
143*ec779b8eSAndroid Build Coastguard Worker                 gAverageNumMemChecks / (float)gFindItemCalls,
144*ec779b8eSAndroid Build Coastguard Worker                 gDupCalls,
145*ec779b8eSAndroid Build Coastguard Worker                 gAverageDupItems / (float)gDupCalls);
146*ec779b8eSAndroid Build Coastguard Worker         gFindItemCalls = gDupCalls = 1;
147*ec779b8eSAndroid Build Coastguard Worker         gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0;
148*ec779b8eSAndroid Build Coastguard Worker         gLastChecked = time;
149*ec779b8eSAndroid Build Coastguard Worker     }
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker #endif
152*ec779b8eSAndroid Build Coastguard Worker 
findItemIndex(const char * name,size_t len) const153*ec779b8eSAndroid Build Coastguard Worker inline size_t AMessage::findItemIndex(const char *name, size_t len) const {
154*ec779b8eSAndroid Build Coastguard Worker #ifdef DUMP_STATS
155*ec779b8eSAndroid Build Coastguard Worker     size_t memchecks = 0;
156*ec779b8eSAndroid Build Coastguard Worker #endif
157*ec779b8eSAndroid Build Coastguard Worker     size_t i = 0;
158*ec779b8eSAndroid Build Coastguard Worker     for (; i < mItems.size(); i++) {
159*ec779b8eSAndroid Build Coastguard Worker         if (len != mItems[i].mNameLength) {
160*ec779b8eSAndroid Build Coastguard Worker             continue;
161*ec779b8eSAndroid Build Coastguard Worker         }
162*ec779b8eSAndroid Build Coastguard Worker #ifdef DUMP_STATS
163*ec779b8eSAndroid Build Coastguard Worker         ++memchecks;
164*ec779b8eSAndroid Build Coastguard Worker #endif
165*ec779b8eSAndroid Build Coastguard Worker         if (!memcmp(mItems[i].mName, name, len)) {
166*ec779b8eSAndroid Build Coastguard Worker             break;
167*ec779b8eSAndroid Build Coastguard Worker         }
168*ec779b8eSAndroid Build Coastguard Worker     }
169*ec779b8eSAndroid Build Coastguard Worker #ifdef DUMP_STATS
170*ec779b8eSAndroid Build Coastguard Worker     {
171*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock _l(gLock);
172*ec779b8eSAndroid Build Coastguard Worker         ++gFindItemCalls;
173*ec779b8eSAndroid Build Coastguard Worker         gAverageNumItems += mItems.size();
174*ec779b8eSAndroid Build Coastguard Worker         gAverageNumMemChecks += memchecks;
175*ec779b8eSAndroid Build Coastguard Worker         gAverageNumChecks += i;
176*ec779b8eSAndroid Build Coastguard Worker         reportStats();
177*ec779b8eSAndroid Build Coastguard Worker     }
178*ec779b8eSAndroid Build Coastguard Worker #endif
179*ec779b8eSAndroid Build Coastguard Worker     return i;
180*ec779b8eSAndroid Build Coastguard Worker }
181*ec779b8eSAndroid Build Coastguard Worker 
182*ec779b8eSAndroid Build Coastguard Worker // assumes item's name was uninitialized or NULL
setName(const char * name,size_t len)183*ec779b8eSAndroid Build Coastguard Worker void AMessage::Item::setName(const char *name, size_t len) {
184*ec779b8eSAndroid Build Coastguard Worker     mNameLength = len;
185*ec779b8eSAndroid Build Coastguard Worker     mName = new char[len + 1];
186*ec779b8eSAndroid Build Coastguard Worker     memcpy((void*)mName, name, len + 1);
187*ec779b8eSAndroid Build Coastguard Worker }
188*ec779b8eSAndroid Build Coastguard Worker 
Item(const char * name,size_t len)189*ec779b8eSAndroid Build Coastguard Worker AMessage::Item::Item(const char *name, size_t len)
190*ec779b8eSAndroid Build Coastguard Worker     : mType(kTypeInt32) {
191*ec779b8eSAndroid Build Coastguard Worker     // mName and mNameLength are initialized by setName
192*ec779b8eSAndroid Build Coastguard Worker     setName(name, len);
193*ec779b8eSAndroid Build Coastguard Worker }
194*ec779b8eSAndroid Build Coastguard Worker 
allocateItem(const char * name)195*ec779b8eSAndroid Build Coastguard Worker AMessage::Item *AMessage::allocateItem(const char *name) {
196*ec779b8eSAndroid Build Coastguard Worker     size_t len = strlen(name);
197*ec779b8eSAndroid Build Coastguard Worker     size_t i = findItemIndex(name, len);
198*ec779b8eSAndroid Build Coastguard Worker     Item *item;
199*ec779b8eSAndroid Build Coastguard Worker 
200*ec779b8eSAndroid Build Coastguard Worker     if (i < mItems.size()) {
201*ec779b8eSAndroid Build Coastguard Worker         item = &mItems[i];
202*ec779b8eSAndroid Build Coastguard Worker         freeItemValue(item);
203*ec779b8eSAndroid Build Coastguard Worker     } else {
204*ec779b8eSAndroid Build Coastguard Worker         CHECK(mItems.size() < kMaxNumItems);
205*ec779b8eSAndroid Build Coastguard Worker         i = mItems.size();
206*ec779b8eSAndroid Build Coastguard Worker         // place a 'blank' item at the end - this is of type kTypeInt32
207*ec779b8eSAndroid Build Coastguard Worker         mItems.emplace_back(name, len);
208*ec779b8eSAndroid Build Coastguard Worker         item = &mItems[i];
209*ec779b8eSAndroid Build Coastguard Worker     }
210*ec779b8eSAndroid Build Coastguard Worker 
211*ec779b8eSAndroid Build Coastguard Worker     return item;
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker 
findItem(const char * name,Type type) const214*ec779b8eSAndroid Build Coastguard Worker const AMessage::Item *AMessage::findItem(
215*ec779b8eSAndroid Build Coastguard Worker         const char *name, Type type) const {
216*ec779b8eSAndroid Build Coastguard Worker     size_t i = findItemIndex(name, strlen(name));
217*ec779b8eSAndroid Build Coastguard Worker     if (i < mItems.size()) {
218*ec779b8eSAndroid Build Coastguard Worker         const Item *item = &mItems[i];
219*ec779b8eSAndroid Build Coastguard Worker         return item->mType == type ? item : NULL;
220*ec779b8eSAndroid Build Coastguard Worker 
221*ec779b8eSAndroid Build Coastguard Worker     }
222*ec779b8eSAndroid Build Coastguard Worker     return NULL;
223*ec779b8eSAndroid Build Coastguard Worker }
224*ec779b8eSAndroid Build Coastguard Worker 
findAsFloat(const char * name,float * value) const225*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findAsFloat(const char *name, float *value) const {
226*ec779b8eSAndroid Build Coastguard Worker     size_t i = findItemIndex(name, strlen(name));
227*ec779b8eSAndroid Build Coastguard Worker     if (i < mItems.size()) {
228*ec779b8eSAndroid Build Coastguard Worker         const Item *item = &mItems[i];
229*ec779b8eSAndroid Build Coastguard Worker         switch (item->mType) {
230*ec779b8eSAndroid Build Coastguard Worker             case kTypeFloat:
231*ec779b8eSAndroid Build Coastguard Worker                 *value = item->u.floatValue;
232*ec779b8eSAndroid Build Coastguard Worker                 return true;
233*ec779b8eSAndroid Build Coastguard Worker             case kTypeDouble:
234*ec779b8eSAndroid Build Coastguard Worker                 *value = (float)item->u.doubleValue;
235*ec779b8eSAndroid Build Coastguard Worker                 return true;
236*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:
237*ec779b8eSAndroid Build Coastguard Worker                 *value = (float)item->u.int64Value;
238*ec779b8eSAndroid Build Coastguard Worker                 return true;
239*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:
240*ec779b8eSAndroid Build Coastguard Worker                 *value = (float)item->u.int32Value;
241*ec779b8eSAndroid Build Coastguard Worker                 return true;
242*ec779b8eSAndroid Build Coastguard Worker             case kTypeSize:
243*ec779b8eSAndroid Build Coastguard Worker                 *value = (float)item->u.sizeValue;
244*ec779b8eSAndroid Build Coastguard Worker                 return true;
245*ec779b8eSAndroid Build Coastguard Worker             default:
246*ec779b8eSAndroid Build Coastguard Worker                 return false;
247*ec779b8eSAndroid Build Coastguard Worker         }
248*ec779b8eSAndroid Build Coastguard Worker     }
249*ec779b8eSAndroid Build Coastguard Worker     return false;
250*ec779b8eSAndroid Build Coastguard Worker }
251*ec779b8eSAndroid Build Coastguard Worker 
findAsInt64(const char * name,int64_t * value) const252*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findAsInt64(const char *name, int64_t *value) const {
253*ec779b8eSAndroid Build Coastguard Worker     size_t i = findItemIndex(name, strlen(name));
254*ec779b8eSAndroid Build Coastguard Worker     if (i < mItems.size()) {
255*ec779b8eSAndroid Build Coastguard Worker         const Item *item = &mItems[i];
256*ec779b8eSAndroid Build Coastguard Worker         switch (item->mType) {
257*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:
258*ec779b8eSAndroid Build Coastguard Worker                 *value = item->u.int64Value;
259*ec779b8eSAndroid Build Coastguard Worker                 return true;
260*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:
261*ec779b8eSAndroid Build Coastguard Worker                 *value = item->u.int32Value;
262*ec779b8eSAndroid Build Coastguard Worker                 return true;
263*ec779b8eSAndroid Build Coastguard Worker             default:
264*ec779b8eSAndroid Build Coastguard Worker                 return false;
265*ec779b8eSAndroid Build Coastguard Worker         }
266*ec779b8eSAndroid Build Coastguard Worker     }
267*ec779b8eSAndroid Build Coastguard Worker     return false;
268*ec779b8eSAndroid Build Coastguard Worker }
269*ec779b8eSAndroid Build Coastguard Worker 
contains(const char * name) const270*ec779b8eSAndroid Build Coastguard Worker bool AMessage::contains(const char *name) const {
271*ec779b8eSAndroid Build Coastguard Worker     size_t i = findItemIndex(name, strlen(name));
272*ec779b8eSAndroid Build Coastguard Worker     return i < mItems.size();
273*ec779b8eSAndroid Build Coastguard Worker }
274*ec779b8eSAndroid Build Coastguard Worker 
275*ec779b8eSAndroid Build Coastguard Worker #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
276*ec779b8eSAndroid Build Coastguard Worker void AMessage::set##NAME(const char *name, TYPENAME value) {            \
277*ec779b8eSAndroid Build Coastguard Worker     Item *item = allocateItem(name);                                    \
278*ec779b8eSAndroid Build Coastguard Worker     if (item) {                                                         \
279*ec779b8eSAndroid Build Coastguard Worker         item->mType = kType##NAME;                                      \
280*ec779b8eSAndroid Build Coastguard Worker         item->u.FIELDNAME = value;                                      \
281*ec779b8eSAndroid Build Coastguard Worker     }                                                                   \
282*ec779b8eSAndroid Build Coastguard Worker }                                                                       \
283*ec779b8eSAndroid Build Coastguard Worker                                                                         \
284*ec779b8eSAndroid Build Coastguard Worker /* NOLINT added to avoid incorrect warning/fix from clang.tidy */       \
285*ec779b8eSAndroid Build Coastguard Worker bool AMessage::find##NAME(const char *name, TYPENAME *value) const {  /* NOLINT */ \
286*ec779b8eSAndroid Build Coastguard Worker     const Item *item = findItem(name, kType##NAME);                     \
287*ec779b8eSAndroid Build Coastguard Worker     if (item) {                                                         \
288*ec779b8eSAndroid Build Coastguard Worker         *value = item->u.FIELDNAME;                                     \
289*ec779b8eSAndroid Build Coastguard Worker         return true;                                                    \
290*ec779b8eSAndroid Build Coastguard Worker     }                                                                   \
291*ec779b8eSAndroid Build Coastguard Worker     return false;                                                       \
292*ec779b8eSAndroid Build Coastguard Worker }
293*ec779b8eSAndroid Build Coastguard Worker 
BASIC_TYPE(Int32,int32Value,int32_t)294*ec779b8eSAndroid Build Coastguard Worker BASIC_TYPE(Int32,int32Value,int32_t)
295*ec779b8eSAndroid Build Coastguard Worker BASIC_TYPE(Int64,int64Value,int64_t)
296*ec779b8eSAndroid Build Coastguard Worker BASIC_TYPE(Size,sizeValue,size_t)
297*ec779b8eSAndroid Build Coastguard Worker BASIC_TYPE(Float,floatValue,float)
298*ec779b8eSAndroid Build Coastguard Worker BASIC_TYPE(Double,doubleValue,double)
299*ec779b8eSAndroid Build Coastguard Worker BASIC_TYPE(Pointer,ptrValue,void *)
300*ec779b8eSAndroid Build Coastguard Worker 
301*ec779b8eSAndroid Build Coastguard Worker #undef BASIC_TYPE
302*ec779b8eSAndroid Build Coastguard Worker 
303*ec779b8eSAndroid Build Coastguard Worker void AMessage::setString(
304*ec779b8eSAndroid Build Coastguard Worker         const char *name, const char *s, ssize_t len) {
305*ec779b8eSAndroid Build Coastguard Worker     Item *item = allocateItem(name);
306*ec779b8eSAndroid Build Coastguard Worker     if (item) {
307*ec779b8eSAndroid Build Coastguard Worker         item->mType = kTypeString;
308*ec779b8eSAndroid Build Coastguard Worker         item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
309*ec779b8eSAndroid Build Coastguard Worker     }
310*ec779b8eSAndroid Build Coastguard Worker }
311*ec779b8eSAndroid Build Coastguard Worker 
setString(const char * name,const AString & s)312*ec779b8eSAndroid Build Coastguard Worker void AMessage::setString(
313*ec779b8eSAndroid Build Coastguard Worker         const char *name, const AString &s) {
314*ec779b8eSAndroid Build Coastguard Worker     setString(name, s.c_str(), s.size());
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker 
setObjectInternal(const char * name,const sp<RefBase> & obj,Type type)317*ec779b8eSAndroid Build Coastguard Worker void AMessage::setObjectInternal(
318*ec779b8eSAndroid Build Coastguard Worker         const char *name, const sp<RefBase> &obj, Type type) {
319*ec779b8eSAndroid Build Coastguard Worker     Item *item = allocateItem(name);
320*ec779b8eSAndroid Build Coastguard Worker     if (item) {
321*ec779b8eSAndroid Build Coastguard Worker         item->mType = type;
322*ec779b8eSAndroid Build Coastguard Worker 
323*ec779b8eSAndroid Build Coastguard Worker         if (obj != NULL) { obj->incStrong(this); }
324*ec779b8eSAndroid Build Coastguard Worker         item->u.refValue = obj.get();
325*ec779b8eSAndroid Build Coastguard Worker     }
326*ec779b8eSAndroid Build Coastguard Worker }
327*ec779b8eSAndroid Build Coastguard Worker 
setObject(const char * name,const sp<RefBase> & obj)328*ec779b8eSAndroid Build Coastguard Worker void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
329*ec779b8eSAndroid Build Coastguard Worker     setObjectInternal(name, obj, kTypeObject);
330*ec779b8eSAndroid Build Coastguard Worker }
331*ec779b8eSAndroid Build Coastguard Worker 
setBuffer(const char * name,const sp<ABuffer> & buffer)332*ec779b8eSAndroid Build Coastguard Worker void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
333*ec779b8eSAndroid Build Coastguard Worker     setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
334*ec779b8eSAndroid Build Coastguard Worker }
335*ec779b8eSAndroid Build Coastguard Worker 
setMessage(const char * name,const sp<AMessage> & obj)336*ec779b8eSAndroid Build Coastguard Worker void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
337*ec779b8eSAndroid Build Coastguard Worker     Item *item = allocateItem(name);
338*ec779b8eSAndroid Build Coastguard Worker     if (item) {
339*ec779b8eSAndroid Build Coastguard Worker         item->mType = kTypeMessage;
340*ec779b8eSAndroid Build Coastguard Worker 
341*ec779b8eSAndroid Build Coastguard Worker         if (obj != NULL) { obj->incStrong(this); }
342*ec779b8eSAndroid Build Coastguard Worker         item->u.refValue = obj.get();
343*ec779b8eSAndroid Build Coastguard Worker     }
344*ec779b8eSAndroid Build Coastguard Worker }
345*ec779b8eSAndroid Build Coastguard Worker 
setRect(const char * name,int32_t left,int32_t top,int32_t right,int32_t bottom)346*ec779b8eSAndroid Build Coastguard Worker void AMessage::setRect(
347*ec779b8eSAndroid Build Coastguard Worker         const char *name,
348*ec779b8eSAndroid Build Coastguard Worker         int32_t left, int32_t top, int32_t right, int32_t bottom) {
349*ec779b8eSAndroid Build Coastguard Worker     Item *item = allocateItem(name);
350*ec779b8eSAndroid Build Coastguard Worker     if (item) {
351*ec779b8eSAndroid Build Coastguard Worker         item->mType = kTypeRect;
352*ec779b8eSAndroid Build Coastguard Worker 
353*ec779b8eSAndroid Build Coastguard Worker         item->u.rectValue.mLeft = left;
354*ec779b8eSAndroid Build Coastguard Worker         item->u.rectValue.mTop = top;
355*ec779b8eSAndroid Build Coastguard Worker         item->u.rectValue.mRight = right;
356*ec779b8eSAndroid Build Coastguard Worker         item->u.rectValue.mBottom = bottom;
357*ec779b8eSAndroid Build Coastguard Worker     }
358*ec779b8eSAndroid Build Coastguard Worker }
359*ec779b8eSAndroid Build Coastguard Worker 
findString(const char * name,AString * value) const360*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findString(const char *name, AString *value) const {
361*ec779b8eSAndroid Build Coastguard Worker     const Item *item = findItem(name, kTypeString);
362*ec779b8eSAndroid Build Coastguard Worker     if (item) {
363*ec779b8eSAndroid Build Coastguard Worker         *value = *item->u.stringValue;
364*ec779b8eSAndroid Build Coastguard Worker         return true;
365*ec779b8eSAndroid Build Coastguard Worker     }
366*ec779b8eSAndroid Build Coastguard Worker     return false;
367*ec779b8eSAndroid Build Coastguard Worker }
368*ec779b8eSAndroid Build Coastguard Worker 
findObject(const char * name,sp<RefBase> * obj) const369*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
370*ec779b8eSAndroid Build Coastguard Worker     const Item *item = findItem(name, kTypeObject);
371*ec779b8eSAndroid Build Coastguard Worker     if (item) {
372*ec779b8eSAndroid Build Coastguard Worker         *obj = item->u.refValue;
373*ec779b8eSAndroid Build Coastguard Worker         return true;
374*ec779b8eSAndroid Build Coastguard Worker     }
375*ec779b8eSAndroid Build Coastguard Worker     return false;
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker 
findBuffer(const char * name,sp<ABuffer> * buf) const378*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const {
379*ec779b8eSAndroid Build Coastguard Worker     const Item *item = findItem(name, kTypeBuffer);
380*ec779b8eSAndroid Build Coastguard Worker     if (item) {
381*ec779b8eSAndroid Build Coastguard Worker         *buf = (ABuffer *)(item->u.refValue);
382*ec779b8eSAndroid Build Coastguard Worker         return true;
383*ec779b8eSAndroid Build Coastguard Worker     }
384*ec779b8eSAndroid Build Coastguard Worker     return false;
385*ec779b8eSAndroid Build Coastguard Worker }
386*ec779b8eSAndroid Build Coastguard Worker 
findMessage(const char * name,sp<AMessage> * obj) const387*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
388*ec779b8eSAndroid Build Coastguard Worker     const Item *item = findItem(name, kTypeMessage);
389*ec779b8eSAndroid Build Coastguard Worker     if (item) {
390*ec779b8eSAndroid Build Coastguard Worker         *obj = static_cast<AMessage *>(item->u.refValue);
391*ec779b8eSAndroid Build Coastguard Worker         return true;
392*ec779b8eSAndroid Build Coastguard Worker     }
393*ec779b8eSAndroid Build Coastguard Worker     return false;
394*ec779b8eSAndroid Build Coastguard Worker }
395*ec779b8eSAndroid Build Coastguard Worker 
findRect(const char * name,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom) const396*ec779b8eSAndroid Build Coastguard Worker bool AMessage::findRect(
397*ec779b8eSAndroid Build Coastguard Worker         const char *name,
398*ec779b8eSAndroid Build Coastguard Worker         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
399*ec779b8eSAndroid Build Coastguard Worker     const Item *item = findItem(name, kTypeRect);
400*ec779b8eSAndroid Build Coastguard Worker     if (item == NULL) {
401*ec779b8eSAndroid Build Coastguard Worker         return false;
402*ec779b8eSAndroid Build Coastguard Worker     }
403*ec779b8eSAndroid Build Coastguard Worker 
404*ec779b8eSAndroid Build Coastguard Worker     *left = item->u.rectValue.mLeft;
405*ec779b8eSAndroid Build Coastguard Worker     *top = item->u.rectValue.mTop;
406*ec779b8eSAndroid Build Coastguard Worker     *right = item->u.rectValue.mRight;
407*ec779b8eSAndroid Build Coastguard Worker     *bottom = item->u.rectValue.mBottom;
408*ec779b8eSAndroid Build Coastguard Worker 
409*ec779b8eSAndroid Build Coastguard Worker     return true;
410*ec779b8eSAndroid Build Coastguard Worker }
411*ec779b8eSAndroid Build Coastguard Worker 
deliver()412*ec779b8eSAndroid Build Coastguard Worker void AMessage::deliver() {
413*ec779b8eSAndroid Build Coastguard Worker     sp<AHandler> handler = mHandler.promote();
414*ec779b8eSAndroid Build Coastguard Worker     if (handler == NULL) {
415*ec779b8eSAndroid Build Coastguard Worker         ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
416*ec779b8eSAndroid Build Coastguard Worker         return;
417*ec779b8eSAndroid Build Coastguard Worker     }
418*ec779b8eSAndroid Build Coastguard Worker 
419*ec779b8eSAndroid Build Coastguard Worker     handler->deliverMessage(this);
420*ec779b8eSAndroid Build Coastguard Worker }
421*ec779b8eSAndroid Build Coastguard Worker 
post(int64_t delayUs)422*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::post(int64_t delayUs) {
423*ec779b8eSAndroid Build Coastguard Worker     sp<ALooper> looper = mLooper.promote();
424*ec779b8eSAndroid Build Coastguard Worker     if (looper == NULL) {
425*ec779b8eSAndroid Build Coastguard Worker         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
426*ec779b8eSAndroid Build Coastguard Worker         return -ENOENT;
427*ec779b8eSAndroid Build Coastguard Worker     }
428*ec779b8eSAndroid Build Coastguard Worker 
429*ec779b8eSAndroid Build Coastguard Worker     looper->post(this, delayUs);
430*ec779b8eSAndroid Build Coastguard Worker     return OK;
431*ec779b8eSAndroid Build Coastguard Worker }
432*ec779b8eSAndroid Build Coastguard Worker 
postUnique(const sp<RefBase> & token,int64_t delayUs)433*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::postUnique(const sp<RefBase> &token, int64_t delayUs) {
434*ec779b8eSAndroid Build Coastguard Worker     sp<ALooper> looper = mLooper.promote();
435*ec779b8eSAndroid Build Coastguard Worker     if (looper == NULL) {
436*ec779b8eSAndroid Build Coastguard Worker         ALOGW("failed to post message as target looper for handler %d is gone.",
437*ec779b8eSAndroid Build Coastguard Worker               mTarget);
438*ec779b8eSAndroid Build Coastguard Worker         return -ENOENT;
439*ec779b8eSAndroid Build Coastguard Worker     }
440*ec779b8eSAndroid Build Coastguard Worker 
441*ec779b8eSAndroid Build Coastguard Worker     return looper->postUnique(this, token, delayUs);
442*ec779b8eSAndroid Build Coastguard Worker }
443*ec779b8eSAndroid Build Coastguard Worker 
postAndAwaitResponse(sp<AMessage> * response)444*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
445*ec779b8eSAndroid Build Coastguard Worker     sp<ALooper> looper = mLooper.promote();
446*ec779b8eSAndroid Build Coastguard Worker     if (looper == NULL) {
447*ec779b8eSAndroid Build Coastguard Worker         ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
448*ec779b8eSAndroid Build Coastguard Worker         return -ENOENT;
449*ec779b8eSAndroid Build Coastguard Worker     }
450*ec779b8eSAndroid Build Coastguard Worker 
451*ec779b8eSAndroid Build Coastguard Worker     sp<AReplyToken> token = looper->createReplyToken();
452*ec779b8eSAndroid Build Coastguard Worker     if (token == NULL) {
453*ec779b8eSAndroid Build Coastguard Worker         ALOGE("failed to create reply token");
454*ec779b8eSAndroid Build Coastguard Worker         return -ENOMEM;
455*ec779b8eSAndroid Build Coastguard Worker     }
456*ec779b8eSAndroid Build Coastguard Worker     setObject("replyID", token);
457*ec779b8eSAndroid Build Coastguard Worker 
458*ec779b8eSAndroid Build Coastguard Worker     looper->post(this, 0 /* delayUs */);
459*ec779b8eSAndroid Build Coastguard Worker     return looper->awaitResponse(token, response);
460*ec779b8eSAndroid Build Coastguard Worker }
461*ec779b8eSAndroid Build Coastguard Worker 
postReply(const sp<AReplyToken> & replyToken)462*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
463*ec779b8eSAndroid Build Coastguard Worker     if (replyToken == NULL) {
464*ec779b8eSAndroid Build Coastguard Worker         ALOGW("failed to post reply to a NULL token");
465*ec779b8eSAndroid Build Coastguard Worker         return -ENOENT;
466*ec779b8eSAndroid Build Coastguard Worker     }
467*ec779b8eSAndroid Build Coastguard Worker     sp<ALooper> looper = replyToken->getLooper();
468*ec779b8eSAndroid Build Coastguard Worker     if (looper == NULL) {
469*ec779b8eSAndroid Build Coastguard Worker         ALOGW("failed to post reply as target looper is gone.");
470*ec779b8eSAndroid Build Coastguard Worker         return -ENOENT;
471*ec779b8eSAndroid Build Coastguard Worker     }
472*ec779b8eSAndroid Build Coastguard Worker     return looper->postReply(replyToken, this);
473*ec779b8eSAndroid Build Coastguard Worker }
474*ec779b8eSAndroid Build Coastguard Worker 
senderAwaitsResponse(sp<AReplyToken> * replyToken)475*ec779b8eSAndroid Build Coastguard Worker bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
476*ec779b8eSAndroid Build Coastguard Worker     sp<RefBase> tmp;
477*ec779b8eSAndroid Build Coastguard Worker     bool found = findObject("replyID", &tmp);
478*ec779b8eSAndroid Build Coastguard Worker 
479*ec779b8eSAndroid Build Coastguard Worker     if (!found) {
480*ec779b8eSAndroid Build Coastguard Worker         return false;
481*ec779b8eSAndroid Build Coastguard Worker     }
482*ec779b8eSAndroid Build Coastguard Worker 
483*ec779b8eSAndroid Build Coastguard Worker     *replyToken = static_cast<AReplyToken *>(tmp.get());
484*ec779b8eSAndroid Build Coastguard Worker     tmp.clear();
485*ec779b8eSAndroid Build Coastguard Worker     setObject("replyID", tmp);
486*ec779b8eSAndroid Build Coastguard Worker     // TODO: delete Object instead of setting it to NULL
487*ec779b8eSAndroid Build Coastguard Worker 
488*ec779b8eSAndroid Build Coastguard Worker     return *replyToken != NULL;
489*ec779b8eSAndroid Build Coastguard Worker }
490*ec779b8eSAndroid Build Coastguard Worker 
dup() const491*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> AMessage::dup() const {
492*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
493*ec779b8eSAndroid Build Coastguard Worker     msg->mItems = mItems;
494*ec779b8eSAndroid Build Coastguard Worker 
495*ec779b8eSAndroid Build Coastguard Worker #ifdef DUMP_STATS
496*ec779b8eSAndroid Build Coastguard Worker     {
497*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock _l(gLock);
498*ec779b8eSAndroid Build Coastguard Worker         ++gDupCalls;
499*ec779b8eSAndroid Build Coastguard Worker         gAverageDupItems += mItems.size();
500*ec779b8eSAndroid Build Coastguard Worker         reportStats();
501*ec779b8eSAndroid Build Coastguard Worker     }
502*ec779b8eSAndroid Build Coastguard Worker #endif
503*ec779b8eSAndroid Build Coastguard Worker 
504*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mItems.size(); ++i) {
505*ec779b8eSAndroid Build Coastguard Worker         const Item *from = &mItems[i];
506*ec779b8eSAndroid Build Coastguard Worker         Item *to = &msg->mItems[i];
507*ec779b8eSAndroid Build Coastguard Worker 
508*ec779b8eSAndroid Build Coastguard Worker         to->setName(from->mName, from->mNameLength);
509*ec779b8eSAndroid Build Coastguard Worker         to->mType = from->mType;
510*ec779b8eSAndroid Build Coastguard Worker 
511*ec779b8eSAndroid Build Coastguard Worker         switch (from->mType) {
512*ec779b8eSAndroid Build Coastguard Worker             case kTypeString:
513*ec779b8eSAndroid Build Coastguard Worker             {
514*ec779b8eSAndroid Build Coastguard Worker                 to->u.stringValue =
515*ec779b8eSAndroid Build Coastguard Worker                     new AString(*from->u.stringValue);
516*ec779b8eSAndroid Build Coastguard Worker                 break;
517*ec779b8eSAndroid Build Coastguard Worker             }
518*ec779b8eSAndroid Build Coastguard Worker 
519*ec779b8eSAndroid Build Coastguard Worker             case kTypeObject:
520*ec779b8eSAndroid Build Coastguard Worker             case kTypeBuffer:
521*ec779b8eSAndroid Build Coastguard Worker             {
522*ec779b8eSAndroid Build Coastguard Worker                 to->u.refValue = from->u.refValue;
523*ec779b8eSAndroid Build Coastguard Worker                 to->u.refValue->incStrong(msg.get());
524*ec779b8eSAndroid Build Coastguard Worker                 break;
525*ec779b8eSAndroid Build Coastguard Worker             }
526*ec779b8eSAndroid Build Coastguard Worker 
527*ec779b8eSAndroid Build Coastguard Worker             case kTypeMessage:
528*ec779b8eSAndroid Build Coastguard Worker             {
529*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> copy =
530*ec779b8eSAndroid Build Coastguard Worker                     static_cast<AMessage *>(from->u.refValue)->dup();
531*ec779b8eSAndroid Build Coastguard Worker 
532*ec779b8eSAndroid Build Coastguard Worker                 to->u.refValue = copy.get();
533*ec779b8eSAndroid Build Coastguard Worker                 to->u.refValue->incStrong(msg.get());
534*ec779b8eSAndroid Build Coastguard Worker                 break;
535*ec779b8eSAndroid Build Coastguard Worker             }
536*ec779b8eSAndroid Build Coastguard Worker 
537*ec779b8eSAndroid Build Coastguard Worker             default:
538*ec779b8eSAndroid Build Coastguard Worker             {
539*ec779b8eSAndroid Build Coastguard Worker                 to->u = from->u;
540*ec779b8eSAndroid Build Coastguard Worker                 break;
541*ec779b8eSAndroid Build Coastguard Worker             }
542*ec779b8eSAndroid Build Coastguard Worker         }
543*ec779b8eSAndroid Build Coastguard Worker     }
544*ec779b8eSAndroid Build Coastguard Worker 
545*ec779b8eSAndroid Build Coastguard Worker     return msg;
546*ec779b8eSAndroid Build Coastguard Worker }
547*ec779b8eSAndroid Build Coastguard Worker 
appendIndent(AString * s,int32_t indent)548*ec779b8eSAndroid Build Coastguard Worker static void appendIndent(AString *s, int32_t indent) {
549*ec779b8eSAndroid Build Coastguard Worker     static const char kWhitespace[] =
550*ec779b8eSAndroid Build Coastguard Worker         "                                        "
551*ec779b8eSAndroid Build Coastguard Worker         "                                        ";
552*ec779b8eSAndroid Build Coastguard Worker 
553*ec779b8eSAndroid Build Coastguard Worker     CHECK_LT((size_t)indent, sizeof(kWhitespace));
554*ec779b8eSAndroid Build Coastguard Worker 
555*ec779b8eSAndroid Build Coastguard Worker     s->append(kWhitespace, indent);
556*ec779b8eSAndroid Build Coastguard Worker }
557*ec779b8eSAndroid Build Coastguard Worker 
isFourcc(uint32_t what)558*ec779b8eSAndroid Build Coastguard Worker static bool isFourcc(uint32_t what) {
559*ec779b8eSAndroid Build Coastguard Worker     return isprint(what & 0xff)
560*ec779b8eSAndroid Build Coastguard Worker         && isprint((what >> 8) & 0xff)
561*ec779b8eSAndroid Build Coastguard Worker         && isprint((what >> 16) & 0xff)
562*ec779b8eSAndroid Build Coastguard Worker         && isprint((what >> 24) & 0xff);
563*ec779b8eSAndroid Build Coastguard Worker }
564*ec779b8eSAndroid Build Coastguard Worker 
debugString(int32_t indent) const565*ec779b8eSAndroid Build Coastguard Worker AString AMessage::debugString(int32_t indent) const {
566*ec779b8eSAndroid Build Coastguard Worker     AString s = "AMessage(what = ";
567*ec779b8eSAndroid Build Coastguard Worker 
568*ec779b8eSAndroid Build Coastguard Worker     AString tmp;
569*ec779b8eSAndroid Build Coastguard Worker     if (isFourcc(mWhat)) {
570*ec779b8eSAndroid Build Coastguard Worker         tmp = AStringPrintf(
571*ec779b8eSAndroid Build Coastguard Worker                 "'%c%c%c%c'",
572*ec779b8eSAndroid Build Coastguard Worker                 (char)(mWhat >> 24),
573*ec779b8eSAndroid Build Coastguard Worker                 (char)((mWhat >> 16) & 0xff),
574*ec779b8eSAndroid Build Coastguard Worker                 (char)((mWhat >> 8) & 0xff),
575*ec779b8eSAndroid Build Coastguard Worker                 (char)(mWhat & 0xff));
576*ec779b8eSAndroid Build Coastguard Worker     } else {
577*ec779b8eSAndroid Build Coastguard Worker         tmp = AStringPrintf("0x%08x", mWhat);
578*ec779b8eSAndroid Build Coastguard Worker     }
579*ec779b8eSAndroid Build Coastguard Worker     s.append(tmp);
580*ec779b8eSAndroid Build Coastguard Worker 
581*ec779b8eSAndroid Build Coastguard Worker     if (mTarget != 0) {
582*ec779b8eSAndroid Build Coastguard Worker         tmp = AStringPrintf(", target = %d", mTarget);
583*ec779b8eSAndroid Build Coastguard Worker         s.append(tmp);
584*ec779b8eSAndroid Build Coastguard Worker     }
585*ec779b8eSAndroid Build Coastguard Worker     s.append(") = {\n");
586*ec779b8eSAndroid Build Coastguard Worker 
587*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mItems.size(); ++i) {
588*ec779b8eSAndroid Build Coastguard Worker         const Item &item = mItems[i];
589*ec779b8eSAndroid Build Coastguard Worker 
590*ec779b8eSAndroid Build Coastguard Worker         switch (item.mType) {
591*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:
592*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
593*ec779b8eSAndroid Build Coastguard Worker                         "int32_t %s = %d", item.mName, item.u.int32Value);
594*ec779b8eSAndroid Build Coastguard Worker                 break;
595*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:
596*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
597*ec779b8eSAndroid Build Coastguard Worker                         "int64_t %s = %lld", item.mName, item.u.int64Value);
598*ec779b8eSAndroid Build Coastguard Worker                 break;
599*ec779b8eSAndroid Build Coastguard Worker             case kTypeSize:
600*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
601*ec779b8eSAndroid Build Coastguard Worker                         "size_t %s = %d", item.mName, item.u.sizeValue);
602*ec779b8eSAndroid Build Coastguard Worker                 break;
603*ec779b8eSAndroid Build Coastguard Worker             case kTypeFloat:
604*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
605*ec779b8eSAndroid Build Coastguard Worker                         "float %s = %f", item.mName, item.u.floatValue);
606*ec779b8eSAndroid Build Coastguard Worker                 break;
607*ec779b8eSAndroid Build Coastguard Worker             case kTypeDouble:
608*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
609*ec779b8eSAndroid Build Coastguard Worker                         "double %s = %f", item.mName, item.u.doubleValue);
610*ec779b8eSAndroid Build Coastguard Worker                 break;
611*ec779b8eSAndroid Build Coastguard Worker             case kTypePointer:
612*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
613*ec779b8eSAndroid Build Coastguard Worker                         "void *%s = %p", item.mName, item.u.ptrValue);
614*ec779b8eSAndroid Build Coastguard Worker                 break;
615*ec779b8eSAndroid Build Coastguard Worker             case kTypeString:
616*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
617*ec779b8eSAndroid Build Coastguard Worker                         "string %s = \"%s\"",
618*ec779b8eSAndroid Build Coastguard Worker                         item.mName,
619*ec779b8eSAndroid Build Coastguard Worker                         item.u.stringValue->c_str());
620*ec779b8eSAndroid Build Coastguard Worker                 break;
621*ec779b8eSAndroid Build Coastguard Worker             case kTypeObject:
622*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
623*ec779b8eSAndroid Build Coastguard Worker                         "RefBase *%s = %p", item.mName, item.u.refValue);
624*ec779b8eSAndroid Build Coastguard Worker                 break;
625*ec779b8eSAndroid Build Coastguard Worker             case kTypeBuffer:
626*ec779b8eSAndroid Build Coastguard Worker             {
627*ec779b8eSAndroid Build Coastguard Worker                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
628*ec779b8eSAndroid Build Coastguard Worker 
629*ec779b8eSAndroid Build Coastguard Worker                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
630*ec779b8eSAndroid Build Coastguard Worker                     tmp = AStringPrintf("Buffer %s = {\n", item.mName);
631*ec779b8eSAndroid Build Coastguard Worker                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
632*ec779b8eSAndroid Build Coastguard Worker                     appendIndent(&tmp, indent + 2);
633*ec779b8eSAndroid Build Coastguard Worker                     tmp.append("}");
634*ec779b8eSAndroid Build Coastguard Worker                 } else {
635*ec779b8eSAndroid Build Coastguard Worker                     tmp = AStringPrintf(
636*ec779b8eSAndroid Build Coastguard Worker                             "Buffer *%s = %p", item.mName, buffer.get());
637*ec779b8eSAndroid Build Coastguard Worker                 }
638*ec779b8eSAndroid Build Coastguard Worker                 break;
639*ec779b8eSAndroid Build Coastguard Worker             }
640*ec779b8eSAndroid Build Coastguard Worker             case kTypeMessage:
641*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
642*ec779b8eSAndroid Build Coastguard Worker                         "AMessage %s = %s",
643*ec779b8eSAndroid Build Coastguard Worker                         item.mName,
644*ec779b8eSAndroid Build Coastguard Worker                         static_cast<AMessage *>(
645*ec779b8eSAndroid Build Coastguard Worker                             item.u.refValue)->debugString(
646*ec779b8eSAndroid Build Coastguard Worker                                 indent + strlen(item.mName) + 14).c_str());
647*ec779b8eSAndroid Build Coastguard Worker                 break;
648*ec779b8eSAndroid Build Coastguard Worker             case kTypeRect:
649*ec779b8eSAndroid Build Coastguard Worker                 tmp = AStringPrintf(
650*ec779b8eSAndroid Build Coastguard Worker                         "Rect %s(%d, %d, %d, %d)",
651*ec779b8eSAndroid Build Coastguard Worker                         item.mName,
652*ec779b8eSAndroid Build Coastguard Worker                         item.u.rectValue.mLeft,
653*ec779b8eSAndroid Build Coastguard Worker                         item.u.rectValue.mTop,
654*ec779b8eSAndroid Build Coastguard Worker                         item.u.rectValue.mRight,
655*ec779b8eSAndroid Build Coastguard Worker                         item.u.rectValue.mBottom);
656*ec779b8eSAndroid Build Coastguard Worker                 break;
657*ec779b8eSAndroid Build Coastguard Worker             default:
658*ec779b8eSAndroid Build Coastguard Worker                 TRESPASS();
659*ec779b8eSAndroid Build Coastguard Worker         }
660*ec779b8eSAndroid Build Coastguard Worker 
661*ec779b8eSAndroid Build Coastguard Worker         appendIndent(&s, indent);
662*ec779b8eSAndroid Build Coastguard Worker         s.append("  ");
663*ec779b8eSAndroid Build Coastguard Worker         s.append(tmp);
664*ec779b8eSAndroid Build Coastguard Worker         s.append("\n");
665*ec779b8eSAndroid Build Coastguard Worker     }
666*ec779b8eSAndroid Build Coastguard Worker 
667*ec779b8eSAndroid Build Coastguard Worker     appendIndent(&s, indent);
668*ec779b8eSAndroid Build Coastguard Worker     s.append("}");
669*ec779b8eSAndroid Build Coastguard Worker 
670*ec779b8eSAndroid Build Coastguard Worker     return s;
671*ec779b8eSAndroid Build Coastguard Worker }
672*ec779b8eSAndroid Build Coastguard Worker 
673*ec779b8eSAndroid Build Coastguard Worker #if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
674*ec779b8eSAndroid Build Coastguard Worker // static
FromParcel(const Parcel & parcel,size_t maxNestingLevel)675*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
676*ec779b8eSAndroid Build Coastguard Worker     int32_t what = parcel.readInt32();
677*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage();
678*ec779b8eSAndroid Build Coastguard Worker     msg->setWhat(what);
679*ec779b8eSAndroid Build Coastguard Worker 
680*ec779b8eSAndroid Build Coastguard Worker     size_t numItems = static_cast<size_t>(parcel.readInt32());
681*ec779b8eSAndroid Build Coastguard Worker     if (numItems > kMaxNumItems) {
682*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Too large number of items clipped.");
683*ec779b8eSAndroid Build Coastguard Worker         numItems = kMaxNumItems;
684*ec779b8eSAndroid Build Coastguard Worker     }
685*ec779b8eSAndroid Build Coastguard Worker     msg->mItems.resize(numItems);
686*ec779b8eSAndroid Build Coastguard Worker 
687*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < msg->mItems.size(); ++i) {
688*ec779b8eSAndroid Build Coastguard Worker         Item *item = &msg->mItems[i];
689*ec779b8eSAndroid Build Coastguard Worker 
690*ec779b8eSAndroid Build Coastguard Worker         const char *name = parcel.readCString();
691*ec779b8eSAndroid Build Coastguard Worker         if (name == NULL) {
692*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Failed reading name for an item. Parsing aborted.");
693*ec779b8eSAndroid Build Coastguard Worker             msg->mItems.resize(i);
694*ec779b8eSAndroid Build Coastguard Worker             break;
695*ec779b8eSAndroid Build Coastguard Worker         }
696*ec779b8eSAndroid Build Coastguard Worker 
697*ec779b8eSAndroid Build Coastguard Worker         item->mType = static_cast<Type>(parcel.readInt32());
698*ec779b8eSAndroid Build Coastguard Worker         // setName() happens below so that we don't leak memory when parsing
699*ec779b8eSAndroid Build Coastguard Worker         // is aborted in the middle.
700*ec779b8eSAndroid Build Coastguard Worker         switch (item->mType) {
701*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:
702*ec779b8eSAndroid Build Coastguard Worker             {
703*ec779b8eSAndroid Build Coastguard Worker                 item->u.int32Value = parcel.readInt32();
704*ec779b8eSAndroid Build Coastguard Worker                 break;
705*ec779b8eSAndroid Build Coastguard Worker             }
706*ec779b8eSAndroid Build Coastguard Worker 
707*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:
708*ec779b8eSAndroid Build Coastguard Worker             {
709*ec779b8eSAndroid Build Coastguard Worker                 item->u.int64Value = parcel.readInt64();
710*ec779b8eSAndroid Build Coastguard Worker                 break;
711*ec779b8eSAndroid Build Coastguard Worker             }
712*ec779b8eSAndroid Build Coastguard Worker 
713*ec779b8eSAndroid Build Coastguard Worker             case kTypeSize:
714*ec779b8eSAndroid Build Coastguard Worker             {
715*ec779b8eSAndroid Build Coastguard Worker                 item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
716*ec779b8eSAndroid Build Coastguard Worker                 break;
717*ec779b8eSAndroid Build Coastguard Worker             }
718*ec779b8eSAndroid Build Coastguard Worker 
719*ec779b8eSAndroid Build Coastguard Worker             case kTypeFloat:
720*ec779b8eSAndroid Build Coastguard Worker             {
721*ec779b8eSAndroid Build Coastguard Worker                 item->u.floatValue = parcel.readFloat();
722*ec779b8eSAndroid Build Coastguard Worker                 break;
723*ec779b8eSAndroid Build Coastguard Worker             }
724*ec779b8eSAndroid Build Coastguard Worker 
725*ec779b8eSAndroid Build Coastguard Worker             case kTypeDouble:
726*ec779b8eSAndroid Build Coastguard Worker             {
727*ec779b8eSAndroid Build Coastguard Worker                 item->u.doubleValue = parcel.readDouble();
728*ec779b8eSAndroid Build Coastguard Worker                 break;
729*ec779b8eSAndroid Build Coastguard Worker             }
730*ec779b8eSAndroid Build Coastguard Worker 
731*ec779b8eSAndroid Build Coastguard Worker             case kTypeString:
732*ec779b8eSAndroid Build Coastguard Worker             {
733*ec779b8eSAndroid Build Coastguard Worker                 const char *stringValue = parcel.readCString();
734*ec779b8eSAndroid Build Coastguard Worker                 if (stringValue == NULL) {
735*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Failed reading string value from a parcel. "
736*ec779b8eSAndroid Build Coastguard Worker                         "Parsing aborted.");
737*ec779b8eSAndroid Build Coastguard Worker                     msg->mItems.resize(i);
738*ec779b8eSAndroid Build Coastguard Worker                     continue;
739*ec779b8eSAndroid Build Coastguard Worker                     // The loop will terminate subsequently.
740*ec779b8eSAndroid Build Coastguard Worker                 } else {
741*ec779b8eSAndroid Build Coastguard Worker                     item->u.stringValue = new AString(stringValue);
742*ec779b8eSAndroid Build Coastguard Worker                 }
743*ec779b8eSAndroid Build Coastguard Worker                 break;
744*ec779b8eSAndroid Build Coastguard Worker             }
745*ec779b8eSAndroid Build Coastguard Worker 
746*ec779b8eSAndroid Build Coastguard Worker             case kTypeMessage:
747*ec779b8eSAndroid Build Coastguard Worker             {
748*ec779b8eSAndroid Build Coastguard Worker                 if (maxNestingLevel == 0) {
749*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Too many levels of AMessage nesting.");
750*ec779b8eSAndroid Build Coastguard Worker                     return NULL;
751*ec779b8eSAndroid Build Coastguard Worker                 }
752*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> subMsg = AMessage::FromParcel(
753*ec779b8eSAndroid Build Coastguard Worker                         parcel,
754*ec779b8eSAndroid Build Coastguard Worker                         maxNestingLevel - 1);
755*ec779b8eSAndroid Build Coastguard Worker                 if (subMsg == NULL) {
756*ec779b8eSAndroid Build Coastguard Worker                     // This condition will be triggered when there exists an
757*ec779b8eSAndroid Build Coastguard Worker                     // object that cannot cross process boundaries or when the
758*ec779b8eSAndroid Build Coastguard Worker                     // level of nested AMessage is too deep.
759*ec779b8eSAndroid Build Coastguard Worker                     return NULL;
760*ec779b8eSAndroid Build Coastguard Worker                 }
761*ec779b8eSAndroid Build Coastguard Worker                 subMsg->incStrong(msg.get());
762*ec779b8eSAndroid Build Coastguard Worker 
763*ec779b8eSAndroid Build Coastguard Worker                 item->u.refValue = subMsg.get();
764*ec779b8eSAndroid Build Coastguard Worker                 break;
765*ec779b8eSAndroid Build Coastguard Worker             }
766*ec779b8eSAndroid Build Coastguard Worker 
767*ec779b8eSAndroid Build Coastguard Worker             default:
768*ec779b8eSAndroid Build Coastguard Worker             {
769*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("This type of object cannot cross process boundaries.");
770*ec779b8eSAndroid Build Coastguard Worker                 return NULL;
771*ec779b8eSAndroid Build Coastguard Worker             }
772*ec779b8eSAndroid Build Coastguard Worker         }
773*ec779b8eSAndroid Build Coastguard Worker 
774*ec779b8eSAndroid Build Coastguard Worker         item->setName(name, strlen(name));
775*ec779b8eSAndroid Build Coastguard Worker     }
776*ec779b8eSAndroid Build Coastguard Worker 
777*ec779b8eSAndroid Build Coastguard Worker     return msg;
778*ec779b8eSAndroid Build Coastguard Worker }
779*ec779b8eSAndroid Build Coastguard Worker 
writeToParcel(Parcel * parcel) const780*ec779b8eSAndroid Build Coastguard Worker void AMessage::writeToParcel(Parcel *parcel) const {
781*ec779b8eSAndroid Build Coastguard Worker     parcel->writeInt32(static_cast<int32_t>(mWhat));
782*ec779b8eSAndroid Build Coastguard Worker     parcel->writeInt32(static_cast<int32_t>(mItems.size()));
783*ec779b8eSAndroid Build Coastguard Worker 
784*ec779b8eSAndroid Build Coastguard Worker     for (const Item &item : mItems) {
785*ec779b8eSAndroid Build Coastguard Worker         parcel->writeCString(item.mName);
786*ec779b8eSAndroid Build Coastguard Worker         parcel->writeInt32(static_cast<int32_t>(item.mType));
787*ec779b8eSAndroid Build Coastguard Worker 
788*ec779b8eSAndroid Build Coastguard Worker         switch (item.mType) {
789*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:
790*ec779b8eSAndroid Build Coastguard Worker             {
791*ec779b8eSAndroid Build Coastguard Worker                 parcel->writeInt32(item.u.int32Value);
792*ec779b8eSAndroid Build Coastguard Worker                 break;
793*ec779b8eSAndroid Build Coastguard Worker             }
794*ec779b8eSAndroid Build Coastguard Worker 
795*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:
796*ec779b8eSAndroid Build Coastguard Worker             {
797*ec779b8eSAndroid Build Coastguard Worker                 parcel->writeInt64(item.u.int64Value);
798*ec779b8eSAndroid Build Coastguard Worker                 break;
799*ec779b8eSAndroid Build Coastguard Worker             }
800*ec779b8eSAndroid Build Coastguard Worker 
801*ec779b8eSAndroid Build Coastguard Worker             case kTypeSize:
802*ec779b8eSAndroid Build Coastguard Worker             {
803*ec779b8eSAndroid Build Coastguard Worker                 parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
804*ec779b8eSAndroid Build Coastguard Worker                 break;
805*ec779b8eSAndroid Build Coastguard Worker             }
806*ec779b8eSAndroid Build Coastguard Worker 
807*ec779b8eSAndroid Build Coastguard Worker             case kTypeFloat:
808*ec779b8eSAndroid Build Coastguard Worker             {
809*ec779b8eSAndroid Build Coastguard Worker                 parcel->writeFloat(item.u.floatValue);
810*ec779b8eSAndroid Build Coastguard Worker                 break;
811*ec779b8eSAndroid Build Coastguard Worker             }
812*ec779b8eSAndroid Build Coastguard Worker 
813*ec779b8eSAndroid Build Coastguard Worker             case kTypeDouble:
814*ec779b8eSAndroid Build Coastguard Worker             {
815*ec779b8eSAndroid Build Coastguard Worker                 parcel->writeDouble(item.u.doubleValue);
816*ec779b8eSAndroid Build Coastguard Worker                 break;
817*ec779b8eSAndroid Build Coastguard Worker             }
818*ec779b8eSAndroid Build Coastguard Worker 
819*ec779b8eSAndroid Build Coastguard Worker             case kTypeString:
820*ec779b8eSAndroid Build Coastguard Worker             {
821*ec779b8eSAndroid Build Coastguard Worker                 parcel->writeCString(item.u.stringValue->c_str());
822*ec779b8eSAndroid Build Coastguard Worker                 break;
823*ec779b8eSAndroid Build Coastguard Worker             }
824*ec779b8eSAndroid Build Coastguard Worker 
825*ec779b8eSAndroid Build Coastguard Worker             case kTypeMessage:
826*ec779b8eSAndroid Build Coastguard Worker             {
827*ec779b8eSAndroid Build Coastguard Worker                 static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
828*ec779b8eSAndroid Build Coastguard Worker                 break;
829*ec779b8eSAndroid Build Coastguard Worker             }
830*ec779b8eSAndroid Build Coastguard Worker 
831*ec779b8eSAndroid Build Coastguard Worker             default:
832*ec779b8eSAndroid Build Coastguard Worker             {
833*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("This type of object cannot cross process boundaries.");
834*ec779b8eSAndroid Build Coastguard Worker                 TRESPASS();
835*ec779b8eSAndroid Build Coastguard Worker             }
836*ec779b8eSAndroid Build Coastguard Worker         }
837*ec779b8eSAndroid Build Coastguard Worker     }
838*ec779b8eSAndroid Build Coastguard Worker }
839*ec779b8eSAndroid Build Coastguard Worker #endif  // defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
840*ec779b8eSAndroid Build Coastguard Worker 
changesFrom(const sp<const AMessage> & other,bool deep) const841*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
842*ec779b8eSAndroid Build Coastguard Worker     if (other == NULL) {
843*ec779b8eSAndroid Build Coastguard Worker         return const_cast<AMessage*>(this);
844*ec779b8eSAndroid Build Coastguard Worker     }
845*ec779b8eSAndroid Build Coastguard Worker 
846*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> diff = new AMessage;
847*ec779b8eSAndroid Build Coastguard Worker     if (mWhat != other->mWhat) {
848*ec779b8eSAndroid Build Coastguard Worker         diff->setWhat(mWhat);
849*ec779b8eSAndroid Build Coastguard Worker     }
850*ec779b8eSAndroid Build Coastguard Worker     if (mHandler != other->mHandler) {
851*ec779b8eSAndroid Build Coastguard Worker         diff->setTarget(mHandler.promote());
852*ec779b8eSAndroid Build Coastguard Worker     }
853*ec779b8eSAndroid Build Coastguard Worker 
854*ec779b8eSAndroid Build Coastguard Worker     for (const Item &item : mItems) {
855*ec779b8eSAndroid Build Coastguard Worker         const Item *oitem = other->findItem(item.mName, item.mType);
856*ec779b8eSAndroid Build Coastguard Worker         switch (item.mType) {
857*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:
858*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
859*ec779b8eSAndroid Build Coastguard Worker                     diff->setInt32(item.mName, item.u.int32Value);
860*ec779b8eSAndroid Build Coastguard Worker                 }
861*ec779b8eSAndroid Build Coastguard Worker                 break;
862*ec779b8eSAndroid Build Coastguard Worker 
863*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:
864*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
865*ec779b8eSAndroid Build Coastguard Worker                     diff->setInt64(item.mName, item.u.int64Value);
866*ec779b8eSAndroid Build Coastguard Worker                 }
867*ec779b8eSAndroid Build Coastguard Worker                 break;
868*ec779b8eSAndroid Build Coastguard Worker 
869*ec779b8eSAndroid Build Coastguard Worker             case kTypeSize:
870*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
871*ec779b8eSAndroid Build Coastguard Worker                     diff->setSize(item.mName, item.u.sizeValue);
872*ec779b8eSAndroid Build Coastguard Worker                 }
873*ec779b8eSAndroid Build Coastguard Worker                 break;
874*ec779b8eSAndroid Build Coastguard Worker 
875*ec779b8eSAndroid Build Coastguard Worker             case kTypeFloat:
876*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
877*ec779b8eSAndroid Build Coastguard Worker                     diff->setFloat(item.mName, item.u.sizeValue);
878*ec779b8eSAndroid Build Coastguard Worker                 }
879*ec779b8eSAndroid Build Coastguard Worker                 break;
880*ec779b8eSAndroid Build Coastguard Worker 
881*ec779b8eSAndroid Build Coastguard Worker             case kTypeDouble:
882*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
883*ec779b8eSAndroid Build Coastguard Worker                     diff->setDouble(item.mName, item.u.sizeValue);
884*ec779b8eSAndroid Build Coastguard Worker                 }
885*ec779b8eSAndroid Build Coastguard Worker                 break;
886*ec779b8eSAndroid Build Coastguard Worker 
887*ec779b8eSAndroid Build Coastguard Worker             case kTypeString:
888*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
889*ec779b8eSAndroid Build Coastguard Worker                     diff->setString(item.mName, *item.u.stringValue);
890*ec779b8eSAndroid Build Coastguard Worker                 }
891*ec779b8eSAndroid Build Coastguard Worker                 break;
892*ec779b8eSAndroid Build Coastguard Worker 
893*ec779b8eSAndroid Build Coastguard Worker             case kTypeRect:
894*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
895*ec779b8eSAndroid Build Coastguard Worker                     diff->setRect(
896*ec779b8eSAndroid Build Coastguard Worker                             item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
897*ec779b8eSAndroid Build Coastguard Worker                             item.u.rectValue.mRight, item.u.rectValue.mBottom);
898*ec779b8eSAndroid Build Coastguard Worker                 }
899*ec779b8eSAndroid Build Coastguard Worker                 break;
900*ec779b8eSAndroid Build Coastguard Worker 
901*ec779b8eSAndroid Build Coastguard Worker             case kTypePointer:
902*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
903*ec779b8eSAndroid Build Coastguard Worker                     diff->setPointer(item.mName, item.u.ptrValue);
904*ec779b8eSAndroid Build Coastguard Worker                 }
905*ec779b8eSAndroid Build Coastguard Worker                 break;
906*ec779b8eSAndroid Build Coastguard Worker 
907*ec779b8eSAndroid Build Coastguard Worker             case kTypeBuffer:
908*ec779b8eSAndroid Build Coastguard Worker             {
909*ec779b8eSAndroid Build Coastguard Worker                 sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
910*ec779b8eSAndroid Build Coastguard Worker                 if (myBuf == NULL) {
911*ec779b8eSAndroid Build Coastguard Worker                     if (oitem == NULL || oitem->u.refValue != NULL) {
912*ec779b8eSAndroid Build Coastguard Worker                         diff->setBuffer(item.mName, NULL);
913*ec779b8eSAndroid Build Coastguard Worker                     }
914*ec779b8eSAndroid Build Coastguard Worker                     break;
915*ec779b8eSAndroid Build Coastguard Worker                 }
916*ec779b8eSAndroid Build Coastguard Worker                 sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
917*ec779b8eSAndroid Build Coastguard Worker                 if (oBuf == NULL
918*ec779b8eSAndroid Build Coastguard Worker                         || myBuf->size() != oBuf->size()
919*ec779b8eSAndroid Build Coastguard Worker                         || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
920*ec779b8eSAndroid Build Coastguard Worker                         || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
921*ec779b8eSAndroid Build Coastguard Worker                     diff->setBuffer(item.mName, myBuf);
922*ec779b8eSAndroid Build Coastguard Worker                 }
923*ec779b8eSAndroid Build Coastguard Worker                 break;
924*ec779b8eSAndroid Build Coastguard Worker             }
925*ec779b8eSAndroid Build Coastguard Worker 
926*ec779b8eSAndroid Build Coastguard Worker             case kTypeMessage:
927*ec779b8eSAndroid Build Coastguard Worker             {
928*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
929*ec779b8eSAndroid Build Coastguard Worker                 if (myMsg == NULL) {
930*ec779b8eSAndroid Build Coastguard Worker                     if (oitem == NULL || oitem->u.refValue != NULL) {
931*ec779b8eSAndroid Build Coastguard Worker                         diff->setMessage(item.mName, NULL);
932*ec779b8eSAndroid Build Coastguard Worker                     }
933*ec779b8eSAndroid Build Coastguard Worker                     break;
934*ec779b8eSAndroid Build Coastguard Worker                 }
935*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> oMsg =
936*ec779b8eSAndroid Build Coastguard Worker                     oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
937*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
938*ec779b8eSAndroid Build Coastguard Worker                 if (changes->countEntries()) {
939*ec779b8eSAndroid Build Coastguard Worker                     diff->setMessage(item.mName, deep ? changes : myMsg);
940*ec779b8eSAndroid Build Coastguard Worker                 }
941*ec779b8eSAndroid Build Coastguard Worker                 break;
942*ec779b8eSAndroid Build Coastguard Worker             }
943*ec779b8eSAndroid Build Coastguard Worker 
944*ec779b8eSAndroid Build Coastguard Worker             case kTypeObject:
945*ec779b8eSAndroid Build Coastguard Worker                 if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
946*ec779b8eSAndroid Build Coastguard Worker                     diff->setObject(item.mName, item.u.refValue);
947*ec779b8eSAndroid Build Coastguard Worker                 }
948*ec779b8eSAndroid Build Coastguard Worker                 break;
949*ec779b8eSAndroid Build Coastguard Worker 
950*ec779b8eSAndroid Build Coastguard Worker             default:
951*ec779b8eSAndroid Build Coastguard Worker             {
952*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Unknown type %d", item.mType);
953*ec779b8eSAndroid Build Coastguard Worker                 TRESPASS();
954*ec779b8eSAndroid Build Coastguard Worker             }
955*ec779b8eSAndroid Build Coastguard Worker         }
956*ec779b8eSAndroid Build Coastguard Worker     }
957*ec779b8eSAndroid Build Coastguard Worker     return diff;
958*ec779b8eSAndroid Build Coastguard Worker }
959*ec779b8eSAndroid Build Coastguard Worker 
countEntries() const960*ec779b8eSAndroid Build Coastguard Worker size_t AMessage::countEntries() const {
961*ec779b8eSAndroid Build Coastguard Worker     return mItems.size();
962*ec779b8eSAndroid Build Coastguard Worker }
963*ec779b8eSAndroid Build Coastguard Worker 
964*ec779b8eSAndroid Build Coastguard Worker /* static */
maxAllowedEntries()965*ec779b8eSAndroid Build Coastguard Worker size_t AMessage::maxAllowedEntries() {
966*ec779b8eSAndroid Build Coastguard Worker     return kMaxNumItems;
967*ec779b8eSAndroid Build Coastguard Worker }
968*ec779b8eSAndroid Build Coastguard Worker 
getEntryNameAt(size_t index,Type * type) const969*ec779b8eSAndroid Build Coastguard Worker const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
970*ec779b8eSAndroid Build Coastguard Worker     if (index >= mItems.size()) {
971*ec779b8eSAndroid Build Coastguard Worker         *type = kTypeInt32;
972*ec779b8eSAndroid Build Coastguard Worker 
973*ec779b8eSAndroid Build Coastguard Worker         return NULL;
974*ec779b8eSAndroid Build Coastguard Worker     }
975*ec779b8eSAndroid Build Coastguard Worker 
976*ec779b8eSAndroid Build Coastguard Worker     *type = mItems[index].mType;
977*ec779b8eSAndroid Build Coastguard Worker 
978*ec779b8eSAndroid Build Coastguard Worker     return mItems[index].mName;
979*ec779b8eSAndroid Build Coastguard Worker }
980*ec779b8eSAndroid Build Coastguard Worker 
getEntryAt(size_t index) const981*ec779b8eSAndroid Build Coastguard Worker AMessage::ItemData AMessage::getEntryAt(size_t index) const {
982*ec779b8eSAndroid Build Coastguard Worker     ItemData it;
983*ec779b8eSAndroid Build Coastguard Worker     if (index < mItems.size()) {
984*ec779b8eSAndroid Build Coastguard Worker         switch (mItems[index].mType) {
985*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt32:    it.set(mItems[index].u.int32Value); break;
986*ec779b8eSAndroid Build Coastguard Worker             case kTypeInt64:    it.set(mItems[index].u.int64Value); break;
987*ec779b8eSAndroid Build Coastguard Worker             case kTypeSize:     it.set(mItems[index].u.sizeValue); break;
988*ec779b8eSAndroid Build Coastguard Worker             case kTypeFloat:    it.set(mItems[index].u.floatValue); break;
989*ec779b8eSAndroid Build Coastguard Worker             case kTypeDouble:   it.set(mItems[index].u.doubleValue); break;
990*ec779b8eSAndroid Build Coastguard Worker             case kTypePointer:  it.set(mItems[index].u.ptrValue); break;
991*ec779b8eSAndroid Build Coastguard Worker             case kTypeRect:     it.set(mItems[index].u.rectValue); break;
992*ec779b8eSAndroid Build Coastguard Worker             case kTypeString:   it.set(*mItems[index].u.stringValue); break;
993*ec779b8eSAndroid Build Coastguard Worker             case kTypeObject: {
994*ec779b8eSAndroid Build Coastguard Worker                 sp<RefBase> obj = mItems[index].u.refValue;
995*ec779b8eSAndroid Build Coastguard Worker                 it.set(obj);
996*ec779b8eSAndroid Build Coastguard Worker                 break;
997*ec779b8eSAndroid Build Coastguard Worker             }
998*ec779b8eSAndroid Build Coastguard Worker             case kTypeMessage: {
999*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> msg = static_cast<AMessage *>(mItems[index].u.refValue);
1000*ec779b8eSAndroid Build Coastguard Worker                 it.set(msg);
1001*ec779b8eSAndroid Build Coastguard Worker                 break;
1002*ec779b8eSAndroid Build Coastguard Worker             }
1003*ec779b8eSAndroid Build Coastguard Worker             case kTypeBuffer: {
1004*ec779b8eSAndroid Build Coastguard Worker                 sp<ABuffer> buf = static_cast<ABuffer *>(mItems[index].u.refValue);
1005*ec779b8eSAndroid Build Coastguard Worker                 it.set(buf);
1006*ec779b8eSAndroid Build Coastguard Worker                 break;
1007*ec779b8eSAndroid Build Coastguard Worker             }
1008*ec779b8eSAndroid Build Coastguard Worker             default:
1009*ec779b8eSAndroid Build Coastguard Worker                 break;
1010*ec779b8eSAndroid Build Coastguard Worker         }
1011*ec779b8eSAndroid Build Coastguard Worker     }
1012*ec779b8eSAndroid Build Coastguard Worker     return it;
1013*ec779b8eSAndroid Build Coastguard Worker }
1014*ec779b8eSAndroid Build Coastguard Worker 
setEntryNameAt(size_t index,const char * name)1015*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::setEntryNameAt(size_t index, const char *name) {
1016*ec779b8eSAndroid Build Coastguard Worker     if (index >= mItems.size()) {
1017*ec779b8eSAndroid Build Coastguard Worker         return BAD_INDEX;
1018*ec779b8eSAndroid Build Coastguard Worker     }
1019*ec779b8eSAndroid Build Coastguard Worker     if (name == nullptr) {
1020*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
1021*ec779b8eSAndroid Build Coastguard Worker     }
1022*ec779b8eSAndroid Build Coastguard Worker     if (!strcmp(name, mItems[index].mName)) {
1023*ec779b8eSAndroid Build Coastguard Worker         return OK; // name has not changed
1024*ec779b8eSAndroid Build Coastguard Worker     }
1025*ec779b8eSAndroid Build Coastguard Worker     size_t len = strlen(name);
1026*ec779b8eSAndroid Build Coastguard Worker     if (findItemIndex(name, len) < mItems.size()) {
1027*ec779b8eSAndroid Build Coastguard Worker         return ALREADY_EXISTS;
1028*ec779b8eSAndroid Build Coastguard Worker     }
1029*ec779b8eSAndroid Build Coastguard Worker     delete[] mItems[index].mName;
1030*ec779b8eSAndroid Build Coastguard Worker     mItems[index].mName = nullptr;
1031*ec779b8eSAndroid Build Coastguard Worker     mItems[index].setName(name, len);
1032*ec779b8eSAndroid Build Coastguard Worker     return OK;
1033*ec779b8eSAndroid Build Coastguard Worker }
1034*ec779b8eSAndroid Build Coastguard Worker 
setEntryAt(size_t index,const ItemData & item)1035*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::setEntryAt(size_t index, const ItemData &item) {
1036*ec779b8eSAndroid Build Coastguard Worker     AString stringValue;
1037*ec779b8eSAndroid Build Coastguard Worker     sp<RefBase> refValue;
1038*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msgValue;
1039*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> bufValue;
1040*ec779b8eSAndroid Build Coastguard Worker 
1041*ec779b8eSAndroid Build Coastguard Worker     if (index >= mItems.size()) {
1042*ec779b8eSAndroid Build Coastguard Worker         return BAD_INDEX;
1043*ec779b8eSAndroid Build Coastguard Worker     }
1044*ec779b8eSAndroid Build Coastguard Worker     if (!item.used()) {
1045*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
1046*ec779b8eSAndroid Build Coastguard Worker     }
1047*ec779b8eSAndroid Build Coastguard Worker     Item *dst = &mItems[index];
1048*ec779b8eSAndroid Build Coastguard Worker     freeItemValue(dst);
1049*ec779b8eSAndroid Build Coastguard Worker 
1050*ec779b8eSAndroid Build Coastguard Worker     // some values can be directly set with the getter. others need items to be allocated
1051*ec779b8eSAndroid Build Coastguard Worker     if (item.find(&dst->u.int32Value)) {
1052*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeInt32;
1053*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&dst->u.int64Value)) {
1054*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeInt64;
1055*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&dst->u.sizeValue)) {
1056*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeSize;
1057*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&dst->u.floatValue)) {
1058*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeFloat;
1059*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&dst->u.doubleValue)) {
1060*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeDouble;
1061*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&dst->u.ptrValue)) {
1062*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypePointer;
1063*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&dst->u.rectValue)) {
1064*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeRect;
1065*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&stringValue)) {
1066*ec779b8eSAndroid Build Coastguard Worker         dst->u.stringValue = new AString(stringValue);
1067*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeString;
1068*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&refValue)) {
1069*ec779b8eSAndroid Build Coastguard Worker         if (refValue != NULL) { refValue->incStrong(this); }
1070*ec779b8eSAndroid Build Coastguard Worker         dst->u.refValue = refValue.get();
1071*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeObject;
1072*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&msgValue)) {
1073*ec779b8eSAndroid Build Coastguard Worker         if (msgValue != NULL) { msgValue->incStrong(this); }
1074*ec779b8eSAndroid Build Coastguard Worker         dst->u.refValue = msgValue.get();
1075*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeMessage;
1076*ec779b8eSAndroid Build Coastguard Worker     } else if (item.find(&bufValue)) {
1077*ec779b8eSAndroid Build Coastguard Worker         if (bufValue != NULL) { bufValue->incStrong(this); }
1078*ec779b8eSAndroid Build Coastguard Worker         dst->u.refValue = bufValue.get();
1079*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeBuffer;
1080*ec779b8eSAndroid Build Coastguard Worker     } else {
1081*ec779b8eSAndroid Build Coastguard Worker         // unsupported item - we should not be here.
1082*ec779b8eSAndroid Build Coastguard Worker         dst->mType = kTypeInt32;
1083*ec779b8eSAndroid Build Coastguard Worker         dst->u.int32Value = 0xDEADDEAD;
1084*ec779b8eSAndroid Build Coastguard Worker         return BAD_TYPE;
1085*ec779b8eSAndroid Build Coastguard Worker     }
1086*ec779b8eSAndroid Build Coastguard Worker     return OK;
1087*ec779b8eSAndroid Build Coastguard Worker }
1088*ec779b8eSAndroid Build Coastguard Worker 
removeEntryAt(size_t index)1089*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::removeEntryAt(size_t index) {
1090*ec779b8eSAndroid Build Coastguard Worker     if (index >= mItems.size()) {
1091*ec779b8eSAndroid Build Coastguard Worker         return BAD_INDEX;
1092*ec779b8eSAndroid Build Coastguard Worker     }
1093*ec779b8eSAndroid Build Coastguard Worker     // delete entry data and objects
1094*ec779b8eSAndroid Build Coastguard Worker     delete[] mItems[index].mName;
1095*ec779b8eSAndroid Build Coastguard Worker     mItems[index].mName = nullptr;
1096*ec779b8eSAndroid Build Coastguard Worker     freeItemValue(&mItems[index]);
1097*ec779b8eSAndroid Build Coastguard Worker 
1098*ec779b8eSAndroid Build Coastguard Worker     // swap entry with last entry and clear last entry's data
1099*ec779b8eSAndroid Build Coastguard Worker     size_t lastIndex = mItems.size() - 1;
1100*ec779b8eSAndroid Build Coastguard Worker     if (index < lastIndex) {
1101*ec779b8eSAndroid Build Coastguard Worker         mItems[index] = mItems[lastIndex];
1102*ec779b8eSAndroid Build Coastguard Worker         mItems[lastIndex].mName = nullptr;
1103*ec779b8eSAndroid Build Coastguard Worker         mItems[lastIndex].mType = kTypeInt32;
1104*ec779b8eSAndroid Build Coastguard Worker     }
1105*ec779b8eSAndroid Build Coastguard Worker     mItems.pop_back();
1106*ec779b8eSAndroid Build Coastguard Worker     return OK;
1107*ec779b8eSAndroid Build Coastguard Worker }
1108*ec779b8eSAndroid Build Coastguard Worker 
removeEntryByName(const char * name)1109*ec779b8eSAndroid Build Coastguard Worker status_t AMessage::removeEntryByName(const char *name) {
1110*ec779b8eSAndroid Build Coastguard Worker     if (name == nullptr) {
1111*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
1112*ec779b8eSAndroid Build Coastguard Worker     }
1113*ec779b8eSAndroid Build Coastguard Worker     size_t index = findEntryByName(name);
1114*ec779b8eSAndroid Build Coastguard Worker     if (index >= mItems.size()) {
1115*ec779b8eSAndroid Build Coastguard Worker         return BAD_INDEX;
1116*ec779b8eSAndroid Build Coastguard Worker     }
1117*ec779b8eSAndroid Build Coastguard Worker     return removeEntryAt(index);
1118*ec779b8eSAndroid Build Coastguard Worker }
1119*ec779b8eSAndroid Build Coastguard Worker 
setItem(const char * name,const ItemData & item)1120*ec779b8eSAndroid Build Coastguard Worker void AMessage::setItem(const char *name, const ItemData &item) {
1121*ec779b8eSAndroid Build Coastguard Worker     if (item.used()) {
1122*ec779b8eSAndroid Build Coastguard Worker         Item *it = allocateItem(name);
1123*ec779b8eSAndroid Build Coastguard Worker         if (it != nullptr) {
1124*ec779b8eSAndroid Build Coastguard Worker             setEntryAt(it - &mItems[0], item);
1125*ec779b8eSAndroid Build Coastguard Worker         }
1126*ec779b8eSAndroid Build Coastguard Worker     }
1127*ec779b8eSAndroid Build Coastguard Worker }
1128*ec779b8eSAndroid Build Coastguard Worker 
findItem(const char * name) const1129*ec779b8eSAndroid Build Coastguard Worker AMessage::ItemData AMessage::findItem(const char *name) const {
1130*ec779b8eSAndroid Build Coastguard Worker     return getEntryAt(findEntryByName(name));
1131*ec779b8eSAndroid Build Coastguard Worker }
1132*ec779b8eSAndroid Build Coastguard Worker 
extend(const sp<AMessage> & other)1133*ec779b8eSAndroid Build Coastguard Worker void AMessage::extend(const sp<AMessage> &other) {
1134*ec779b8eSAndroid Build Coastguard Worker     // ignore null messages
1135*ec779b8eSAndroid Build Coastguard Worker     if (other == nullptr) {
1136*ec779b8eSAndroid Build Coastguard Worker         return;
1137*ec779b8eSAndroid Build Coastguard Worker     }
1138*ec779b8eSAndroid Build Coastguard Worker 
1139*ec779b8eSAndroid Build Coastguard Worker     for (size_t ix = 0; ix < other->mItems.size(); ++ix) {
1140*ec779b8eSAndroid Build Coastguard Worker         Item *it = allocateItem(other->mItems[ix].mName);
1141*ec779b8eSAndroid Build Coastguard Worker         if (it != nullptr) {
1142*ec779b8eSAndroid Build Coastguard Worker             ItemData data = other->getEntryAt(ix);
1143*ec779b8eSAndroid Build Coastguard Worker             setEntryAt(it - &mItems[0], data);
1144*ec779b8eSAndroid Build Coastguard Worker         }
1145*ec779b8eSAndroid Build Coastguard Worker     }
1146*ec779b8eSAndroid Build Coastguard Worker }
1147*ec779b8eSAndroid Build Coastguard Worker 
findEntryByName(const char * name) const1148*ec779b8eSAndroid Build Coastguard Worker size_t AMessage::findEntryByName(const char *name) const {
1149*ec779b8eSAndroid Build Coastguard Worker     return name == nullptr ? countEntries() : findItemIndex(name, strlen(name));
1150*ec779b8eSAndroid Build Coastguard Worker }
1151*ec779b8eSAndroid Build Coastguard Worker 
1152*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
1153