AMessage.cpp revision 72961230a5890071bcca436eb5630172ce84ec41
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "AMessage.h"
18
19#include "AAtomizer.h"
20#include "ADebug.h"
21#include "ALooperRoster.h"
22#include "AString.h"
23
24namespace android {
25
26AMessage::AMessage(uint32_t what, ALooper::handler_id target)
27    : mWhat(what),
28      mTarget(target),
29      mNumItems(0) {
30}
31
32AMessage::~AMessage() {
33    clear();
34}
35
36void AMessage::setWhat(uint32_t what) {
37    mWhat = what;
38}
39
40uint32_t AMessage::what() const {
41    return mWhat;
42}
43
44void AMessage::setTarget(ALooper::handler_id handlerID) {
45    mTarget = handlerID;
46}
47
48ALooper::handler_id AMessage::target() const {
49    return mTarget;
50}
51
52void AMessage::clear() {
53    for (size_t i = 0; i < mNumItems; ++i) {
54        Item *item = &mItems[i];
55        freeItem(item);
56    }
57    mNumItems = 0;
58}
59
60void AMessage::freeItem(Item *item) {
61    switch (item->mType) {
62        case kTypeString:
63        {
64            delete item->u.stringValue;
65            break;
66        }
67
68        case kTypeObject:
69        case kTypeMessage:
70        {
71            if (item->u.refValue != NULL) {
72                item->u.refValue->decStrong(this);
73            }
74            break;
75        }
76
77        default:
78            break;
79    }
80}
81
82AMessage::Item *AMessage::allocateItem(const char *name) {
83    name = AAtomizer::Atomize(name);
84
85    size_t i = 0;
86    while (i < mNumItems && mItems[i].mName != name) {
87        ++i;
88    }
89
90    Item *item;
91
92    if (i < mNumItems) {
93        item = &mItems[i];
94        freeItem(item);
95    } else {
96        CHECK(mNumItems < kMaxNumItems);
97        i = mNumItems++;
98        item = &mItems[i];
99
100        item->mName = name;
101    }
102
103    return item;
104}
105
106const AMessage::Item *AMessage::findItem(
107        const char *name, Type type) const {
108    name = AAtomizer::Atomize(name);
109
110    for (size_t i = 0; i < mNumItems; ++i) {
111        const Item *item = &mItems[i];
112
113        if (item->mName == name) {
114            return item->mType == type ? item : NULL;
115        }
116    }
117
118    return NULL;
119}
120
121#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
122void AMessage::set##NAME(const char *name, TYPENAME value) {            \
123    Item *item = allocateItem(name);                                    \
124                                                                        \
125    item->mType = kType##NAME;                                          \
126    item->u.FIELDNAME = value;                                          \
127}                                                                       \
128                                                                        \
129bool AMessage::find##NAME(const char *name, TYPENAME *value) const {    \
130    const Item *item = findItem(name, kType##NAME);                     \
131    if (item) {                                                         \
132        *value = item->u.FIELDNAME;                                     \
133        return true;                                                    \
134    }                                                                   \
135    return false;                                                       \
136}
137
138BASIC_TYPE(Int32,int32Value,int32_t)
139BASIC_TYPE(Int64,int64Value,int64_t)
140BASIC_TYPE(Size,sizeValue,size_t)
141BASIC_TYPE(Float,floatValue,float)
142BASIC_TYPE(Double,doubleValue,double)
143BASIC_TYPE(Pointer,ptrValue,void *)
144
145#undef BASIC_TYPE
146
147void AMessage::setString(
148        const char *name, const char *s, ssize_t len) {
149    Item *item = allocateItem(name);
150    item->mType = kTypeString;
151    item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
152}
153
154void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
155    Item *item = allocateItem(name);
156    item->mType = kTypeObject;
157
158    if (obj != NULL) { obj->incStrong(this); }
159    item->u.refValue = obj.get();
160}
161
162void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
163    Item *item = allocateItem(name);
164    item->mType = kTypeMessage;
165
166    if (obj != NULL) { obj->incStrong(this); }
167    item->u.refValue = obj.get();
168}
169
170bool AMessage::findString(const char *name, AString *value) const {
171    const Item *item = findItem(name, kTypeString);
172    if (item) {
173        *value = *item->u.stringValue;
174        return true;
175    }
176    return false;
177}
178
179bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
180    const Item *item = findItem(name, kTypeObject);
181    if (item) {
182        *obj = item->u.refValue;
183        return true;
184    }
185    return false;
186}
187
188bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
189    const Item *item = findItem(name, kTypeMessage);
190    if (item) {
191        *obj = static_cast<AMessage *>(item->u.refValue);
192        return true;
193    }
194    return false;
195}
196
197void AMessage::post(int64_t delayUs) {
198    extern ALooperRoster gLooperRoster;
199
200    gLooperRoster.postMessage(this, delayUs);
201}
202
203sp<AMessage> AMessage::dup() const {
204    sp<AMessage> msg = new AMessage(mWhat, mTarget);
205    msg->mNumItems = mNumItems;
206
207    for (size_t i = 0; i < mNumItems; ++i) {
208        const Item *from = &mItems[i];
209        Item *to = &msg->mItems[i];
210
211        to->mName = from->mName;
212        to->mType = from->mType;
213
214        switch (from->mType) {
215            case kTypeString:
216            {
217                to->u.stringValue =
218                    new AString(*from->u.stringValue);
219                break;
220            }
221
222            case kTypeObject:
223            case kTypeMessage:
224            {
225                to->u.refValue = from->u.refValue;
226                to->u.refValue->incStrong(msg.get());
227                break;
228            }
229
230            default:
231            {
232                to->u = from->u;
233                break;
234            }
235        }
236    }
237
238    return msg;
239}
240
241}  // namespace android
242