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

Commit 8f02a1fb authored by Calin Juravle's avatar Calin Juravle Committed by android-build-merger
Browse files

Refactor argument parsing in ota preopt am: 315d1f54

am: 1c4e7896

Change-Id: I467d5d810b775d9b4f01111c02f0973fefffb069
parents 55c89075 1c4e7896
Loading
Loading
Loading
Loading
+77 −335
Original line number Diff line number Diff line
@@ -93,9 +93,9 @@ bool OTAPreoptParameters::ReadArguments(int argc, const char** argv) {
                                    + 1   // libs
                                    + 1;  // seinfo
        if (argc == kV2ArgCount) {
            return ReadArgumentsV2(argc, argv, false);
            return ReadArgumentsPostV1(2, argv, false);
        } else {
            return ReadArgumentsV1(argc, argv);
            return ReadArgumentsV1(argv);
        }
    }

@@ -105,38 +105,27 @@ bool OTAPreoptParameters::ReadArguments(int argc, const char** argv) {
        return false;
    }

    switch (version) {
        case 2:
            return ReadArgumentsV2(argc, argv, true);
        case 3:
            return ReadArgumentsV3(argc, argv);
        case 4:
            return ReadArgumentsV4(argc, argv);
        case 5:
            return ReadArgumentsV5(argc, argv);

        default:
            LOG(ERROR) << "Unsupported version " << version;
            return false;
    }
    return ReadArgumentsPostV1(version, argv, true);
}

bool OTAPreoptParameters::ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, const char** argv, bool versioned) {
    size_t dexopt_index = versioned ? 3 : 2;
static int ReplaceMask(int input, int old_mask, int new_mask) {
    return (input & old_mask) != 0 ? new_mask : 0;
}

bool OTAPreoptParameters::ReadArgumentsV1(const char** argv) {
    // Check for "dexopt".
    if (argv[dexopt_index] == nullptr) {
    if (argv[2] == nullptr) {
        LOG(ERROR) << "Missing parameters";
        return false;
    }
    if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
        LOG(ERROR) << "Expected \"dexopt\"";
    if (std::string("dexopt").compare(argv[2]) != 0) {
        LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[2];
        return false;
    }

    size_t param_index = 0;
    for (;; ++param_index) {
        const char* param = argv[dexopt_index + 1 + param_index];
        const char* param = argv[3 + param_index];
        if (param == nullptr) {
            break;
        }
@@ -158,17 +147,38 @@ bool OTAPreoptParameters::ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, const char*
                instruction_set = param;
                break;

            case 4:
                dexopt_needed = atoi(param);
            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.
                dexopt_needed = DEX2OAT_FROM_SCRATCH;
                break;
            }

            case 5:
                oat_dir = param;
                break;

            case 6:
                dexopt_flags = atoi(param);
            case 6: {
                // Version 1 had:
                constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
                // Note: DEXOPT_SAFEMODE has been removed.
                // 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);
                dexopt_flags =
                        ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
                        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:
                compiler_filter = param;
@@ -182,16 +192,21 @@ bool OTAPreoptParameters::ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, const char*
                shared_libraries = ParseNull(param);
                break;

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

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

    if (param_index != 10) {
        LOG(ERROR) << "Not enough parameters";
        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.
    se_info = nullptr;

    // Set downgrade to false. It is only relevant when downgrading compiler
    // filter, which is not the case during ota.
    downgrade = false;
@@ -203,106 +218,21 @@ bool OTAPreoptParameters::ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, const char*
    // Set the profile name to the primary apk profile.
    profile_name = "primary.prof";

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

    return true;
}

bool OTAPreoptParameters::ReadArgumentsV3(int argc ATTRIBUTE_UNUSED, const char** argv) {
    size_t dexopt_index = 3;

    // 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:
                apk_path = param;
                break;

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

            case 2:
                pkgName = param;
                break;

            case 3:
                instruction_set = param;
                break;

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

            case 5:
                oat_dir = param;
                break;

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

            case 7:
                compiler_filter = param;
                break;

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

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

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

            case 11:
                downgrade = ParseBool(param);
                break;

bool OTAPreoptParameters::ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned) {
    size_t num_args_expected = 0;
    switch (version) {
        case 2: num_args_expected = 11; break;
        case 3: num_args_expected = 12; break;
        case 4: num_args_expected = 13; break;
        case 5: num_args_expected = 14; break;
        default:
                LOG(ERROR) << "Too many arguments, got " << param;
            LOG(ERROR) << "Don't know how to read arguments for version " << version;
            return false;
    }
    }

    // Set target_sdk_version to 0, ie the platform SDK version. This is
    // conservative and may force some classes to verify at runtime.
    target_sdk_version = 0;

    // Set the profile name to the primary apk profile.
    profile_name = "primary.prof";

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

    return true;
}

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

    // Check for "dexopt".
    if (argv[dexopt_index] == nullptr) {
@@ -310,109 +240,39 @@ bool OTAPreoptParameters::ReadArgumentsV4(int argc ATTRIBUTE_UNUSED, const char*
        return false;
    }
    if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
        LOG(ERROR) << "Expected \"dexopt\"";
        LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[dexopt_index];
        return false;
    }

    size_t param_index = 0;
    for (;; ++param_index) {
        const char* param = argv[dexopt_index + 1 + param_index];
        if (param == nullptr) {
            break;
    // Validate the number of arguments.
    size_t num_args_actual = 0;
    while (argv[dexopt_index + 1 + num_args_actual] != nullptr) {
        num_args_actual++;
    }

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

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

            case 2:
                pkgName = param;
                break;

            case 3:
                instruction_set = param;
                break;

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

            case 5:
                oat_dir = param;
                break;

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

            case 7:
                compiler_filter = param;
                break;

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

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

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

            case 11:
                downgrade = ParseBool(param);
                break;

            case 12:
                target_sdk_version = atoi(param);
                break;

            default:
                LOG(ERROR) << "Too many arguments, got " << param;
    if (num_args_actual != num_args_expected) {
        LOG(ERROR) << "Invalid number of arguments. expected="
                << num_args_expected << " actual=" << num_args_actual;
        return false;
    }
    }

    // Set the profile name to the primary apk profile.
    profile_name = "primary.prof";

    if (param_index != 13) {
        LOG(ERROR) << "Not enough parameters";
        return false;
    }
    // The number of arguments is OK.
    // Configure the default values for the parameters that were added after V1.
    // The default values will be overwritten in case they are passed as arguments.

    return true;
}
    // Set downgrade to false. It is only relevant when downgrading compiler
    // filter, which is not the case during ota.
    downgrade = false;

// TODO: this pattern does not scale and result in a lot of code duplication.
// Either find a better pattern or refactor the code to eliminate the duplication.
bool OTAPreoptParameters::ReadArgumentsV5(int argc ATTRIBUTE_UNUSED, const char** argv) {
    size_t dexopt_index = 3;
    // Set target_sdk_version to 0, ie the platform SDK version. This is
    // conservative and may force some classes to verify at runtime.
    target_sdk_version = 0;

    // 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;
    }
    // Set the profile name to the primary apk profile.
    profile_name = "primary.prof";

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

        switch (param_index) {
            case 0:
                apk_path = param;
@@ -471,131 +331,13 @@ bool OTAPreoptParameters::ReadArgumentsV5(int argc ATTRIBUTE_UNUSED, const char*
                break;

            default:
                LOG(ERROR) << "Too many arguments, got " << param;
                return false;
        }
                CHECK(false) << "Should not get here. Did you call ReadArguments "
                        << "with the right expectation?";
        }

    if (param_index != 14) {
        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 OTAPreoptParameters::ReadArgumentsV1(int argc ATTRIBUTE_UNUSED, const char** argv) {
    // Check for "dexopt".
    if (argv[2] == nullptr) {
        LOG(ERROR) << "Missing parameters";
        return false;
    }
    if (std::string("dexopt").compare(argv[2]) != 0) {
        LOG(ERROR) << "Expected \"dexopt\"";
        return false;
    }

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

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

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

            case 2:
                pkgName = param;
                break;

            case 3:
                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.
                dexopt_needed = DEX2OAT_FROM_SCRATCH;
                break;
            }

            case 5:
                oat_dir = param;
                break;

            case 6: {
                // Version 1 had:
                constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
                // Note: DEXOPT_SAFEMODE has been removed.
                // 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);
                dexopt_flags =
                        ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
                        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:
                compiler_filter = param;
                break;

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

            case 9:
                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;
    }

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

    // Set downgrade to false. It is only relevant when downgrading compiler
    // filter, which is not the case during ota.
    downgrade = false;

    // Set target_sdk_version to 0, ie the platform SDK version. This is
    // conservative and may force some classes to verify at runtime.
    target_sdk_version = 0;

    // Set the profile name to the primary apk profile.
    profile_name = "primary.prof";

    return true;
}

}  // namespace installd
}  // namespace android
+2 −5
Original line number Diff line number Diff line
@@ -28,11 +28,8 @@ class OTAPreoptParameters {
    bool ReadArguments(int argc, const char** argv);

  private:
    bool ReadArgumentsV1(int argc, const char** argv);
    bool ReadArgumentsV2(int argc, const char** argv, bool versioned);
    bool ReadArgumentsV3(int argc, const char** argv);
    bool ReadArgumentsV4(int argc, const char** argv);
    bool ReadArgumentsV5(int argc, const char** argv);
    bool ReadArgumentsV1(const char** argv);
    bool ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned);

    const char* apk_path;
    uid_t uid;