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