summaryrefslogtreecommitdiff
path: root/transport/include
diff options
context:
space:
mode:
Diffstat (limited to 'transport/include')
-rw-r--r--transport/include/hidl/ConcurrentMap.h17
-rw-r--r--transport/include/hidl/HidlBinderSupport.h57
-rw-r--r--transport/include/hidl/HidlLazyUtils.h41
-rw-r--r--transport/include/hidl/HidlTransportSupport.h24
-rw-r--r--transport/include/hidl/LegacySupport.h92
-rw-r--r--transport/include/hidl/ServiceManagement.h28
-rw-r--r--transport/include/hidl/Static.h22
7 files changed, 189 insertions, 92 deletions
diff --git a/transport/include/hidl/ConcurrentMap.h b/transport/include/hidl/ConcurrentMap.h
index 1b06dfd..329752c 100644
--- a/transport/include/hidl/ConcurrentMap.h
+++ b/transport/include/hidl/ConcurrentMap.h
@@ -90,6 +90,23 @@ public:
std::map<K, V> mMap;
};
+namespace details {
+
+// TODO(b/69122224): remove this type and usages of it
+// DO NOT ADD USAGES
+template <typename T>
+class DoNotDestruct {
+ public:
+ DoNotDestruct() { new (buffer) T(); }
+ T& get() { return *reinterpret_cast<T*>(buffer); }
+ T* operator->() { return reinterpret_cast<T*>(buffer); }
+
+ private:
+ alignas(T) char buffer[sizeof(T)];
+};
+
+} // namespace details
+
} // namespace hardware
} // namespace android
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 9759af1..a098805 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -24,11 +24,10 @@
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportUtils.h>
#include <hidl/MQDescriptor.h>
-#include <hidl/Static.h>
#include <hwbinder/IBinder.h>
-#include <hwbinder/IPCThreadState.h>
#include <hwbinder/Parcel.h>
-#include <hwbinder/ProcessState.h>
+#include <log/log.h> // TODO(b/65843592): remove. Too many users depending on this transitively.
+
// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
// etc. to interact with Parcel.
@@ -49,6 +48,14 @@ private:
wp<::android::hidl::base::V1_0::IBase> mBase;
};
+// ---------------------- hidl_handle
+
+status_t readEmbeddedFromParcel(const hidl_handle &handle,
+ const Parcel &parcel, size_t parentHandle, size_t parentOffset);
+
+status_t writeEmbeddedToParcel(const hidl_handle &handle,
+ Parcel *parcel, size_t parentHandle, size_t parentOffset);
+
// ---------------------- hidl_memory
status_t readEmbeddedFromParcel(const hidl_memory &memory,
@@ -301,6 +308,10 @@ static status_t writeReferenceToParcel(
// ---------------------- support for casting interfaces
+// Constructs a binder for this interface and caches it. If it has already been created
+// then it returns it.
+sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr);
+
// 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
@@ -310,43 +321,7 @@ template <typename IType,
typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>>
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<BpInterface<IType>*>(ifacePtr));
- } else {
- std::string myDescriptor = details::getDescriptor(ifacePtr);
- if (myDescriptor.empty()) {
- // interfaceDescriptor fails
- return nullptr;
- }
-
- // for get + set
- std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
-
- wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
- sp<IBinder> sBnObj = wBnObj.promote();
-
- if (sBnObj == nullptr) {
- auto func = details::getBnConstructorMap().get(myDescriptor, nullptr);
- if (!func) {
- func = details::gBnConstructorMap.get(myDescriptor, nullptr);
- if (!func) {
- return nullptr;
- }
- }
-
- sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
-
- if (sBnObj != nullptr) {
- details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
- }
- }
-
- return sBnObj;
- }
+ return getOrCreateCachedBinder(ifacePtr);
}
template <typename IType, typename ProxyType, typename StubType>
@@ -374,6 +349,8 @@ void joinBinderRpcThreadpool();
int setupBinderPolling();
status_t handleBinderPoll();
+void addPostCommandTask(const std::function<void(void)> task);
+
} // namespace hardware
} // namespace android
diff --git a/transport/include/hidl/HidlLazyUtils.h b/transport/include/hidl/HidlLazyUtils.h
new file mode 100644
index 0000000..2205daa
--- /dev/null
+++ b/transport/include/hidl/HidlLazyUtils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <android/hidl/base/1.0/IBase.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace details {
+class LazyServiceRegistrarImpl;
+} // namespace details
+
+/** Exits when all HALs registered through this object have 0 clients */
+class LazyServiceRegistrar {
+ public:
+ LazyServiceRegistrar();
+ status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
+ const std::string& name = "default");
+
+ private:
+ std::shared_ptr<details::LazyServiceRegistrarImpl> mImpl;
+};
+
+} // namespace hardware
+} // namespace android
diff --git a/transport/include/hidl/HidlTransportSupport.h b/transport/include/hidl/HidlTransportSupport.h
index cdcb03e..a132bfa 100644
--- a/transport/include/hidl/HidlTransportSupport.h
+++ b/transport/include/hidl/HidlTransportSupport.h
@@ -84,18 +84,6 @@ status_t handleTransportPoll(int fd);
bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
int policy, int priority);
-template <typename ILeft,
- typename IRight,
- typename = std::enable_if_t<std::is_same<details::i_tag, typename ILeft::_hidl_tag>::value>,
- typename = std::enable_if_t<std::is_same<details::i_tag, typename IRight::_hidl_tag>::value>>
-bool interfacesEqual(sp<ILeft> left, sp<IRight> right) {
- if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
- return left == right;
- }
-
- return toBinder<ILeft>(left) == toBinder<IRight>(right);
-}
-
/**
* Sets whether or not this object should request security contexts to be populatd for incoming
* calls (e.g. with getCallingSid).
@@ -108,6 +96,14 @@ bool interfacesEqual(sp<ILeft> left, sp<IRight> right) {
*/
bool setRequestingSid(const sp<::android::hidl::base::V1_0::IBase>& service, bool requesting);
+/**
+ * Returns whether two interfaces represent the same interface. References to interfaces in the same
+ * process will always be equivalent. However, in order to compare a service that is a proxy to a
+ * different process, its underlying structure may have to be checked.
+ */
+bool interfacesEqual(const sp<::android::hidl::base::V1_0::IBase>& left,
+ const sp<::android::hidl::base::V1_0::IBase>& right);
+
namespace details {
// Return PID on userdebug / eng builds and IServiceManager::PidConstant::NO_PID on user builds.
@@ -141,7 +137,7 @@ Return<sp<IChild>> castInterface(sp<IParent> parent, const char* childIndicator,
// 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>(parent)));
+ return sp<IChild>(new BpChild(getOrCreateCachedBinder(parent.get())));
}
// Passthrough mode. Got BnChild or BsChild.
return sp<IChild>(static_cast<IChild *>(parent.get()));
@@ -161,7 +157,7 @@ sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getSt
if (base->isRemote()) {
// getRawServiceInternal guarantees we get the proper class
- return sp<IType>(new BpType(toBinder<IBase>(base)));
+ return sp<IType>(new BpType(getOrCreateCachedBinder(base.get())));
}
return IType::castFrom(base);
diff --git a/transport/include/hidl/LegacySupport.h b/transport/include/hidl/LegacySupport.h
index f03d34d..1e983eb 100644
--- a/transport/include/hidl/LegacySupport.h
+++ b/transport/include/hidl/LegacySupport.h
@@ -14,25 +14,21 @@
* limitations under the License.
*/
+#include <hidl/HidlLazyUtils.h>
#include <hidl/HidlTransportSupport.h>
#include <sys/wait.h>
-#include <utils/Log.h>
#include <utils/Errors.h>
+#include <utils/Log.h>
#include <utils/StrongPointer.h>
-#ifndef ANDROID_HIDL_LEGACY_SUPPORT_H
-#define ANDROID_HIDL_LEGACY_SUPPORT_H
+#pragma once
namespace android {
namespace hardware {
-
-/**
- * Registers passthrough service implementation.
- */
-template<class Interface>
-__attribute__((warn_unused_result))
-status_t registerPassthroughServiceImplementation(
- std::string name = "default") {
+namespace details {
+template <class Interface, typename Func>
+__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
+ Func registerServiceCb, const std::string& name = "default") {
sp<Interface> service = Interface::getService(name, true /* getStub */);
if (service == nullptr) {
@@ -44,7 +40,7 @@ status_t registerPassthroughServiceImplementation(
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
- status_t status = service->registerAsService(name);
+ status_t status = registerServiceCb(service, name);
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
@@ -56,16 +52,29 @@ status_t registerPassthroughServiceImplementation(
return status;
}
+} // namespace details
+
+/**
+ * Registers passthrough service implementation.
+ */
+template <class Interface>
+__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
+ const std::string& name = "default") {
+ return details::registerPassthroughServiceImplementation<Interface>(
+ [](const sp<Interface>& service, const std::string& name) {
+ return service->registerAsService(name);
+ },
+ name);
+}
/**
* Creates default passthrough service implementation. This method never returns.
*
* Return value is exit status.
*/
-template<class Interface>
-__attribute__((warn_unused_result))
-status_t defaultPassthroughServiceImplementation(std::string name,
- size_t maxThreads = 1) {
+template <class Interface>
+__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(
+ const std::string& name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true);
status_t result = registerPassthroughServiceImplementation<Interface>(name);
@@ -82,7 +91,54 @@ status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) {
return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);
}
+/**
+ * Registers a passthrough service implementation that exits when there are 0 clients.
+ *
+ * If this function is called multiple times to register different services, then this process will
+ * only exit once all services have 0 clients. This function does not know about clients registered
+ * through registerPassthroughServiceImplementation, so if that function is used in conjunction with
+ * this one, the process may exit while a client is still using the HAL.
+ */
+template <class Interface>
+__attribute__((warn_unused_result)) status_t registerLazyPassthroughServiceImplementation(
+ const std::string& name = "default") {
+ // Make LazyServiceRegistrar static so that multiple calls to
+ // registerLazyPassthroughServiceImplementation work as expected: each HAL is registered and the
+ // process only exits once all HALs have 0 clients.
+ using android::hardware::LazyServiceRegistrar;
+ static auto serviceCounter(std::make_shared<LazyServiceRegistrar>());
+
+ return details::registerPassthroughServiceImplementation<Interface>(
+ [](const sp<Interface>& service, const std::string& name) {
+ return serviceCounter->registerService(service, name);
+ },
+ name);
+}
+
+/**
+ * Creates default passthrough service implementation that exits when there are 0 clients. This
+ * method never returns.
+ *
+ * Return value is exit status.
+ */
+template <class Interface>
+__attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplementation(
+ const std::string& name, size_t maxThreads = 1) {
+ configureRpcThreadpool(maxThreads, true);
+ status_t result = registerLazyPassthroughServiceImplementation<Interface>(name);
+
+ if (result != OK) {
+ return result;
+ }
+
+ joinRpcThreadpool();
+ return UNKNOWN_ERROR;
+}
+template <class Interface>
+__attribute__((warn_unused_result)) status_t defaultLazyPassthroughServiceImplementation(
+ size_t maxThreads = 1) {
+ return defaultLazyPassthroughServiceImplementation<Interface>("default", maxThreads);
+}
+
} // namespace hardware
} // namespace android
-
-#endif // ANDROID_HIDL_LEGACY_SUPPORT_H
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 4df156b..a962034 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -28,21 +28,21 @@ namespace hidl {
namespace manager {
namespace V1_0 {
struct IServiceManager;
-}; // namespace V1_0
+} // namespace V1_0
namespace V1_1 {
- struct IServiceManager;
-}; // namespace V1_0
-}; // namespace manager
-}; // namespace hidl
+struct IServiceManager;
+} // namespace V1_1
+namespace V1_2 {
+struct IServiceManager;
+} // namespace V1_2
+} // namespace manager
+} // namespace hidl
namespace hardware {
namespace details {
-// e.x.: android.hardware.foo@1.0, IFoo, default
-void onRegistration(const std::string &packageName,
- const std::string &interfaceName,
- const std::string &instanceName);
+// Will not attempt to start a lazy HAL
// e.x.: android.hardware.foo@1.0::IFoo, default
void waitForHwService(const std::string &interface, const std::string &instanceName);
@@ -57,12 +57,16 @@ void preloadPassthroughService(const std::string &descriptor);
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
const std::string& instance,
bool retry, bool getStub);
-};
+
+status_t registerAsServiceInternal(const sp<::android::hidl::base::V1_0::IBase>& service,
+ const std::string& name);
+} // namespace details
// These functions are for internal use by hidl. If you want to get ahold
// of an interface, the best way to do this is by calling IFoo::getService()
sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
sp<::android::hidl::manager::V1_1::IServiceManager> defaultServiceManager1_1();
+sp<::android::hidl::manager::V1_2::IServiceManager> defaultServiceManager1_2();
sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
sp<::android::hidl::manager::V1_1::IServiceManager> getPassthroughServiceManager1_1();
@@ -77,8 +81,8 @@ static inline void preloadPassthroughService() {
details::preloadPassthroughService(I::descriptor);
}
-}; // namespace hardware
-}; // namespace android
+} // namespace hardware
+} // namespace android
#endif // ANDROID_HARDWARE_ISERVICE_MANAGER_H
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index b15be68..be74bae 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -17,6 +17,9 @@
// All static variables go here, to control initialization and
// destruction order in the library.
+#ifndef ANDROID_HARDWARE_HIDL_STATIC_H
+#define ANDROID_HARDWARE_HIDL_STATIC_H
+
#include <functional>
#include <android/hidl/base/1.0/IBase.h>
@@ -34,19 +37,22 @@ struct SchedPrio {
int prio;
};
-extern ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio> gServicePrioMap;
-extern ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool> gServiceSidMap;
+// TODO(b/69122224): remove this
+extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, SchedPrio>>
+ gServicePrioMap;
+// TODO(b/69122224): remove this
+extern DoNotDestruct<ConcurrentMap<wp<::android::hidl::base::V1_0::IBase>, bool>> gServiceSidMap;
+// TODO(b/69122224): remove this
// For HidlBinderSupport and autogenerated code
-extern ConcurrentMap<const ::android::hidl::base::V1_0::IBase*, wp<::android::hardware::BHwBinder>>
- gBnMap;
+extern DoNotDestruct<ConcurrentMap<const ::android::hidl::base::V1_0::IBase*,
+ wp<::android::hardware::BHwBinder>>>
+ gBnMap;
using BnConstructorMap = ConcurrentMap<std::string, std::function<sp<IBinder>(void*)>>;
// For HidlBinderSupport and autogenerated code
// value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
// returns sp<IBinder>
-// deprecated; use getBnConstructorMap instead.
-extern BnConstructorMap gBnConstructorMap;
BnConstructorMap& getBnConstructorMap();
using BsConstructorMap = ConcurrentMap<std::string,
@@ -54,9 +60,9 @@ using BsConstructorMap = ConcurrentMap<std::string,
// For HidlPassthroughSupport and autogenerated code
// value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
// returns sp<IBase>
-// deprecated; use getBsConstructorMap instead.
-extern BsConstructorMap gBsConstructorMap;
BsConstructorMap& getBsConstructorMap();
} // namespace details
} // namespace hardware
} // namespace android
+
+#endif