blob: 6be7254c6059799b1123c7374552d07709aab846 [file] [log] [blame]
Yifan Hong7f97f442016-11-14 18:31:05 -08001/*
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
Martijn Coenen30791002016-12-01 15:40:46 +010028const 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) {
Steven Moreland1f535a22017-01-06 19:25:49 -080033 const native_handle_t *handle;
34 ::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
Martijn Coenen30791002016-12-01 15:40:46 +010035 parentHandle,
Steven Moreland1f535a22017-01-06 19:25:49 -080036 parentOffset + hidl_memory::kOffsetOfHandle,
37 &handle);
Martijn Coenen30791002016-12-01 15:40:46 +010038
Steven Moreland1f535a22017-01-06 19:25:49 -080039 if (_hidl_err == ::android::OK) {
40 _hidl_err = readEmbeddedFromParcel(
41 (hidl_string*) nullptr,
42 parcel,
43 parentHandle,
44 parentOffset + hidl_memory::kOffsetOfName);
Martijn Coenen30791002016-12-01 15:40:46 +010045 }
46
Martijn Coenen30791002016-12-01 15:40:46 +010047 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}
Yifan Hong7f97f442016-11-14 18:31:05 -080067// 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) {
Steven Moreland1f535a22017-01-06 19:25:49 -080072 const void *out;
73 return parcel.readEmbeddedBuffer(
Yifan Hong7f97f442016-11-14 18:31:05 -080074 nullptr /* buffer_handle */,
75 parentHandle,
Steven Moreland1f535a22017-01-06 19:25:49 -080076 parentOffset + hidl_string::kOffsetOfBuffer,
77 &out);
Yifan Hong7f97f442016-11-14 18:31:05 -080078}
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