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. */
internal_type_ptr()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. */
internal_type_ptr(const T &)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;
Content(const T & value)100 explicit Content(const T & value) : mValue(value) { }
101
102 virtual ~Content() = default;
103
104 #ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
type() const105 virtual const std::type_info &type() const override
106 {
107 return typeid(T);
108 }
109 #endif
110
type_ptr() const111 virtual const void* type_ptr() const override
112 {
113 return internal_type_ptr<T>();
114 }
115
clone() const116 virtual ContentBase * clone() const override
117 {
118 return new Content(mValue);
119 };
120
operator ==(const ContentBase & rhs) const121 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
get(T * out) const132 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
Value()146 Value::Value() : mContent(nullptr)
147 {
148 }
149
Value(const Value & value)150 Value::Value(const Value& value)
151 : mContent(value.mContent ? value.mContent->clone() : nullptr)
152 {
153 }
154
~Value()155 Value::~Value()
156 {
157 delete mContent;
158 }
159
operator ==(const Value & rhs) const160 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 == nullptr)
169 || (rhs.mContent == nullptr)
170 ) {
171 return false;
172 }
173
174 return *lhs.mContent == *rhs.mContent;
175 }
176
swap(Value & rhs)177 Value& Value::swap(Value &rhs)
178 {
179 std::swap(mContent, rhs.mContent);
180 return *this;
181 }
182
operator =(const Value & rhs)183 Value& Value::operator=(const Value& rhs)
184 {
185 if (this != &rhs) {
186 delete mContent;
187 mContent = rhs.mContent
188 ? rhs.mContent->clone()
189 : nullptr;
190 }
191 return *this;
192 }
193
empty() const194 bool Value::empty() const
195 {
196 return mContent == nullptr;
197 }
198
clear()199 void Value::clear()
200 {
201 delete mContent;
202 mContent = nullptr;
203 }
204
parcelType() const205 int32_t Value::parcelType() const
206 {
207 const void* t_info(mContent ? mContent->type_ptr() : nullptr);
208
209 if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN;
210 if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE;
211 if (t_info == internal_type_ptr<int32_t>()) return VAL_INTEGER;
212 if (t_info == internal_type_ptr<int64_t>()) return VAL_LONG;
213 if (t_info == internal_type_ptr<double>()) return VAL_DOUBLE;
214 if (t_info == internal_type_ptr<String16>()) return VAL_STRING;
215
216 if (t_info == internal_type_ptr<vector<bool>>()) return VAL_BOOLEANARRAY;
217 if (t_info == internal_type_ptr<vector<uint8_t>>()) return VAL_BYTEARRAY;
218 if (t_info == internal_type_ptr<vector<int32_t>>()) return VAL_INTARRAY;
219 if (t_info == internal_type_ptr<vector<int64_t>>()) return VAL_LONGARRAY;
220 if (t_info == internal_type_ptr<vector<double>>()) return VAL_DOUBLEARRAY;
221 if (t_info == internal_type_ptr<vector<String16>>()) return VAL_STRINGARRAY;
222
223 if (t_info == internal_type_ptr<Map>()) return VAL_MAP;
224 if (t_info == internal_type_ptr<PersistableBundle>()) return VAL_PERSISTABLEBUNDLE;
225
226 return VAL_NULL;
227 }
228
229 #ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
type() const230 const std::type_info& Value::type() const
231 {
232 return mContent != nullptr
233 ? mContent->type()
234 : typeid(void);
235 }
236 #endif // ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
237
238 #define DEF_TYPE_ACCESSORS(T, TYPENAME) \
239 bool Value::is ## TYPENAME() const \
240 { \
241 return mContent \
242 ? internal_type_ptr<T>() == mContent->type_ptr() \
243 : false; \
244 } \
245 bool Value::get ## TYPENAME(T* out) const \
246 { \
247 return mContent \
248 ? mContent->get(out) \
249 : false; \
250 } \
251 void Value::put ## TYPENAME(const T& in) \
252 { \
253 *this = in; \
254 } \
255 Value& Value::operator=(const T& rhs) \
256 { \
257 delete mContent; \
258 mContent = new Content< T >(rhs); \
259 return *this; \
260 } \
261 Value::Value(const T& value) \
262 : mContent(new Content< T >(value)) \
263 { }
264
DEF_TYPE_ACCESSORS(bool,Boolean)265 DEF_TYPE_ACCESSORS(bool, Boolean)
266 DEF_TYPE_ACCESSORS(int8_t, Byte)
267 DEF_TYPE_ACCESSORS(int32_t, Int)
268 DEF_TYPE_ACCESSORS(int64_t, Long)
269 DEF_TYPE_ACCESSORS(double, Double)
270 DEF_TYPE_ACCESSORS(String16, String)
271
272 DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
273 DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
274 DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
275 DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
276 DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
277 DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
278
279 DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
280 DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
281
282 bool Value::getString(String8* out) const
283 {
284 String16 val;
285 bool ret = getString(&val);
286 if (ret) {
287 *out = String8(val);
288 }
289 return ret;
290 }
291
getString(::std::string * out) const292 bool Value::getString(::std::string* out) const
293 {
294 String8 val;
295 bool ret = getString(&val);
296 if (ret) {
297 *out = val.string();
298 }
299 return ret;
300 }
301
writeToParcel(Parcel * parcel) const302 status_t Value::writeToParcel(Parcel* parcel) const
303 {
304 // This implementation needs to be kept in sync with the writeValue
305 // implementation in frameworks/base/core/java/android/os/Parcel.java
306
307 #define BEGIN_HANDLE_WRITE() \
308 do { \
309 const void* t_info(mContent?mContent->type_ptr():nullptr); \
310 if (false) { }
311 #define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD) \
312 else if (t_info == internal_type_ptr<T>()) { \
313 RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \
314 RETURN_IF_FAILED(parcel->TYPEMETHOD(static_cast<const Content<T>*>(mContent)->mValue)); \
315 }
316 #define HANDLE_WRITE_PARCELABLE(T, TYPEVAL) \
317 else if (t_info == internal_type_ptr<T>()) { \
318 RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \
319 RETURN_IF_FAILED(static_cast<const Content<T>*>(mContent)->mValue.writeToParcel(parcel)); \
320 }
321 #define END_HANDLE_WRITE() \
322 else { \
323 ALOGE("writeToParcel: Type not supported"); \
324 return BAD_TYPE; \
325 } \
326 } while (false);
327
328 BEGIN_HANDLE_WRITE()
329
330 HANDLE_WRITE_TYPE(bool, VAL_BOOLEAN, writeBool)
331 HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte)
332 HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte)
333 HANDLE_WRITE_TYPE(int32_t, VAL_INTEGER, writeInt32)
334 HANDLE_WRITE_TYPE(int64_t, VAL_LONG, writeInt64)
335 HANDLE_WRITE_TYPE(double, VAL_DOUBLE, writeDouble)
336 HANDLE_WRITE_TYPE(String16, VAL_STRING, writeString16)
337
338 HANDLE_WRITE_TYPE(vector<bool>, VAL_BOOLEANARRAY, writeBoolVector)
339 HANDLE_WRITE_TYPE(vector<uint8_t>, VAL_BYTEARRAY, writeByteVector)
340 HANDLE_WRITE_TYPE(vector<int8_t>, VAL_BYTEARRAY, writeByteVector)
341 HANDLE_WRITE_TYPE(vector<int32_t>, VAL_INTARRAY, writeInt32Vector)
342 HANDLE_WRITE_TYPE(vector<int64_t>, VAL_LONGARRAY, writeInt64Vector)
343 HANDLE_WRITE_TYPE(vector<double>, VAL_DOUBLEARRAY, writeDoubleVector)
344 HANDLE_WRITE_TYPE(vector<String16>, VAL_STRINGARRAY, writeString16Vector)
345
346 HANDLE_WRITE_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
347
348 END_HANDLE_WRITE()
349
350 return NO_ERROR;
351
352 #undef BEGIN_HANDLE_WRITE
353 #undef HANDLE_WRITE_TYPE
354 #undef HANDLE_WRITE_PARCELABLE
355 #undef END_HANDLE_WRITE
356 }
357
readFromParcel(const Parcel * parcel)358 status_t Value::readFromParcel(const Parcel* parcel)
359 {
360 // This implementation needs to be kept in sync with the readValue
361 // implementation in frameworks/base/core/java/android/os/Parcel.javai
362
363 #define BEGIN_HANDLE_READ() \
364 switch(value_type) { \
365 default: \
366 ALOGE("readFromParcel: Parcel type %d is not supported", value_type); \
367 return BAD_TYPE;
368 #define HANDLE_READ_TYPE(T, TYPEVAL, TYPEMETHOD) \
369 case TYPEVAL: \
370 mContent = new Content<T>(); \
371 RETURN_IF_FAILED(parcel->TYPEMETHOD(&static_cast<Content<T>*>(mContent)->mValue)); \
372 break;
373 #define HANDLE_READ_PARCELABLE(T, TYPEVAL) \
374 case TYPEVAL: \
375 mContent = new Content<T>(); \
376 RETURN_IF_FAILED(static_cast<Content<T>*>(mContent)->mValue.readFromParcel(parcel)); \
377 break;
378 #define END_HANDLE_READ() \
379 }
380
381 int32_t value_type = VAL_NULL;
382
383 delete mContent;
384 mContent = nullptr;
385
386 RETURN_IF_FAILED(parcel->readInt32(&value_type));
387
388 BEGIN_HANDLE_READ()
389
390 HANDLE_READ_TYPE(bool, VAL_BOOLEAN, readBool)
391 HANDLE_READ_TYPE(int8_t, VAL_BYTE, readByte)
392 HANDLE_READ_TYPE(int32_t, VAL_INTEGER, readInt32)
393 HANDLE_READ_TYPE(int64_t, VAL_LONG, readInt64)
394 HANDLE_READ_TYPE(double, VAL_DOUBLE, readDouble)
395 HANDLE_READ_TYPE(String16, VAL_STRING, readString16)
396
397 HANDLE_READ_TYPE(vector<bool>, VAL_BOOLEANARRAY, readBoolVector)
398 HANDLE_READ_TYPE(vector<uint8_t>, VAL_BYTEARRAY, readByteVector)
399 HANDLE_READ_TYPE(vector<int32_t>, VAL_INTARRAY, readInt32Vector)
400 HANDLE_READ_TYPE(vector<int64_t>, VAL_LONGARRAY, readInt64Vector)
401 HANDLE_READ_TYPE(vector<double>, VAL_DOUBLEARRAY, readDoubleVector)
402 HANDLE_READ_TYPE(vector<String16>, VAL_STRINGARRAY, readString16Vector)
403
404 HANDLE_READ_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
405
406 END_HANDLE_READ()
407
408 return NO_ERROR;
409
410 #undef BEGIN_HANDLE_READ
411 #undef HANDLE_READ_TYPE
412 #undef HANDLE_READ_PARCELABLE
413 #undef END_HANDLE_READ
414 }
415
416 } // namespace binder
417
418 } // namespace android
419
420 /* vim: set ts=4 sw=4 tw=0 et :*/
421