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
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    if (this != &rhs) {
186        delete mContent;
187        mContent = rhs.mContent
188            ? rhs.mContent->clone()
189            : NULL;
190    }
191    return *this;
192}
193
194bool Value::empty() const
195{
196    return mContent == NULL;
197}
198
199void Value::clear()
200{
201    delete mContent;
202    mContent = NULL;
203}
204
205int32_t Value::parcelType() const
206{
207    const void* t_info(mContent ? mContent->type_ptr() : NULL);
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
230const std::type_info& Value::type() const
231{
232    return mContent != NULL
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
265DEF_TYPE_ACCESSORS(bool, Boolean)
266DEF_TYPE_ACCESSORS(int8_t, Byte)
267DEF_TYPE_ACCESSORS(int32_t, Int)
268DEF_TYPE_ACCESSORS(int64_t, Long)
269DEF_TYPE_ACCESSORS(double, Double)
270DEF_TYPE_ACCESSORS(String16, String)
271
272DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
273DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
274DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
275DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
276DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
277DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
278
279DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
280DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
281
282bool 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
292bool 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
302status_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():NULL);                                   \
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
358status_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 = NULL;
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