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