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