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