blob: 84ba966e7f19ef5b6b513170f3c0debf4e8300da [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>
21#include <hidl/MQDescriptor.h>
22#include <hwbinder/IBinder.h>
23#include <hwbinder/Parcel.h>
24
25// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
26// etc. to interact with Parcel.
27
28namespace android {
29namespace hardware {
30
31// ---------------------- hidl_string
32
33status_t readEmbeddedFromParcel(hidl_string *string,
34 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
35
36status_t writeEmbeddedToParcel(const hidl_string &string,
37 Parcel *parcel, size_t parentHandle, size_t parentOffset);
38
39// ---------------------- hidl_version
40
41status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
42
43// Caller is responsible for freeing the returned object.
44hidl_version* readFromParcel(const android::hardware::Parcel& parcel);
45
46// ---------------------- Status
47
48// Bear in mind that if the client or service is a Java endpoint, this
49// is not the logic which will provide/interpret the data here.
50status_t readFromParcel(Status *status, const Parcel& parcel);
51status_t writeToParcel(const Status &status, Parcel* parcel);
52
53// ---------------------- hidl_vec
54
55template<typename T>
56status_t readEmbeddedFromParcel(
57 hidl_vec<T> * /*vec*/,
58 const Parcel &parcel,
59 size_t parentHandle,
60 size_t parentOffset,
61 size_t *handle) {
62 const void *ptr = parcel.readEmbeddedBuffer(
63 handle,
64 parentHandle,
65 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
66
67 return ptr != NULL ? OK : UNKNOWN_ERROR;
68}
69
70template<typename T>
71status_t writeEmbeddedToParcel(
72 const hidl_vec<T> &vec,
73 Parcel *parcel,
74 size_t parentHandle,
75 size_t parentOffset,
76 size_t *handle) {
77 return parcel->writeEmbeddedBuffer(
78 vec.data(),
79 sizeof(T) * vec.size(),
80 handle,
81 parentHandle,
82 parentOffset + hidl_vec<T>::kOffsetOfBuffer);
83}
84
85template<typename T>
86status_t findInParcel(const hidl_vec<T> &vec, const Parcel &parcel, size_t *handle) {
87 return parcel.quickFindBuffer(vec.data(), handle);
88}
89
90// ---------------------- MQDescriptor
91
92template<MQFlavor flavor>
93::android::status_t readEmbeddedFromParcel(
94 MQDescriptor<flavor> *obj,
95 const ::android::hardware::Parcel &parcel,
96 size_t parentHandle,
97 size_t parentOffset) {
98 ::android::status_t _hidl_err = ::android::OK;
99
100 size_t _hidl_grantors_child;
101
102 _hidl_err = ::android::hardware::readEmbeddedFromParcel(
103 &obj->grantors(),
104 parcel,
105 parentHandle,
106 parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors,
107 &_hidl_grantors_child);
108
109 if (_hidl_err != ::android::OK) { return _hidl_err; }
110
111 const native_handle_t *_hidl_mq_handle_ptr = parcel.readEmbeddedNativeHandle(
112 parentHandle,
113 parentOffset + MQDescriptor<flavor>::kOffsetOfHandle);
114
115 if (_hidl_mq_handle_ptr == nullptr) {
116 _hidl_err = ::android::UNKNOWN_ERROR;
117 return _hidl_err;
118 }
119
120 return _hidl_err;
121}
122
123template<MQFlavor flavor>
124::android::status_t writeEmbeddedToParcel(
125 const MQDescriptor<flavor> &obj,
126 ::android::hardware::Parcel *parcel,
127 size_t parentHandle,
128 size_t parentOffset) {
129 ::android::status_t _hidl_err = ::android::OK;
130
131 size_t _hidl_grantors_child;
132
133 _hidl_err = ::android::hardware::writeEmbeddedToParcel(
134 obj.grantors(),
135 parcel,
136 parentHandle,
137 parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors,
138 &_hidl_grantors_child);
139
140 if (_hidl_err != ::android::OK) { return _hidl_err; }
141
142 _hidl_err = parcel->writeEmbeddedNativeHandle(
143 obj.handle(),
144 parentHandle,
145 parentOffset + MQDescriptor<flavor>::kOffsetOfHandle);
146
147 if (_hidl_err != ::android::OK) { return _hidl_err; }
148
149 return _hidl_err;
150}
151
152// ---------------------- pointers for HIDL
153
154template <typename T>
155static status_t readEmbeddedReferenceFromParcel(
156 T const* * /* bufptr */,
157 const Parcel & parcel,
158 size_t parentHandle,
159 size_t parentOffset,
160 size_t *handle,
161 bool *shouldResolveRefInBuffer
162 ) {
163 // *bufptr is ignored because, if I am embedded in some
164 // other buffer, the kernel should have fixed me up already.
165 bool isPreviouslyWritten;
166 status_t result = parcel.readEmbeddedReference(
167 nullptr, // ignored, not written to bufptr.
168 handle,
169 parentHandle,
170 parentOffset,
171 &isPreviouslyWritten);
172 // tell caller to run T::readEmbeddedToParcel and
173 // T::readEmbeddedReferenceToParcel if necessary.
174 // It is not called here because we don't know if these two are valid methods.
175 *shouldResolveRefInBuffer = !isPreviouslyWritten;
176 return result;
177}
178
179template <typename T>
180static status_t writeEmbeddedReferenceToParcel(
181 T const* buf,
182 Parcel *parcel, size_t parentHandle, size_t parentOffset,
183 size_t *handle,
184 bool *shouldResolveRefInBuffer
185 ) {
186
187 if(buf == nullptr) {
188 *shouldResolveRefInBuffer = false;
189 return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset);
190 }
191
192 // find whether the buffer exists
193 size_t childHandle, childOffset;
194 status_t result;
195 bool found;
196
197 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
198
199 // tell caller to run T::writeEmbeddedToParcel and
200 // T::writeEmbeddedReferenceToParcel if necessary.
201 // It is not called here because we don't know if these two are valid methods.
202 *shouldResolveRefInBuffer = !found;
203
204 if(result != OK) {
205 return result; // bad pointers and length given
206 }
207 if(!found) { // did not find it.
208 return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle,
209 parentHandle, parentOffset);
210 }
211 // found the buffer. easy case.
212 return parcel->writeEmbeddedReference(
213 handle,
214 childHandle,
215 childOffset,
216 parentHandle,
217 parentOffset);
218}
219
220template <typename T>
221static status_t readReferenceFromParcel(
222 T const* *bufptr,
223 const Parcel & parcel,
224 size_t *handle,
225 bool *shouldResolveRefInBuffer
226 ) {
227 bool isPreviouslyWritten;
228 status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr),
229 handle, &isPreviouslyWritten);
230 // tell caller to run T::readEmbeddedToParcel and
231 // T::readEmbeddedReferenceToParcel if necessary.
232 // It is not called here because we don't know if these two are valid methods.
233 *shouldResolveRefInBuffer = !isPreviouslyWritten;
234 return result;
235}
236
237template <typename T>
238static status_t writeReferenceToParcel(
239 T const *buf,
240 Parcel * parcel,
241 size_t *handle,
242 bool *shouldResolveRefInBuffer
243 ) {
244
245 if(buf == nullptr) {
246 *shouldResolveRefInBuffer = false;
247 return parcel->writeNullReference(handle);
248 }
249
250 // find whether the buffer exists
251 size_t childHandle, childOffset;
252 status_t result;
253 bool found;
254
255 result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset);
256
257 // tell caller to run T::writeEmbeddedToParcel and
258 // T::writeEmbeddedReferenceToParcel if necessary.
259 // It is not called here because we don't know if these two are valid methods.
260 *shouldResolveRefInBuffer = !found;
261
262 if(result != OK) {
263 return result; // bad pointers and length given
264 }
265 if(!found) { // did not find it.
266 return parcel->writeBuffer(buf, sizeof(T), handle);
267 }
268 // found the buffer. easy case.
269 return parcel->writeReference(handle,
270 childHandle, childOffset);
271}
272
273// ---------------------- support for casting interfaces
274
275extern std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap;
276
277// Construct a smallest possible binder from the given interface.
278// If it is remote, then its remote() will be retrieved.
279// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
280// and iface is of class IChild. BnChild will be used to wrapped the given iface.
281// Return nullptr if iface is null or any failure.
282template <typename IType, typename IHwType>
283sp<IBinder> toBinder(sp<IType> iface) {
284 IType *ifacePtr = iface.get();
285 if (ifacePtr == nullptr) {
286 return nullptr;
287 }
288 if (ifacePtr->isRemote()) {
289 return ::android::hardware::IInterface::asBinder(static_cast<IHwType *>(ifacePtr));
290 } else {
291 std::string myDescriptor{};
292 ifacePtr->interfaceChain([&](const hidl_vec<hidl_string> &types) {
293 if (types.size() > 0) {
294 myDescriptor = types[0].c_str();
295 }
296 });
297 if (myDescriptor.empty()) {
298 // interfaceChain fails || types.size() == 0
299 return nullptr;
300 }
301 auto iter = gBnConstructorMap.find(myDescriptor);
302 if (iter == gBnConstructorMap.end()) {
303 return nullptr;
304 }
305 return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr)));
306 }
307}
308
309#define IMPLEMENT_SERVICE_MANAGER_INTERACTIONS(INTERFACE, PACKAGE) \
310 ::android::sp<I##INTERFACE> I##INTERFACE::getService( \
311 const std::string &serviceName, bool getStub) \
312 { \
313 using ::android::sp; \
314 using ::android::hardware::defaultServiceManager; \
315 using ::android::hardware::IBinder; \
316 using ::android::hidl::manager::V1_0::IServiceManager; \
317 sp<I##INTERFACE> iface; \
318 const sp<IServiceManager> sm = defaultServiceManager(); \
319 if (sm != nullptr && !getStub) { \
320 sp<IBinder> binderIface; \
321 ::android::hardware::Return<void> ret = \
322 sm->get(PACKAGE "::I" #INTERFACE, serviceName.c_str(), \
323 [&binderIface](sp<IBinder> iface) { \
324 binderIface = iface; \
325 }); \
326 if (ret.getStatus().isOk()) { \
327 iface = IHw##INTERFACE::asInterface(binderIface); \
328 if (iface != nullptr) { \
329 return iface; \
330 } \
331 } \
332 } \
333 int dlMode = RTLD_LAZY; \
334 void *handle = dlopen(HAL_LIBRARY_PATH_ODM PACKAGE "-impl.so", dlMode); \
335 if (handle == nullptr) { \
336 handle = dlopen(HAL_LIBRARY_PATH_VENDOR PACKAGE "-impl.so", dlMode); \
337 } \
338 if (handle == nullptr) { \
339 handle = dlopen(HAL_LIBRARY_PATH_SYSTEM PACKAGE "-impl.so", dlMode); \
340 } \
341 if (handle == nullptr) { \
342 return iface; \
343 } \
344 I##INTERFACE* (*generator)(const char* name); \
345 *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \
346 if (generator) { \
347 iface = (*generator)(serviceName.c_str()); \
348 if (iface != nullptr) { \
349 iface = new Bs##INTERFACE(iface); \
350 } \
351 } \
352 return iface; \
353 } \
354 ::android::status_t I##INTERFACE::registerAsService( \
355 const std::string &serviceName) \
356 { \
357 using ::android::sp; \
358 using ::android::hardware::defaultServiceManager; \
359 using ::android::hidl::manager::V1_0::IServiceManager; \
360 sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \
361 const sp<IServiceManager> sm = defaultServiceManager(); \
362 bool success = false; \
363 ::android::hardware::Return<void> ret = \
364 this->interfaceChain( \
365 [&success, &sm, &serviceName, &binderIface](const auto &chain) { \
Steven Moreland337c3ae2016-11-22 13:37:32 -0800366 ::android::hardware::Return<bool> addRet = \
367 sm->add(chain, serviceName.c_str(), binderIface); \
368 success = addRet.isOk() && addRet.get(); \
Yifan Hong7f97f442016-11-14 18:31:05 -0800369 }); \
370 success = success && ret.getStatus().isOk(); \
371 return success ? ::android::OK : ::android::UNKNOWN_ERROR; \
372 } \
373 bool I##INTERFACE::registerForNotifications( \
374 const std::string &serviceName, \
375 const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \
376 &notification) \
377 { \
378 using ::android::sp; \
379 using ::android::hardware::defaultServiceManager; \
380 using ::android::hidl::manager::V1_0::IServiceManager; \
381 const sp<IServiceManager> sm = defaultServiceManager(); \
382 if (sm == nullptr) { \
383 return false; \
384 } \
Steven Moreland337c3ae2016-11-22 13:37:32 -0800385 ::android::hardware::Return<bool> success = \
386 sm->registerForNotifications(PACKAGE "::I" #INTERFACE, \
387 serviceName, \
388 notification); \
389 return success.isOk() && success.get(); \
Yifan Hong7f97f442016-11-14 18:31:05 -0800390 }
391
392
393} // namespace hardware
394} // namespace android
395
396
397#endif // ANDROID_HIDL_BINDER_SUPPORT_H