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