diff options
Diffstat (limited to 'cmds/installd/otapreopt_chroot.cpp')
-rw-r--r-- | cmds/installd/otapreopt_chroot.cpp | 126 |
1 files changed, 34 insertions, 92 deletions
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp index c62734a925..6459805ba3 100644 --- a/cmds/installd/otapreopt_chroot.cpp +++ b/cmds/installd/otapreopt_chroot.cpp @@ -20,19 +20,16 @@ #include <sys/stat.h> #include <sys/wait.h> -#include <array> -#include <fstream> #include <sstream> -#include <android-base/file.h> #include <android-base/logging.h> #include <android-base/macros.h> -#include <android-base/scopeguard.h> #include <android-base/stringprintf.h> -#include <android-base/unique_fd.h> #include <libdm/dm.h> #include <selinux/android.h> +#include <apexd.h> + #include "installd_constants.h" #include "otapreopt_utils.h" @@ -62,23 +59,28 @@ static void CloseDescriptor(const char* descriptor_string) { } } -static void ActivateApexPackages() { - std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"}; - std::string apexd_error_msg; - - bool exec_result = Exec(apexd_cmd, &apexd_error_msg); - if (!exec_result) { - PLOG(ERROR) << "Running otapreopt failed: " << apexd_error_msg; - exit(220); +static std::vector<apex::ApexFile> ActivateApexPackages() { + // The logic here is (partially) copied and adapted from + // system/apex/apexd/apexd.cpp. + // + // Only scan the APEX directory under /system, /system_ext and /vendor (within the chroot dir). + std::vector<const char*> apex_dirs{apex::kApexPackageSystemDir, apex::kApexPackageSystemExtDir, + apex::kApexPackageVendorDir}; + for (const auto& dir : apex_dirs) { + // Cast call to void to suppress warn_unused_result. + static_cast<void>(apex::scanPackagesDirAndActivate(dir)); } + return apex::getActivePackages(); } -static void DeactivateApexPackages() { - std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--unmount-all"}; - std::string apexd_error_msg; - bool exec_result = Exec(apexd_cmd, &apexd_error_msg); - if (!exec_result) { - PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg; +static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) { + for (const apex::ApexFile& apex_file : active_packages) { + const std::string& package_path = apex_file.GetPath(); + base::Result<void> status = apex::deactivatePackage(package_path); + if (!status.ok()) { + LOG(ERROR) << "Failed to deactivate " << package_path << ": " + << status.error(); + } } } @@ -179,18 +181,6 @@ static int otapreopt_chroot(const int argc, char **arg) { // want it for product APKs. Same notes as vendor above. TryExtraMount("product", arg[2], "/postinstall/product"); - // Try to mount the system_ext partition. update_engine doesn't do this for - // us, but we want it for system_ext APKs. Same notes as vendor and product - // above. - TryExtraMount("system_ext", arg[2], "/postinstall/system_ext"); - - constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig"; - // Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot - if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) { - PLOG(ERROR) << "Failed to mount a tmpfs for " << kPostInstallLinkerconfig; - exit(215); - } - // Setup APEX mount point and its security context. static constexpr const char* kPostinstallApexDir = "/postinstall/apex"; // The following logic is similar to the one in system/core/rootdir/init.rc: @@ -246,71 +236,20 @@ static int otapreopt_chroot(const int argc, char **arg) { exit(205); } - // Call apexd --unmount-all to free up loop and dm block devices, so that we can re-use - // them during the next invocation. Since otapreopt_chroot calls exit in case something goes - // wrong we need to register our own atexit handler. - // We want to register this handler before actually activating apex packages. This is mostly - // due to the fact that if fail to unmount apexes, then on the next run of otapreopt_chroot - // we will ask for new loop devices instead of re-using existing ones, and we really don't want - // to do that. :) - if (atexit(DeactivateApexPackages) != 0) { - LOG(ERROR) << "Failed to register atexit hander"; - exit(206); - } - // Try to mount APEX packages in "/apex" in the chroot dir. We need at least // the ART APEX, as it is required by otapreopt to run dex2oat. - ActivateApexPackages(); - - auto cleanup = android::base::make_scope_guard([](){ - std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--unmount-all"}; - std::string apexd_error_msg; - bool exec_result = Exec(apexd_cmd, &apexd_error_msg); - if (!exec_result) { - PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg; - } - }); + std::vector<apex::ApexFile> active_packages = ActivateApexPackages(); + // Check that an ART APEX has been activated; clean up and exit // early otherwise. - static constexpr const std::string_view kRequiredApexs[] = { - "com.android.art", - "com.android.runtime", - "com.android.sdkext", // For derive_classpath - }; - std::array<bool, arraysize(kRequiredApexs)> found_apexs{ false, false }; - DIR* apex_dir = opendir("/apex"); - if (apex_dir == nullptr) { - PLOG(ERROR) << "unable to open /apex"; - exit(220); - } - for (dirent* entry = readdir(apex_dir); entry != nullptr; entry = readdir(apex_dir)) { - for (int i = 0; i < found_apexs.size(); i++) { - if (kRequiredApexs[i] == std::string_view(entry->d_name)) { - found_apexs[i] = true; - break; - } - } - } - closedir(apex_dir); - auto it = std::find(found_apexs.cbegin(), found_apexs.cend(), false); - if (it != found_apexs.cend()) { - LOG(ERROR) << "No activated " << kRequiredApexs[std::distance(found_apexs.cbegin(), it)] - << " package!"; - exit(221); - } - - // Setup /linkerconfig. Doing it after the chroot means it doesn't need its own category - if (selinux_android_restorecon("/linkerconfig", 0) < 0) { - PLOG(ERROR) << "Failed to restorecon /linkerconfig"; - exit(219); - } - std::vector<std::string> linkerconfig_cmd{"/apex/com.android.runtime/bin/linkerconfig", - "--target", "/linkerconfig"}; - std::string linkerconfig_error_msg; - bool linkerconfig_exec_result = Exec(linkerconfig_cmd, &linkerconfig_error_msg); - if (!linkerconfig_exec_result) { - LOG(ERROR) << "Running linkerconfig failed: " << linkerconfig_error_msg; - exit(218); + if (std::none_of(active_packages.begin(), + active_packages.end(), + [](const apex::ApexFile& package){ + return package.GetManifest().name() == "com.android.art"; + })) { + LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package."; + DeactivateApexPackages(active_packages); + exit(217); } // Now go on and run otapreopt. @@ -333,6 +272,9 @@ static int otapreopt_chroot(const int argc, char **arg) { LOG(ERROR) << "Running otapreopt failed: " << error_msg; } + // Tear down the work down by the apexd logic. (i.e. deactivate packages). + DeactivateApexPackages(active_packages); + if (!exec_result) { exit(213); } |