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