From 7d8c25b0c99bc5628ea9464f89e7771a82077283 Mon Sep 17 00:00:00 2001 From: Suchang Woo Date: Mon, 20 Dec 2021 13:23:28 +0900 Subject: [PATCH] ueventd: Wait for runtime apex before running external firmware handler External firmware handlers cannot run until com.android.runtime.apex is activated. However, it may be possible to request firmware from the kernel before apex activation. Waiting for runtime apex is required before running an external firmware handler. Test: atest CtsInitTestCases Change-Id: Id63b7f29084d3cecb901049162d3e5cd0055566f Signed-off-by: Suchang Woo --- init/firmware_handler.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp index 30e808d9f..b682cd0ae 100644 --- a/init/firmware_handler.cpp +++ b/init/firmware_handler.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ using android::base::Split; using android::base::Timer; using android::base::Trim; using android::base::unique_fd; +using android::base::WaitForProperty; using android::base::WriteFully; namespace android { @@ -82,6 +84,33 @@ static bool IsBooting() { return access("/dev/.booting", F_OK) == 0; } +static bool IsApexActivated() { + static bool apex_activated = []() { + // Wait for com.android.runtime.apex activation + // Property name and value must be kept in sync with system/apexd/apex/apex_constants.h + // 60s is the default firmware sysfs fallback timeout. (/sys/class/firmware/timeout) + if (!WaitForProperty("apexd.status", "activated", 60s)) { + LOG(ERROR) << "Apexd activation wait timeout"; + return false; + } + return true; + }(); + + return apex_activated; +} + +static bool NeedsRerunExternalHandler() { + static bool first = true; + + // Rerun external handler only on the first try and when apex is activated + if (first) { + first = false; + return IsApexActivated(); + } + + return first; +} + ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, gid_t gid, std::string handler_path) : devpath(std::move(devpath)), uid(uid), gid(gid), handler_path(std::move(handler_path)) { @@ -210,6 +239,11 @@ std::string FirmwareHandler::GetFirmwarePath(const Uevent& uevent) const { auto result = RunExternalHandler(external_handler.handler_path, external_handler.uid, external_handler.gid, uevent); + if (!result.ok() && NeedsRerunExternalHandler()) { + auto res = RunExternalHandler(external_handler.handler_path, external_handler.uid, + external_handler.gid, uevent); + result = std::move(res); + } if (!result.ok()) { LOG(ERROR) << "Using default firmware; External firmware handler failed: " << result.error();