Loading init/Android.bp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -89,6 +89,7 @@ cc_library_static { whole_static_libs: ["libcap"], whole_static_libs: ["libcap"], static_libs: [ static_libs: [ "libbase", "libbase", "libhidl-gen-utils", "libselinux", "libselinux", "liblog", "liblog", "libprocessgroup", "libprocessgroup", Loading Loading @@ -136,6 +137,7 @@ cc_binary { "libfs_mgr", "libfs_mgr", "libfec", "libfec", "libfec_rs", "libfec_rs", "libhidl-gen-utils", "libsquashfs_utils", "libsquashfs_utils", "liblogwrap", "liblogwrap", "libext4_utils", "libext4_utils", Loading Loading @@ -185,6 +187,7 @@ cc_test { ], ], static_libs: [ static_libs: [ "libinit", "libinit", "libhidl-gen-utils", "libselinux", "libselinux", "libcrypto", "libcrypto", "libprotobuf-cpp-lite", "libprotobuf-cpp-lite", Loading init/Android.mk +1 −0 Original line number Original line Diff line number Diff line Loading @@ -64,6 +64,7 @@ LOCAL_STATIC_LIBRARIES := \ libfs_mgr \ libfs_mgr \ libfec \ libfec \ libfec_rs \ libfec_rs \ libhidl-gen-utils \ libsquashfs_utils \ libsquashfs_utils \ liblogwrap \ liblogwrap \ libext4_utils \ libext4_utils \ Loading init/init.cpp +78 −12 Original line number Original line Diff line number Diff line Loading @@ -202,24 +202,90 @@ static std::optional<boot_clock::time_point> RestartProcesses() { return next_process_restart_time; 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) { void handle_control_message(const std::string& msg, const std::string& 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; } const ControlMessageFunction& function = it->second; if (function.target == ControlTarget::SERVICE) { Service* svc = ServiceList::GetInstance().FindService(name); Service* svc = ServiceList::GetInstance().FindService(name); if (svc == nullptr) { if (svc == nullptr) { LOG(ERROR) << "no such service '" << name << "'"; LOG(ERROR) << "No such service '" << name << "' for ctl." << msg; return; return; } } if (auto result = function.action(svc); !result) { LOG(ERROR) << "Could not ctl." << msg << " for service " << name << ": " << result.error(); } if (msg == "start") { return; if (auto result = svc->Start(); !result) { LOG(ERROR) << "Could not ctl.start service '" << name << "': " << result.error(); } } } else if (msg == "stop") { svc->Stop(); if (function.target == ControlTarget::INTERFACE) { } else if (msg == "restart") { for (const auto& svc : ServiceList::GetInstance()) { svc->Restart(); if (svc->interfaces().count(name) == 0) { } else { continue; LOG(ERROR) << "unknown control msg '" << msg << "'"; } } 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) { static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) { Loading init/service.cpp +33 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include <android-base/scopeguard.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <hidl-util/FQName.h> #include <processgroup/processgroup.h> #include <processgroup/processgroup.h> #include <selinux/selinux.h> #include <selinux/selinux.h> #include <system/thread_defs.h> #include <system/thread_defs.h> Loading Loading @@ -418,6 +419,37 @@ Result<Success> Service::ParsePriority(const std::vector<std::string>& args) { return Success(); 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) { Result<Success> Service::ParseIoprio(const std::vector<std::string>& args) { if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) { if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) { return Error() << "priority value must be range 0 - 7"; return Error() << "priority value must be range 0 - 7"; Loading Loading @@ -619,6 +651,7 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { {"critical", {0, 0, &Service::ParseCritical}}, {"critical", {0, 0, &Service::ParseCritical}}, {"disabled", {0, 0, &Service::ParseDisabled}}, {"disabled", {0, 0, &Service::ParseDisabled}}, {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}}, {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}}, {"interface", {2, 2, &Service::ParseInterface}}, {"ioprio", {2, 2, &Service::ParseIoprio}}, {"ioprio", {2, 2, &Service::ParseIoprio}}, {"priority", {1, 1, &Service::ParsePriority}}, {"priority", {1, 1, &Service::ParsePriority}}, {"keycodes", {1, kMax, &Service::ParseKeycodes}}, {"keycodes", {1, kMax, &Service::ParseKeycodes}}, Loading init/service.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -108,6 +108,7 @@ class Service { void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; } void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; } IoSchedClass ioprio_class() const { return ioprio_class_; } IoSchedClass ioprio_class() const { return ioprio_class_; } int ioprio_pri() const { return ioprio_pri_; } int ioprio_pri() const { return ioprio_pri_; } const std::set<std::string>& interfaces() const { return interfaces_; } int priority() const { return priority_; } int priority() const { return priority_; } int oom_score_adjust() const { return oom_score_adjust_; } int oom_score_adjust() const { return oom_score_adjust_; } bool process_cgroup_empty() const { return process_cgroup_empty_; } bool process_cgroup_empty() const { return process_cgroup_empty_; } Loading @@ -132,6 +133,7 @@ class Service { Result<Success> ParseDisabled(const std::vector<std::string>& args); Result<Success> ParseDisabled(const std::vector<std::string>& args); Result<Success> ParseGroup(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> 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> ParseIoprio(const std::vector<std::string>& args); Result<Success> ParseKeycodes(const std::vector<std::string>& args); Result<Success> ParseKeycodes(const std::vector<std::string>& args); Result<Success> ParseOneshot(const std::vector<std::string>& args); Result<Success> ParseOneshot(const std::vector<std::string>& args); Loading Loading @@ -181,6 +183,8 @@ class Service { std::vector<std::string> writepid_files_; 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 // keycodes for triggering this service via /dev/keychord std::vector<int> keycodes_; std::vector<int> keycodes_; int keychord_id_; int keychord_id_; Loading Loading
init/Android.bp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -89,6 +89,7 @@ cc_library_static { whole_static_libs: ["libcap"], whole_static_libs: ["libcap"], static_libs: [ static_libs: [ "libbase", "libbase", "libhidl-gen-utils", "libselinux", "libselinux", "liblog", "liblog", "libprocessgroup", "libprocessgroup", Loading Loading @@ -136,6 +137,7 @@ cc_binary { "libfs_mgr", "libfs_mgr", "libfec", "libfec", "libfec_rs", "libfec_rs", "libhidl-gen-utils", "libsquashfs_utils", "libsquashfs_utils", "liblogwrap", "liblogwrap", "libext4_utils", "libext4_utils", Loading Loading @@ -185,6 +187,7 @@ cc_test { ], ], static_libs: [ static_libs: [ "libinit", "libinit", "libhidl-gen-utils", "libselinux", "libselinux", "libcrypto", "libcrypto", "libprotobuf-cpp-lite", "libprotobuf-cpp-lite", Loading
init/Android.mk +1 −0 Original line number Original line Diff line number Diff line Loading @@ -64,6 +64,7 @@ LOCAL_STATIC_LIBRARIES := \ libfs_mgr \ libfs_mgr \ libfec \ libfec \ libfec_rs \ libfec_rs \ libhidl-gen-utils \ libsquashfs_utils \ libsquashfs_utils \ liblogwrap \ liblogwrap \ libext4_utils \ libext4_utils \ Loading
init/init.cpp +78 −12 Original line number Original line Diff line number Diff line Loading @@ -202,24 +202,90 @@ static std::optional<boot_clock::time_point> RestartProcesses() { return next_process_restart_time; 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) { void handle_control_message(const std::string& msg, const std::string& 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; } const ControlMessageFunction& function = it->second; if (function.target == ControlTarget::SERVICE) { Service* svc = ServiceList::GetInstance().FindService(name); Service* svc = ServiceList::GetInstance().FindService(name); if (svc == nullptr) { if (svc == nullptr) { LOG(ERROR) << "no such service '" << name << "'"; LOG(ERROR) << "No such service '" << name << "' for ctl." << msg; return; return; } } if (auto result = function.action(svc); !result) { LOG(ERROR) << "Could not ctl." << msg << " for service " << name << ": " << result.error(); } if (msg == "start") { return; if (auto result = svc->Start(); !result) { LOG(ERROR) << "Could not ctl.start service '" << name << "': " << result.error(); } } } else if (msg == "stop") { svc->Stop(); if (function.target == ControlTarget::INTERFACE) { } else if (msg == "restart") { for (const auto& svc : ServiceList::GetInstance()) { svc->Restart(); if (svc->interfaces().count(name) == 0) { } else { continue; LOG(ERROR) << "unknown control msg '" << msg << "'"; } } 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) { static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) { Loading
init/service.cpp +33 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include <android-base/scopeguard.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <hidl-util/FQName.h> #include <processgroup/processgroup.h> #include <processgroup/processgroup.h> #include <selinux/selinux.h> #include <selinux/selinux.h> #include <system/thread_defs.h> #include <system/thread_defs.h> Loading Loading @@ -418,6 +419,37 @@ Result<Success> Service::ParsePriority(const std::vector<std::string>& args) { return Success(); 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) { Result<Success> Service::ParseIoprio(const std::vector<std::string>& args) { if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) { if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) { return Error() << "priority value must be range 0 - 7"; return Error() << "priority value must be range 0 - 7"; Loading Loading @@ -619,6 +651,7 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { {"critical", {0, 0, &Service::ParseCritical}}, {"critical", {0, 0, &Service::ParseCritical}}, {"disabled", {0, 0, &Service::ParseDisabled}}, {"disabled", {0, 0, &Service::ParseDisabled}}, {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}}, {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}}, {"interface", {2, 2, &Service::ParseInterface}}, {"ioprio", {2, 2, &Service::ParseIoprio}}, {"ioprio", {2, 2, &Service::ParseIoprio}}, {"priority", {1, 1, &Service::ParsePriority}}, {"priority", {1, 1, &Service::ParsePriority}}, {"keycodes", {1, kMax, &Service::ParseKeycodes}}, {"keycodes", {1, kMax, &Service::ParseKeycodes}}, Loading
init/service.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -108,6 +108,7 @@ class Service { void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; } void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; } IoSchedClass ioprio_class() const { return ioprio_class_; } IoSchedClass ioprio_class() const { return ioprio_class_; } int ioprio_pri() const { return ioprio_pri_; } int ioprio_pri() const { return ioprio_pri_; } const std::set<std::string>& interfaces() const { return interfaces_; } int priority() const { return priority_; } int priority() const { return priority_; } int oom_score_adjust() const { return oom_score_adjust_; } int oom_score_adjust() const { return oom_score_adjust_; } bool process_cgroup_empty() const { return process_cgroup_empty_; } bool process_cgroup_empty() const { return process_cgroup_empty_; } Loading @@ -132,6 +133,7 @@ class Service { Result<Success> ParseDisabled(const std::vector<std::string>& args); Result<Success> ParseDisabled(const std::vector<std::string>& args); Result<Success> ParseGroup(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> 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> ParseIoprio(const std::vector<std::string>& args); Result<Success> ParseKeycodes(const std::vector<std::string>& args); Result<Success> ParseKeycodes(const std::vector<std::string>& args); Result<Success> ParseOneshot(const std::vector<std::string>& args); Result<Success> ParseOneshot(const std::vector<std::string>& args); Loading Loading @@ -181,6 +183,8 @@ class Service { std::vector<std::string> writepid_files_; 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 // keycodes for triggering this service via /dev/keychord std::vector<int> keycodes_; std::vector<int> keycodes_; int keychord_id_; int keychord_id_; Loading