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     if (binderIface->localBinder() == nullptr) {
208         return new ProxyType(binderIface);
209     }
210     sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl();
211     if (details::canCastInterface(base.get(), IType::descriptor)) {
212         StubType* stub = static_cast<StubType*>(binderIface.get());
213         return stub->getImpl();
214     } else {
215         return nullptr;
216     }
217 }
218 
219 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin);
220 void joinBinderRpcThreadpool();
221 int setupBinderPolling();
222 status_t handleBinderPoll();
223 
224 void addPostCommandTask(const std::function<void(void)> task);
225 
226 }  // namespace hardware
227 }  // namespace android
228 
229 
230 #endif  // ANDROID_HIDL_BINDER_SUPPORT_H
231