blob: fd1dfd5ada48d4c6df97074f9d257f9a35c959d9 [file] [log] [blame]
Robert Quattlebaum6316f5b2017-01-04 13:25:14 -08001/*
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
30using android::BAD_TYPE;
31using android::BAD_VALUE;
32using android::NO_ERROR;
33using android::UNEXPECTED_NULL;
34using android::Parcel;
35using android::sp;
36using android::status_t;
37using std::map;
38using std::set;
39using std::vector;
40using android::binder::Value;
41using android::IBinder;
42using android::os::PersistableBundle;
43using 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. */
63template<class T> const void* internal_type_ptr()
64{
65 static const T *marker;
66 return (void*)&marker;
67}
68
69/* Allows the type to be specified by the argument
70 * instead of inside angle brackets. */
71template<class T> const void* internal_type_ptr(const T&)
72{
73 return internal_type_ptr<T>();
74}
75
76// ====================================================================
77
78namespace android {
79
80namespace binder {
81
82class Value::ContentBase {
83public:
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. */
97template<typename T> class Value::Content : public Value::ContentBase {
98public:
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
132template<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
146Value::Value() : mContent(NULL)
147{
148}
149
150Value::Value(const Value& value)
151 : mContent(value.mContent ? value.mContent->clone() : NULL)
152{
153}
154
155Value::~Value()
156{
157 delete mContent;
158}
159
160bool 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
177Value& Value::swap(Value &rhs)
178{
179 std::swap(mContent, rhs.mContent);
180 return *this;
181}
182
183Value& Value::operator=(const Value& rhs)
184{
185 delete mContent;
186 mContent = rhs.mContent
187 ? rhs.mContent->clone()
188 : NULL;
189 return *this;
190}
191
192bool Value::empty() const
193{
194 return mContent == NULL;
195}
196
197void Value::clear()
198{
199 delete mContent;
200 mContent = NULL;
201}
202
203int32_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
228const 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
263DEF_TYPE_ACCESSORS(bool, Boolean)
264DEF_TYPE_ACCESSORS(int8_t, Byte)
265DEF_TYPE_ACCESSORS(int32_t, Int)
266DEF_TYPE_ACCESSORS(int64_t, Long)
267DEF_TYPE_ACCESSORS(double, Double)
268DEF_TYPE_ACCESSORS(String16, String)
269
270DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
271DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
272DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
273DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
274DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
275DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
276
277DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
278DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
279
280bool 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
290bool 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
300status_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
356status_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 :*/