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 <suchang.woo@samsung.com>
This commit is contained in:
Suchang Woo 2021-12-20 13:23:28 +09:00
parent 155bba8b0c
commit 7d8c25b0c9

View file

@ -33,6 +33,7 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@ -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();