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