Merge "logcat: clean up handling of logd control commands with -f and -L"
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index e7a3ff2..824ee43 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -20,6 +20,7 @@
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 
+#include <chrono>
 #include <functional>
 #include <thread>
 
@@ -79,14 +80,24 @@
     return true;
 }
 
-bool DeviceMapper::DeleteDeviceIfExists(const std::string& name) {
+bool DeviceMapper::DeleteDeviceIfExists(const std::string& name,
+                                        const std::chrono::milliseconds& timeout_ms) {
     if (GetState(name) == DmDeviceState::INVALID) {
         return true;
     }
-    return DeleteDevice(name);
+    return DeleteDevice(name, timeout_ms);
 }
 
-bool DeviceMapper::DeleteDevice(const std::string& name) {
+bool DeviceMapper::DeleteDeviceIfExists(const std::string& name) {
+    return DeleteDeviceIfExists(name, 0ms);
+}
+
+bool DeviceMapper::DeleteDevice(const std::string& name,
+                                const std::chrono::milliseconds& timeout_ms) {
+    std::string unique_path;
+    if (!GetDeviceUniquePath(name, &unique_path)) {
+        LOG(ERROR) << "Failed to get unique path for device " << name;
+    }
     struct dm_ioctl io;
     InitIo(&io, name);
 
@@ -100,9 +111,23 @@
     CHECK(io.flags & DM_UEVENT_GENERATED_FLAG)
             << "Didn't generate uevent for [" << name << "] removal";
 
+    if (timeout_ms <= std::chrono::milliseconds::zero()) {
+        return true;
+    }
+    if (unique_path.empty()) {
+        return false;
+    }
+    if (!WaitForFileDeleted(unique_path, timeout_ms)) {
+        LOG(ERROR) << "Timeout out waiting for " << unique_path << " to be deleted";
+        return false;
+    }
     return true;
 }
 
+bool DeviceMapper::DeleteDevice(const std::string& name) {
+    return DeleteDevice(name, 0ms);
+}
+
 static std::string GenerateUuid() {
     uuid_t uuid_bytes;
     uuid_generate(uuid_bytes);
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index ed2fa83..1695953 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -520,3 +520,27 @@
     ASSERT_TRUE(target.Valid());
     ASSERT_EQ(target.GetParameterString(), "AES-256-XTS abcdef0123456789 /dev/loop0 0");
 }
+
+TEST(libdm, DeleteDeviceWithTimeout) {
+    unique_fd tmp(CreateTempFile("file_1", 4096));
+    ASSERT_GE(tmp, 0);
+    LoopDevice loop(tmp, 10s);
+    ASSERT_TRUE(loop.valid());
+
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
+    ASSERT_TRUE(table.valid());
+    TempDevice dev("libdm-test-dm-linear", table);
+    ASSERT_TRUE(dev.valid());
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+
+    std::string path;
+    ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
+    ASSERT_EQ(0, access(path.c_str(), F_OK));
+
+    ASSERT_TRUE(dm.DeleteDevice("libdm-test-dm-linear", 5s));
+    ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
+    ASSERT_NE(0, access(path.c_str(), F_OK));
+    ASSERT_EQ(ENOENT, errno);
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index e25ce7f..830c5e8 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -90,6 +90,10 @@
     // Returns 'true' on success, false otherwise.
     bool DeleteDevice(const std::string& name);
     bool DeleteDeviceIfExists(const std::string& name);
+    // Removes a device mapper device with the given name and waits for |timeout_ms| milliseconds
+    // for the corresponding block device to be deleted.
+    bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
+    bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms);
 
     // Fetches and returns the complete state of the underlying device mapper
     // device with given name.
diff --git a/fs_mgr/libdm/utility.cpp b/fs_mgr/libdm/utility.cpp
index eccf2fb..f252565 100644
--- a/fs_mgr/libdm/utility.cpp
+++ b/fs_mgr/libdm/utility.cpp
@@ -52,5 +52,15 @@
     return WaitForCondition(condition, timeout_ms);
 }
 
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms) {
+    auto condition = [&]() -> WaitResult {
+        if (access(path.c_str(), F_OK) == 0 || errno != ENOENT) {
+            return WaitResult::Wait;
+        }
+        return WaitResult::Done;
+    };
+    return WaitForCondition(condition, timeout_ms);
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/utility.h b/fs_mgr/libdm/utility.h
index f1dce9e..58fa96b 100644
--- a/fs_mgr/libdm/utility.h
+++ b/fs_mgr/libdm/utility.h
@@ -23,6 +23,7 @@
 enum class WaitResult { Wait, Done, Fail };
 
 bool WaitForFile(const std::string& path, const std::chrono::milliseconds& timeout_ms);
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms);
 bool WaitForCondition(const std::function<WaitResult()>& condition,
                       const std::chrono::milliseconds& timeout_ms);
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 1028330..6bf3997 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1181,7 +1181,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 c457de6..6ba64ee 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -121,11 +121,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 e9d918e..0e61234 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -797,6 +797,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 cc97d94..be46585 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
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 250e600..0ab68db 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -139,6 +139,9 @@
       if (start == info->start && end == info->end && flags == info->flags && *name == info->name) {
         // No need to check
         search_map_idx = old_map_idx + 1;
+        if (new_map_idx + 1 < maps_.size()) {
+          maps_[new_map_idx + 1]->prev_map = info.get();
+        }
         maps_[new_map_idx] = nullptr;
         total_entries--;
         break;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 782fb92..ff68734 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -669,6 +669,7 @@
     # Wait for apexd to finish activating APEXes before starting more processes.
     wait_for_prop apexd.status ready
     parse_apex_configs
+    exec_start derive_sdk
 
     init_user0