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