blob: 8fe145093eabc0d64f675f58b2d8340e996548e9 [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
Yifan Hong777bef92017-02-01 15:50:36 -080020#include <sys/types.h>
21
22#include <android/hidl/base/1.0/BnHwBase.h>
Martijn Coenen9b8f9c32016-12-09 15:51:06 +010023#include <android/hidl/base/1.0/IBase.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080024#include <hidl/HidlSupport.h>
Martijn Coenen12f04d92016-12-07 17:29:41 +010025#include <hidl/HidlTransportUtils.h>
Yifan Hong7f97f442016-11-14 18:31:05 -080026#include <hidl/MQDescriptor.h>
27#include <hwbinder/IBinder.h>
28#include <hwbinder/Parcel.h>
Steven Morelandb9173182018-08-08 20:06:08 +000029#include <log/log.h> // TODO(b/65843592): remove. Too many users depending on this transitively.
30
Yifan Hong7f97f442016-11-14 18:31:05 -080031// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
32// etc. to interact with Parcel.
33
34namespace android {
35namespace hardware {
36
Martijn Coenen9b8f9c32016-12-09 15:51:06 +010037// hidl_binder_death_recipient wraps a transport-independent
38// hidl_death_recipient, and implements the binder-specific
39// DeathRecipient interface.
40struct hidl_binder_death_recipient : IBinder::DeathRecipient {
41 hidl_binder_death_recipient(const sp<hidl_death_recipient> &recipient,
Steven Moreland108d09d2017-05-05 16:15:38 -070042 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();
Martijn Coenen9b8f9c32016-12-09 15:51:06 +010045private:
46 wp<hidl_death_recipient> mRecipient;
47 uint64_t mCookie;
48 wp<::android::hidl::base::V1_0::IBase> mBase;
49};
50
Nirav Atre564a8d22018-07-26 18:29:12 -070051// ---------------------- hidl_handle
52
53status_t readEmbeddedFromParcel(const hidl_handle &handle,
54 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
55
56status_t writeEmbeddedToParcel(const hidl_handle &handle,
57 Parcel *parcel, size_t parentHandle, size_t parentOffset);
58
Martijn Coenen30791002016-12-01 15:40:46 +010059// ---------------------- hidl_memory
60
Martijn Coenen9d3eb352017-04-18 20:28:03 -070061status_t readEmbeddedFromParcel(const hidl_memory &memory,
Martijn Coenen30791002016-12-01 15:40:46 +010062 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
63
64status_t writeEmbeddedToParcel(const hidl_memory &memory,
65 Parcel *parcel, size_t parentHandle, size_t parentOffset);
66
Yifan Hong7f97f442016-11-14 18:31:05 -080067// ---------------------- hidl_string
68
Martijn Coenen9d3eb352017-04-18 20:28:03 -070069status_t readEmbeddedFromParcel(const hidl_string &string,
Yifan Hong7f97f442016-11-14 18:31:05 -080070 const Parcel &parcel, size_t parentHandle, size_t parentOffset);
71
72status_t writeEmbeddedToParcel(const hidl_string &string,
73 Parcel *parcel, size_t parentHandle, size_t parentOffset);
74
75// ---------------------- hidl_version
76
77status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel);
78
79// Caller is responsible for freeing the returned object.
80hidl_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.
86status_t readFromParcel(Status *status, const Parcel& parcel);
87status_t writeToParcel(const Status &status, Parcel* parcel);
88
89// ---------------------- hidl_vec
90
91template<typename T>
92status_t readEmbeddedFromParcel(
Martijn Coenen9d3eb352017-04-18 20:28:03 -070093 const hidl_vec<T> &vec,
Yifan Hong7f97f442016-11-14 18:31:05 -080094 const Parcel &parcel,
95 size_t parentHandle,
96 size_t parentOffset,
97 size_t *handle) {
Steven Moreland1f535a22017-01-06 19:25:49 -080098 const void *out;
Martijn Coenen6091d182017-01-13 00:18:54 +010099 return parcel.readNullableEmbeddedBuffer(
Martijn Coenen9d3eb352017-04-18 20:28:03 -0700100 vec.size() * sizeof(T),
Yifan Hong7f97f442016-11-14 18:31:05 -0800101 handle,
102 parentHandle,
Steven Moreland1f535a22017-01-06 19:25:49 -0800103 parentOffset + hidl_vec<T>::kOffsetOfBuffer,
104 &out);
Yifan Hong7f97f442016-11-14 18:31:05 -0800105}
106
107template<typename T>
108status_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
122template<typename T>
123status_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
Hridya Valsaraju7e6404d2016-12-27 09:13:34 -0800129template<typename T, MQFlavor flavor>
Yifan Hong7f97f442016-11-14 18:31:05 -0800130::android::status_t readEmbeddedFromParcel(
Martijn Coenen9d3eb352017-04-18 20:28:03 -0700131 MQDescriptor<T, flavor> &obj,
Yifan Hong7f97f442016-11-14 18:31:05 -0800132 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(
Martijn Coenen9d3eb352017-04-18 20:28:03 -0700140 obj.grantors(),
Yifan Hong7f97f442016-11-14 18:31:05 -0800141 parcel,
142 parentHandle,
Hridya Valsaraju7e6404d2016-12-27 09:13:34 -0800143 parentOffset + MQDescriptor<T, flavor>::kOffsetOfGrantors,
Yifan Hong7f97f442016-11-14 18:31:05 -0800144 &_hidl_grantors_child);
145
146 if (_hidl_err != ::android::OK) { return _hidl_err; }
147
Steven Moreland1f535a22017-01-06 19:25:49 -0800148 const native_handle_t *_hidl_mq_handle_ptr;
Hridya Valsarajuf6fa2a92017-03-08 15:20:07 -0800149 _hidl_err = parcel.readNullableEmbeddedNativeHandle(
Yifan Hong7f97f442016-11-14 18:31:05 -0800150 parentHandle,
Steven Moreland1f535a22017-01-06 19:25:49 -0800151 parentOffset + MQDescriptor<T, flavor>::kOffsetOfHandle,
152 &_hidl_mq_handle_ptr);
Yifan Hong7f97f442016-11-14 18:31:05 -0800153
Steven Moreland1f535a22017-01-06 19:25:49 -0800154 if (_hidl_err != ::android::OK) { return _hidl_err; }
Yifan Hong7f97f442016-11-14 18:31:05 -0800155
156 return _hidl_err;
157}
158
Hridya Valsaraju7e6404d2016-12-27 09:13:34 -0800159template<typename T, MQFlavor flavor>
Yifan Hong7f97f442016-11-14 18:31:05 -0800160::android::status_t writeEmbeddedToParcel(
Hridya Valsaraju7e6404d2016-12-27 09:13:34 -0800161 const MQDescriptor<T, flavor> &obj,
Yifan Hong7f97f442016-11-14 18:31:05 -0800162 ::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,
Hridya Valsaraju7e6404d2016-12-27 09:13:34 -0800173 parentOffset + MQDescriptor<T, flavor>::kOffsetOfGrantors,
Yifan Hong7f97f442016-11-14 18:31:05 -0800174 &_hidl_grantors_child);
175
176 if (_hidl_err != ::android::OK) { return _hidl_err; }
177
178 _hidl_err = parcel->writeEmbeddedNativeHandle(
179 obj.handle(),
180 parentHandle,
Hridya Valsaraju7e6404d2016-12-27 09:13:34 -0800181 parentOffset + MQDescriptor<T, flavor>::kOffsetOfHandle);
Yifan Hong7f97f442016-11-14 18:31:05 -0800182
183 if (_hidl_err != ::android::OK) { return _hidl_err; }
184
185 return _hidl_err;
186}
187
188// ---------------------- pointers for HIDL
189
190template <typename T>
191static 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
215template <typename T>
216static 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
256template <typename T>
257static 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
273template <typename T>
274static 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
Steven Moreland9cbef742018-06-26 16:23:50 -0700311// Constructs a binder for this interface and caches it. If it has already been created
312// then it returns it. ifacePtr must be a local object.
313sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr);
314
Yifan Hong7f97f442016-11-14 18:31:05 -0800315// 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.
Steven Moreland5f82d3e2017-07-27 13:57:56 -0700320template <typename IType,
321 typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>>
Yifan Hong7f97f442016-11-14 18:31:05 -0800322sp<IBinder> toBinder(sp<IType> iface) {
323 IType *ifacePtr = iface.get();
324 if (ifacePtr == nullptr) {
325 return nullptr;
326 }
327 if (ifacePtr->isRemote()) {
Steven Moreland2932c132017-07-21 19:29:54 +0000328 return ::android::hardware::IInterface::asBinder(
329 static_cast<BpInterface<IType>*>(ifacePtr));
Yifan Hong7f97f442016-11-14 18:31:05 -0800330 } else {
Steven Moreland9cbef742018-06-26 16:23:50 -0700331 return getOrCreateCachedBinder(ifacePtr);
Yifan Hong7f97f442016-11-14 18:31:05 -0800332 }
333}
334
Martijn Coenen12f04d92016-12-07 17:29:41 +0100335template <typename IType, typename ProxyType, typename StubType>
336sp<IType> fromBinder(const sp<IBinder>& binderIface) {
337 using ::android::hidl::base::V1_0::IBase;
Yifan Hong4e925992017-01-09 17:47:17 -0800338 using ::android::hidl::base::V1_0::BnHwBase;
Martijn Coenen12f04d92016-12-07 17:29:41 +0100339
340 if (binderIface.get() == nullptr) {
341 return nullptr;
342 }
343 if (binderIface->localBinder() == nullptr) {
344 return new ProxyType(binderIface);
345 }
Yifan Hong4e925992017-01-09 17:47:17 -0800346 sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl();
Yifan Hong2ac326f2017-02-22 18:13:06 -0800347 if (details::canCastInterface(base.get(), IType::descriptor)) {
Martijn Coenen12f04d92016-12-07 17:29:41 +0100348 StubType* stub = static_cast<StubType*>(binderIface.get());
349 return stub->getImpl();
350 } else {
351 return nullptr;
352 }
353}
354
Steven Moreland6cf8fa22017-02-21 13:38:17 -0800355void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin);
356void joinBinderRpcThreadpool();
Martijn Coenen3f5ac4c2017-11-27 15:09:28 -0800357int setupBinderPolling();
358status_t handleBinderPoll();
Martijn Coenene76c7a22016-11-22 14:53:47 +0100359
Steven Morelandd40af8e2018-05-01 16:33:21 -0700360void addPostCommandTask(const std::function<void(void)> task);
361
Yifan Hong7f97f442016-11-14 18:31:05 -0800362} // namespace hardware
363} // namespace android
364
365
366#endif // ANDROID_HIDL_BINDER_SUPPORT_H