Stop services when unload an apex

Bug: 238854102
Test: atest CtsInitTestCases ApexTestCases
Change-Id: I3b9df9424f7841c42bd1bde27cd0e0750615bd6c
diff --git a/init/init.cpp b/init/init.cpp
index 5f516b7..9192214 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -79,6 +79,7 @@
 #include "selabel.h"
 #include "selinux.h"
 #include "service.h"
+#include "service_list.h"
 #include "service_parser.h"
 #include "sigchld_handler.h"
 #include "snapuserd_transition.h"
@@ -443,11 +444,32 @@
     return {};
 }
 
+int StopServicesFromApex(const std::string& apex_name) {
+    auto services = ServiceList::GetInstance().FindServicesByApexName(apex_name);
+    if (services.empty()) {
+        LOG(INFO) << "No service found for APEX: " << apex_name;
+        return 0;
+    }
+    std::set<std::string> service_names;
+    for (const auto& service : services) {
+        service_names.emplace(service->name());
+    }
+    constexpr std::chrono::milliseconds kServiceStopTimeout = 10s;
+    int still_running = StopServicesAndLogViolations(service_names, kServiceStopTimeout,
+                        true /*SIGTERM*/);
+    // Send SIGKILL to ones that didn't terminate cleanly.
+    if (still_running > 0) {
+        still_running = StopServicesAndLogViolations(service_names, 0ms, false /*SIGKILL*/);
+    }
+    return still_running;
+}
+
 static Result<void> DoUnloadApex(const std::string& apex_name) {
-    std::string prop_name = "init.apex." + apex_name;
+    if (StopServicesFromApex(apex_name) > 0) {
+        return Error() << "Unable to stop all service from " << 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");
+    SetProperty("init.apex." + apex_name, "unloaded");
     return {};
 }
 
@@ -471,14 +493,12 @@
 }
 
 static Result<void> DoLoadApex(const std::string& apex_name) {
-    std::string prop_name = "init.apex." + apex_name;
     // TODO(b/232799709) read .rc files from the apex
-
     if (auto result = UpdateApexLinkerConfig(apex_name); !result.ok()) {
         return result.error();
     }
 
-    SetProperty(prop_name, "loaded");
+    SetProperty("init.apex." + apex_name, "loaded");
     return {};
 }