summaryrefslogtreecommitdiff
path: root/cmds/installd/otapreopt_chroot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/installd/otapreopt_chroot.cpp')
-rw-r--r--cmds/installd/otapreopt_chroot.cpp126
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);
}