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