Merge "init language extension for lazy HIDL services."
This commit is contained in:
commit
0f40200577
|
@ -89,6 +89,7 @@ cc_library_static {
|
|||
whole_static_libs: ["libcap"],
|
||||
static_libs: [
|
||||
"libbase",
|
||||
"libhidl-gen-utils",
|
||||
"libselinux",
|
||||
"liblog",
|
||||
"libprocessgroup",
|
||||
|
@ -136,6 +137,7 @@ cc_binary {
|
|||
"libfs_mgr",
|
||||
"libfec",
|
||||
"libfec_rs",
|
||||
"libhidl-gen-utils",
|
||||
"libsquashfs_utils",
|
||||
"liblogwrap",
|
||||
"libext4_utils",
|
||||
|
@ -185,6 +187,7 @@ cc_test {
|
|||
],
|
||||
static_libs: [
|
||||
"libinit",
|
||||
"libhidl-gen-utils",
|
||||
"libselinux",
|
||||
"libcrypto",
|
||||
"libprotobuf-cpp-lite",
|
||||
|
|
|
@ -64,6 +64,7 @@ LOCAL_STATIC_LIBRARIES := \
|
|||
libfs_mgr \
|
||||
libfec \
|
||||
libfec_rs \
|
||||
libhidl-gen-utils \
|
||||
libsquashfs_utils \
|
||||
liblogwrap \
|
||||
libext4_utils \
|
||||
|
|
|
@ -202,24 +202,90 @@ static std::optional<boot_clock::time_point> RestartProcesses() {
|
|||
return next_process_restart_time;
|
||||
}
|
||||
|
||||
static Result<Success> DoControlStart(Service* service) {
|
||||
return service->Start();
|
||||
}
|
||||
|
||||
static Result<Success> DoControlStop(Service* service) {
|
||||
service->Stop();
|
||||
return Success();
|
||||
}
|
||||
|
||||
static Result<Success> DoControlRestart(Service* service) {
|
||||
service->Restart();
|
||||
return Success();
|
||||
}
|
||||
|
||||
enum class ControlTarget {
|
||||
SERVICE, // function gets called for the named service
|
||||
INTERFACE, // action gets called for every service that holds this interface
|
||||
};
|
||||
|
||||
struct ControlMessageFunction {
|
||||
ControlTarget target;
|
||||
std::function<Result<Success>(Service*)> action;
|
||||
};
|
||||
|
||||
static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
|
||||
// clang-format off
|
||||
static const std::map<std::string, ControlMessageFunction> control_message_functions = {
|
||||
{"start", {ControlTarget::SERVICE, DoControlStart}},
|
||||
{"stop", {ControlTarget::SERVICE, DoControlStop}},
|
||||
{"restart", {ControlTarget::SERVICE, DoControlRestart}},
|
||||
{"interface_start", {ControlTarget::INTERFACE, DoControlStart}},
|
||||
{"interface_stop", {ControlTarget::INTERFACE, DoControlStop}},
|
||||
{"interface_restart", {ControlTarget::INTERFACE, DoControlRestart}},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
return control_message_functions;
|
||||
}
|
||||
|
||||
void handle_control_message(const std::string& msg, const std::string& name) {
|
||||
Service* svc = ServiceList::GetInstance().FindService(name);
|
||||
if (svc == nullptr) {
|
||||
LOG(ERROR) << "no such service '" << name << "'";
|
||||
const auto& map = get_control_message_map();
|
||||
const auto it = map.find(msg);
|
||||
|
||||
if (it == map.end()) {
|
||||
LOG(ERROR) << "Unknown control msg '" << msg << "'";
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg == "start") {
|
||||
if (auto result = svc->Start(); !result) {
|
||||
LOG(ERROR) << "Could not ctl.start service '" << name << "': " << result.error();
|
||||
const ControlMessageFunction& function = it->second;
|
||||
|
||||
if (function.target == ControlTarget::SERVICE) {
|
||||
Service* svc = ServiceList::GetInstance().FindService(name);
|
||||
if (svc == nullptr) {
|
||||
LOG(ERROR) << "No such service '" << name << "' for ctl." << msg;
|
||||
return;
|
||||
}
|
||||
} else if (msg == "stop") {
|
||||
svc->Stop();
|
||||
} else if (msg == "restart") {
|
||||
svc->Restart();
|
||||
} else {
|
||||
LOG(ERROR) << "unknown control msg '" << msg << "'";
|
||||
if (auto result = function.action(svc); !result) {
|
||||
LOG(ERROR) << "Could not ctl." << msg << " for service " << name << ": "
|
||||
<< result.error();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (function.target == ControlTarget::INTERFACE) {
|
||||
for (const auto& svc : ServiceList::GetInstance()) {
|
||||
if (svc->interfaces().count(name) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto result = function.action(svc.get()); !result) {
|
||||
LOG(ERROR) << "Could not handle ctl." << msg << " for service " << svc->name()
|
||||
<< " with interface " << name << ": " << result.error();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Could not find service hosting interface " << name;
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Invalid function target from static map key '" << msg
|
||||
<< "': " << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
|
||||
}
|
||||
|
||||
static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <android-base/scopeguard.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <hidl-util/FQName.h>
|
||||
#include <processgroup/processgroup.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <system/thread_defs.h>
|
||||
|
@ -418,6 +419,37 @@ Result<Success> Service::ParsePriority(const std::vector<std::string>& args) {
|
|||
return Success();
|
||||
}
|
||||
|
||||
Result<Success> Service::ParseInterface(const std::vector<std::string>& args) {
|
||||
const std::string& interface_name = args[1];
|
||||
const std::string& instance_name = args[2];
|
||||
|
||||
const FQName fq_name = FQName(interface_name);
|
||||
if (!fq_name.isValid()) {
|
||||
return Error() << "Invalid fully-qualified name for interface '" << interface_name << "'";
|
||||
}
|
||||
|
||||
if (!fq_name.isFullyQualified()) {
|
||||
return Error() << "Interface name not fully-qualified '" << interface_name << "'";
|
||||
}
|
||||
|
||||
if (fq_name.isValidValueName()) {
|
||||
return Error() << "Interface name must not be a value name '" << interface_name << "'";
|
||||
}
|
||||
|
||||
const std::string fullname = interface_name + "/" + instance_name;
|
||||
|
||||
for (const auto& svc : ServiceList::GetInstance()) {
|
||||
if (svc->interfaces().count(fullname) > 0) {
|
||||
return Error() << "Interface '" << fullname << "' redefined in " << name()
|
||||
<< " but is already defined by " << svc->name();
|
||||
}
|
||||
}
|
||||
|
||||
interfaces_.insert(fullname);
|
||||
|
||||
return Success();
|
||||
}
|
||||
|
||||
Result<Success> Service::ParseIoprio(const std::vector<std::string>& args) {
|
||||
if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) {
|
||||
return Error() << "priority value must be range 0 - 7";
|
||||
|
@ -619,6 +651,7 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
|
|||
{"critical", {0, 0, &Service::ParseCritical}},
|
||||
{"disabled", {0, 0, &Service::ParseDisabled}},
|
||||
{"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},
|
||||
{"interface", {2, 2, &Service::ParseInterface}},
|
||||
{"ioprio", {2, 2, &Service::ParseIoprio}},
|
||||
{"priority", {1, 1, &Service::ParsePriority}},
|
||||
{"keycodes", {1, kMax, &Service::ParseKeycodes}},
|
||||
|
|
|
@ -108,6 +108,7 @@ class Service {
|
|||
void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; }
|
||||
IoSchedClass ioprio_class() const { return ioprio_class_; }
|
||||
int ioprio_pri() const { return ioprio_pri_; }
|
||||
const std::set<std::string>& interfaces() const { return interfaces_; }
|
||||
int priority() const { return priority_; }
|
||||
int oom_score_adjust() const { return oom_score_adjust_; }
|
||||
bool process_cgroup_empty() const { return process_cgroup_empty_; }
|
||||
|
@ -132,6 +133,7 @@ class Service {
|
|||
Result<Success> ParseDisabled(const std::vector<std::string>& args);
|
||||
Result<Success> ParseGroup(const std::vector<std::string>& args);
|
||||
Result<Success> ParsePriority(const std::vector<std::string>& args);
|
||||
Result<Success> ParseInterface(const std::vector<std::string>& args);
|
||||
Result<Success> ParseIoprio(const std::vector<std::string>& args);
|
||||
Result<Success> ParseKeycodes(const std::vector<std::string>& args);
|
||||
Result<Success> ParseOneshot(const std::vector<std::string>& args);
|
||||
|
@ -181,6 +183,8 @@ class Service {
|
|||
|
||||
std::vector<std::string> writepid_files_;
|
||||
|
||||
std::set<std::string> interfaces_; // e.g. some.package.foo@1.0::IBaz/instance-name
|
||||
|
||||
// keycodes for triggering this service via /dev/keychord
|
||||
std::vector<int> keycodes_;
|
||||
int keychord_id_;
|
||||
|
|
Loading…
Reference in New Issue