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, 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 // ---------------------- 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 // ---------------------- support for casting interfaces
182
183 // Constructs a binder for this interface and caches it. If it has already been created
184 // then it returns it.
185 sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr);
186
187 // Construct a smallest possible binder from the given interface.
188 // If it is remote, then its remote() will be retrieved.
189 // Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
190 // and iface is of class IChild. BnChild will be used to wrapped the given iface.
191 // Return nullptr if iface is null or any failure.
192 template <typename IType,
193 typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>>
toBinder(sp<IType> iface)194 sp<IBinder> toBinder(sp<IType> iface) {
195 IType *ifacePtr = iface.get();
196 return getOrCreateCachedBinder(ifacePtr);
197 }
198
199 template <typename IType, typename ProxyType, typename StubType>
fromBinder(const sp<IBinder> & binderIface)200 sp<IType> fromBinder(const sp<IBinder>& binderIface) {
201 using ::android::hidl::base::V1_0::IBase;
202 using ::android::hidl::base::V1_0::BnHwBase;
203
204 if (binderIface.get() == nullptr) {
205 return nullptr;
206 }
207
208 if (binderIface->localBinder() == nullptr) {
209 return new ProxyType(binderIface);
210 }
211
212 // Ensure that IBinder is BnHwBase (not JHwBinder, for instance)
213 if (!binderIface->checkSubclass(IBase::descriptor)) {
214 return new ProxyType(binderIface);
215 }
216 sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl();
217
218 if (details::canCastInterface(base.get(), IType::descriptor)) {
219 return static_cast<IType*>(base.get());
220 } else {
221 return nullptr;
222 }
223 }
224
225 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin);
226 void joinBinderRpcThreadpool();
227 int setupBinderPolling();
228 status_t handleBinderPoll();
229
230 void addPostCommandTask(const std::function<void(void)> task);
231
232 } // namespace hardware
233 } // namespace android
234
235
236 #endif // ANDROID_HIDL_BINDER_SUPPORT_H
237