diff options
40 files changed, 867 insertions, 301 deletions
@@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["system_libhidl_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "system_libhidl_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "libhidl-defaults", cflags: [ @@ -69,6 +86,7 @@ cc_library { native_bridge_supported: true, recovery_available: true, vendor_available: true, + product_available: true, apex_available: [ // TODO(b/137948090): not fully supported in APEX for certain usecases // - large dependency sizes @@ -110,13 +128,18 @@ cc_library { } // WARNING: deprecated -// This library is no longer required, and dependencies should be taken -// on libhidlbase instead. +// This library is no longer required, and dependencies should be taken on libhidlbase instead. +// This is automatically removed by bpfix. Once there are no makefiles, fixes can be automatically applied, and this can be removed. cc_library { name: "libhidltransport", vendor_available: true, - visibility: [":__subpackages__"], + visibility: [ + ":__subpackages__", + "//hardware:__subpackages__", + "//test/sts:__subpackages__", + "//vendor:__subpackages__", + ], } cc_defaults { @@ -160,6 +183,13 @@ cc_defaults { "transport/include", ], + header_libs: [ + "libfmq-base", + ], + export_header_lib_headers: [ + "libfmq-base", + ], + generated_sources: [ "android.hidl.manager@1.0_genc++", "android.hidl.manager@1.1_genc++", diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/TEST_MAPPING b/TEST_MAPPING index 01179d5..22c9d36 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -8,6 +8,9 @@ }, { "name": "hal_implementation_test" + }, + { + "name": "hidl_lazy_test" } ] } diff --git a/adapter/Android.bp b/adapter/Android.bp index 07faa10..83609ff 100644 --- a/adapter/Android.bp +++ b/adapter/Android.bp @@ -12,10 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_library { name: "libhidladapter", defaults: ["libhidl-defaults"], vendor_available: true, + product_available: true, // TODO(b/153609531): remove when no longer needed. native_bridge_supported: true, srcs: [ @@ -33,4 +43,3 @@ cc_library { "libutils", ], } - diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp index af805b9..78faa2f 100644 --- a/base/HidlSupport.cpp +++ b/base/HidlSupport.cpp @@ -217,6 +217,14 @@ void hidl_string::copyFrom(const char *data, size_t size) { if (size >= UINT32_MAX) { LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size; } + + if (size == 0) { + mBuffer = kEmptyString; + mSize = 0; + mOwnsBuffer = false; + return; + } + char *buf = (char *)malloc(size + 1); memcpy(buf, data, size); buf[size] = '\0'; diff --git a/base/include/hidl/HidlInternal.h b/base/include/hidl/HidlInternal.h index 3cd246a..3d1a444 100644 --- a/base/include/hidl/HidlInternal.h +++ b/base/include/hidl/HidlInternal.h @@ -201,7 +201,10 @@ struct HidlInstrumentor { // A list of registered instrumentation callbacks. std::vector<InstrumentationCallback> mInstrumentationCallbacks; // Flag whether to enable instrumentation. - bool mEnableInstrumentation; + union { + bool mEnableInstrumentation; + void* mReserved0; + }; // Prefix to lookup the instrumentation libraries. std::string mInstrumentationLibPackage; // Used for dlsym to load the profiling method for given interface. @@ -209,6 +212,12 @@ struct HidlInstrumentor { }; +#ifdef __LP64__ +static_assert(sizeof(HidlInstrumentor) == 88, "HidlInstrumentor size frozen by prebuilts"); +#else +static_assert(sizeof(HidlInstrumentor) == 44, "HidlInstrumentor size frozen by prebuilts"); +#endif + } // namespace details } // namespace hardware } // namespace android diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h index 1b91c26..1bb38e8 100644 --- a/base/include/hidl/HidlSupport.h +++ b/base/include/hidl/HidlSupport.h @@ -342,7 +342,6 @@ struct hidl_vec { memset(mPad, 0, sizeof(mPad)); } - // Note, does not initialize primitive types. hidl_vec(size_t size) : hidl_vec() { resize(size); } hidl_vec(const hidl_vec<T> &other) : hidl_vec() { @@ -412,7 +411,7 @@ struct hidl_vec { } T *releaseData() { - if (!mOwnsBuffer && mSize > 0) { + if (!mOwnsBuffer && mBuffer != nullptr) { resize(mSize); } mOwnsBuffer = false; @@ -507,7 +506,7 @@ struct hidl_vec { return mBuffer[index]; } - // Does not initialize primitive types if new size > old size. + // Copies over old elements fitting in new size. Value initializes the rest. void resize(size_t size) { if (size > UINT32_MAX) { details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements."); @@ -1044,6 +1043,9 @@ constexpr hidl_invalid_type<T> hidl_enum_values; */ template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>> struct hidl_enum_range { + // Container-like associated type. + using value_type = T; + constexpr auto begin() const { return std::begin(details::hidl_enum_values<T>); } constexpr auto cbegin() const { return begin(); } constexpr auto rbegin() const { return std::rbegin(details::hidl_enum_values<T>); } diff --git a/base/include/hidl/MQDescriptor.h b/base/include/hidl/MQDescriptor.h index 0f61cb5..0429444 100644 --- a/base/include/hidl/MQDescriptor.h +++ b/base/include/hidl/MQDescriptor.h @@ -20,43 +20,13 @@ #include <unistd.h> #include <cutils/native_handle.h> +#include <fmq/MQDescriptorBase.h> #include <hidl/HidlInternal.h> #include <hidl/HidlSupport.h> namespace android { namespace hardware { -typedef uint64_t RingBufferPosition; - -struct GrantorDescriptor { - uint32_t flags __attribute__ ((aligned(4))); - uint32_t fdIndex __attribute__ ((aligned(4))); - uint32_t offset __attribute__ ((aligned(4))); - uint64_t extent __attribute__ ((aligned(8))); -}; - -static_assert(offsetof(GrantorDescriptor, flags) == 0, "wrong offset"); -static_assert(offsetof(GrantorDescriptor, fdIndex) == 4, "wrong offset"); -static_assert(offsetof(GrantorDescriptor, offset) == 8, "wrong offset"); -static_assert(offsetof(GrantorDescriptor, extent) == 16, "wrong offset"); -static_assert(sizeof(GrantorDescriptor) == 24, "wrong size"); -static_assert(__alignof(GrantorDescriptor) == 8, "wrong alignment"); - -enum MQFlavor : uint32_t { - /* - * kSynchronizedReadWrite represents the wait-free synchronized flavor of the - * FMQ. It is intended to be have a single reader and single writer. - * Attempts to overflow/underflow returns a failure. - */ - kSynchronizedReadWrite = 0x01, - /* - * kUnsynchronizedWrite represents the flavor of FMQ where writes always - * succeed. This flavor allows one writer and many readers. A read operation - * can detect an overwrite and reset the read counter. - */ - kUnsynchronizedWrite = 0x02 -}; - template <typename T, MQFlavor flavor> struct MQDescriptor { // Takes ownership of handle @@ -87,10 +57,6 @@ struct MQDescriptor { return mGrantors; } - inline ::android::hardware::hidl_vec<GrantorDescriptor> &grantors() { - return mGrantors; - } - inline const ::native_handle_t *handle() const { return mHandle; } @@ -101,42 +67,7 @@ struct MQDescriptor { static const size_t kOffsetOfGrantors; static const size_t kOffsetOfHandle; - enum GrantorType : int { READPTRPOS = 0, WRITEPTRPOS, DATAPTRPOS, EVFLAGWORDPOS }; - - /* - * There should at least be GrantorDescriptors for the read counter, write - * counter and data buffer. A GrantorDescriptor for an EventFlag word is - * not required if there is no need for blocking FMQ operations. - */ - static constexpr int32_t kMinGrantorCount = DATAPTRPOS + 1; - - /* - * Minimum number of GrantorDescriptors required if EventFlag support is - * needed for blocking FMQ operations. - */ - static constexpr int32_t kMinGrantorCountForEvFlagSupport = EVFLAGWORDPOS + 1; - - //TODO(b/34160777) Identify a better solution that supports remoting. - static inline size_t alignToWordBoundary(size_t length) { - constexpr size_t kAlignmentSize = 64; - if (kAlignmentSize % __WORDSIZE != 0) { - details::logAlwaysFatal("Incompatible word size"); - } - - /* - * Check if alignment to word boundary would cause an overflow. - */ - if (length > SIZE_MAX - kAlignmentSize/8 + 1) { - details::logAlwaysFatal("Queue size too large"); - } - - return (length + kAlignmentSize/8 - 1) & ~(kAlignmentSize/8 - 1U); - } - static inline size_t isAlignedToWordBoundary(size_t offset) { - constexpr size_t kAlignmentSize = 64; - return (offset & (kAlignmentSize/8 - 1)) == 0; - } private: ::android::hardware::hidl_vec<GrantorDescriptor> mGrantors; ::android::hardware::details::hidl_pointer<native_handle_t> mHandle; @@ -164,38 +95,34 @@ using MQDescriptorSync = MQDescriptor<T, kSynchronizedReadWrite>; template<typename T> using MQDescriptorUnsync = MQDescriptor<T, kUnsynchronizedWrite>; -template<typename T, MQFlavor flavor> -MQDescriptor<T, flavor>::MQDescriptor( - const std::vector<GrantorDescriptor>& grantors, - native_handle_t* nhandle, - size_t size) - : mHandle(nhandle), - mQuantum(size), - mFlags(flavor) { +template <typename T, MQFlavor flavor> +MQDescriptor<T, flavor>::MQDescriptor(const std::vector<GrantorDescriptor>& grantors, + native_handle_t* nhandle, size_t size) + : mHandle(nhandle), mQuantum(static_cast<uint32_t>(size)), mFlags(flavor) { mGrantors.resize(grantors.size()); for (size_t i = 0; i < grantors.size(); ++i) { - if (isAlignedToWordBoundary(grantors[i].offset) == false) { - details::logAlwaysFatal("Grantor offsets need to be aligned"); - } mGrantors[i] = grantors[i]; } } -template<typename T, MQFlavor flavor> -MQDescriptor<T, flavor>::MQDescriptor(size_t bufferSize, native_handle_t *nHandle, - size_t messageSize, bool configureEventFlag) - : mHandle(nHandle), mQuantum(messageSize), mFlags(flavor) { +template <typename T, MQFlavor flavor> +MQDescriptor<T, flavor>::MQDescriptor(size_t bufferSize, native_handle_t* nHandle, + size_t messageSize, bool configureEventFlag) + : mHandle(nHandle), mQuantum(static_cast<uint32_t>(messageSize)), mFlags(flavor) { /* * If configureEventFlag is true, allocate an additional spot in mGrantor * for containing the fd and offset for mmapping the EventFlag word. */ - mGrantors.resize(configureEventFlag? kMinGrantorCountForEvFlagSupport : kMinGrantorCount); + mGrantors.resize(configureEventFlag ? details::kMinGrantorCountForEvFlagSupport + : details::kMinGrantorCount); size_t memSize[] = { - sizeof(RingBufferPosition), /* memory to be allocated for read pointer counter */ - sizeof(RingBufferPosition), /* memory to be allocated for write pointer counter */ - bufferSize, /* memory to be allocated for data buffer */ - sizeof(std::atomic<uint32_t>)/* memory to be allocated for EventFlag word */ + sizeof(details::RingBufferPosition), /* memory to be allocated for read pointer counter + */ + sizeof(details::RingBufferPosition), /* memory to be allocated for write pointer counter + */ + bufferSize, /* memory to be allocated for data buffer */ + sizeof(std::atomic<uint32_t>) /* memory to be allocated for EventFlag word */ }; /* @@ -206,12 +133,9 @@ MQDescriptor<T, flavor>::MQDescriptor(size_t bufferSize, native_handle_t *nHandl for (size_t grantorPos = 0, offset = 0; grantorPos < mGrantors.size(); offset += memSize[grantorPos++]) { - mGrantors[grantorPos] = { - 0 /* grantor flags */, - 0 /* fdIndex */, - static_cast<uint32_t>(alignToWordBoundary(offset)), - memSize[grantorPos] - }; + mGrantors[grantorPos] = {0 /* grantor flags */, 0 /* fdIndex */, + static_cast<uint32_t>(details::alignToWordBoundary(offset)), + memSize[grantorPos]}; } } @@ -234,9 +158,8 @@ MQDescriptor<T, flavor>& MQDescriptor<T, flavor>::operator=(const MQDescriptor& mHandle->data[i] = dup(other.mHandle->data[i]); } - memcpy(&mHandle->data[other.mHandle->numFds], - &other.mHandle->data[other.mHandle->numFds], - other.mHandle->numInts * sizeof(int)); + memcpy(&mHandle->data[other.mHandle->numFds], &other.mHandle->data[other.mHandle->numFds], + static_cast<size_t>(other.mHandle->numInts) * sizeof(int)); } return *this; @@ -258,7 +181,7 @@ MQDescriptor<T, flavor>::~MQDescriptor() { template<typename T, MQFlavor flavor> size_t MQDescriptor<T, flavor>::getSize() const { - return mGrantors[DATAPTRPOS].extent; + return static_cast<size_t>(mGrantors[details::DATAPTRPOS].extent); } template<typename T, MQFlavor flavor> diff --git a/libhidlmemory/Android.bp b/libhidlmemory/Android.bp index 41da614..fc5770c 100644 --- a/libhidlmemory/Android.bp +++ b/libhidlmemory/Android.bp @@ -12,11 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_library { name: "libhidlmemory", vendor_available: true, + product_available: true, + // Host support is needed for testing only + host_supported: true, // TODO(b/153609531): remove when no longer needed. native_bridge_supported: true, + target: { + darwin: { + enabled: false, + }, + }, vndk: { enabled: true, support_system_process: true, diff --git a/minijail/Android.bp b/minijail/Android.bp index e025033..ad12dad 100644 --- a/minijail/Android.bp +++ b/minijail/Android.bp @@ -1,6 +1,15 @@ // TODO(b/110363419): remove or make failures harder // Deprecated: most minijail users should either use libavservices_minijail // or reinstitute this (w/ fatal checks). +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_library_shared { name: "libhwminijail", defaults: ["hidl_defaults"], @@ -13,5 +22,9 @@ cc_library_shared { "libbase", "libminijail", ], - visibility: [":__subpackages__"], + visibility: [ + ":__subpackages__", + "//hardware/interfaces/configstore/1.1/default", + "//vendor:__subpackages__", + ], } diff --git a/test_main.cpp b/test_main.cpp index e4cdd29..5c6c78e 100644 --- a/test_main.cpp +++ b/test_main.cpp @@ -17,7 +17,7 @@ #define LOG_TAG "LibHidlTest" #pragma clang diagnostic push -#pragma clang diagnostic fatal "-Wpadded" +#pragma clang diagnostic error "-Wpadded" #include <hidl/HidlInternal.h> #include <hidl/HidlSupport.h> #pragma clang diagnostic pop @@ -175,6 +175,20 @@ TEST_F(LibHidlTest, StringTest) { EXPECT_FALSE(hs2 <= hs1); } +// empty string optimization should apply for any constructor +TEST_F(LibHidlTest, HidlStringEmptyLiteralAllocation) { + using android::hardware::hidl_string; + + hidl_string empty1; + hidl_string empty2(""); + hidl_string empty3("foo", 0); + hidl_string empty4((std::string())); + + EXPECT_EQ(empty1.c_str(), empty2.c_str()); + EXPECT_EQ(empty1.c_str(), empty3.c_str()); + EXPECT_EQ(empty1.c_str(), empty4.c_str()); +} + TEST_F(LibHidlTest, MemoryTest) { using android::hardware::hidl_memory; @@ -222,6 +236,24 @@ TEST_F(LibHidlTest, VecInitTest) { EXPECT_ARRAYEQ(v3, array, v3.size()); } +TEST_F(LibHidlTest, VecReleaseTest) { + // this test indicates an inconsistency of behaviors which is undesirable. + // Perhaps hidl-vec should always allocate an empty vector whenever it + // exposes its data. Alternatively, perhaps it should always free/reject + // empty vectors and always return nullptr for this state. While this second + // alternative is faster, it makes client code harder to write, and it would + // break existing client code. + using android::hardware::hidl_vec; + + hidl_vec<int32_t> empty; + EXPECT_EQ(nullptr, empty.releaseData()); + + empty.resize(0); + int32_t* data = empty.releaseData(); + EXPECT_NE(nullptr, data); + delete data; +} + TEST_F(LibHidlTest, VecIterTest) { int32_t array[] = {5, 6, 7}; android::hardware::hidl_vec<int32_t> hv1 = std::vector<int32_t>(array, array + 3); diff --git a/transport/Android.bp b/transport/Android.bp index 86603ee..10f31a7 100644 --- a/transport/Android.bp +++ b/transport/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_package_root { name: "android.hidl", } diff --git a/transport/HidlLazyUtils.cpp b/transport/HidlLazyUtils.cpp index 08ed676..be7470f 100644 --- a/transport/HidlLazyUtils.cpp +++ b/transport/HidlLazyUtils.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "HidlLazyUtils" + #include <hidl/HidlLazyUtils.h> #include <hidl/HidlTransportSupport.h> @@ -29,15 +31,35 @@ namespace details { using ::android::hidl::base::V1_0::IBase; class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback { - public: - ClientCounterCallback() : mNumConnectedServices(0) {} + public: + ClientCounterCallback() {} bool addRegisteredService(const sp<IBase>& service, const std::string& name); - protected: + bool tryUnregister(); + + void reRegister(); + + void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback); + + protected: Return<void> onClients(const sp<IBase>& service, bool clients) override; - private: + private: + struct Service { + sp<IBase> service; + std::string name; + bool clients = false; + // Used to keep track of unregistered services to allow re-registry + bool registered = true; + }; + + /** + * Looks up service that is guaranteed to be registered (service from + * onClients). + */ + Service& assertRegisteredService(const sp<IBase>& service); + /** * Registers or re-registers services. Returns whether successful. */ @@ -50,28 +72,32 @@ class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCall void tryShutdown(); /** - * Counter of the number of services that currently have at least one client. + * Number of services that have been registered. */ - size_t mNumConnectedServices; + std::vector<Service> mRegisteredServices; - struct Service { - sp<IBase> service; - std::string name; - }; /** - * Number of services that have been registered. + * Callback for reporting the number of services with clients. */ - std::vector<Service> mRegisteredServices; + std::function<bool(bool)> mActiveServicesCallback; + + /** + * Previous value passed to the active services callback. + */ + std::optional<bool> mPreviousHasClients; }; class LazyServiceRegistrarImpl { - public: + public: LazyServiceRegistrarImpl() : mClientCallback(new ClientCounterCallback) {} status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name); + bool tryUnregister(); + void reRegister(); + void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback); - private: + private: sp<ClientCounterCallback> mClientCallback; }; @@ -86,6 +112,17 @@ bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service, return success; } +ClientCounterCallback::Service& ClientCounterCallback::assertRegisteredService( + const sp<IBase>& service) { + for (Service& registered : mRegisteredServices) { + if (registered.service != service) continue; + return registered; + } + LOG(FATAL) << "Got callback on service " << getDescriptor(service.get()) + << " which we did not register."; + __builtin_unreachable(); +} + bool ClientCounterCallback::registerService(const sp<IBase>& service, const std::string& name) { auto manager = hardware::defaultServiceManager1_2(); @@ -114,56 +151,94 @@ bool ClientCounterCallback::registerService(const sp<IBase>& service, const std: */ Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service, bool clients) { - if (clients) { - mNumConnectedServices++; - } else { - mNumConnectedServices--; + Service& registered = assertRegisteredService(service); + if (registered.clients == clients) { + LOG(FATAL) << "Process already thought " << getDescriptor(service.get()) << "/" + << registered.name << " had clients: " << registered.clients + << " but hwservicemanager has notified has clients: " << clients; + } + registered.clients = clients; + + size_t numWithClients = 0; + for (const Service& registered : mRegisteredServices) { + if (registered.clients) numWithClients++; } - LOG(INFO) << "Process has " << mNumConnectedServices << " (of " << mRegisteredServices.size() + LOG(INFO) << "Process has " << numWithClients << " (of " << mRegisteredServices.size() << " available) client(s) in use after notification " << getDescriptor(service.get()) - << " has clients: " << clients; + << "/" << registered.name << " has clients: " << clients; + + bool handledInCallback = false; + if (mActiveServicesCallback != nullptr) { + bool hasClients = numWithClients != 0; + if (hasClients != mPreviousHasClients) { + handledInCallback = mActiveServicesCallback(hasClients); + mPreviousHasClients = hasClients; + } + } - if (mNumConnectedServices == 0) { + // If there is no callback defined or the callback did not handle this + // client count change event, try to shutdown the process if its services + // have no clients. + if (!handledInCallback && numWithClients == 0) { tryShutdown(); } return Status::ok(); } -void ClientCounterCallback::tryShutdown() { - LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process."; - +bool ClientCounterCallback::tryUnregister() { auto manager = hardware::defaultServiceManager1_2(); - auto unRegisterIt = mRegisteredServices.begin(); - for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) { - auto& entry = (*unRegisterIt); - + for (Service& entry : mRegisteredServices) { const std::string descriptor = getDescriptor(entry.service.get()); bool success = manager->tryUnregister(descriptor, entry.name, entry.service); if (!success) { LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name; - break; + return false; } - } - if (unRegisterIt == mRegisteredServices.end()) { - LOG(INFO) << "Unregistered all clients and exiting"; - exit(EXIT_SUCCESS); + // Mark the entry unregistered, but do not remove it (may still be re-registered) + entry.registered = false; } - for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt; - reRegisterIt++) { - auto& entry = (*reRegisterIt); + return true; +} + +void ClientCounterCallback::reRegister() { + for (Service& entry : mRegisteredServices) { + // re-register entry if not already registered + if (entry.registered) { + continue; + } - // re-register entry if (!registerService(entry.service, entry.name)) { // Must restart. Otherwise, clients will never be able to get ahold of this service. LOG(FATAL) << "Bad state: could not re-register " << getDescriptor(entry.service.get()); } + + entry.registered = true; + } +} + +void ClientCounterCallback::tryShutdown() { + LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process."; + + if (tryUnregister()) { + LOG(INFO) << "Unregistered all clients and exiting"; + exit(EXIT_SUCCESS); } + + // At this point, we failed to unregister some of the services, leaving the + // server in an inconsistent state. Re-register all services that were + // unregistered by tryUnregister(). + reRegister(); +} + +void ClientCounterCallback::setActiveServicesCallback( + const std::function<bool(bool)>& activeServicesCallback) { + mActiveServicesCallback = activeServicesCallback; } status_t LazyServiceRegistrarImpl::registerService( @@ -175,6 +250,19 @@ status_t LazyServiceRegistrarImpl::registerService( return ::android::OK; } +bool LazyServiceRegistrarImpl::tryUnregister() { + return mClientCallback->tryUnregister(); +} + +void LazyServiceRegistrarImpl::reRegister() { + mClientCallback->reRegister(); +} + +void LazyServiceRegistrarImpl::setActiveServicesCallback( + const std::function<bool(bool)>& activeServicesCallback) { + mClientCallback->setActiveServicesCallback(activeServicesCallback); +} + } // namespace details LazyServiceRegistrar::LazyServiceRegistrar() { @@ -191,5 +279,18 @@ status_t LazyServiceRegistrar::registerService( return mImpl->registerService(service, name); } +bool LazyServiceRegistrar::tryUnregister() { + return mImpl->tryUnregister(); +} + +void LazyServiceRegistrar::reRegister() { + mImpl->reRegister(); +} + +void LazyServiceRegistrar::setActiveServicesCallback( + const std::function<bool(bool)>& activeServicesCallback) { + mImpl->setActiveServicesCallback(activeServicesCallback); +} + } // namespace hardware } // namespace android diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp index e645cd0..d0ac243 100644 --- a/transport/HidlTransportSupport.cpp +++ b/transport/HidlTransportSupport.cpp @@ -128,12 +128,7 @@ bool interfacesEqual(const sp<IBase>& left, const sp<IBase>& right) { namespace details { int32_t getPidIfSharable() { -#if LIBHIDL_TARGET_DEBUGGABLE return getpid(); -#else - using android::hidl::manager::V1_0::IServiceManager; - return static_cast<int32_t>(IServiceManager::PidConstant::NO_PID); -#endif } } // namespace details diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp index 8f59f38..c638279 100644 --- a/transport/ServiceManagement.cpp +++ b/transport/ServiceManagement.cpp @@ -87,7 +87,7 @@ static void waitForHwServiceManager() { static std::string binaryName() { std::ifstream ifs("/proc/self/cmdline"); std::string cmdline; - if (!ifs.is_open()) { + if (!ifs) { return ""; } ifs >> cmdline; @@ -106,7 +106,7 @@ static std::string packageWithoutVersion(const std::string& packageAndVersion) { return packageAndVersion.substr(0, at); } -static void tryShortenProcessName(const std::string& descriptor) { +__attribute__((noinline)) static void tryShortenProcessName(const std::string& descriptor) { const static std::string kTasks = "/proc/self/task/"; // make sure that this binary name is in the same package @@ -135,17 +135,17 @@ static void tryShortenProcessName(const std::string& descriptor) { if (dp->d_name[0] == '.') continue; std::fstream fs(kTasks + dp->d_name + "/comm"); - if (!fs.is_open()) { + if (!fs) { ALOGI("Could not rename process, failed read comm for %s.", dp->d_name); continue; } std::string oldComm; - fs >> oldComm; + if (!(fs >> oldComm)) continue; // don't rename if it already has an explicit name if (base::StartsWith(descriptor, oldComm)) { - fs.seekg(0, fs.beg); + if (!fs.seekg(0, fs.beg)) continue; fs << newName; } } @@ -153,45 +153,41 @@ static void tryShortenProcessName(const std::string& descriptor) { namespace details { -/* - * Returns the age of the current process by reading /proc/self/stat and comparing starttime to the - * current time. This is useful for measuring how long it took a HAL to register itself. - */ -static long getProcessAgeMs() { - constexpr const int PROCFS_STAT_STARTTIME_INDEX = 21; - std::string content; - android::base::ReadFileToString("/proc/self/stat", &content, false); - auto stats = android::base::Split(content, " "); - if (stats.size() <= PROCFS_STAT_STARTTIME_INDEX) { - LOG(INFO) << "Could not read starttime from /proc/self/stat"; - return -1; - } - const std::string& startTimeString = stats[PROCFS_STAT_STARTTIME_INDEX]; - static const int64_t ticksPerSecond = sysconf(_SC_CLK_TCK); - const int64_t uptime = android::uptimeMillis(); - - unsigned long long startTimeInClockTicks = 0; - if (android::base::ParseUint(startTimeString, &startTimeInClockTicks)) { - long startTimeMs = 1000ULL * startTimeInClockTicks / ticksPerSecond; - return uptime - startTimeMs; - } - return -1; +#ifdef ENFORCE_VINTF_MANIFEST +static constexpr bool kEnforceVintfManifest = true; +#else +static constexpr bool kEnforceVintfManifest = false; +#endif + +static bool* getTrebleTestingOverridePtr() { + static bool gTrebleTestingOverride = false; + return &gTrebleTestingOverride; } -static void onRegistrationImpl(const std::string& descriptor, const std::string& instanceName) { - long halStartDelay = getProcessAgeMs(); - if (halStartDelay >= 0) { - // The "start delay" printed here is an estimate of how long it took the HAL to go from - // process creation to registering itself as a HAL. Actual start time could be longer - // because the process might not have joined the threadpool yet, so it might not be ready to - // process transactions. - LOG(INFO) << "Registered " << descriptor << "/" << instanceName << " (start delay of " - << halStartDelay << "ms)"; +void setTrebleTestingOverride(bool testingOverride) { + *getTrebleTestingOverridePtr() = testingOverride; +} + +static bool isDebuggable() { + static bool debuggable = base::GetBoolProperty("ro.debuggable", false); + return debuggable; +} + +static inline bool isTrebleTestingOverride() { + if (kEnforceVintfManifest && !isDebuggable()) { + // don't allow testing override in production + return false; } + return *getTrebleTestingOverridePtr(); +} + +static void onRegistrationImpl(const std::string& descriptor, const std::string& instanceName) { + LOG(INFO) << "Registered " << descriptor << "/" << instanceName; tryShortenProcessName(descriptor); } +// only used by prebuilts - should be able to remove void onRegistration(const std::string& packageName, const std::string& interfaceName, const std::string& instanceName) { return onRegistrationImpl(packageName + "::" + interfaceName, instanceName); @@ -371,10 +367,7 @@ struct PassthroughServiceManager : IServiceManager1_1 { #endif }; -#ifdef LIBHIDL_TARGET_DEBUGGABLE - const char* env = std::getenv("TREBLE_TESTING_OVERRIDE"); - const bool trebleTestingOverride = env && !strcmp(env, "true"); - if (trebleTestingOverride) { + if (details::isTrebleTestingOverride()) { // Load HAL implementations that are statically linked handle = dlopen(nullptr, dlMode); if (handle == nullptr) { @@ -385,7 +378,6 @@ struct PassthroughServiceManager : IServiceManager1_1 { return; } } -#endif for (const std::string& path : paths) { std::vector<std::string> libs = findFiles(path, prefix, ".so"); @@ -424,18 +416,27 @@ struct PassthroughServiceManager : IServiceManager1_1 { *(void **)(&generator) = dlsym(handle, sym.c_str()); if(!generator) { const char* error = dlerror(); - LOG(ERROR) << "Passthrough lookup opened " << lib - << " but could not find symbol " << sym << ": " - << (error == nullptr ? "unknown error" : error); - dlclose(handle); - return true; + LOG(ERROR) << "Passthrough lookup opened " << lib << " but could not find symbol " + << sym << ": " << (error == nullptr ? "unknown error" : error) + << ". Keeping library open."; + + // dlclose too problematic in multi-threaded environment + // dlclose(handle); + + return true; // continue } ret = (*generator)(name.c_str()); if (ret == nullptr) { - dlclose(handle); - return true; // this module doesn't provide this instance name + LOG(ERROR) << "Could not find instance '" << name.c_str() << "' in library " << lib + << ". Keeping library open."; + + // dlclose too problematic in multi-threaded environment + // dlclose(handle); + + // this module doesn't provide this particular instance + return true; // continue } // Actual fqname might be a subclass. @@ -734,28 +735,6 @@ bool handleCastError(const Return<bool>& castReturn, const std::string& descript return false; } -#ifdef ENFORCE_VINTF_MANIFEST -static constexpr bool kEnforceVintfManifest = true; -#else -static constexpr bool kEnforceVintfManifest = false; -#endif - -#ifdef LIBHIDL_TARGET_DEBUGGABLE -static constexpr bool kDebuggable = true; -#else -static constexpr bool kDebuggable = false; -#endif - -static inline bool isTrebleTestingOverride() { - if (kEnforceVintfManifest && !kDebuggable) { - // don't allow testing override in production - return false; - } - - const char* env = std::getenv("TREBLE_TESTING_OVERRIDE"); - return env && !strcmp(env, "true"); -} - sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor, const std::string& instance, bool retry, bool getStub) { @@ -786,7 +765,7 @@ sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& const bool vintfHwbinder = (transport == Transport::HWBINDER); const bool vintfPassthru = (transport == Transport::PASSTHROUGH); const bool trebleTestingOverride = isTrebleTestingOverride(); - const bool allowLegacy = !kEnforceVintfManifest || (trebleTestingOverride && kDebuggable); + const bool allowLegacy = !kEnforceVintfManifest || (trebleTestingOverride && isDebuggable()); const bool vintfLegacy = (transport == Transport::EMPTY) && allowLegacy; if (!kEnforceVintfManifest) { @@ -868,7 +847,13 @@ status_t registerAsServiceInternal(const sp<IBase>& service, const std::string& if (kEnforceVintfManifest && !isTrebleTestingOverride()) { using Transport = IServiceManager1_0::Transport; - Transport transport = sm->getTransport(descriptor, name); + Return<Transport> transport = sm->getTransport(descriptor, name); + + if (!transport.isOk()) { + LOG(ERROR) << "Could not get transport for " << descriptor << "/" << name << ": " + << transport.description(); + return UNKNOWN_ERROR; + } if (transport != Transport::HWBINDER) { LOG(ERROR) << "Service " << descriptor << "/" << name diff --git a/transport/allocator/1.0/Android.bp b/transport/allocator/1.0/Android.bp index 6da3793..0cc3b62 100644 --- a/transport/allocator/1.0/Android.bp +++ b/transport/allocator/1.0/Android.bp @@ -1,13 +1,19 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.allocator@1.0", root: "android.hidl", // TODO(b/153609531): remove when no longer needed. native_bridge_supported: true, - vndk: { - enabled: true, - }, srcs: [ "IAllocator.hal", ], @@ -15,4 +21,8 @@ hidl_interface { "android.hidl.base@1.0", ], gen_java: false, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/allocator/1.0/default/Android.bp b/transport/allocator/1.0/default/Android.bp index 1116f1d..42abe9c 100644 --- a/transport/allocator/1.0/default/Android.bp +++ b/transport/allocator/1.0/default/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_binary { name: "android.hidl.allocator@1.0-service", relative_install_path: "hw", diff --git a/transport/allocator/1.0/utils/Android.bp b/transport/allocator/1.0/utils/Android.bp index b324ef1..f21047d 100644 --- a/transport/allocator/1.0/utils/Android.bp +++ b/transport/allocator/1.0/utils/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_library { name: "libhidlallocatorutils", vendor_available: true, diff --git a/transport/allocator/1.0/vts/functional/Android.bp b/transport/allocator/1.0/vts/functional/Android.bp index 31d9821..f53fc4f 100644 --- a/transport/allocator/1.0/vts/functional/Android.bp +++ b/transport/allocator/1.0/vts/functional/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_test { name: "VtsHidlAllocatorV1_0TargetTest", defaults: ["VtsHalTargetTestDefaults"], @@ -26,4 +35,3 @@ cc_test { ], test_suites: ["general-tests", "vts"], } - diff --git a/transport/base/1.0/Android.bp b/transport/base/1.0/Android.bp index 8c796b2..461f7e7 100644 --- a/transport/base/1.0/Android.bp +++ b/transport/base/1.0/Android.bp @@ -1,16 +1,26 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.base@1.0", root: "android.hidl", // TODO(b/153609531): remove when no longer needed. native_bridge_supported: true, - vndk: { - enabled: true, - }, srcs: [ "types.hal", "IBase.hal", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/base/1.0/vts/functional/Android.bp b/transport/base/1.0/vts/functional/Android.bp index 0c814ae..f25aaaa 100644 --- a/transport/base/1.0/vts/functional/Android.bp +++ b/transport/base/1.0/vts/functional/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_test { name: "vts_ibase_test", defaults: ["libinit_test_utils_libraries_defaults"], diff --git a/transport/base/1.0/vts/functional/Android.mk b/transport/base/1.0/vts/functional/Android.mk deleted file mode 100644 index 61c6e31..0000000 --- a/transport/base/1.0/vts/functional/Android.mk +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (C) 2017 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. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := VtsHalBaseV1_0TargetTest --include test/vts/tools/build/Android.host_config.mk diff --git a/transport/base/1.0/vts/functional/AndroidTest.xml b/transport/base/1.0/vts/functional/AndroidTest.xml deleted file mode 100644 index 80154f2..0000000 --- a/transport/base/1.0/vts/functional/AndroidTest.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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. ---> -<configuration description="Config for VTS VtsHalBaseV1_0TargetTest test cases"> - <option name="config-descriptor:metadata" key="plan" value="vts-treble" /> - <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher"> - <option name="abort-on-push-failure" value="false"/> - <option name="push-group" value="HalHidlTargetTest.push"/> - </target_preparer> - <multi_target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" /> - <test class="com.android.tradefed.testtype.VtsMultiDeviceTest"> - <option name="test-module-name" value="VtsHalBaseV1_0TargetTest"/> - <option name="binary-test-working-directory" value="_32bit::/data/nativetest/" /> - <option name="binary-test-working-directory" value="_64bit::/data/nativetest64/" /> - <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_ibase_test/vts_ibase_test" /> - <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_ibase_test/vts_ibase_test" /> - <option name="binary-test-type" value="gtest"/> - <option name="test-timeout" value="5m"/> - </test> -</configuration> diff --git a/transport/include/hidl/HidlLazyUtils.h b/transport/include/hidl/HidlLazyUtils.h index 6a62c97..427611b 100644 --- a/transport/include/hidl/HidlLazyUtils.h +++ b/transport/include/hidl/HidlLazyUtils.h @@ -16,6 +16,8 @@ #pragma once +#include <functional> + #include <android/hidl/base/1.0/IBase.h> #include <utils/RefBase.h> #include <utils/StrongPointer.h> @@ -26,12 +28,53 @@ namespace details { class LazyServiceRegistrarImpl; } // namespace details -/** Exits when all HALs registered through this object have 0 clients */ +/** + * Exits when all HALs registered through this object have 0 clients + * + * In order to use this class, it's expected that your service: + * - registers all services in the process with this API + * - configures services as oneshot + disabled in init .rc files + * - uses 'interface' declarations in init .rc files + * + * For more information on init .rc configuration, see system/core/init/README.md + **/ class LazyServiceRegistrar { public: static LazyServiceRegistrar& getInstance(); status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name = "default"); + /** + * Set a callback that is invoked when the active HAL count (i.e. HALs with clients) + * registered with this process drops to zero (or becomes nonzero). + * The callback takes a boolean argument, which is 'true' if there is + * at least one HAL with clients. + * + * Callback return value: + * - false: Default behavior for lazy HALs (shut down the process if there + * are no clients). + * - true: Don't shut down the process even if there are no clients. + * + * This callback gives a chance to: + * 1 - Perform some additional operations before exiting; + * 2 - Prevent the process from exiting by returning "true" from the + * callback. + * + * This method should be called before 'registerService' to avoid races. + */ + void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback); + + /** + * Try to unregister all services previously registered with 'registerService'. + * Returns 'true' if successful. + */ + bool tryUnregister(); + + /** + * Re-register services that were unregistered by 'tryUnregister'. + * This method should be called in the case 'tryUnregister' fails + * (and should be called on the same thread). + */ + void reRegister(); private: std::shared_ptr<details::LazyServiceRegistrarImpl> mImpl; diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h index 4573a25..886e816 100644 --- a/transport/include/hidl/ServiceManagement.h +++ b/transport/include/hidl/ServiceManagement.h @@ -47,10 +47,17 @@ namespace details { // e.x.: android.hardware.foo@1.0::IFoo, default void waitForHwService(const std::string &interface, const std::string &instanceName); +// Only works on userdebug/eng builds. This allows getService to bypass the +// VINTF manifest for testing only. +void setTrebleTestingOverride(bool testingOverride); + void preloadPassthroughService(const std::string &descriptor); // Returns a service with the following constraints: -// - retry => service is waited for and returned if available in this process +// - retry => service is waited for and returned if it is declared in the +// manifest AND it is available in this process (if errors indicate an +// sepolicy denial, then this will return - TODO(b/28321379) more precise +// errors to handle more cases) // - getStub => internal only. Forces to get the unwrapped (no BsFoo) if available. // TODO(b/65843592) // If the service is a remote service, this function returns BpBase. If the service is diff --git a/transport/manager/1.0/Android.bp b/transport/manager/1.0/Android.bp index c91dcd2..4a84b86 100644 --- a/transport/manager/1.0/Android.bp +++ b/transport/manager/1.0/Android.bp @@ -1,11 +1,17 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.manager@1.0", root: "android.hidl", - vndk: { - enabled: true, - }, srcs: [ "IServiceManager.hal", "IServiceNotification.hal", @@ -14,4 +20,8 @@ hidl_interface { "android.hidl.base@1.0", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/manager/1.1/Android.bp b/transport/manager/1.1/Android.bp index 82545e5..c9e22c9 100644 --- a/transport/manager/1.1/Android.bp +++ b/transport/manager/1.1/Android.bp @@ -1,11 +1,17 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.manager@1.1", root: "android.hidl", - vndk: { - enabled: true, - }, srcs: [ "IServiceManager.hal", ], @@ -14,4 +20,8 @@ hidl_interface { "android.hidl.manager@1.0", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/manager/1.2/Android.bp b/transport/manager/1.2/Android.bp index e7ee143..a58c12e 100644 --- a/transport/manager/1.2/Android.bp +++ b/transport/manager/1.2/Android.bp @@ -1,11 +1,17 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.manager@1.2", root: "android.hidl", - vndk: { - enabled: true, - }, srcs: [ "IClientCallback.hal", "IServiceManager.hal", @@ -16,4 +22,8 @@ hidl_interface { "android.hidl.manager@1.1", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/memory/1.0/Android.bp b/transport/memory/1.0/Android.bp index 9ce04ed..8e066a9 100644 --- a/transport/memory/1.0/Android.bp +++ b/transport/memory/1.0/Android.bp @@ -1,5 +1,14 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.memory@1.0", root: "android.hidl", @@ -17,4 +26,8 @@ hidl_interface { "android.hidl.base@1.0", ], gen_java: false, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/memory/1.0/default/Android.bp b/transport/memory/1.0/default/Android.bp index f56ee95..a44a0db 100644 --- a/transport/memory/1.0/default/Android.bp +++ b/transport/memory/1.0/default/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_library_shared { name: "android.hidl.memory@1.0-impl", vendor_available: true, diff --git a/transport/memory/block/1.0/Android.bp b/transport/memory/block/1.0/Android.bp index f26a6d3..bfaf139 100644 --- a/transport/memory/block/1.0/Android.bp +++ b/transport/memory/block/1.0/Android.bp @@ -1,11 +1,17 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.memory.block@1.0", root: "android.hidl", - vndk: { - enabled: true, - }, srcs: [ "types.hal", ], diff --git a/transport/memory/token/1.0/Android.bp b/transport/memory/token/1.0/Android.bp index 46c3387..c304284 100644 --- a/transport/memory/token/1.0/Android.bp +++ b/transport/memory/token/1.0/Android.bp @@ -1,5 +1,14 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.memory.token@1.0", root: "android.hidl", @@ -16,4 +25,8 @@ hidl_interface { "android.hidl.base@1.0", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/safe_union/1.0/Android.bp b/transport/safe_union/1.0/Android.bp index 2760863..cae92dd 100644 --- a/transport/safe_union/1.0/Android.bp +++ b/transport/safe_union/1.0/Android.bp @@ -1,5 +1,14 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.safe_union@1.0", root: "android.hidl", @@ -11,4 +20,8 @@ hidl_interface { "types.hal", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/token/1.0/Android.bp b/transport/token/1.0/Android.bp index 28f16f7..8bda482 100644 --- a/transport/token/1.0/Android.bp +++ b/transport/token/1.0/Android.bp @@ -1,5 +1,14 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + hidl_interface { name: "android.hidl.token@1.0", root: "android.hidl", @@ -13,4 +22,8 @@ hidl_interface { "android.hidl.base@1.0", ], gen_java: true, + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp index 5ccbe75..84f6f0f 100644 --- a/transport/token/1.0/utils/Android.bp +++ b/transport/token/1.0/utils/Android.bp @@ -12,10 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_libhidl_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_libhidl_license"], +} + cc_library { name: "android.hidl.token@1.0-utils", defaults: ["libhidl-defaults"], vendor_available: true, + // Host support is needed for testing only + host_supported: true, + target: { + darwin: { + enabled: false, + }, + }, vndk: { enabled: true, }, @@ -48,4 +64,8 @@ cc_library { "include", ], min_sdk_version: "29", + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], } diff --git a/vintfdata/Android.mk b/vintfdata/Android.mk index d873e29..4c5cca5 100644 --- a/vintfdata/Android.mk +++ b/vintfdata/Android.mk @@ -48,6 +48,9 @@ endif include $(CLEAR_VARS) LOCAL_MODULE := vendor_compatibility_matrix.xml +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE LOCAL_MODULE_STEM := compatibility_matrix.xml LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/vintf @@ -69,6 +72,9 @@ include $(BUILD_PREBUILT) # System Manifest include $(CLEAR_VARS) LOCAL_MODULE := system_manifest.xml +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE LOCAL_MODULE_STEM := manifest.xml LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf @@ -89,6 +95,9 @@ include $(BUILD_PREBUILT) ifneq ($(PRODUCT_MANIFEST_FILES),) include $(CLEAR_VARS) LOCAL_MODULE := product_manifest.xml +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE LOCAL_MODULE_STEM := manifest.xml LOCAL_MODULE_CLASS := ETC LOCAL_PRODUCT_MODULE := true @@ -107,6 +116,9 @@ endif # System_ext Manifest include $(CLEAR_VARS) LOCAL_MODULE := system_ext_manifest.xml +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE LOCAL_MODULE_STEM := manifest.xml LOCAL_MODULE_CLASS := ETC LOCAL_SYSTEM_EXT_MODULE := true @@ -128,3 +140,5 @@ SYSTEM_MANIFEST_INPUT_FILES := SYSTEM_EXT_MANIFEST_INPUT_FILES := DEVICE_MATRIX_INPUT_FILE := PRODUCT_MANIFEST_INPUT_FILES := + +VINTF_FRAMEWORK_MANIFEST_FROZEN_DIR := $(LOCAL_PATH)/frozen diff --git a/vintfdata/README.md b/vintfdata/README.md new file mode 100644 index 0000000..cfc1da7 --- /dev/null +++ b/vintfdata/README.md @@ -0,0 +1,91 @@ +# Updating the latest framework manifest + +## Adding new HALs / Major version update + +Add a new `<hal>` entry without a `max-level` attribute. The `<hal>` entry can +be added to the main manifest under `manifest.xml`, or to the manifest +fragment for the server module specified in `vintf_fragments`. + +Introducing new HALs are backwards compatible. + +## Minor version update + +When a framework HAL updates its minor version, simply update the `<version>` or +`<fqname>` field to the latest version. This is the same as any other HALs. + +For example, when `IServiceManager` updates to 1.2, change its `<fqname>` field +to `@1.2::IServiceManager/default`. + +Because minor version updates are backwards compatible, all devices that require +a lower minor version of the HAL are still compatible. + +Leave `max-level` attribute empty. + +## Deprecating HAL + +When a framework HAL is deprecated, set `max-level` field of the HAL from empty +to the last frozen version. +For example, if IDisplayService is deprecated in Android S, set `max-level` to +Android R (5): + +```xml +<manifest version="3.0" type="framework"> + <hal format="hidl" max-level="5"> <!-- Level::R --> + <name>android.frameworks.displayservice</name> + <transport>hwbinder</transport> + <fqname>@1.0::IDisplayService/default</fqname> + </hal> +</manifest> +``` + +Note that the `max-level` of the HAL is set to Android R, meaning that the HAL +is last available in Android R and disabled in Android S. + +Deprecating a HAL doesn’t mean dropping support of the HAL, so no devices will +break. + +When setting `max-level` of a HAL: +- If `optional="false"` in frozen DCMs, the build system checks that adding the + attribute does not break backwards compatibility; that is, + `max-level > last_frozen_level`. +- If `optional="true"`, the check is disabled. Care must be taken to ensure + `max-level` is set appropriately. + +## Removing HAL + +When the framework drops support of a certain HAL, the corresponding HAL entry +is removed from the framework manifest, and code that serves and registers the +HAL must be removed simultaneously. + +Devices that are lower than the `max-level` attribute of the HAL may start to +break if they require this HAL. Hence, this must only be done when there is +enough evidence that the devices are not updateable to the latest Android +release. + +# Freezing framework HAL manifest + +First, check `libvintf` or `hardware/interfaces/compatibility_matrices` to +determine the current level. + +Execute the following, replacing the argument with the level to freeze: + +```shell script +lunch cf_x86_phone-userdebug # or any generic target +LEVEL=5 +./freeze.sh ${LEVEL} +``` + +A new file, `frozen/${LEVEL}.xml`, will be created after the command is +executed. Frozen system manifests are stored in compatibility matrices. Then, +manually inspect the frozen compatibility matrix. Modify the `optional` +field for certain HALs. See comments in the compatibility matrix of the previous +level for details. + +These compatibility matrices served as a reference for devices at that +target FCM version. Devices at the given target FCM version should +reference DCMs in the `frozen/` dir, with some of the HALs marked +as `optional="true"` or even omitted if unused by device-specific code. + +At build time, compatibiltiy is checked between framework manifest and +the respective frozen DCM. HALs in the framework manifest with `max-level` +less than the specified level are omitted. diff --git a/vintfdata/freeze.sh b/vintfdata/freeze.sh new file mode 100755 index 0000000..a624ee3 --- /dev/null +++ b/vintfdata/freeze.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +mydir="$(dirname $0)" + +function freeze() { + [[ $# == 1 ]] || { + echo "usage: freeze.sh <level>" + echo "e.g. To freeze framework manifest for Android R, run:" + echo " freeze.sh 5" + return 1 + } + local level="$1" + [[ "${ANDROID_BUILD_TOP}" ]] || { + echo "ANDROID_BUILD_TOP is not set; did you run envsetup.sh?" + return 1 + } + [[ "${ANDROID_HOST_OUT}" ]] || { + echo "ANDROID_HOST_OUT is not set; did you run envsetup.sh?" + return 1 + } + + local modules_to_build=check-vintf-all + echo "Building ${modules_to_build}" + "${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash" --build-mode --all-modules --dir="$(pwd)" ${modules_to_build} || { + echo "${modules_to_build} failed. Backwards compatibility might be broken." + echo "Check framework manifest changes. If this is intentional, run " + echo " \`vintffm --update\` with appropriate options to update frozen files." + return 1 + } + + echo "Updating level ${level}" + "${ANDROID_HOST_OUT}/bin/vintffm" --update --level "${level}" --dirmap "/system:${ANDROID_PRODUCT_OUT}/system" "${mydir}/frozen" || return 1 + + local files_to_diff="$(printf "${mydir}/frozen/%s\n" $(ls -1 -t -r ${mydir}/frozen | xargs -I{} basename {} | grep -B1 "${level}.xml"))" + + echo + echo "Summary of changes:" + echo diff ${files_to_diff} + diff ${files_to_diff} || true +} + +freeze $@ diff --git a/vintfdata/frozen/5.xml b/vintfdata/frozen/5.xml new file mode 100644 index 0000000..525829d --- /dev/null +++ b/vintfdata/frozen/5.xml @@ -0,0 +1,110 @@ +<compatibility-matrix version="3.0" type="device"> + <!-- + cameraserver is installed for all phones and tablets, but not + auto or TV. + --> + <hal format="hidl" optional="true"> + <name>android.frameworks.cameraservice.service</name> + <version>2.1</version> + <interface> + <name>ICameraService</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.frameworks.displayservice</name> + <version>1.0</version> + <interface> + <name>IDisplayService</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.frameworks.schedulerservice</name> + <version>1.0</version> + <interface> + <name>ISchedulingPolicyService</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.frameworks.sensorservice</name> + <version>1.0</version> + <interface> + <name>ISensorManager</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.frameworks.stats</name> + <version>1.0</version> + <interface> + <name>IStats</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.hardware.media.c2</name> + <version>1.1</version> + <interface> + <name>IComponentStore</name> + <instance>software</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.hidl.allocator</name> + <version>1.0</version> + <interface> + <name>IAllocator</name> + <instance>ashmem</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.hidl.manager</name> + <version>1.2</version> + <interface> + <name>IServiceManager</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.hidl.memory</name> + <version>1.0</version> + <interface> + <name>IMapper</name> + <instance>ashmem</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.hidl.token</name> + <version>1.0</version> + <interface> + <name>ITokenManager</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.system.net.netd</name> + <version>1.1</version> + <interface> + <name>INetd</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.system.suspend</name> + <version>1.0</version> + <interface> + <name>ISystemSuspend</name> + <instance>default</instance> + </interface> + </hal> + <hal format="hidl" optional="false"> + <name>android.system.wifi.keystore</name> + <version>1.0</version> + <interface> + <name>IKeystore</name> + <instance>default</instance> + </interface> + </hal> +</compatibility-matrix> diff --git a/vintfdata/manifest.xml b/vintfdata/manifest.xml index e204671..8fd69b9 100644 --- a/vintfdata/manifest.xml +++ b/vintfdata/manifest.xml @@ -35,7 +35,12 @@ <instance>default</instance> </interface> </hal> - <hal> + <!-- + Instead of calling this, prefer to set priority in init .rc files via + `ioprio <class> <priority>`. For more information, see + system/core/init/README.md + --> + <hal max-level="5"> <name>android.frameworks.schedulerservice</name> <transport>hwbinder</transport> <version>1.0</version> |