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 35namespace android { 36namespace hardware { 37 38// hidl_binder_death_recipient wraps a transport-independent 39// hidl_death_recipient, and implements the binder-specific 40// DeathRecipient interface. 41struct 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(); 46private: 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 54status_t readEmbeddedFromParcel(const hidl_memory &memory, 55 const Parcel &parcel, size_t parentHandle, size_t parentOffset); 56 57status_t writeEmbeddedToParcel(const hidl_memory &memory, 58 Parcel *parcel, size_t parentHandle, size_t parentOffset); 59 60// ---------------------- hidl_string 61 62status_t readEmbeddedFromParcel(const hidl_string &string, 63 const Parcel &parcel, size_t parentHandle, size_t parentOffset); 64 65status_t writeEmbeddedToParcel(const hidl_string &string, 66 Parcel *parcel, size_t parentHandle, size_t parentOffset); 67 68// ---------------------- hidl_version 69 70status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel); 71 72// Caller is responsible for freeing the returned object. 73hidl_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. 79status_t readFromParcel(Status *status, const Parcel& parcel); 80status_t writeToParcel(const Status &status, Parcel* parcel); 81 82// ---------------------- hidl_vec 83 84template<typename T> 85status_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 100template<typename T> 101status_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 115template<typename T> 116status_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 122template<typename T, MQFlavor flavor> 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 152template<typename T, MQFlavor flavor> 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 183template <typename T> 184static 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 208template <typename T> 209static 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 249template <typename T> 250static 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 266template <typename T> 267static 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. 309template <typename IType, 310 typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>> 311sp<IBinder> toBinder(sp<IType> iface) { 312 IType *ifacePtr = iface.get(); 313 if (ifacePtr == nullptr) { 314 return nullptr; 315 } 316 if (ifacePtr->isRemote()) { 317 return ::android::hardware::IInterface::asBinder( 318 static_cast<BpInterface<IType>*>(ifacePtr)); 319 } else { 320 std::string myDescriptor = details::getDescriptor(ifacePtr); 321 if (myDescriptor.empty()) { 322 // interfaceDescriptor fails 323 return nullptr; 324 } 325 326 // for get + set 327 std::unique_lock<std::mutex> _lock = details::gBnMap.lock(); 328 329 wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr); 330 sp<IBinder> sBnObj = wBnObj.promote(); 331 332 if (sBnObj == nullptr) { 333 auto func = details::getBnConstructorMap().get(myDescriptor, nullptr); 334 if (!func) { 335 func = details::gBnConstructorMap.get(myDescriptor, nullptr); 336 if (!func) { 337 return nullptr; 338 } 339 } 340 341 sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr))); 342 343 if (sBnObj != nullptr) { 344 details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get())); 345 } 346 } 347 348 return sBnObj; 349 } 350} 351 352template <typename IType, typename ProxyType, typename StubType> 353sp<IType> fromBinder(const sp<IBinder>& binderIface) { 354 using ::android::hidl::base::V1_0::IBase; 355 using ::android::hidl::base::V1_0::BnHwBase; 356 357 if (binderIface.get() == nullptr) { 358 return nullptr; 359 } 360 if (binderIface->localBinder() == nullptr) { 361 return new ProxyType(binderIface); 362 } 363 sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl(); 364 if (details::canCastInterface(base.get(), IType::descriptor)) { 365 StubType* stub = static_cast<StubType*>(binderIface.get()); 366 return stub->getImpl(); 367 } else { 368 return nullptr; 369 } 370} 371 372void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin); 373void joinBinderRpcThreadpool(); 374int setupBinderPolling(); 375status_t handleBinderPoll(); 376 377} // namespace hardware 378} // namespace android 379 380 381#endif // ANDROID_HIDL_BINDER_SUPPORT_H 382