diff options
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | HidlBinderSupport.cpp | 145 | ||||
-rw-r--r-- | HidlSupport.cpp | 24 | ||||
-rw-r--r-- | Status.cpp | 69 | ||||
-rw-r--r-- | include/hidl/HidlBinderSupport.h | 393 | ||||
-rw-r--r-- | include/hidl/HidlSupport.h | 320 | ||||
-rw-r--r-- | include/hidl/HidlTransportSupport.h | 60 | ||||
-rw-r--r-- | include/hidl/MQDescriptor.h | 60 | ||||
-rw-r--r-- | include/hidl/Status.h | 6 |
9 files changed, 600 insertions, 478 deletions
@@ -44,6 +44,7 @@ cc_library_shared { srcs: [ "HidlSupport.cpp", + "HidlBinderSupport.cpp", "ServiceManagement.cpp", "Static.cpp", "Status.cpp", diff --git a/HidlBinderSupport.cpp b/HidlBinderSupport.cpp new file mode 100644 index 0000000..c206018 --- /dev/null +++ b/HidlBinderSupport.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "HidlSupport" + +#include <hidl/HidlBinderSupport.h> + +#ifdef LIBHIDL_TARGET_DEBUGGABLE +#include <android-base/logging.h> +#endif + +namespace android { +namespace hardware { + +std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap{}; + +// static +const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer); + +status_t readEmbeddedFromParcel(hidl_string * /* string */, + const Parcel &parcel, size_t parentHandle, size_t parentOffset) { + const void *ptr = parcel.readEmbeddedBuffer( + nullptr /* buffer_handle */, + parentHandle, + parentOffset + hidl_string::kOffsetOfBuffer); + + return ptr != NULL ? OK : UNKNOWN_ERROR; +} + +status_t writeEmbeddedToParcel(const hidl_string &string, + Parcel *parcel, size_t parentHandle, size_t parentOffset) { + return parcel->writeEmbeddedBuffer( + string.c_str(), + string.size() + 1, + nullptr /* handle */, + parentHandle, + parentOffset + hidl_string::kOffsetOfBuffer); +} + +android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) { + return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor()); +} + +hidl_version* readFromParcel(const android::hardware::Parcel& parcel) { + uint32_t version; + android::status_t status = parcel.readUint32(&version); + if (status != OK) { + return nullptr; + } else { + return new hidl_version(version >> 16, version & 0xFFFF); + } +} + +status_t readFromParcel(Status *s, const Parcel& parcel) { + int32_t exception; + int32_t errorCode; + status_t status = parcel.readInt32(&exception); + if (status != OK) { + s->setFromStatusT(status); + return status; + } + + // Skip over fat response headers. Not used (or propagated) in native code. + if (exception == Status::EX_HAS_REPLY_HEADER) { + // Note that the header size includes the 4 byte size field. + const int32_t header_start = parcel.dataPosition(); + int32_t header_size; + status = parcel.readInt32(&header_size); + if (status != OK) { + s->setFromStatusT(status); + return status; + } + parcel.setDataPosition(header_start + header_size); + // And fat response headers are currently only used when there are no + // exceptions, so act like there was no error. + exception = Status::EX_NONE; + } + + if (exception == Status::EX_NONE) { + *s = Status::ok(); + return status; + } + + // The remote threw an exception. Get the message back. + String16 message; + status = parcel.readString16(&message); + if (status != OK) { + s->setFromStatusT(status); + return status; + } + + if (exception == Status::EX_SERVICE_SPECIFIC) { + status = parcel.readInt32(&errorCode); + } + if (status != OK) { + s->setFromStatusT(status); + return status; + } + + if (exception == Status::EX_SERVICE_SPECIFIC) { + s->setServiceSpecificError(errorCode, String8(message)); + } else { + s->setException(exception, String8(message)); + } + + return status; +} + +status_t writeToParcel(const Status &s, Parcel* parcel) { + // Something really bad has happened, and we're not going to even + // try returning rich error data. + if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) { + return s.transactionError(); + } + + status_t status = parcel->writeInt32(s.exceptionCode()); + if (status != OK) { return status; } + if (s.exceptionCode() == Status::EX_NONE) { + // We have no more information to write. + return status; + } + status = parcel->writeString16(String16(s.exceptionMessage())); + if (s.exceptionCode() != Status::EX_SERVICE_SPECIFIC) { + // We have no more information to write. + return status; + } + status = parcel->writeInt32(s.serviceSpecificErrorCode()); + return status; +} + +} // namespace hardware +} // namespace android diff --git a/HidlSupport.cpp b/HidlSupport.cpp index edab4de..8c5ac17 100644 --- a/HidlSupport.cpp +++ b/HidlSupport.cpp @@ -29,7 +29,6 @@ namespace android { namespace hardware { static const char *const kEmptyString = ""; -std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap{}; hidl_string::hidl_string() : mBuffer(kEmptyString), @@ -146,29 +145,6 @@ bool hidl_string::empty() const { return mSize == 0; } -// static -const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer); - -status_t readEmbeddedFromParcel(hidl_string * /* string */, - const Parcel &parcel, size_t parentHandle, size_t parentOffset) { - const void *ptr = parcel.readEmbeddedBuffer( - nullptr /* buffer_handle */, - parentHandle, - parentOffset + hidl_string::kOffsetOfBuffer); - - return ptr != NULL ? OK : UNKNOWN_ERROR; -} - -status_t writeEmbeddedToParcel(const hidl_string &string, - Parcel *parcel, size_t parentHandle, size_t parentOffset) { - return parcel->writeEmbeddedBuffer( - string.c_str(), - string.size() + 1, - nullptr /* handle */, - parentHandle, - parentOffset + hidl_string::kOffsetOfBuffer); -} - const char* IBase::descriptor = "android.hardware.base@0.0::IBase"; // ---------------------------------------------------------------------- @@ -56,75 +56,6 @@ Status::Status(int32_t exceptionCode, int32_t errorCode, const String8& message) mErrorCode(errorCode), mMessage(message) {} -status_t Status::readFromParcel(const Parcel& parcel) { - status_t status = parcel.readInt32(&mException); - if (status != OK) { - setFromStatusT(status); - return status; - } - - // Skip over fat response headers. Not used (or propagated) in native code. - if (mException == EX_HAS_REPLY_HEADER) { - // Note that the header size includes the 4 byte size field. - const int32_t header_start = parcel.dataPosition(); - int32_t header_size; - status = parcel.readInt32(&header_size); - if (status != OK) { - setFromStatusT(status); - return status; - } - parcel.setDataPosition(header_start + header_size); - // And fat response headers are currently only used when there are no - // exceptions, so act like there was no error. - mException = EX_NONE; - } - - if (mException == EX_NONE) { - return status; - } - - // The remote threw an exception. Get the message back. - String16 message; - status = parcel.readString16(&message); - if (status != OK) { - setFromStatusT(status); - return status; - } - mMessage = String8(message); - - if (mException == EX_SERVICE_SPECIFIC) { - status = parcel.readInt32(&mErrorCode); - } - if (status != OK) { - setFromStatusT(status); - return status; - } - - return status; -} - -status_t Status::writeToParcel(Parcel* parcel) const { - // Something really bad has happened, and we're not going to even - // try returning rich error data. - if (mException == EX_TRANSACTION_FAILED) { - return mErrorCode; - } - - status_t status = parcel->writeInt32(mException); - if (status != OK) { return status; } - if (mException == EX_NONE) { - // We have no more information to write. - return status; - } - status = parcel->writeString16(String16(mMessage)); - if (mException != EX_SERVICE_SPECIFIC) { - // We have no more information to write. - return status; - } - status = parcel->writeInt32(mErrorCode); - return status; -} - void Status::setException(int32_t ex, const String8& message) { mException = ex; mErrorCode = NO_ERROR; // an exception, not a transaction failure. diff --git a/include/hidl/HidlBinderSupport.h b/include/hidl/HidlBinderSupport.h new file mode 100644 index 0000000..b4a2aa2 --- /dev/null +++ b/include/hidl/HidlBinderSupport.h @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HIDL_BINDER_SUPPORT_H +#define ANDROID_HIDL_BINDER_SUPPORT_H + +#include <hidl/HidlSupport.h> +#include <hidl/MQDescriptor.h> +#include <hwbinder/IBinder.h> +#include <hwbinder/Parcel.h> + +// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor, +// etc. to interact with Parcel. + +namespace android { +namespace hardware { + +// ---------------------- hidl_string + +status_t readEmbeddedFromParcel(hidl_string *string, + const Parcel &parcel, size_t parentHandle, size_t parentOffset); + +status_t writeEmbeddedToParcel(const hidl_string &string, + Parcel *parcel, size_t parentHandle, size_t parentOffset); + +// ---------------------- hidl_version + +status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel); + +// Caller is responsible for freeing the returned object. +hidl_version* readFromParcel(const android::hardware::Parcel& parcel); + +// ---------------------- Status + +// Bear in mind that if the client or service is a Java endpoint, this +// is not the logic which will provide/interpret the data here. +status_t readFromParcel(Status *status, const Parcel& parcel); +status_t writeToParcel(const Status &status, Parcel* parcel); + +// ---------------------- hidl_vec + +template<typename T> +status_t readEmbeddedFromParcel( + hidl_vec<T> * /*vec*/, + const Parcel &parcel, + size_t parentHandle, + size_t parentOffset, + size_t *handle) { + const void *ptr = parcel.readEmbeddedBuffer( + handle, + parentHandle, + parentOffset + hidl_vec<T>::kOffsetOfBuffer); + + return ptr != NULL ? OK : UNKNOWN_ERROR; +} + +template<typename T> +status_t writeEmbeddedToParcel( + const hidl_vec<T> &vec, + Parcel *parcel, + size_t parentHandle, + size_t parentOffset, + size_t *handle) { + return parcel->writeEmbeddedBuffer( + vec.data(), + sizeof(T) * vec.size(), + handle, + parentHandle, + parentOffset + hidl_vec<T>::kOffsetOfBuffer); +} + +template<typename T> +status_t findInParcel(const hidl_vec<T> &vec, const Parcel &parcel, size_t *handle) { + return parcel.quickFindBuffer(vec.data(), handle); +} + +// ---------------------- MQDescriptor + +template<MQFlavor flavor> +::android::status_t readEmbeddedFromParcel( + MQDescriptor<flavor> *obj, + const ::android::hardware::Parcel &parcel, + size_t parentHandle, + size_t parentOffset) { + ::android::status_t _hidl_err = ::android::OK; + + size_t _hidl_grantors_child; + + _hidl_err = ::android::hardware::readEmbeddedFromParcel( + &obj->grantors(), + parcel, + parentHandle, + parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors, + &_hidl_grantors_child); + + if (_hidl_err != ::android::OK) { return _hidl_err; } + + const native_handle_t *_hidl_mq_handle_ptr = parcel.readEmbeddedNativeHandle( + parentHandle, + parentOffset + MQDescriptor<flavor>::kOffsetOfHandle); + + if (_hidl_mq_handle_ptr == nullptr) { + _hidl_err = ::android::UNKNOWN_ERROR; + return _hidl_err; + } + + return _hidl_err; +} + +template<MQFlavor flavor> +::android::status_t writeEmbeddedToParcel( + const MQDescriptor<flavor> &obj, + ::android::hardware::Parcel *parcel, + size_t parentHandle, + size_t parentOffset) { + ::android::status_t _hidl_err = ::android::OK; + + size_t _hidl_grantors_child; + + _hidl_err = ::android::hardware::writeEmbeddedToParcel( + obj.grantors(), + parcel, + parentHandle, + parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors, + &_hidl_grantors_child); + + if (_hidl_err != ::android::OK) { return _hidl_err; } + + _hidl_err = parcel->writeEmbeddedNativeHandle( + obj.handle(), + parentHandle, + parentOffset + MQDescriptor<flavor>::kOffsetOfHandle); + + if (_hidl_err != ::android::OK) { return _hidl_err; } + + return _hidl_err; +} + +// ---------------------- pointers for HIDL + +template <typename T> +static status_t readEmbeddedReferenceFromParcel( + T const* * /* bufptr */, + const Parcel & parcel, + size_t parentHandle, + size_t parentOffset, + size_t *handle, + bool *shouldResolveRefInBuffer + ) { + // *bufptr is ignored because, if I am embedded in some + // other buffer, the kernel should have fixed me up already. + bool isPreviouslyWritten; + status_t result = parcel.readEmbeddedReference( + nullptr, // ignored, not written to bufptr. + handle, + parentHandle, + parentOffset, + &isPreviouslyWritten); + // tell caller to run T::readEmbeddedToParcel and + // T::readEmbeddedReferenceToParcel if necessary. + // It is not called here because we don't know if these two are valid methods. + *shouldResolveRefInBuffer = !isPreviouslyWritten; + return result; +} + +template <typename T> +static status_t writeEmbeddedReferenceToParcel( + T const* buf, + Parcel *parcel, size_t parentHandle, size_t parentOffset, + size_t *handle, + bool *shouldResolveRefInBuffer + ) { + + if(buf == nullptr) { + *shouldResolveRefInBuffer = false; + return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset); + } + + // find whether the buffer exists + size_t childHandle, childOffset; + status_t result; + bool found; + + result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset); + + // tell caller to run T::writeEmbeddedToParcel and + // T::writeEmbeddedReferenceToParcel if necessary. + // It is not called here because we don't know if these two are valid methods. + *shouldResolveRefInBuffer = !found; + + if(result != OK) { + return result; // bad pointers and length given + } + if(!found) { // did not find it. + return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle, + parentHandle, parentOffset); + } + // found the buffer. easy case. + return parcel->writeEmbeddedReference( + handle, + childHandle, + childOffset, + parentHandle, + parentOffset); +} + +template <typename T> +static status_t readReferenceFromParcel( + T const* *bufptr, + const Parcel & parcel, + size_t *handle, + bool *shouldResolveRefInBuffer + ) { + bool isPreviouslyWritten; + status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr), + handle, &isPreviouslyWritten); + // tell caller to run T::readEmbeddedToParcel and + // T::readEmbeddedReferenceToParcel if necessary. + // It is not called here because we don't know if these two are valid methods. + *shouldResolveRefInBuffer = !isPreviouslyWritten; + return result; +} + +template <typename T> +static status_t writeReferenceToParcel( + T const *buf, + Parcel * parcel, + size_t *handle, + bool *shouldResolveRefInBuffer + ) { + + if(buf == nullptr) { + *shouldResolveRefInBuffer = false; + return parcel->writeNullReference(handle); + } + + // find whether the buffer exists + size_t childHandle, childOffset; + status_t result; + bool found; + + result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset); + + // tell caller to run T::writeEmbeddedToParcel and + // T::writeEmbeddedReferenceToParcel if necessary. + // It is not called here because we don't know if these two are valid methods. + *shouldResolveRefInBuffer = !found; + + if(result != OK) { + return result; // bad pointers and length given + } + if(!found) { // did not find it. + return parcel->writeBuffer(buf, sizeof(T), handle); + } + // found the buffer. easy case. + return parcel->writeReference(handle, + childHandle, childOffset); +} + +// ---------------------- support for casting interfaces + +extern std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap; + +// Construct a smallest possible binder from the given interface. +// If it is remote, then its remote() will be retrieved. +// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType +// and iface is of class IChild. BnChild will be used to wrapped the given iface. +// Return nullptr if iface is null or any failure. +template <typename IType, typename IHwType> +sp<IBinder> toBinder(sp<IType> iface) { + IType *ifacePtr = iface.get(); + if (ifacePtr == nullptr) { + return nullptr; + } + if (ifacePtr->isRemote()) { + return ::android::hardware::IInterface::asBinder(static_cast<IHwType *>(ifacePtr)); + } else { + std::string myDescriptor{}; + ifacePtr->interfaceChain([&](const hidl_vec<hidl_string> &types) { + if (types.size() > 0) { + myDescriptor = types[0].c_str(); + } + }); + if (myDescriptor.empty()) { + // interfaceChain fails || types.size() == 0 + return nullptr; + } + auto iter = gBnConstructorMap.find(myDescriptor); + if (iter == gBnConstructorMap.end()) { + return nullptr; + } + return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr))); + } +} + +#define IMPLEMENT_SERVICE_MANAGER_INTERACTIONS(INTERFACE, PACKAGE) \ + ::android::sp<I##INTERFACE> I##INTERFACE::getService( \ + const std::string &serviceName, bool getStub) \ + { \ + using ::android::sp; \ + using ::android::hardware::defaultServiceManager; \ + using ::android::hardware::IBinder; \ + using ::android::hidl::manager::V1_0::IServiceManager; \ + sp<I##INTERFACE> iface; \ + const sp<IServiceManager> sm = defaultServiceManager(); \ + if (sm != nullptr && !getStub) { \ + sp<IBinder> binderIface; \ + ::android::hardware::Return<void> ret = \ + sm->get(PACKAGE "::I" #INTERFACE, serviceName.c_str(), \ + [&binderIface](sp<IBinder> iface) { \ + binderIface = iface; \ + }); \ + if (ret.getStatus().isOk()) { \ + iface = IHw##INTERFACE::asInterface(binderIface); \ + if (iface != nullptr) { \ + return iface; \ + } \ + } \ + } \ + int dlMode = RTLD_LAZY; \ + void *handle = dlopen(HAL_LIBRARY_PATH_ODM PACKAGE "-impl.so", dlMode); \ + if (handle == nullptr) { \ + handle = dlopen(HAL_LIBRARY_PATH_VENDOR PACKAGE "-impl.so", dlMode); \ + } \ + if (handle == nullptr) { \ + handle = dlopen(HAL_LIBRARY_PATH_SYSTEM PACKAGE "-impl.so", dlMode); \ + } \ + if (handle == nullptr) { \ + return iface; \ + } \ + I##INTERFACE* (*generator)(const char* name); \ + *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \ + if (generator) { \ + iface = (*generator)(serviceName.c_str()); \ + if (iface != nullptr) { \ + iface = new Bs##INTERFACE(iface); \ + } \ + } \ + return iface; \ + } \ + ::android::status_t I##INTERFACE::registerAsService( \ + const std::string &serviceName) \ + { \ + using ::android::sp; \ + using ::android::hardware::defaultServiceManager; \ + using ::android::hidl::manager::V1_0::IServiceManager; \ + sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \ + const sp<IServiceManager> sm = defaultServiceManager(); \ + bool success = false; \ + ::android::hardware::Return<void> ret = \ + this->interfaceChain( \ + [&success, &sm, &serviceName, &binderIface](const auto &chain) { \ + success = sm->add(chain, serviceName.c_str(), binderIface); \ + }); \ + success = success && ret.getStatus().isOk(); \ + return success ? ::android::OK : ::android::UNKNOWN_ERROR; \ + } \ + bool I##INTERFACE::registerForNotifications( \ + const std::string &serviceName, \ + const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \ + ¬ification) \ + { \ + using ::android::sp; \ + using ::android::hardware::defaultServiceManager; \ + using ::android::hidl::manager::V1_0::IServiceManager; \ + const sp<IServiceManager> sm = defaultServiceManager(); \ + if (sm == nullptr) { \ + return false; \ + } \ + return sm->registerForNotifications(PACKAGE "::I" #INTERFACE, \ + serviceName, \ + notification); \ + } + + +} // namespace hardware +} // namespace android + + +#endif // ANDROID_HIDL_BINDER_SUPPORT_H diff --git a/include/hidl/HidlSupport.h b/include/hidl/HidlSupport.h index 4e63613..48cfd26 100644 --- a/include/hidl/HidlSupport.h +++ b/include/hidl/HidlSupport.h @@ -23,13 +23,12 @@ #include <cutils/properties.h> #include <functional> #include <hidl/Status.h> -#include <hwbinder/IBinder.h> -#include <hwbinder/Parcel.h> #include <map> #include <tuple> #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/StrongPointer.h> +#include <vector> namespace android { namespace hardware { @@ -88,12 +87,6 @@ private: void moveFrom(hidl_string &&); }; -status_t readEmbeddedFromParcel(hidl_string *string, - const Parcel &parcel, size_t parentHandle, size_t parentOffset); - -status_t writeEmbeddedToParcel(const hidl_string &string, - Parcel *parcel, size_t parentHandle, size_t parentOffset); - inline bool operator==(const hidl_string &hs, const char *s) { return strcmp(hs.c_str(), s) == 0; } @@ -247,10 +240,6 @@ struct hidl_vec { mOwnsBuffer = true; } - status_t findInParcel(const Parcel &parcel, size_t *handle) const { - return parcel.quickFindBuffer(mBuffer, handle); - } - // offsetof(hidl_string, mBuffer) exposed since mBuffer is private. static const size_t kOffsetOfBuffer; private: @@ -277,36 +266,6 @@ private: template <typename T> const size_t hidl_vec<T>::kOffsetOfBuffer = offsetof(hidl_vec<T>, mBuffer); -template<typename T> -status_t readEmbeddedFromParcel( - hidl_vec<T> * /*vec*/, - const Parcel &parcel, - size_t parentHandle, - size_t parentOffset, - size_t *handle) { - const void *ptr = parcel.readEmbeddedBuffer( - handle, - parentHandle, - parentOffset + hidl_vec<T>::kOffsetOfBuffer); - - return ptr != NULL ? OK : UNKNOWN_ERROR; -} - -template<typename T> -status_t writeEmbeddedToParcel( - const hidl_vec<T> &vec, - Parcel *parcel, - size_t parentHandle, - size_t parentOffset, - size_t *handle) { - return parcel->writeEmbeddedBuffer( - vec.data(), - sizeof(T) * vec.size(), - handle, - parentHandle, - parentOffset + hidl_vec<T>::kOffsetOfBuffer); -} - //////////////////////////////////////////////////////////////////////////////// namespace details { @@ -431,127 +390,6 @@ private: T mBuffer[SIZE1]; }; -///////////////////////////// pointers for HIDL - -template <typename T> -static status_t readEmbeddedReferenceFromParcel( - T const* * /* bufptr */, - const Parcel & parcel, - size_t parentHandle, - size_t parentOffset, - size_t *handle, - bool *shouldResolveRefInBuffer - ) { - // *bufptr is ignored because, if I am embedded in some - // other buffer, the kernel should have fixed me up already. - bool isPreviouslyWritten; - status_t result = parcel.readEmbeddedReference( - nullptr, // ignored, not written to bufptr. - handle, - parentHandle, - parentOffset, - &isPreviouslyWritten); - // tell caller to run T::readEmbeddedToParcel and - // T::readEmbeddedReferenceToParcel if necessary. - // It is not called here because we don't know if these two are valid methods. - *shouldResolveRefInBuffer = !isPreviouslyWritten; - return result; -} - -template <typename T> -static status_t writeEmbeddedReferenceToParcel( - T const* buf, - Parcel *parcel, size_t parentHandle, size_t parentOffset, - size_t *handle, - bool *shouldResolveRefInBuffer - ) { - - if(buf == nullptr) { - *shouldResolveRefInBuffer = false; - return parcel->writeEmbeddedNullReference(handle, parentHandle, parentOffset); - } - - // find whether the buffer exists - size_t childHandle, childOffset; - status_t result; - bool found; - - result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset); - - // tell caller to run T::writeEmbeddedToParcel and - // T::writeEmbeddedReferenceToParcel if necessary. - // It is not called here because we don't know if these two are valid methods. - *shouldResolveRefInBuffer = !found; - - if(result != OK) { - return result; // bad pointers and length given - } - if(!found) { // did not find it. - return parcel->writeEmbeddedBuffer(buf, sizeof(T), handle, - parentHandle, parentOffset); - } - // found the buffer. easy case. - return parcel->writeEmbeddedReference( - handle, - childHandle, - childOffset, - parentHandle, - parentOffset); -} - -template <typename T> -static status_t readReferenceFromParcel( - T const* *bufptr, - const Parcel & parcel, - size_t *handle, - bool *shouldResolveRefInBuffer - ) { - bool isPreviouslyWritten; - status_t result = parcel.readReference(reinterpret_cast<void const* *>(bufptr), - handle, &isPreviouslyWritten); - // tell caller to run T::readEmbeddedToParcel and - // T::readEmbeddedReferenceToParcel if necessary. - // It is not called here because we don't know if these two are valid methods. - *shouldResolveRefInBuffer = !isPreviouslyWritten; - return result; -} - -template <typename T> -static status_t writeReferenceToParcel( - T const *buf, - Parcel * parcel, - size_t *handle, - bool *shouldResolveRefInBuffer - ) { - - if(buf == nullptr) { - *shouldResolveRefInBuffer = false; - return parcel->writeNullReference(handle); - } - - // find whether the buffer exists - size_t childHandle, childOffset; - status_t result; - bool found; - - result = parcel->findBuffer(buf, sizeof(T), &found, &childHandle, &childOffset); - - // tell caller to run T::writeEmbeddedToParcel and - // T::writeEmbeddedReferenceToParcel if necessary. - // It is not called here because we don't know if these two are valid methods. - *shouldResolveRefInBuffer = !found; - - if(result != OK) { - return result; // bad pointers and length given - } - if(!found) { // did not find it. - return parcel->writeBuffer(buf, sizeof(T), handle); - } - // found the buffer. easy case. - return parcel->writeReference(handle, - childHandle, childOffset); -} - // ---------------------------------------------------------------------- // Version functions struct hidl_version { @@ -565,20 +403,6 @@ public: constexpr uint16_t get_major() const { return mMajor; } constexpr uint16_t get_minor() const { return mMinor; } - android::status_t writeToParcel(android::hardware::Parcel& parcel) const { - return parcel.writeUint32(static_cast<uint32_t>(mMajor) << 16 | mMinor); - } - - static hidl_version* readFromParcel(const android::hardware::Parcel& parcel) { - uint32_t version; - android::status_t status = parcel.readUint32(&version); - if (status != OK) { - return nullptr; - } else { - return new hidl_version(version >> 16, version & 0xFFFF); - } - } - private: uint16_t mMajor; uint16_t mMinor; @@ -597,69 +421,6 @@ struct IBase : virtual public RefBase { static const char* descriptor; }; -extern std::map<std::string, std::function<sp<IBinder>(void*)>> gBnConstructorMap; - -// Construct a smallest possible binder from the given interface. -// If it is remote, then its remote() will be retrieved. -// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType -// and iface is of class IChild. BnChild will be used to wrapped the given iface. -// Return nullptr if iface is null or any failure. -template <typename IType, typename IHwType> -sp<IBinder> toBinder(sp<IType> iface) { - IType *ifacePtr = iface.get(); - if (ifacePtr == nullptr) { - return nullptr; - } - if (ifacePtr->isRemote()) { - return ::android::hardware::IInterface::asBinder(static_cast<IHwType *>(ifacePtr)); - } else { - std::string myDescriptor{}; - ifacePtr->interfaceChain([&](const hidl_vec<hidl_string> &types) { - if (types.size() > 0) { - myDescriptor = types[0].c_str(); - } - }); - if (myDescriptor.empty()) { - // interfaceChain fails || types.size() == 0 - return nullptr; - } - auto iter = gBnConstructorMap.find(myDescriptor); - if (iter == gBnConstructorMap.end()) { - return nullptr; - } - return sp<IBinder>((iter->second)(reinterpret_cast<void *>(ifacePtr))); - } -} - -// cast the interface IParent to IChild. -// Return nullptr if parent is null or any failure. -template<typename IChild, typename IParent, typename BpChild, typename IHwParent> -sp<IChild> castInterface(sp<IParent> parent, const char *childIndicator) { - if (parent.get() == nullptr) { - // casts always succeed with nullptrs. - return nullptr; - } - bool canCast = false; - parent->interfaceChain([&](const hidl_vec<hidl_string> &allowedCastTypes) { - for (size_t i = 0; i < allowedCastTypes.size(); i++) { - if (allowedCastTypes[i] == childIndicator) { - canCast = true; - break; - } - } - }); - - if (!canCast) { - return sp<IChild>(nullptr); // cast failed. - } - if (parent->isRemote()) { - // binderized mode. Got BpChild. grab the remote and wrap it. - return sp<IChild>(new BpChild(toBinder<IParent, IHwParent>(parent))); - } - // Passthrough mode. Got BnChild and BsChild. - return sp<IChild>(static_cast<IChild *>(parent.get())); -} - #if defined(__LP64__) #define HAL_LIBRARY_PATH_SYSTEM "/system/lib64/hw/" #define HAL_LIBRARY_PATH_VENDOR "/vendor/lib64/hw/" @@ -679,85 +440,6 @@ sp<IChild> castInterface(sp<IParent> parent, const char *childIndicator) { const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \ ¬ification); \ -#define IMPLEMENT_SERVICE_MANAGER_INTERACTIONS(INTERFACE, PACKAGE) \ - ::android::sp<I##INTERFACE> I##INTERFACE::getService( \ - const std::string &serviceName, bool getStub) \ - { \ - using ::android::sp; \ - using ::android::hardware::defaultServiceManager; \ - using ::android::hardware::IBinder; \ - using ::android::hidl::manager::V1_0::IServiceManager; \ - sp<I##INTERFACE> iface; \ - const sp<IServiceManager> sm = defaultServiceManager(); \ - if (sm != nullptr && !getStub) { \ - sp<IBinder> binderIface; \ - ::android::hardware::Return<void> ret = \ - sm->get(PACKAGE "::I" #INTERFACE, serviceName.c_str(), \ - [&binderIface](sp<IBinder> iface) { \ - binderIface = iface; \ - }); \ - if (ret.getStatus().isOk()) { \ - iface = IHw##INTERFACE::asInterface(binderIface); \ - if (iface != nullptr) { \ - return iface; \ - } \ - } \ - } \ - int dlMode = RTLD_LAZY; \ - void *handle = dlopen(HAL_LIBRARY_PATH_ODM PACKAGE "-impl.so", dlMode); \ - if (handle == nullptr) { \ - handle = dlopen(HAL_LIBRARY_PATH_VENDOR PACKAGE "-impl.so", dlMode); \ - } \ - if (handle == nullptr) { \ - handle = dlopen(HAL_LIBRARY_PATH_SYSTEM PACKAGE "-impl.so", dlMode); \ - } \ - if (handle == nullptr) { \ - return iface; \ - } \ - I##INTERFACE* (*generator)(const char* name); \ - *(void **)(&generator) = dlsym(handle, "HIDL_FETCH_I"#INTERFACE); \ - if (generator) { \ - iface = (*generator)(serviceName.c_str()); \ - if (iface != nullptr) { \ - iface = new Bs##INTERFACE(iface); \ - } \ - } \ - return iface; \ - } \ - ::android::status_t I##INTERFACE::registerAsService( \ - const std::string &serviceName) \ - { \ - using ::android::sp; \ - using ::android::hardware::defaultServiceManager; \ - using ::android::hidl::manager::V1_0::IServiceManager; \ - sp<Bn##INTERFACE> binderIface = new Bn##INTERFACE(this); \ - const sp<IServiceManager> sm = defaultServiceManager(); \ - bool success = false; \ - ::android::hardware::Return<void> ret = \ - this->interfaceChain( \ - [&success, &sm, &serviceName, &binderIface](const auto &chain) { \ - success = sm->add(chain, serviceName.c_str(), binderIface); \ - }); \ - success = success && ret.getStatus().isOk(); \ - return success ? ::android::OK : ::android::UNKNOWN_ERROR; \ - } \ - bool I##INTERFACE::registerForNotifications( \ - const std::string &serviceName, \ - const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> \ - ¬ification) \ - { \ - using ::android::sp; \ - using ::android::hardware::defaultServiceManager; \ - using ::android::hidl::manager::V1_0::IServiceManager; \ - const sp<IServiceManager> sm = defaultServiceManager(); \ - if (sm == nullptr) { \ - return false; \ - } \ - return sm->registerForNotifications(PACKAGE "::I" #INTERFACE, \ - serviceName, \ - notification); \ - } - // ---------------------------------------------------------------------- // Class that provides Hidl instrumentation utilities. struct HidlInstrumentor { diff --git a/include/hidl/HidlTransportSupport.h b/include/hidl/HidlTransportSupport.h new file mode 100644 index 0000000..f8cae2e --- /dev/null +++ b/include/hidl/HidlTransportSupport.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HIDL_TRANSPORT_SUPPORT_H +#define ANDROID_HIDL_TRANSPORT_SUPPORT_H + +#include <hidl/HidlSupport.h> +#include <hidl/HidlBinderSupport.h> + +namespace android { +namespace hardware { + +// cast the interface IParent to IChild. +// Return nullptr if parent is null or any failure. +template<typename IChild, typename IParent, typename BpChild, typename IHwParent> +sp<IChild> castInterface(sp<IParent> parent, const char *childIndicator) { + if (parent.get() == nullptr) { + // casts always succeed with nullptrs. + return nullptr; + } + bool canCast = false; + parent->interfaceChain([&](const hidl_vec<hidl_string> &allowedCastTypes) { + for (size_t i = 0; i < allowedCastTypes.size(); i++) { + if (allowedCastTypes[i] == childIndicator) { + canCast = true; + break; + } + } + }); + + if (!canCast) { + return sp<IChild>(nullptr); // cast failed. + } + // TODO b/32001926 Needs to be fixed for socket mode. + if (parent->isRemote()) { + // binderized mode. Got BpChild. grab the remote and wrap it. + return sp<IChild>(new BpChild(toBinder<IParent, IHwParent>(parent))); + } + // Passthrough mode. Got BnChild and BsChild. + return sp<IChild>(static_cast<IChild *>(parent.get())); +} + +} // namespace hardware +} // namespace android + + +#endif // ANDROID_HIDL_TRANSPORT_SUPPORT_H diff --git a/include/hidl/MQDescriptor.h b/include/hidl/MQDescriptor.h index f323834..8292035 100644 --- a/include/hidl/MQDescriptor.h +++ b/include/hidl/MQDescriptor.h @@ -194,66 +194,6 @@ MQDescriptor<flavor>::~MQDescriptor() { } template<MQFlavor flavor> -::android::status_t readEmbeddedFromParcel( - MQDescriptor<flavor> *obj, - const ::android::hardware::Parcel &parcel, - size_t parentHandle, - size_t parentOffset) { - ::android::status_t _hidl_err = ::android::OK; - - size_t _hidl_grantors_child; - - _hidl_err = ::android::hardware::readEmbeddedFromParcel( - &obj->grantors(), - parcel, - parentHandle, - parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors, - &_hidl_grantors_child); - - if (_hidl_err != ::android::OK) { return _hidl_err; } - - const native_handle_t *_hidl_mq_handle_ptr = parcel.readEmbeddedNativeHandle( - parentHandle, - parentOffset + MQDescriptor<flavor>::kOffsetOfHandle); - - if (_hidl_mq_handle_ptr == nullptr) { - _hidl_err = ::android::UNKNOWN_ERROR; - return _hidl_err; - } - - return _hidl_err; -} - -template<MQFlavor flavor> -::android::status_t writeEmbeddedToParcel( - const MQDescriptor<flavor> &obj, - ::android::hardware::Parcel *parcel, - size_t parentHandle, - size_t parentOffset) { - ::android::status_t _hidl_err = ::android::OK; - - size_t _hidl_grantors_child; - - _hidl_err = ::android::hardware::writeEmbeddedToParcel( - obj.grantors(), - parcel, - parentHandle, - parentOffset + MQDescriptor<flavor>::kOffsetOfGrantors, - &_hidl_grantors_child); - - if (_hidl_err != ::android::OK) { return _hidl_err; } - - _hidl_err = parcel->writeEmbeddedNativeHandle( - obj.handle(), - parentHandle, - parentOffset + MQDescriptor<flavor>::kOffsetOfHandle); - - if (_hidl_err != ::android::OK) { return _hidl_err; } - - return _hidl_err; -} - -template<MQFlavor flavor> size_t MQDescriptor<flavor>::getSize() const { return mGrantors[DATAPTRPOS].extent; } diff --git a/include/hidl/Status.h b/include/hidl/Status.h index 6dde65c..248d51c 100644 --- a/include/hidl/Status.h +++ b/include/hidl/Status.h @@ -20,7 +20,6 @@ #include <cstdint> #include <sstream> -#include <hwbinder/Parcel.h> #include <utils/String8.h> #include <android-base/macros.h> @@ -98,11 +97,6 @@ public: Status(Status&& status) = default; Status& operator=(const Status& status) = default; - // Bear in mind that if the client or service is a Java endpoint, this - // is not the logic which will provide/interpret the data here. - status_t readFromParcel(const Parcel& parcel); - status_t writeToParcel(Parcel* parcel) const; - // Set one of the pre-defined exception types defined above. void setException(int32_t ex, const String8& message); // Set a service specific exception with error code. |