Loading init/init.cpp +32 −1 Original line number Diff line number Diff line Loading @@ -442,6 +442,19 @@ static Result<void> DoControlRestart(Service* service) { return {}; } static void DoUnloadApex(const std::string& apex_name) { std::string prop_name = "init.apex." + apex_name; // TODO(b/232114573) remove services and actions read from the apex // TODO(b/232799709) kill services from the apex SetProperty(prop_name, "unloaded"); } static void DoLoadApex(const std::string& apex_name) { std::string prop_name = "init.apex." + apex_name; // TODO(b/232799709) read .rc files from the apex SetProperty(prop_name, "loaded"); } enum class ControlTarget { SERVICE, // function gets called for the named service INTERFACE, // action gets called for every service that holds this interface Loading @@ -465,6 +478,20 @@ static const std::map<std::string, ControlMessageFunction, std::less<>>& GetCont return control_message_functions; } static bool HandleApexControlMessage(std::string_view action, const std::string& name, std::string_view message) { if (action == "load") { DoLoadApex(name); return true; } else if (action == "unload") { DoUnloadApex(name); return true; } else { LOG(ERROR) << "Unknown control msg '" << message << "'"; return false; } } static bool HandleControlMessage(std::string_view message, const std::string& name, pid_t from_pid) { std::string cmdline_path = StringPrintf("proc/%d/cmdline", from_pid); Loading @@ -476,8 +503,12 @@ static bool HandleControlMessage(std::string_view message, const std::string& na process_cmdline = "unknown process"; } Service* service = nullptr; auto action = message; if (ConsumePrefix(&action, "apex_")) { return HandleApexControlMessage(action, name, message); } Service* service = nullptr; if (ConsumePrefix(&action, "interface_")) { service = ServiceList::GetInstance().FindInterface(name); } else { Loading init/init_test.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ #include "util.h" using android::base::GetIntProperty; using android::base::GetProperty; using android::base::SetProperty; using android::base::WaitForProperty; using namespace std::literals; namespace android { namespace init { Loading Loading @@ -334,6 +338,20 @@ TEST(init, LazilyLoadedActionsCanBeTriggeredByTheNextTrigger) { EXPECT_EQ(2, num_executed); } TEST(init, RespondToCtlApexMessages) { if (getuid() != 0) { GTEST_SKIP() << "Skipping test, must be run as root."; return; } std::string apex_name = "com.android.apex.cts.shim"; SetProperty("ctl.apex_unload", apex_name); EXPECT_TRUE(WaitForProperty("init.apex." + apex_name, "unloaded", 10s)); SetProperty("ctl.apex_load", apex_name); EXPECT_TRUE(WaitForProperty("init.apex." + apex_name, "loaded", 10s)); } TEST(init, RejectsCriticalAndOneshotService) { if (GetIntProperty("ro.product.first_api_level", 10000) < 30) { GTEST_SKIP() << "Test only valid for devices launching with R or later"; Loading Loading
init/init.cpp +32 −1 Original line number Diff line number Diff line Loading @@ -442,6 +442,19 @@ static Result<void> DoControlRestart(Service* service) { return {}; } static void DoUnloadApex(const std::string& apex_name) { std::string prop_name = "init.apex." + apex_name; // TODO(b/232114573) remove services and actions read from the apex // TODO(b/232799709) kill services from the apex SetProperty(prop_name, "unloaded"); } static void DoLoadApex(const std::string& apex_name) { std::string prop_name = "init.apex." + apex_name; // TODO(b/232799709) read .rc files from the apex SetProperty(prop_name, "loaded"); } enum class ControlTarget { SERVICE, // function gets called for the named service INTERFACE, // action gets called for every service that holds this interface Loading @@ -465,6 +478,20 @@ static const std::map<std::string, ControlMessageFunction, std::less<>>& GetCont return control_message_functions; } static bool HandleApexControlMessage(std::string_view action, const std::string& name, std::string_view message) { if (action == "load") { DoLoadApex(name); return true; } else if (action == "unload") { DoUnloadApex(name); return true; } else { LOG(ERROR) << "Unknown control msg '" << message << "'"; return false; } } static bool HandleControlMessage(std::string_view message, const std::string& name, pid_t from_pid) { std::string cmdline_path = StringPrintf("proc/%d/cmdline", from_pid); Loading @@ -476,8 +503,12 @@ static bool HandleControlMessage(std::string_view message, const std::string& na process_cmdline = "unknown process"; } Service* service = nullptr; auto action = message; if (ConsumePrefix(&action, "apex_")) { return HandleApexControlMessage(action, name, message); } Service* service = nullptr; if (ConsumePrefix(&action, "interface_")) { service = ServiceList::GetInstance().FindInterface(name); } else { Loading
init/init_test.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ #include "util.h" using android::base::GetIntProperty; using android::base::GetProperty; using android::base::SetProperty; using android::base::WaitForProperty; using namespace std::literals; namespace android { namespace init { Loading Loading @@ -334,6 +338,20 @@ TEST(init, LazilyLoadedActionsCanBeTriggeredByTheNextTrigger) { EXPECT_EQ(2, num_executed); } TEST(init, RespondToCtlApexMessages) { if (getuid() != 0) { GTEST_SKIP() << "Skipping test, must be run as root."; return; } std::string apex_name = "com.android.apex.cts.shim"; SetProperty("ctl.apex_unload", apex_name); EXPECT_TRUE(WaitForProperty("init.apex." + apex_name, "unloaded", 10s)); SetProperty("ctl.apex_load", apex_name); EXPECT_TRUE(WaitForProperty("init.apex." + apex_name, "loaded", 10s)); } TEST(init, RejectsCriticalAndOneshotService) { if (GetIntProperty("ro.product.first_api_level", 10000) < 30) { GTEST_SKIP() << "Test only valid for devices launching with R or later"; Loading