HidlBinderSupport.cpp revision b2c9c75b74c87e651dd08a100015eab17319556e
1/*
2 * Copyright (C) 2016 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 "HidlSupport"
18
19#include <hidl/HidlBinderSupport.h>
20
21#ifdef LIBHIDL_TARGET_DEBUGGABLE
22#include <android-base/logging.h>
23#endif
24
25namespace android {
26namespace hardware {
27
28const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
29const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
30
31status_t readEmbeddedFromParcel(hidl_memory * /* memory */,
32        const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
33    ::android::status_t _hidl_err = ::android::OK;
34    const native_handle_t *_hidl_memory_handle = parcel.readEmbeddedNativeHandle(
35            parentHandle,
36            parentOffset + hidl_memory::kOffsetOfHandle);
37
38    if (_hidl_memory_handle == nullptr) {
39        _hidl_err = ::android::UNKNOWN_ERROR;
40        return _hidl_err;
41    }
42
43    _hidl_err = readEmbeddedFromParcel(
44            (hidl_string*) nullptr,
45            parcel,
46            parentHandle,
47            parentOffset + hidl_memory::kOffsetOfName);
48
49    return _hidl_err;
50}
51
52status_t writeEmbeddedToParcel(const hidl_memory &memory,
53        Parcel *parcel, size_t parentHandle, size_t parentOffset) {
54    status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
55            memory.handle(),
56            parentHandle,
57            parentOffset + hidl_memory::kOffsetOfHandle);
58
59    if (_hidl_err == ::android::OK) {
60        _hidl_err = writeEmbeddedToParcel(
61            memory.name(),
62            parcel,
63            parentHandle,
64            parentOffset + hidl_memory::kOffsetOfName);
65    }
66
67    return _hidl_err;
68}
69// static
70const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer);
71
72status_t readEmbeddedFromParcel(hidl_string * /* string */,
73        const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
74    const void *ptr = parcel.readEmbeddedBuffer(
75            nullptr /* buffer_handle */,
76            parentHandle,
77            parentOffset + hidl_string::kOffsetOfBuffer);
78
79    return ptr != NULL ? OK : UNKNOWN_ERROR;
80}
81
82status_t writeEmbeddedToParcel(const hidl_string &string,
83        Parcel *parcel, size_t parentHandle, size_t parentOffset) {
84    return parcel->writeEmbeddedBuffer(
85            string.c_str(),
86            string.size() + 1,
87            nullptr /* handle */,
88            parentHandle,
89            parentOffset + hidl_string::kOffsetOfBuffer);
90}
91
92android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) {
93    return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor());
94}
95
96hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
97    uint32_t version;
98    android::status_t status = parcel.readUint32(&version);
99    if (status != OK) {
100        return nullptr;
101    } else {
102        return new hidl_version(version >> 16, version & 0xFFFF);
103    }
104}
105
106status_t readFromParcel(Status *s, const Parcel& parcel) {
107    int32_t exception;
108    int32_t errorCode;
109    status_t status = parcel.readInt32(&exception);
110    if (status != OK) {
111        s->setFromStatusT(status);
112        return status;
113    }
114
115    // Skip over fat response headers.  Not used (or propagated) in native code.
116    if (exception == Status::EX_HAS_REPLY_HEADER) {
117        // Note that the header size includes the 4 byte size field.
118        const int32_t header_start = parcel.dataPosition();
119        int32_t header_size;
120        status = parcel.readInt32(&header_size);
121        if (status != OK) {
122            s->setFromStatusT(status);
123            return status;
124        }
125        parcel.setDataPosition(header_start + header_size);
126        // And fat response headers are currently only used when there are no
127        // exceptions, so act like there was no error.
128        exception = Status::EX_NONE;
129    }
130
131    if (exception == Status::EX_NONE) {
132        *s = Status::ok();
133        return status;
134    }
135
136    // The remote threw an exception.  Get the message back.
137    String16 message;
138    status = parcel.readString16(&message);
139    if (status != OK) {
140        s->setFromStatusT(status);
141        return status;
142    }
143
144    if (exception == Status::EX_SERVICE_SPECIFIC) {
145        status = parcel.readInt32(&errorCode);
146    }
147    if (status != OK) {
148        s->setFromStatusT(status);
149        return status;
150    }
151
152    if (exception == Status::EX_SERVICE_SPECIFIC) {
153        s->setServiceSpecificError(errorCode, String8(message));
154    } else {
155        s->setException(exception, String8(message));
156    }
157
158    return status;
159}
160
161status_t writeToParcel(const Status &s, Parcel* parcel) {
162    // Something really bad has happened, and we're not going to even
163    // try returning rich error data.
164    if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
165        return s.transactionError();
166    }
167
168    status_t status = parcel->writeInt32(s.exceptionCode());
169    if (status != OK) { return status; }
170    if (s.exceptionCode() == Status::EX_NONE) {
171        // We have no more information to write.
172        return status;
173    }
174    status = parcel->writeString16(String16(s.exceptionMessage()));
175    if (s.exceptionCode() != Status::EX_SERVICE_SPECIFIC) {
176        // We have no more information to write.
177        return status;
178    }
179    status = parcel->writeInt32(s.serviceSpecificErrorCode());
180    return status;
181}
182
183}  // namespace hardware
184}  // namespace android
185