Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7dc8f63 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Use apexd to set up chroot apex dir" am: cad66dc0

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1626823

Change-Id: I79cc9cad0b140bfb4c07aa09a7f6e626626a40e2
parents 93169e30 cad66dc0
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -189,8 +189,8 @@ cc_binary {
        "liblog",
        "libutils",
    ],
    static_libs: [
        "libapexd",
    required: [
      "apexd"
    ],
}

+28 −57
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <sys/stat.h>
#include <sys/wait.h>

#include <array>
#include <fstream>
#include <sstream>

@@ -31,10 +32,6 @@
#include <libdm/dm.h>
#include <selinux/android.h>

#include <apex_file_repository.h>
#include <apex_constants.h>
#include <apexd.h>

#include "installd_constants.h"
#include "otapreopt_utils.h"

@@ -64,47 +61,14 @@ static void CloseDescriptor(const char* descriptor_string) {
    }
}

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<std::string> apex_dirs{apex::kApexPackageSystemDir, apex::kApexPackageSystemExtDir,
                                       apex::kApexPackageVendorDir};
    // Initialize ApexFileRepository used internally in ScanPackagesDirAndActivate.
    // This is a quick fix to fix apex activation in otapreopt_chroot.
    apex::ApexFileRepository::GetInstance().AddPreInstalledApex(apex_dirs);
    for (const auto& dir : apex_dirs) {
        // Cast call to void to suppress warn_unused_result.
        static_cast<void>(apex::ScanPackagesDirAndActivate(dir.c_str()));
    }
    return apex::GetActivePackages();
}

static void CreateApexInfoList(const std::vector<apex::ApexFile>& apex_files) {
    // Setup the apex-info-list.xml file
    const std::string apex_info_file = std::string(apex::kApexRoot) + "/" + apex::kApexInfoList;
    std::fstream xml(apex_info_file.c_str(), std::ios::out | std::ios::trunc);
    if (!xml.is_open()) {
        PLOG(ERROR) << "Failed to open " << apex_info_file;
        exit(216);
    }

    // we do not care about inactive apexs
    std::vector<apex::ApexFile> inactive;
    apex::CollectApexInfoList(xml, apex_files, inactive);
    xml.flush();
    xml.close();
}
static void ActivateApexPackages() {
    std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"};
    std::string 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();
        }
    bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
    if (!exec_result) {
        PLOG(ERROR) << "Running otapreopt failed: " << apexd_error_msg;
        exit(220);
    }
}

@@ -269,8 +233,7 @@ static int otapreopt_chroot(const int argc, char **arg) {

    // 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.
    std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
    CreateApexInfoList(active_packages);
    ActivateApexPackages();

    // Check that an ART APEX has been activated; clean up and exit
    // early otherwise.
@@ -278,16 +241,27 @@ static int otapreopt_chroot(const int argc, char **arg) {
      "com.android.art",
      "com.android.runtime",
    };
    for (std::string_view apex : kRequiredApexs) {
        if (std::none_of(active_packages.begin(), active_packages.end(),
                         [&](const apex::ApexFile& package) {
                             return package.GetManifest().name() == apex;
                         })) {
            LOG(FATAL_WITHOUT_ABORT) << "No activated " << apex << " APEX package.";
            DeactivateApexPackages(active_packages);
            exit(217);
    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) {
@@ -323,9 +297,6 @@ 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);
    }