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