summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Uhler <ruhler@google.com>2015-03-18 12:39:09 -0700
committerSteve Kondik <steve@cyngn.com>2015-04-23 16:07:09 -0700
commitf22a457adc407a64abf1bfcf9846aaa6136479d9 (patch)
tree21912fc3637b162da28502da651dec6d59404679
parenteb229905b6d45dadfd2ab1891990e71c3b8cea55 (diff)
downloadandroid_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.c99
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);