1 /* 2 * Copyright (C) 2015 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 #define LOG_TAG "Value" 18 19 #include <binder/Value.h> 20 21 #include <limits> 22 23 #include <binder/IBinder.h> 24 #include <binder/Parcel.h> 25 #include <binder/Map.h> 26 #include <private/binder/ParcelValTypes.h> 27 #include <log/log.h> 28 #include <utils/Errors.h> 29 30 using android::BAD_TYPE; 31 using android::BAD_VALUE; 32 using android::NO_ERROR; 33 using android::UNEXPECTED_NULL; 34 using android::Parcel; 35 using android::sp; 36 using android::status_t; 37 using std::map; 38 using std::set; 39 using std::vector; 40 using android::binder::Value; 41 using android::IBinder; 42 using android::os::PersistableBundle; 43 using namespace android::binder; 44 45 // ==================================================================== 46 47 #define RETURN_IF_FAILED(calledOnce) \ 48 do { \ 49 status_t returnStatus = calledOnce; \ 50 if (returnStatus) { \ 51 ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \ 52 return returnStatus; \ 53 } \ 54 } while(false) 55 56 // ==================================================================== 57 58 /* These `internal_type_ptr()` functions allow this 59 * class to work without C++ RTTI support. This technique 60 * only works properly when called directly from this file, 61 * but that is OK because that is the only place we will 62 * be calling them from. */ 63 template<class T> const void* internal_type_ptr() 64 { 65 static const T *marker; 66 return (void*)▮ 67 } 68 69 /* Allows the type to be specified by the argument 70 * instead of inside angle brackets. */ 71 template<class T> const void* internal_type_ptr(const T&) 72 { 73 return internal_type_ptr<T>(); 74 } 75 76 // ==================================================================== 77 78 namespace android { 79 80 namespace binder { 81 82 class Value::ContentBase { 83 public: 84 virtual ~ContentBase() = default; 85 virtual const void* type_ptr() const = 0; 86 virtual ContentBase * clone() const = 0; 87 virtual bool operator==(const ContentBase& rhs) const = 0; 88 89 #ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO 90 virtual const std::type_info &type() const = 0; 91 #endif 92 93 template<typename T> bool get(T* out) const; 94 }; 95 96 /* This is the actual class that holds the value. */ 97 template<typename T> class Value::Content : public Value::ContentBase { 98 public: 99 Content() = default; 100 Content(const T & value) : mValue(value) { } 101 102 virtual ~Content() = default; 103 104 #ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO 105 virtual const std::type_info &type() const override 106 { 107 return typeid(T); 108 } 109 #endif 110 111 virtual const void* type_ptr() const override 112 { 113 return internal_type_ptr<T>(); 114 } 115 116 virtual ContentBase * clone() const override 117 { 118 return new Content(mValue); 119 }; 120 121 virtual bool operator==(const ContentBase& rhs) const override 122 { 123 if (type_ptr() != rhs.type_ptr()) { 124 return false; 125 } 126 return mValue == static_cast<const Content<T>* >(&rhs)->mValue; 127 } 128 129 T mValue; 130 }; 131 132 template<typename T> bool Value::ContentBase::get(T* out) const 133 { 134 if (internal_type_ptr(*out) != type_ptr()) 135 { 136 return false; 137 } 138 139 *out = static_cast<const Content<T>*>(this)->mValue; 140 141 return true; 142 } 143 144 // ==================================================================== 145 146 Value::Value() : mContent(NULL) 147 { 148 } 149 150 Value::Value(const Value& value) 151 : mContent(value.mContent ? value.mContent->clone() : NULL) 152 { 153 } 154 155 Value::~Value() 156 { 157 delete mContent; 158 } 159 160 bool Value::operator==(const Value& rhs) const 161 { 162 const Value& lhs(*this); 163 164 if (lhs.empty() && rhs.empty()) { 165 return true; 166 } 167 168 if ( (lhs.mContent == NULL) 169 || (rhs.mContent == NULL) 170 ) { 171 return false; 172 } 173 174 return *lhs.mContent == *rhs.mContent; 175 } 176 177 Value& Value::swap(Value &rhs) 178 { 179 std::swap(mContent, rhs.mContent); 180 return *this; 181 } 182 183 Value& Value::operator=(const Value& rhs) 184 { 185 delete mContent; 186 mContent = rhs.mContent 187 ? rhs.mContent->clone() 188 : NULL; 189 return *this; 190 } 191 192 bool Value::empty() const 193 { 194 return mContent == NULL; 195 } 196 197 void Value::clear() 198 { 199 delete mContent; 200 mContent = NULL; 201 } 202 203 int32_t Value::parcelType() const 204 { 205 const void* t_info(mContent ? mContent->type_ptr() : NULL); 206 207 if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN; 208 if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE; 209 if (t_info == internal_type_ptr<int32_t>()) return VAL_INTEGER; 210 if (t_info == internal_type_ptr<int64_t>()) return VAL_LONG; 211 if (t_info == internal_type_ptr<double>()) return VAL_DOUBLE; 212 if (t_info == internal_type_ptr<String16>()) return VAL_STRING; 213 214 if (t_info == internal_type_ptr<vector<bool>>()) return VAL_BOOLEANARRAY; 215 if (t_info == internal_type_ptr<vector<uint8_t>>()) return VAL_BYTEARRAY; 216 if (t_info == internal_type_ptr<vector<int32_t>>()) return VAL_INTARRAY; 217 if (t_info == internal_type_ptr<vector<int64_t>>()) return VAL_LONGARRAY; 218 if (t_info == internal_type_ptr<vector<double>>()) return VAL_DOUBLEARRAY; 219 if (t_info == internal_type_ptr<vector<String16>>()) return VAL_STRINGARRAY; 220 221 if (t_info == internal_type_ptr<Map>()) return VAL_MAP; 222 if (t_info == internal_type_ptr<PersistableBundle>()) return VAL_PERSISTABLEBUNDLE; 223 224 return VAL_NULL; 225 } 226 227 #ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO 228 const std::type_info& Value::type() const 229 { 230 return mContent != NULL 231 ? mContent->type() 232 : typeid(void); 233 } 234 #endif // ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO 235 236 #define DEF_TYPE_ACCESSORS(T, TYPENAME) \ 237 bool Value::is ## TYPENAME() const \ 238 { \ 239 return mContent \ 240 ? internal_type_ptr<T>() == mContent->type_ptr() \ 241 : false; \ 242 } \ 243 bool Value::get ## TYPENAME(T* out) const \ 244 { \ 245 return mContent \ 246 ? mContent->get(out) \ 247 : false; \ 248 } \ 249 void Value::put ## TYPENAME(const T& in) \ 250 { \ 251 *this = in; \ 252 } \ 253 Value& Value::operator=(const T& rhs) \ 254 { \ 255 delete mContent; \ 256 mContent = new Content< T >(rhs); \ 257 return *this; \ 258 } \ 259 Value::Value(const T& value) \ 260 : mContent(new Content< T >(value)) \ 261 { } 262 263 DEF_TYPE_ACCESSORS(bool, Boolean) 264 DEF_TYPE_ACCESSORS(int8_t, Byte) 265 DEF_TYPE_ACCESSORS(int32_t, Int) 266 DEF_TYPE_ACCESSORS(int64_t, Long) 267 DEF_TYPE_ACCESSORS(double, Double) 268 DEF_TYPE_ACCESSORS(String16, String) 269 270 DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector) 271 DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector) 272 DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector) 273 DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector) 274 DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector) 275 DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector) 276 277 DEF_TYPE_ACCESSORS(::android::binder::Map, Map) 278 DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle) 279 280 bool Value::getString(String8* out) const 281 { 282 String16 val; 283 bool ret = getString(&val); 284 if (ret) { 285 *out = String8(val); 286 } 287 return ret; 288 } 289 290 bool Value::getString(::std::string* out) const 291 { 292 String8 val; 293 bool ret = getString(&val); 294 if (ret) { 295 *out = val.string(); 296 } 297 return ret; 298 } 299 300 status_t Value::writeToParcel(Parcel* parcel) const 301 { 302 // This implementation needs to be kept in sync with the writeValue 303 // implementation in frameworks/base/core/java/android/os/Parcel.java 304 305 #define BEGIN_HANDLE_WRITE() \ 306 do { \ 307 const void* t_info(mContent?mContent->type_ptr():NULL); \ 308 if (false) { } 309 #define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD) \ 310 else if (t_info == internal_type_ptr<T>()) { \ 311 RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \ 312 RETURN_IF_FAILED(parcel->TYPEMETHOD(static_cast<const Content<T>*>(mContent)->mValue)); \ 313 } 314 #define HANDLE_WRITE_PARCELABLE(T, TYPEVAL) \ 315 else if (t_info == internal_type_ptr<T>()) { \ 316 RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \ 317 RETURN_IF_FAILED(static_cast<const Content<T>*>(mContent)->mValue.writeToParcel(parcel)); \ 318 } 319 #define END_HANDLE_WRITE() \ 320 else { \ 321 ALOGE("writeToParcel: Type not supported"); \ 322 return BAD_TYPE; \ 323 } \ 324 } while (false); 325 326 BEGIN_HANDLE_WRITE() 327 328 HANDLE_WRITE_TYPE(bool, VAL_BOOLEAN, writeBool) 329 HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte) 330 HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte) 331 HANDLE_WRITE_TYPE(int32_t, VAL_INTEGER, writeInt32) 332 HANDLE_WRITE_TYPE(int64_t, VAL_LONG, writeInt64) 333 HANDLE_WRITE_TYPE(double, VAL_DOUBLE, writeDouble) 334 HANDLE_WRITE_TYPE(String16, VAL_STRING, writeString16) 335 336 HANDLE_WRITE_TYPE(vector<bool>, VAL_BOOLEANARRAY, writeBoolVector) 337 HANDLE_WRITE_TYPE(vector<uint8_t>, VAL_BYTEARRAY, writeByteVector) 338 HANDLE_WRITE_TYPE(vector<int8_t>, VAL_BYTEARRAY, writeByteVector) 339 HANDLE_WRITE_TYPE(vector<int32_t>, VAL_INTARRAY, writeInt32Vector) 340 HANDLE_WRITE_TYPE(vector<int64_t>, VAL_LONGARRAY, writeInt64Vector) 341 HANDLE_WRITE_TYPE(vector<double>, VAL_DOUBLEARRAY, writeDoubleVector) 342 HANDLE_WRITE_TYPE(vector<String16>, VAL_STRINGARRAY, writeString16Vector) 343 344 HANDLE_WRITE_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE) 345 346 END_HANDLE_WRITE() 347 348 return NO_ERROR; 349 350 #undef BEGIN_HANDLE_WRITE 351 #undef HANDLE_WRITE_TYPE 352 #undef HANDLE_WRITE_PARCELABLE 353 #undef END_HANDLE_WRITE 354 } 355 356 status_t Value::readFromParcel(const Parcel* parcel) 357 { 358 // This implementation needs to be kept in sync with the readValue 359 // implementation in frameworks/base/core/java/android/os/Parcel.javai 360 361 #define BEGIN_HANDLE_READ() \ 362 switch(value_type) { \ 363 default: \ 364 ALOGE("readFromParcel: Parcel type %d is not supported", value_type); \ 365 return BAD_TYPE; 366 #define HANDLE_READ_TYPE(T, TYPEVAL, TYPEMETHOD) \ 367 case TYPEVAL: \ 368 mContent = new Content<T>(); \ 369 RETURN_IF_FAILED(parcel->TYPEMETHOD(&static_cast<Content<T>*>(mContent)->mValue)); \ 370 break; 371 #define HANDLE_READ_PARCELABLE(T, TYPEVAL) \ 372 case TYPEVAL: \ 373 mContent = new Content<T>(); \ 374 RETURN_IF_FAILED(static_cast<Content<T>*>(mContent)->mValue.readFromParcel(parcel)); \ 375 break; 376 #define END_HANDLE_READ() \ 377 } 378 379 int32_t value_type = VAL_NULL; 380 381 delete mContent; 382 mContent = NULL; 383 384 RETURN_IF_FAILED(parcel->readInt32(&value_type)); 385 386 BEGIN_HANDLE_READ() 387 388 HANDLE_READ_TYPE(bool, VAL_BOOLEAN, readBool) 389 HANDLE_READ_TYPE(int8_t, VAL_BYTE, readByte) 390 HANDLE_READ_TYPE(int32_t, VAL_INTEGER, readInt32) 391 HANDLE_READ_TYPE(int64_t, VAL_LONG, readInt64) 392 HANDLE_READ_TYPE(double, VAL_DOUBLE, readDouble) 393 HANDLE_READ_TYPE(String16, VAL_STRING, readString16) 394 395 HANDLE_READ_TYPE(vector<bool>, VAL_BOOLEANARRAY, readBoolVector) 396 HANDLE_READ_TYPE(vector<uint8_t>, VAL_BYTEARRAY, readByteVector) 397 HANDLE_READ_TYPE(vector<int32_t>, VAL_INTARRAY, readInt32Vector) 398 HANDLE_READ_TYPE(vector<int64_t>, VAL_LONGARRAY, readInt64Vector) 399 HANDLE_READ_TYPE(vector<double>, VAL_DOUBLEARRAY, readDoubleVector) 400 HANDLE_READ_TYPE(vector<String16>, VAL_STRINGARRAY, readString16Vector) 401 402 HANDLE_READ_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE) 403 404 END_HANDLE_READ() 405 406 return NO_ERROR; 407 408 #undef BEGIN_HANDLE_READ 409 #undef HANDLE_READ_TYPE 410 #undef HANDLE_READ_PARCELABLE 411 #undef END_HANDLE_READ 412 } 413 414 } // namespace binder 415 416 } // namespace android 417 418 /* vim: set ts=4 sw=4 tw=0 et :*/ 419