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

Commit c7ad3fb0 authored by Andreas Gampe's avatar Andreas Gampe Committed by android-build-merger
Browse files

OtaPreopt: Add version support

am: c4ced4f0

Change-Id: I79b9057f781751623dc321f280e6b4680aa1f952
parents b8a71496 c4ced4f0
Loading
Loading
Loading
Loading
+0 −23
Original line number Original line Diff line number Diff line
@@ -67,14 +67,6 @@ static unique_fd invalid_unique_fd() {
    return unique_fd(-1);
    return unique_fd(-1);
}
}


static const char* parse_null(const char* arg) {
    if (strcmp(arg, "!") == 0) {
        return nullptr;
    } else {
        return arg;
    }
}

static bool clear_profile(const std::string& profile) {
static bool clear_profile(const std::string& profile) {
    unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
    unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
    if (ufd.get() < 0) {
    if (ufd.get() < 0) {
@@ -1863,20 +1855,5 @@ bool delete_odex(const char* apk_path, const char* instruction_set, const char*
    return return_value_oat && return_value_art;
    return return_value_oat && return_value_art;
}
}


int dexopt(const char* const params[DEXOPT_PARAM_COUNT]) {
    return dexopt(params[0],                    // apk_path
                  atoi(params[1]),              // uid
                  params[2],                    // pkgname
                  params[3],                    // instruction_set
                  atoi(params[4]),              // dexopt_needed
                  params[5],                    // oat_dir
                  atoi(params[6]),              // dexopt_flags
                  params[7],                    // compiler_filter
                  parse_null(params[8]),        // volume_uuid
                  parse_null(params[9]),        // shared_libraries
                  parse_null(params[10]));       // se_info
    static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param count");
}

}  // namespace installd
}  // namespace installd
}  // namespace android
}  // namespace android
+0 −6
Original line number Original line Diff line number Diff line
@@ -61,12 +61,6 @@ int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *ins
        int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
        int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
        const char* volume_uuid, const char* shared_libraries, const char* se_info);
        const char* volume_uuid, const char* shared_libraries, const char* se_info);


static constexpr size_t DEXOPT_PARAM_COUNT = 11U;
static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param size");

// Helper for the above, converting arguments.
int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);

}  // namespace installd
}  // namespace installd
}  // namespace android
}  // namespace android


+276 −33
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


#include <algorithm>
#include <algorithm>
#include <inttypes.h>
#include <inttypes.h>
#include <limits>
#include <random>
#include <random>
#include <regex>
#include <regex>
#include <selinux/android.h>
#include <selinux/android.h>
@@ -40,6 +41,7 @@
#include "dexopt.h"
#include "dexopt.h"
#include "file_parsing.h"
#include "file_parsing.h"
#include "globals.h"
#include "globals.h"
#include "installd_constants.h"
#include "installd_deps.h"  // Need to fill in requirements of commands.
#include "installd_deps.h"  // Need to fill in requirements of commands.
#include "otapreopt_utils.h"
#include "otapreopt_utils.h"
#include "system_properties.h"
#include "system_properties.h"
@@ -145,6 +147,20 @@ class OTAPreoptService {


private:
private:


    struct Parameters {
        const char *apk_path;
        uid_t uid;
        const char *pkgName;
        const char *instruction_set;
        int dexopt_needed;
        const char* oat_dir;
        int dexopt_flags;
        const char* compiler_filter;
        const char* volume_uuid;
        const char* shared_libraries;
        const char* se_info;
    };

    bool ReadSystemProperties() {
    bool ReadSystemProperties() {
        static constexpr const char* kPropertyFiles[] = {
        static constexpr const char* kPropertyFiles[] = {
                "/default.prop", "/system/build.prop"
                "/default.prop", "/system/build.prop"
@@ -246,15 +262,23 @@ private:
        return true;
        return true;
    }
    }


    bool ReadArguments(int argc ATTRIBUTE_UNUSED, char** argv) {
    bool ParseUInt(const char* in, uint32_t* out) {
        // Expected command line:
        char* end;
        //   target-slot dexopt {DEXOPT_PARAMETERS}
        long long int result = strtoll(in, &end, 0);
        // The DEXOPT_PARAMETERS are passed on to dexopt(), so we expect DEXOPT_PARAM_COUNT
        if (in == end || *end != '\0') {
        // of them. We store them in package_parameters_ (size checks are done when
            return false;
        // parsing the special parameters and when copying into package_parameters_.
        }
        if (result < std::numeric_limits<uint32_t>::min() ||
                std::numeric_limits<uint32_t>::max() < result) {
            return false;
        }
        *out = static_cast<uint32_t>(result);
        return true;
    }


        static_assert(DEXOPT_PARAM_COUNT == ARRAY_SIZE(package_parameters_),
    bool ReadArguments(int argc, char** argv) {
                      "Unexpected dexopt param count");
        // Expected command line:
        //   target-slot [version] dexopt {DEXOPT_PARAMETERS}


        const char* target_slot_arg = argv[1];
        const char* target_slot_arg = argv[1];
        if (target_slot_arg == nullptr) {
        if (target_slot_arg == nullptr) {
@@ -268,28 +292,230 @@ private:
            return false;
            return false;
        }
        }


        // Check for "dexopt" next.
        // Check for version or "dexopt" next.
        if (argv[2] == nullptr) {
            LOG(ERROR) << "Missing parameters";
            return false;
        }

        if (std::string("dexopt").compare(argv[2]) == 0) {
            // This is version 1 (N) or pre-versioning version 2.
            constexpr int kV2ArgCount =   1   // "otapreopt"
                                        + 1   // slot
                                        + 1   // "dexopt"
                                        + 1   // apk_path
                                        + 1   // uid
                                        + 1   // pkg
                                        + 1   // isa
                                        + 1   // dexopt_needed
                                        + 1   // oat_dir
                                        + 1   // dexopt_flags
                                        + 1   // filter
                                        + 1   // volume
                                        + 1   // libs
                                        + 1   // seinfo
                                        + 1;  // null
            if (argc == kV2ArgCount) {
                return ReadArgumentsV2(argc, argv, false);
            } else {
                return ReadArgumentsV1(argc, argv);
            }
        }

        uint32_t version;
        if (!ParseUInt(argv[2], &version)) {
            LOG(ERROR) << "Could not parse version: " << argv[2];
            return false;
        }

        switch (version) {
            case 2:
                return ReadArgumentsV2(argc, argv, true);

            default:
                LOG(ERROR) << "Unsupported version " << version;
                return false;
        }
    }

    bool ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, char** argv, bool versioned) {
        size_t dexopt_index = versioned ? 3 : 2;

        // Check for "dexopt".
        if (argv[dexopt_index] == nullptr) {
            LOG(ERROR) << "Missing parameters";
            return false;
        }
        if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
            LOG(ERROR) << "Expected \"dexopt\"";
            return false;
        }

        size_t param_index = 0;
        for (;; ++param_index) {
            const char* param = argv[dexopt_index + 1 + param_index];
            if (param == nullptr) {
                break;
            }

            switch (param_index) {
                case 0:
                    package_parameters_.apk_path = param;
                    break;

                case 1:
                    package_parameters_.uid = atoi(param);
                    break;

                case 2:
                    package_parameters_.pkgName = param;
                    break;

                case 3:
                    package_parameters_.instruction_set = param;
                    break;

                case 4:
                    package_parameters_.dexopt_needed = atoi(param);
                    break;

                case 5:
                    package_parameters_.oat_dir = param;
                    break;

                case 6:
                    package_parameters_.dexopt_flags = atoi(param);
                    break;

                case 7:
                    package_parameters_.compiler_filter = param;
                    break;

                case 8:
                    package_parameters_.volume_uuid = ParseNull(param);
                    break;

                case 9:
                    package_parameters_.shared_libraries = ParseNull(param);
                    break;

                case 10:
                    package_parameters_.se_info = ParseNull(param);
                    break;

                default:
                    LOG(ERROR) << "Too many arguments, got " << param;
                    return false;
            }
        }

        if (param_index != 11) {
            LOG(ERROR) << "Not enough parameters";
            return false;
        }

        return true;
    }

    static int ReplaceMask(int input, int old_mask, int new_mask) {
        return (input & old_mask) != 0 ? new_mask : 0;
    }

    bool ReadArgumentsV1(int argc ATTRIBUTE_UNUSED, char** argv) {
        // Check for "dexopt".
        if (argv[2] == nullptr) {
        if (argv[2] == nullptr) {
            LOG(ERROR) << "Missing parameters";
            LOG(ERROR) << "Missing parameters";
            return false;
            return false;
        }
        }
        if (std::string("dexopt").compare(argv[2]) != 0) {
        if (std::string("dexopt").compare(argv[2]) != 0) {
            LOG(ERROR) << "Second parameter not dexopt: " << argv[2];
            LOG(ERROR) << "Expected \"dexopt\"";
            return false;
            return false;
        }
        }


        // Copy the rest into package_parameters_, but be careful about over- and underflow.
        size_t param_index = 0;
        size_t index = 0;
        for (;; ++param_index) {
        while (index < DEXOPT_PARAM_COUNT &&
            const char* param = argv[3 + param_index];
                argv[index + 3] != nullptr) {
            if (param == nullptr) {
            package_parameters_[index] = argv[index + 3];
                break;
            index++;
            }
            }
        if (index != ARRAY_SIZE(package_parameters_) || argv[index + 3] != nullptr) {

            LOG(ERROR) << "Wrong number of parameters";
            switch (param_index) {
                case 0:
                    package_parameters_.apk_path = param;
                    break;

                case 1:
                    package_parameters_.uid = atoi(param);
                    break;

                case 2:
                    package_parameters_.pkgName = param;
                    break;

                case 3:
                    package_parameters_.instruction_set = param;
                    break;

                case 4: {
                    // Version 1 had:
                    //   DEXOPT_DEX2OAT_NEEDED       = 1
                    //   DEXOPT_PATCHOAT_NEEDED      = 2
                    //   DEXOPT_SELF_PATCHOAT_NEEDED = 3
                    // We will simply use DEX2OAT_FROM_SCRATCH.
                    package_parameters_.dexopt_needed = DEX2OAT_FROM_SCRATCH;
                    break;
                }

                case 5:
                    package_parameters_.oat_dir = param;
                    break;

                case 6: {
                    // Version 1 had:
                    constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
                    constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
                    constexpr int OLD_DEXOPT_DEBUGGABLE     = 1 << 3;
                    constexpr int OLD_DEXOPT_BOOTCOMPLETE   = 1 << 4;
                    constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
                    constexpr int OLD_DEXOPT_OTA            = 1 << 6;
                    int input = atoi(param);
                    package_parameters_.dexopt_flags =
                            ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
                            ReplaceMask(input, OLD_DEXOPT_SAFEMODE, DEXOPT_SAFEMODE) |
                            ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
                            ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
                            ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
                            ReplaceMask(input, OLD_DEXOPT_OTA, 0);
                    break;
                }

                case 7:
                    package_parameters_.compiler_filter = param;
                    break;

                case 8:
                    package_parameters_.volume_uuid = ParseNull(param);
                    break;

                case 9:
                    package_parameters_.shared_libraries = ParseNull(param);
                    break;

                default:
                    LOG(ERROR) << "Too many arguments, got " << param;
                    return false;
            }
        }

        if (param_index != 10) {
            LOG(ERROR) << "Not enough parameters";
            return false;
            return false;
        }
        }


        // Set se_info to null. It is only relevant for secondary dex files, which we won't
        // receive from a v1 A side.
        package_parameters_.se_info = nullptr;

        return true;
        return true;
    }
    }


@@ -306,11 +532,11 @@ private:
    // Ensure that we have the right boot image. The first time any app is
    // Ensure that we have the right boot image. The first time any app is
    // compiled, we'll try to generate it.
    // compiled, we'll try to generate it.
    bool PrepareBootImage(bool force) const {
    bool PrepareBootImage(bool force) const {
        if (package_parameters_[kISAIndex] == nullptr) {
        if (package_parameters_.instruction_set == nullptr) {
            LOG(ERROR) << "Instruction set missing.";
            LOG(ERROR) << "Instruction set missing.";
            return false;
            return false;
        }
        }
        const char* isa = package_parameters_[kISAIndex];
        const char* isa = package_parameters_.instruction_set;


        // Check whether the file exists where expected.
        // Check whether the file exists where expected.
        std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
        std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
@@ -536,14 +762,12 @@ private:
        //       (This is ugly as it's the only thing where we need to understand the contents
        //       (This is ugly as it's the only thing where we need to understand the contents
        //        of package_parameters_, but it beats postponing the decision or using the call-
        //        of package_parameters_, but it beats postponing the decision or using the call-
        //        backs to do weird things.)
        //        backs to do weird things.)
        constexpr size_t kApkPathIndex = 0;
        const char* apk_path = package_parameters_.apk_path;
        CHECK_GT(DEXOPT_PARAM_COUNT, kApkPathIndex);
        CHECK(apk_path != nullptr);
        CHECK(package_parameters_[kApkPathIndex] != nullptr);
        if (StartsWith(apk_path, android_root_.c_str())) {
        if (StartsWith(package_parameters_[kApkPathIndex], android_root_.c_str())) {
            const char* last_slash = strrchr(apk_path, '/');
            const char* last_slash = strrchr(package_parameters_[kApkPathIndex], '/');
            if (last_slash != nullptr) {
            if (last_slash != nullptr) {
                std::string path(package_parameters_[kApkPathIndex],
                std::string path(apk_path, last_slash - apk_path + 1);
                                 last_slash - package_parameters_[kApkPathIndex] + 1);
                CHECK(EndsWith(path, "/"));
                CHECK(EndsWith(path, "/"));
                path = path + "oat";
                path = path + "oat";
                if (access(path.c_str(), F_OK) == 0) {
                if (access(path.c_str(), F_OK) == 0) {
@@ -557,9 +781,8 @@ private:
        // partition will not be available and fail to build. This is problematic, as
        // partition will not be available and fail to build. This is problematic, as
        // this tool will wipe the OTA artifact cache and try again (for robustness after
        // this tool will wipe the OTA artifact cache and try again (for robustness after
        // a failed OTA with remaining cache artifacts).
        // a failed OTA with remaining cache artifacts).
        if (access(package_parameters_[kApkPathIndex], F_OK) != 0) {
        if (access(apk_path, F_OK) != 0) {
            LOG(WARNING) << "Skipping preopt of non-existing package "
            LOG(WARNING) << "Skipping preopt of non-existing package " << apk_path;
                         << package_parameters_[kApkPathIndex];
            return true;
            return true;
        }
        }


@@ -571,7 +794,17 @@ private:
            return 0;
            return 0;
        }
        }


        int dexopt_result = dexopt(package_parameters_);
        int dexopt_result = dexopt(package_parameters_.apk_path,
                                   package_parameters_.uid,
                                   package_parameters_.pkgName,
                                   package_parameters_.instruction_set,
                                   package_parameters_.dexopt_needed,
                                   package_parameters_.oat_dir,
                                   package_parameters_.dexopt_flags,
                                   package_parameters_.compiler_filter,
                                   package_parameters_.volume_uuid,
                                   package_parameters_.shared_libraries,
                                   package_parameters_.se_info);
        if (dexopt_result == 0) {
        if (dexopt_result == 0) {
            return 0;
            return 0;
        }
        }
@@ -590,7 +823,17 @@ private:
        }
        }


        LOG(WARNING) << "Original dexopt failed, re-trying after boot image was regenerated.";
        LOG(WARNING) << "Original dexopt failed, re-trying after boot image was regenerated.";
        return dexopt(package_parameters_);
        return dexopt(package_parameters_.apk_path,
                      package_parameters_.uid,
                      package_parameters_.pkgName,
                      package_parameters_.instruction_set,
                      package_parameters_.dexopt_needed,
                      package_parameters_.oat_dir,
                      package_parameters_.dexopt_flags,
                      package_parameters_.compiler_filter,
                      package_parameters_.volume_uuid,
                      package_parameters_.shared_libraries,
                      package_parameters_.se_info);
    }
    }


    ////////////////////////////////////
    ////////////////////////////////////
@@ -720,7 +963,7 @@ private:
    std::string boot_classpath_;
    std::string boot_classpath_;
    std::string asec_mountpoint_;
    std::string asec_mountpoint_;


    const char* package_parameters_[DEXOPT_PARAM_COUNT];
    Parameters package_parameters_;


    // Store environment values we need to set.
    // Store environment values we need to set.
    std::vector<std::string> environ_;
    std::vector<std::string> environ_;