summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--HidlBinderSupport.cpp145
-rw-r--r--HidlSupport.cpp24
-rw-r--r--Status.cpp69
-rw-r--r--include/hidl/HidlBinderSupport.h393
-rw-r--r--include/hidl/HidlSupport.h320
-rw-r--r--include/hidl/HidlTransportSupport.h60
-rw-r--r--include/hidl/MQDescriptor.h60
-rw-r--r--include/hidl/Status.h6
9 files changed, 600 insertions, 478 deletions
diff --git a/Android.bp b/Android.bp
index 6b08c87..87bee79 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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";
// ----------------------------------------------------------------------
diff --git a/Status.cpp b/Status.cpp
index 0a9f513..f018918 100644
--- a/Status.cpp
+++ b/Status.cpp
@@ -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> \
+ &notification) \
+ { \
+ 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> \
&notification); \
-#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> \
- &notification) \
- { \
- 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.