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