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