blob: 38ff6c900c4eb9f1b36b4de32aff53b53af7b679 [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#ifndef ANDROID_HIDL_BINDER_SUPPORT_H
18#define ANDROID_HIDL_BINDER_SUPPORT_H
19
20#include <hidl/HidlSupport.h>
Martijn Coenen12f04d92016-12-07 17:29:41 +010021#include <hidl/HidlTransportUtils.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080022#include <hidl/MQDescriptor.h>
Yifan Hongb2c9c752016-12-07 15:15:41 -080023#include <hidl/Static.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080024#include <hwbinder/IBinder.h>
25#include <hwbinder/Parcel.h>
Martijn Coenen12f04d92016-12-07 17:29:41 +010026#include <android/hidl/base/1.0/BnBase.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080027// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
28// etc. to interact with Parcel.
29
30namespace android {
31namespace hardware {
32
Martijn Coenen30791002016-12-01 15:40:46 +010033// ---------------------- hidl_memory
34
35status_t readEmbeddedFromParcel(hidl_memory *memory,
36 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
37
38status_t writeEmbeddedToParcel(const hidl_memory &memory,
39 Parcel *parcel, size_t parentHandle, size_t parentOffset);
40
Yifan Hong7f97f442016-11-14 18:31:05 -080041// ---------------------- hidl_string
42
43status_t readEmbeddedFromParcel(hidl_string *string,
44 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
45
46status_t writeEmbeddedToParcel(const hidl_string &string,
47 Parcel *parcel, size_t parentHandle, size_t parentOffset);
48
49// ---------------------- hidl_version
50
51status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
52
53// Caller is responsible for freeing the returned object.
54hidl_version* readFromParcel(const android::hardware::Parcel& parcel);
55
56// ---------------------- Status
57
58// Bear in mind that if the client or service is a Java endpoint, this
59// is not the logic which will provide/interpret the data here.
60status_t readFromParcel(Status *status, const Parcel& parcel);
61status_t writeToParcel(const Status &status, Parcel* parcel);
62
63// ---------------------- hidl_vec
64
65template<typename T>
66status_t readEmbeddedFromParcel(
67 hidl_vec<T> * /*vec*/,
68 const Parcel &parcel,
69 size_t parentHandle,
70 size_t parentOffset,
71 size_t *handle) {
72 const void *ptr = parcel.readEmbeddedBuffer(
73 handle,
74 parentHandle,
75 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
76
77 return ptr != NULL ? OK : UNKNOWN_ERROR;
78}
79
80template<typename T>
81status_t writeEmbeddedToParcel(
82 const hidl_vec<T> &vec,
83 Parcel *parcel,
84 size_t parentHandle,
85 size_t parentOffset,
86 size_t *handle) {
87 return parcel->writeEmbeddedBuffer(
88 vec.data(),
89 sizeof(T) * vec.size(),
90 handle,
91 parentHandle,
92 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
93}
94
95template<typename T>
96status_t findInParcel(const hidl_vec<T> &vec, const Parcel &parcel, size_t *handle) {
97 return parcel.quickFindBuffer(vec.data(), handle);
98}
99
100// ---------------------- MQDescriptor
101
102template<MQFlavor flavor>
103::android::status_t readEmbeddedFromParcel(
104 MQDescriptor<flavor> *obj,
105 const ::android::hardware::Parcel &parcel,
106 size_t parentHandle,
107 size_t parentOffset) {
108 ::android::status_t _hidl_err = ::android::OK;
109
110 size_t _hidl_grantors_child;
111
112 _hidl_err = ::android::hardware::readEmbeddedFromParcel(
113 &obj->grantors(),
114 parcel,
115 parentHandle,
116 parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors,
117 &_hidl_grantors_child);
118
119 if (_hidl_err != ::android::OK) { return _hidl_err; }
120
121 const native_handle_t *_hidl_mq_handle_ptr = parcel.readEmbeddedNativeHandle(
122 parentHandle,
123 parentOffset + MQDescriptor<flavor>::kOffsetOfHandle);
124
125 if (_hidl_mq_handle_ptr == nullptr) {
126 _hidl_err = ::android::UNKNOWN_ERROR;
127 return _hidl_err;
128 }
129
130 return _hidl_err;
131}
132
133template<MQFlavor flavor>
134::android::status_t writeEmbeddedToParcel(
135 const MQDescriptor<flavor> &obj,
136 ::android::hardware::Parcel *parcel,
137 size_t parentHandle,
138 size_t parentOffset) {
139 ::android::status_t _hidl_err = ::android::OK;
140
141 size_t _hidl_grantors_child;
142
143 _hidl_err = ::android::hardware::writeEmbeddedToParcel(
144 obj.grantors(),
145 parcel,
146 parentHandle,
147 parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors,
148 &_hidl_grantors_child);
149
150 if (_hidl_err != ::android::OK) { return _hidl_err; }
151
152 _hidl_err = parcel->writeEmbeddedNativeHandle(
153 obj.handle(),
154 parentHandle,
155 parentOffset + MQDescriptor<flavor>::kOffsetOfHandle);
156
157 if (_hidl_err != ::android::OK) { return _hidl_err; }
158
159 return _hidl_err;
160}
161
162// ---------------------- pointers for HIDL
163
164template <typename T>
165static status_t readEmbeddedReferenceFromParcel(
166 T const* * /* bufptr */,
167 const Parcel & parcel,
168 size_t parentHandle,
169 size_t parentOffset,
170 size_t *handle,
171 bool *shouldResolveRefInBuffer
172 ) {
173 // *bufptr is ignored because, if I am embedded in some
174 // other buffer, the kernel should have fixed me up already.
175 bool isPreviouslyWritten;
176 status_t result = parcel.readEmbeddedReference(
177 nullptr, // ignored, not written to bufptr.
178 handle,
179 parentHandle,
180 parentOffset,
181 &isPreviouslyWritten);
182 // tell caller to run T::readEmbeddedToParcel and
183 // T::readEmbeddedReferenceToParcel if necessary.
184 // It is not called here because we don't know if these two are valid methods.
185 *shouldResolveRefInBuffer = !isPreviouslyWritten;
186 return result;
187}
188
189template <typename T>
190static status_t writeEmbeddedReferenceToParcel(
191 T const* buf,
192 Parcel *parcel, size_t parentHandle, size_t parentOffset,
193 size_t *handle,
194 bool *shouldResolveRefInBuffer
195 ) {
196
197 if(buf == nullptr) {
198 *shouldResolveRefInBuffer = false;
199 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
200 }
201
202 // find whether the buffer exists
203 size_t childHandle, childOffset;
204 status_t result;
205 bool found;
206
207 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
208
209 // tell caller to run T::writeEmbeddedToParcel and
210 // T::writeEmbeddedReferenceToParcel if necessary.
211 // It is not called here because we don't know if these two are valid methods.
212 *shouldResolveRefInBuffer = !found;
213
214 if(result != OK) {
215 return result; // bad pointers and length given
216 }
217 if(!found) { // did not find it.
218 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
219 parentHandle, parentOffset);
220 }
221 // found the buffer. easy case.
222 return parcel->writeEmbeddedReference(
223 handle,
224 childHandle,
225 childOffset,
226 parentHandle,
227 parentOffset);
228}
229
230template <typename T>
231static status_t readReferenceFromParcel(
232 T const* *bufptr,
233 const Parcel & parcel,
234 size_t *handle,
235 bool *shouldResolveRefInBuffer
236 ) {
237 bool isPreviouslyWritten;
238 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
239 handle, &isPreviouslyWritten);
240 // tell caller to run T::readEmbeddedToParcel and
241 // T::readEmbeddedReferenceToParcel if necessary.
242 // It is not called here because we don't know if these two are valid methods.
243 *shouldResolveRefInBuffer = !isPreviouslyWritten;
244 return result;
245}
246
247template <typename T>
248static status_t writeReferenceToParcel(
249 T const *buf,
250 Parcel * parcel,
251 size_t *handle,
252 bool *shouldResolveRefInBuffer
253 ) {
254
255 if(buf == nullptr) {
256 *shouldResolveRefInBuffer = false;
257 return parcel->writeNullReference(handle);
258 }
259
260 // find whether the buffer exists
261 size_t childHandle, childOffset;
262 status_t result;
263 bool found;
264
265 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
266
267 // tell caller to run T::writeEmbeddedToParcel and
268 // T::writeEmbeddedReferenceToParcel if necessary.
269 // It is not called here because we don't know if these two are valid methods.
270 *shouldResolveRefInBuffer = !found;
271
272 if(result != OK) {
273 return result; // bad pointers and length given
274 }
275 if(!found) { // did not find it.
276 return parcel->writeBuffer(buf, sizeof(T), handle);
277 }
278 // found the buffer. easy case.
279 return parcel->writeReference(handle,
280 childHandle, childOffset);
281}
282
283// ---------------------- support for casting interfaces
284
Yifan Hong7f97f442016-11-14 18:31:05 -0800285// Construct a smallest possible binder from the given interface.
286// If it is remote, then its remote() will be retrieved.
287// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
288// and iface is of class IChild. BnChild will be used to wrapped the given iface.
289// Return nullptr if iface is null or any failure.
Martijn Coenen12f04d92016-12-07 17:29:41 +0100290template <typename IType, typename ProxyType>
Yifan Hong7f97f442016-11-14 18:31:05 -0800291sp<IBinder> toBinder(sp<IType> iface) {
292 IType *ifacePtr = iface.get();
293 if (ifacePtr == nullptr) {
294 return nullptr;
295 }
296 if (ifacePtr->isRemote()) {
Martijn Coenen12f04d92016-12-07 17:29:41 +0100297 return ::android::hardware::IInterface::asBinder(static_cast<ProxyType *>(ifacePtr));
Yifan Hong7f97f442016-11-14 18:31:05 -0800298 } else {
Yifan Hong6bf733e2016-12-07 14:42:02 -0800299 std::string myDescriptor = getDescriptor(ifacePtr);
Yifan Hong7f97f442016-11-14 18:31:05 -0800300 if (myDescriptor.empty()) {
Yifan Hongb2c9c752016-12-07 15:15:41 -0800301 // interfaceChain fails
Yifan Hong7f97f442016-11-14 18:31:05 -0800302 return nullptr;
303 }
304 auto iter = gBnConstructorMap.find(myDescriptor);
305 if (iter == gBnConstructorMap.end()) {
306 return nullptr;
307 }
308 return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr)));
309 }
310}
311
Martijn Coenen12f04d92016-12-07 17:29:41 +0100312template <typename IType, typename ProxyType, typename StubType>
313sp<IType> fromBinder(const sp<IBinder>& binderIface) {
314 using ::android::hidl::base::V1_0::IBase;
315 using ::android::hidl::base::V1_0::BnBase;
316
317 if (binderIface.get() == nullptr) {
318 return nullptr;
319 }
320 if (binderIface->localBinder() == nullptr) {
321 return new ProxyType(binderIface);
322 }
323 sp<IBase> base = static_cast<BnBase*>(binderIface.get())->getImpl();
324 if (canCastInterface(base.get(), IType::descriptor)) {
325 StubType* stub = static_cast<StubType*>(binderIface.get());
326 return stub->getImpl();
327 } else {
328 return nullptr;
329 }
330}
331
Yifan Hong7f97f442016-11-14 18:31:05 -0800332} // namespace hardware
333} // namespace android
334
335
336#endif // ANDROID_HIDL_BINDER_SUPPORT_H