diff options
author | Richard Uhler <ruhler@google.com> | 2015-03-18 12:39:09 -0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-04-23 16:07:09 -0700 |
commit | f22a457adc407a64abf1bfcf9846aaa6136479d9 (patch) | |
tree | 21912fc3637b162da28502da651dec6d59404679 | |
parent | eb229905b6d45dadfd2ab1891990e71c3b8cea55 (diff) | |
download | android_frameworks_native-stable/cm-12.1-YOG3C.tar.gz android_frameworks_native-stable/cm-12.1-YOG3C.tar.bz2 android_frameworks_native-stable/cm-12.1-YOG3C.zip |
installd: Add gzipped odex supportstable/cm-12.1-YOG3C
Instead of all dex2oat commands with source that has a precompiled
compressed odex file the installd executes the patchoat command that
patches that precompiled file.
The installd needs the patchoat to support 2 additional options:
--input-oat-gz-fd and --swap-fd. Patchoat decompresses the input.
Change-Id: Ifa61af39c5644529699c17d6c19ef03742989afd
Depends-Change-Id: I54dbfcdc58bc0f57f7eccc3929c09295c597794b
Signed-off-by: Julien Delayen <julien.delayen@intel.com>
Signed-off-by: Yevgeny Rouban <yevgeny.y.rouban@intel.com>
-rw-r--r-- | cmds/installd/commands.c | 99 |
1 files changed, 73 insertions, 26 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index eafeb4be2..75de88083 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -648,7 +648,8 @@ static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name, } static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, - const char* output_file_name, const char *pkgname, const char *instruction_set) + const char* output_file_name, const char *pkgname __unused, const char *instruction_set, + int is_gz, int swap_fd) { static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; @@ -661,27 +662,37 @@ static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, } /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/ + const char* input_option = is_gz ? "--input-oat-gz-fd=" : "--input-oat-fd="; char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN]; - char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN]; + char input_oat_fd_arg[strlen(input_option) + MAX_INT_LEN]; const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art"; + char swap_fd_str[strlen("--swap-fd=") + MAX_INT_LEN]; + // The caller has already gotten all the locks we need. const char* no_lock_arg = "--no-lock-output"; sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd); - sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd); - ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n", - PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name); + sprintf(input_oat_fd_arg, "%s%d", input_option, input_fd); + + if (swap_fd >= 0) { + sprintf(swap_fd_str, "--swap-fd=%d", swap_fd); + } /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */ - char* argv[7]; + char* argv[8]; argv[0] = (char*) PATCHOAT_BIN; argv[1] = (char*) patched_image_location_arg; argv[2] = (char*) no_lock_arg; argv[3] = instruction_set_arg; argv[4] = output_oat_fd_arg; argv[5] = input_oat_fd_arg; - argv[6] = NULL; + argv[6] = swap_fd != -1 ? swap_fd_str : NULL; + argv[7] = NULL; + + ALOGE("Patching from '%s' to '%s': %s %s %s %s %s %s %s", + input_file_name, output_file_name, argv[0], argv[1], argv[2], argv[3], + argv[4], argv[5], argv[6] == NULL ? "" : argv[6]); execv(PATCHOAT_BIN, (char* const *)argv); ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); @@ -888,6 +899,41 @@ static bool ShouldUseSwapFileForDexopt() { return (strcmp(low_mem_buf, "true") == 0); } +/* + * Computes the odex file for the given apk_path and instruction_set. + * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex + * + * Returns false if it failed to determine the odex file path. + */ +static bool calculate_odex_file_path(char path[PKG_PATH_MAX], + const char *apk_path, + const char *instruction_set) +{ + if (strlen(apk_path) + + strlen(instruction_set) + + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { + ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); + return false; + } + + strcpy(path, apk_path); + char *end = strrchr(path, '/'); + if (end == NULL) { + ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); + return false; + } + const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); + + strcpy(end + 1, instruction_set); // path = /system/framework/\0 + strcat(path, apk_end); // path = /system/framework/<isa>/whatever.jar\0 + end = strrchr(path, '.'); + if (end == NULL) { + ALOGE("apk_path '%s' has no extension.\n", apk_path); + return false; + } + strcpy(end + 1, "odex"); + return true; +} + 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) @@ -900,7 +946,9 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, char *end; const char *input_file; char in_odex_path[PKG_PATH_MAX]; - int res, input_fd=-1, out_fd=-1, swap_fd=-1; + char gz_file[PKG_PATH_MAX]; + char tmp_path[PKG_PATH_MAX]; + int res, input_fd=-1, out_fd=-1, swap_fd=-1, is_gz=0; // Early best-effort check whether we can fit the the path into our buffers. // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run @@ -936,31 +984,29 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, return -1; } + if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { + return -1; + } + if (is_patchoat) { - /* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */ - strcpy(in_odex_path, apk_path); - end = strrchr(in_odex_path, '/'); - if (end == NULL) { - ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); - return -1; - } - const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/'); - strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0 - strcat(in_odex_path, apk_end); - end = strrchr(in_odex_path, '.'); - if (end == NULL) { - return -1; - } - strcpy(end + 1, "odex"); input_file = in_odex_path; } else { - input_file = apk_path; + strcpy(gz_file, in_odex_path); + strcat(gz_file, ".gz"); + if (!access(gz_file, F_OK)) { + is_patchoat = 1; + is_gz = 1; + input_file = gz_file; + } else { + input_file = apk_path; + } } memset(&input_stat, 0, sizeof(input_stat)); stat(input_file, &input_stat); input_fd = open(input_file, O_RDONLY, 0); + if (input_fd < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", input_file); return -1; @@ -989,7 +1035,7 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, } // Create a swap file if necessary. - if (!is_patchoat && ShouldUseSwapFileForDexopt()) { + if (is_gz || (!is_patchoat && ShouldUseSwapFileForDexopt())) { // Make sure there really is enough space. size_t out_len = strlen(out_path); if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) { @@ -1052,7 +1098,8 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, run_dexopt(input_fd, out_fd, input_file, out_path); } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) { if (is_patchoat) { - run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); + run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, + instruction_set, is_gz, swap_fd); } else { run_dex2oat(input_fd, out_fd, input_file, out_path, swap_fd, pkgname, instruction_set, vm_safe_mode); |