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