blob: 38e06400cccc76abd9007c17f2f6f8e93a9ae8c2 [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) {
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}
Yifan Hong7f97f442016-11-14 18:31:05 -080069// 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