Robert Quattlebaum | 6316f5b | 2017-01-04 13:25:14 -0800 | [diff] [blame] | 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 :*/ |