Merge "Use apexservice to get the list of apexes" into main
diff --git a/Android.bp b/Android.bp
index 7e41f22..1240efc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -239,7 +239,10 @@
 
 cc_binary {
     name: "vold_prepare_subdirs",
-    defaults: ["vold_default_flags"],
+    defaults: [
+        "vold_default_flags",
+        "libapexservice-deps",
+    ],
 
     srcs: [
         "vold_prepare_subdirs.cpp",
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index 60e82f5..e41e994 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -30,7 +30,11 @@
 #include <sys/types.h>
 
 #include <android-base/logging.h>
+#include <android-base/result.h>
 #include <android-base/scopeguard.h>
+#include <android/apex/ApexInfo.h>
+#include <android/apex/IApexService.h>
+#include <binder/IServiceManager.h>
 
 #include <cutils/fs.h>
 #include <selinux/android.h>
@@ -141,24 +145,35 @@
     }
 }
 
+static android::base::Result<std::vector<std::string>> get_apex_list() {
+    auto sm = android::defaultServiceManager();
+    auto binder = sm->waitForService(android::String16("apexservice"));
+    if (binder == nullptr) {
+        return android::base::Error() << "Failed to get apexservice";
+    }
+    auto service = android::interface_cast<android::apex::IApexService>(binder);
+    std::vector<android::apex::ApexInfo> list;
+    auto status = service->getActivePackages(&list);
+    if (!status.isOk()) {
+        return android::base::Error() << status.exceptionMessage().c_str();
+    }
+    std::vector<std::string> names;
+    names.reserve(list.size());
+    for (const auto& apex_info : list) {
+        names.push_back(apex_info.moduleName);
+    }
+    return names;
+}
+
 static bool prepare_apex_subdirs(struct selabel_handle* sehandle, const std::string& path) {
     if (!prepare_dir(sehandle, 0711, 0, 0, path + "/apexdata")) return false;
 
-    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
-    if (!dirp) {
-        PLOG(ERROR) << "Unable to open apex directory";
+    auto apex_list = get_apex_list();
+    if (!apex_list.ok()) {
+        LOG(ERROR) << apex_list.error();
         return false;
     }
-    struct dirent* entry;
-    while ((entry = readdir(dirp.get())) != nullptr) {
-        if (entry->d_type != DT_DIR) continue;
-
-        const char* name = entry->d_name;
-        // skip any starting with "."
-        if (name[0] == '.') continue;
-
-        if (strchr(name, '@') != NULL) continue;
-
+    for (const auto& name : *apex_list) {
         if (!prepare_dir(sehandle, 0771, AID_ROOT, AID_SYSTEM, path + "/apexdata/" + name)) {
             return false;
         }