diff options
Diffstat (limited to 'transport/include')
-rw-r--r-- | transport/include/hidl/ConcurrentMap.h | 17 | ||||
-rw-r--r-- | transport/include/hidl/HidlBinderSupport.h | 57 | ||||
-rw-r--r-- | transport/include/hidl/HidlLazyUtils.h | 41 | ||||
-rw-r--r-- | transport/include/hidl/HidlTransportSupport.h | 24 | ||||
-rw-r--r-- | transport/include/hidl/LegacySupport.h | 92 | ||||
-rw-r--r-- | transport/include/hidl/ServiceManagement.h | 28 | ||||
-rw-r--r-- | transport/include/hidl/Static.h | 22 |
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 |