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

Commit 4eb88f88 authored by Fyodor Kupolov's avatar Fyodor Kupolov Committed by Gerrit Code Review
Browse files

Merge "Support for storing OAT files in app directory"

parents 23b204e1 88ce4ff7
Loading
Loading
Loading
Loading
+88 −18
Original line number Diff line number Diff line
@@ -988,7 +988,7 @@ static bool calculate_odex_file_path(char path[PKG_PATH_MAX],

int dexopt(const char *apk_path, uid_t uid, bool is_public,
           const char *pkgname, const char *instruction_set,
           bool vm_safe_mode, bool is_patchoat, bool debuggable)
           bool vm_safe_mode, bool is_patchoat, bool debuggable, const char* oat_dir)
{
    struct utimbuf ut;
    struct stat input_stat, dex_stat;
@@ -1003,26 +1003,23 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public,
    // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
    // without a swap file, if necessary.
    if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
        ALOGE("apk_path too long '%s'\n", apk_path);
        return -1;
    }

    /* Before anything else: is there a .odex file?  If so, we have
     * precompiled the apk and there is nothing to do here.
     *
     * We skip this if we are doing a patchoat.
     */
    strcpy(out_path, apk_path);
    end = strrchr(out_path, '.');
    if (end != NULL && !is_patchoat) {
        strcpy(end, ".odex");
        if (stat(out_path, &dex_stat) == 0) {
            return 0;
    if (oat_dir != NULL && oat_dir[0] != '!') {
        if (validate_apk_path(oat_dir)) {
            ALOGE("invalid oat_dir '%s'\n", oat_dir);
            return -1;
        }
        if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
            return -1;
        }

    } else {
        if (create_cache_path(out_path, apk_path, instruction_set)) {
            return -1;
        }
    }

    if (is_patchoat) {
        if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
@@ -1127,8 +1124,14 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public,
        if (is_patchoat) {
            run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
        } else {
            run_dex2oat(input_fd, out_fd, input_file, out_path, swap_fd, pkgname, instruction_set,
                        vm_safe_mode, debuggable);
            const char *input_file_name = strrchr(input_file, '/');
            if (input_file_name == NULL) {
                input_file_name = input_file;
            } else {
                input_file_name++;
            }
            run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
                        instruction_set, vm_safe_mode, debuggable);
        }
        exit(68);   /* only get here on exec failure */
    } else {
@@ -1701,3 +1704,70 @@ int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
    return ret;
}

int create_oat_dir(const char* oat_dir, const char* instruction_set)
{
    char oat_instr_dir[PKG_PATH_MAX];

    if (validate_apk_path(oat_dir)) {
        ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir);
        return -1;
    }
    if ((mkdir(oat_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) && (errno != EEXIST))  {
        ALOGE("cannot create dir '%s': %s\n", oat_dir, strerror(errno));
        return -1;
    }
    if (chmod(oat_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) {
        ALOGE("cannot chmod dir '%s': %s\n", oat_dir, strerror(errno));
        return -1;
    }
    if (selinux_android_restorecon(oat_dir, 0)) {
        ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno));
        return -1;
    }
    snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
    if ((mkdir(oat_instr_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0)  && (errno != EEXIST)) {
        ALOGE("cannot create dir '%s': %s\n", oat_instr_dir, strerror(errno));
        return -1;
    }
    if (chmod(oat_instr_dir, S_IRWXU|S_IRWXG|S_IXOTH) < 0) {
        ALOGE("cannot chmod dir '%s': %s\n", oat_dir, strerror(errno));
        return -1;
    }
    return 0;
}

int rm_package_dir(const char* apk_path)
{
    if (validate_apk_path(apk_path)) {
        ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path);
        return -1;
    }
    return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
}

int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
        const char *instruction_set) {
    char *file_name_start;
    char *file_name_end;

    file_name_start = strrchr(apk_path, '/');
    if (file_name_start == NULL) {
         ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
        return -1;
    }
    file_name_end = strrchr(apk_path, '.');
    if (file_name_end < file_name_start) {
        ALOGE("apk_path '%s' has no extension\n", apk_path);
        return -1;
    }

    // Calculate file_name
    int file_name_len = file_name_end - file_name_start - 1;
    char file_name[file_name_len + 1];
    memcpy(file_name, file_name_start + 1, file_name_len);
    file_name[file_name_len] = '\0';

    // <apk_parent_dir>/oat/<isa>/<file_name>.odex
    snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
    return 0;
}
+22 −8
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@


#define BUFFER_MAX    1024  /* input buffer for commands */
#define TOKEN_MAX     8     /* max number of arguments in buffer */
#define TOKEN_MAX     16    /* max number of arguments in buffer */
#define REPLY_MAX     256   /* largest reply allowed */

static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused)
@@ -38,10 +38,10 @@ static int do_install(char **arg, char reply[REPLY_MAX] __unused)

static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
{
    /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate,
       debuggable */
    /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate
       debuggable, outputPath */
    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), 0, 
                  atoi(arg[6]));
                  atoi(arg[6]), arg[7]);
}

static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
@@ -154,8 +154,20 @@ static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((u

static int do_patchoat(char **arg, char reply[REPLY_MAX] __unused) {
    /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate,
       debuggable */
    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0, 1, 0);
       debuggable, outputPath */
    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0, 1, 0, "!");
}

static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] __unused)
{
    /* oat_dir, instruction_set */
    return create_oat_dir(arg[0], arg[1]);
}

static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] __unused)
{
    /* oat_dir */
    return rm_package_dir(arg[0]);
}

struct cmdinfo {
@@ -167,7 +179,7 @@ struct cmdinfo {
struct cmdinfo cmds[] = {
    { "ping",                 0, do_ping },
    { "install",              4, do_install },
    { "dexopt",               7, do_dexopt },
    { "dexopt",               8, do_dexopt },
    { "markbootcomplete",     1, do_mark_boot_complete },
    { "movedex",              3, do_move_dex },
    { "rmdex",                2, do_rm_dex },
@@ -187,6 +199,8 @@ struct cmdinfo cmds[] = {
    { "idmap",                3, do_idmap },
    { "restorecondata",       3, do_restorecon_data },
    { "patchoat",             5, do_patchoat },
    { "createoatdir",         2, do_create_oat_dir },
    { "rmpackagedir",         1, do_rm_package_dir},
};

static int readx(int s, void *_buf, int count)
+6 −1
Original line number Diff line number Diff line
@@ -220,9 +220,14 @@ int get_size(const char *pkgname, userid_t userid, const char *apkpath, const ch
             int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
int free_cache(int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
           const char *instruction_set, bool vm_safe_mode, bool should_relocate, bool debuggable);
           const char *instruction_set, bool vm_safe_mode, bool should_relocate, bool debuggable, 
           const char* outputPath);
int mark_boot_complete(const char *instruction_set);
int movefiles();
int linklib(const char* target, const char* source, int userId);
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
int restorecon_data();
int create_oat_dir(const char* oat_dir, const char *instruction_set);
int rm_package_dir(const char* apk_path);
int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
                            const char *instruction_set);
 No newline at end of file