Remove service defined in an APEX during userspace reboot

Such services will be re-parsed and added back to the service list
during post-fs-data stage.

Test: adb reboot userspace
Test: atest CtsInitTestCases
Bug: 145669993
Bug: 135984674
Change-Id: Ibb393dfe0f101c4ebe37bc763733fd5d981d3691
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 98a9805..1a98f4e 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1180,7 +1180,7 @@
         return Error() << "glob pattern '" << glob_pattern << "' failed";
     }
     std::vector<std::string> configs;
-    Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance());
+    Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance(), true);
     for (size_t i = 0; i < glob_result.gl_pathc; i++) {
         std::string path = glob_result.gl_pathv[i];
         // Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
diff --git a/init/init.cpp b/init/init.cpp
index 8e2da59..736beb1 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -123,11 +123,12 @@
 }
 
 // parser that only accepts new services
-Parser CreateServiceOnlyParser(ServiceList& service_list) {
+Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex) {
     Parser parser;
 
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(
-                                               &service_list, subcontext.get(), std::nullopt));
+    parser.AddSectionParser("service",
+                            std::make_unique<ServiceParser>(&service_list, subcontext.get(),
+                                                            std::nullopt, from_apex));
     return parser;
 }
 
diff --git a/init/init.h b/init/init.h
index 0805940..4bbca6f 100644
--- a/init/init.h
+++ b/init/init.h
@@ -29,7 +29,7 @@
 namespace init {
 
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
-Parser CreateServiceOnlyParser(ServiceList& service_list);
+Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex);
 
 bool start_waiting_for_property(const char *name, const char *value);
 
diff --git a/init/reboot.cpp b/init/reboot.cpp
index b04db7f..b987f7d 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -798,6 +798,14 @@
     if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
         return Error() << "Failed to switch to bootstrap namespace";
     }
+    // Remove services that were defined in an APEX.
+    ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr<Service>& s) -> bool {
+        if (s->is_from_apex()) {
+            LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX";
+            return true;
+        }
+        return false;
+    });
     // Re-enable services
     for (const auto& s : were_enabled) {
         LOG(INFO) << "Re-enabling service '" << s->name() << "'";
diff --git a/init/service.cpp b/init/service.cpp
index ad42df7..05daec0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -131,13 +131,13 @@
 bool Service::is_exec_service_running_ = false;
 
 Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
-                 const std::vector<std::string>& args)
-    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
+                 const std::vector<std::string>& args, bool from_apex)
+    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args, from_apex) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
                  const std::vector<gid_t>& supp_gids, int namespace_flags,
                  const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
-                 const std::vector<std::string>& args)
+                 const std::vector<std::string>& args, bool from_apex)
     : name_(name),
       classnames_({"default"}),
       flags_(flags),
@@ -155,7 +155,8 @@
                  "onrestart", {}),
       oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
       start_order_(0),
-      args_(args) {}
+      args_(args),
+      from_apex_(from_apex) {}
 
 void Service::NotifyStateChange(const std::string& new_state) const {
     if ((flags_ & SVC_TEMPORARY) != 0) {
@@ -763,7 +764,7 @@
     }
 
     return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
-                                     nullptr, str_args);
+                                     nullptr, str_args, false);
 }
 
 }  // namespace init
diff --git a/init/service.h b/init/service.h
index f842b3c..cf3f0c2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -65,11 +65,12 @@
 
   public:
     Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
-            const std::vector<std::string>& args);
+            const std::vector<std::string>& args, bool from_apex = false);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
             const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
-            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
+            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args,
+            bool from_apex = false);
 
     static Result<std::unique_ptr<Service>> MakeTemporaryOneshotService(
             const std::vector<std::string>& args);
@@ -128,6 +129,7 @@
     const std::vector<std::string>& args() const { return args_; }
     bool is_updatable() const { return updatable_; }
     bool is_post_data() const { return post_data_; }
+    bool is_from_apex() const { return from_apex_; }
 
   private:
     void NotifyStateChange(const std::string& new_state) const;
@@ -199,6 +201,8 @@
     bool running_at_post_data_reset_ = false;
 
     std::optional<std::string> on_failure_reboot_target_;
+
+    bool from_apex_ = false;
 };
 
 }  // namespace init
diff --git a/init/service_list.h b/init/service_list.h
index ee2c702..1838624 100644
--- a/init/service_list.h
+++ b/init/service_list.h
@@ -34,6 +34,11 @@
 
     void AddService(std::unique_ptr<Service> service);
     void RemoveService(const Service& svc);
+    template <class UnaryPredicate>
+    void RemoveServiceIf(UnaryPredicate predicate) {
+        services_.erase(std::remove_if(services_.begin(), services_.end(), predicate),
+                        services_.end());
+    }
 
     template <typename T, typename F = decltype(&Service::name)>
     Service* FindService(T value, F function = &Service::name) const {
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 154d1dd..1d431e3 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -569,7 +569,7 @@
         }
     }
 
-    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
+    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args, from_apex_);
     return {};
 }
 
diff --git a/init/service_parser.h b/init/service_parser.h
index b1281f5..7bb0cc0 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -31,11 +31,13 @@
   public:
     ServiceParser(
             ServiceList* service_list, Subcontext* subcontext,
-            const std::optional<InterfaceInheritanceHierarchyMap>& interface_inheritance_hierarchy)
+            const std::optional<InterfaceInheritanceHierarchyMap>& interface_inheritance_hierarchy,
+            bool from_apex = false)
         : service_list_(service_list),
           subcontext_(subcontext),
           interface_inheritance_hierarchy_(interface_inheritance_hierarchy),
-          service_(nullptr) {}
+          service_(nullptr),
+          from_apex_(from_apex) {}
     Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                               int line) override;
     Result<void> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -89,6 +91,7 @@
     std::optional<InterfaceInheritanceHierarchyMap> interface_inheritance_hierarchy_;
     std::unique_ptr<Service> service_;
     std::string filename_;
+    bool from_apex_ = false;
 };
 
 }  // namespace init