AMessage.cpp revision bbc2b8289458cfde931b133bad0c9d1026674ee7
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "AMessage.h" 18 19#include <ctype.h> 20 21#include "AAtomizer.h" 22#include "ADebug.h" 23#include "ALooperRoster.h" 24#include "AString.h" 25 26namespace android { 27 28AMessage::AMessage(uint32_t what, ALooper::handler_id target) 29 : mWhat(what), 30 mTarget(target), 31 mNumItems(0) { 32} 33 34AMessage::~AMessage() { 35 clear(); 36} 37 38void AMessage::setWhat(uint32_t what) { 39 mWhat = what; 40} 41 42uint32_t AMessage::what() const { 43 return mWhat; 44} 45 46void AMessage::setTarget(ALooper::handler_id handlerID) { 47 mTarget = handlerID; 48} 49 50ALooper::handler_id AMessage::target() const { 51 return mTarget; 52} 53 54void AMessage::clear() { 55 for (size_t i = 0; i < mNumItems; ++i) { 56 Item *item = &mItems[i]; 57 freeItem(item); 58 } 59 mNumItems = 0; 60} 61 62void AMessage::freeItem(Item *item) { 63 switch (item->mType) { 64 case kTypeString: 65 { 66 delete item->u.stringValue; 67 break; 68 } 69 70 case kTypeObject: 71 case kTypeMessage: 72 { 73 if (item->u.refValue != NULL) { 74 item->u.refValue->decStrong(this); 75 } 76 break; 77 } 78 79 default: 80 break; 81 } 82} 83 84AMessage::Item *AMessage::allocateItem(const char *name) { 85 name = AAtomizer::Atomize(name); 86 87 size_t i = 0; 88 while (i < mNumItems && mItems[i].mName != name) { 89 ++i; 90 } 91 92 Item *item; 93 94 if (i < mNumItems) { 95 item = &mItems[i]; 96 freeItem(item); 97 } else { 98 CHECK(mNumItems < kMaxNumItems); 99 i = mNumItems++; 100 item = &mItems[i]; 101 102 item->mName = name; 103 } 104 105 return item; 106} 107 108const AMessage::Item *AMessage::findItem( 109 const char *name, Type type) const { 110 name = AAtomizer::Atomize(name); 111 112 for (size_t i = 0; i < mNumItems; ++i) { 113 const Item *item = &mItems[i]; 114 115 if (item->mName == name) { 116 return item->mType == type ? item : NULL; 117 } 118 } 119 120 return NULL; 121} 122 123#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ 124void AMessage::set##NAME(const char *name, TYPENAME value) { \ 125 Item *item = allocateItem(name); \ 126 \ 127 item->mType = kType##NAME; \ 128 item->u.FIELDNAME = value; \ 129} \ 130 \ 131bool AMessage::find##NAME(const char *name, TYPENAME *value) const { \ 132 const Item *item = findItem(name, kType##NAME); \ 133 if (item) { \ 134 *value = item->u.FIELDNAME; \ 135 return true; \ 136 } \ 137 return false; \ 138} 139 140BASIC_TYPE(Int32,int32Value,int32_t) 141BASIC_TYPE(Int64,int64Value,int64_t) 142BASIC_TYPE(Size,sizeValue,size_t) 143BASIC_TYPE(Float,floatValue,float) 144BASIC_TYPE(Double,doubleValue,double) 145BASIC_TYPE(Pointer,ptrValue,void *) 146 147#undef BASIC_TYPE 148 149void AMessage::setString( 150 const char *name, const char *s, ssize_t len) { 151 Item *item = allocateItem(name); 152 item->mType = kTypeString; 153 item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); 154} 155 156void AMessage::setObject(const char *name, const sp<RefBase> &obj) { 157 Item *item = allocateItem(name); 158 item->mType = kTypeObject; 159 160 if (obj != NULL) { obj->incStrong(this); } 161 item->u.refValue = obj.get(); 162} 163 164void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { 165 Item *item = allocateItem(name); 166 item->mType = kTypeMessage; 167 168 if (obj != NULL) { obj->incStrong(this); } 169 item->u.refValue = obj.get(); 170} 171 172bool AMessage::findString(const char *name, AString *value) const { 173 const Item *item = findItem(name, kTypeString); 174 if (item) { 175 *value = *item->u.stringValue; 176 return true; 177 } 178 return false; 179} 180 181bool AMessage::findObject(const char *name, sp<RefBase> *obj) const { 182 const Item *item = findItem(name, kTypeObject); 183 if (item) { 184 *obj = item->u.refValue; 185 return true; 186 } 187 return false; 188} 189 190bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const { 191 const Item *item = findItem(name, kTypeMessage); 192 if (item) { 193 *obj = static_cast<AMessage *>(item->u.refValue); 194 return true; 195 } 196 return false; 197} 198 199void AMessage::post(int64_t delayUs) { 200 extern ALooperRoster gLooperRoster; 201 202 gLooperRoster.postMessage(this, delayUs); 203} 204 205sp<AMessage> AMessage::dup() const { 206 sp<AMessage> msg = new AMessage(mWhat, mTarget); 207 msg->mNumItems = mNumItems; 208 209 for (size_t i = 0; i < mNumItems; ++i) { 210 const Item *from = &mItems[i]; 211 Item *to = &msg->mItems[i]; 212 213 to->mName = from->mName; 214 to->mType = from->mType; 215 216 switch (from->mType) { 217 case kTypeString: 218 { 219 to->u.stringValue = 220 new AString(*from->u.stringValue); 221 break; 222 } 223 224 case kTypeObject: 225 case kTypeMessage: 226 { 227 to->u.refValue = from->u.refValue; 228 to->u.refValue->incStrong(msg.get()); 229 break; 230 } 231 232 default: 233 { 234 to->u = from->u; 235 break; 236 } 237 } 238 } 239 240 return msg; 241} 242 243static void appendIndent(AString *s, int32_t indent) { 244 static const char kWhitespace[] = 245 " " 246 " "; 247 248 CHECK_LT((size_t)indent, sizeof(kWhitespace)); 249 250 s->append(kWhitespace, indent); 251} 252 253static bool isFourcc(uint32_t what) { 254 return isprint(what & 0xff) 255 && isprint((what >> 8) & 0xff) 256 && isprint((what >> 16) & 0xff) 257 && isprint((what >> 24) & 0xff); 258} 259 260AString AMessage::debugString(int32_t indent) const { 261 AString s = "AMessage(what = "; 262 263 AString tmp; 264 if (isFourcc(mWhat)) { 265 tmp = StringPrintf( 266 "'%c%c%c%c'", 267 (char)(mWhat >> 24), 268 (char)((mWhat >> 16) & 0xff), 269 (char)((mWhat >> 8) & 0xff), 270 (char)(mWhat & 0xff)); 271 } else { 272 tmp = StringPrintf("0x%08x", mWhat); 273 } 274 s.append(tmp); 275 276 if (mTarget != 0) { 277 tmp = StringPrintf(", target = %d", mTarget); 278 s.append(tmp); 279 } 280 s.append(") = {\n"); 281 282 for (size_t i = 0; i < mNumItems; ++i) { 283 const Item &item = mItems[i]; 284 285 switch (item.mType) { 286 case kTypeInt32: 287 tmp = StringPrintf( 288 "int32_t %s = %d", item.mName, item.u.int32Value); 289 break; 290 case kTypeInt64: 291 tmp = StringPrintf( 292 "int64_t %s = %lld", item.mName, item.u.int64Value); 293 break; 294 case kTypeSize: 295 tmp = StringPrintf( 296 "size_t %s = %d", item.mName, item.u.sizeValue); 297 break; 298 case kTypeFloat: 299 tmp = StringPrintf( 300 "float %s = %f", item.mName, item.u.floatValue); 301 break; 302 case kTypeDouble: 303 tmp = StringPrintf( 304 "double %s = %f", item.mName, item.u.doubleValue); 305 break; 306 case kTypePointer: 307 tmp = StringPrintf( 308 "void *%s = %p", item.mName, item.u.ptrValue); 309 break; 310 case kTypeString: 311 tmp = StringPrintf( 312 "string %s = \"%s\"", 313 item.mName, 314 item.u.stringValue->c_str()); 315 break; 316 case kTypeObject: 317 tmp = StringPrintf( 318 "RefBase *%s = %p", item.mName, item.u.refValue); 319 break; 320 case kTypeMessage: 321 tmp = StringPrintf( 322 "AMessage %s = %s", 323 item.mName, 324 static_cast<AMessage *>( 325 item.u.refValue)->debugString( 326 indent + strlen(item.mName) + 14).c_str()); 327 break; 328 default: 329 TRESPASS(); 330 } 331 332 appendIndent(&s, indent); 333 s.append(" "); 334 s.append(tmp); 335 s.append("\n"); 336 } 337 338 appendIndent(&s, indent); 339 s.append("}"); 340 341 return s; 342} 343 344} // namespace android 345