diff options
author | Clark Scheff <clark@cyngn.com> | 2014-11-25 12:04:16 -0800 |
---|---|---|
committer | Clark Scheff <clark@cyngn.com> | 2015-01-15 11:44:34 -0800 |
commit | a1a4f7a3e4a0e4d737671818600a5d77a28203ae (patch) | |
tree | f4fbc9660138682664ee1c0d330aa661b9b69d20 | |
parent | 1816143805334acb6f7b15da36eb13ba308b68ef (diff) | |
download | android_frameworks_native-a1a4f7a3e4a0e4d737671818600a5d77a28203ae.tar.gz android_frameworks_native-a1a4f7a3e4a0e4d737671818600a5d77a28203ae.tar.bz2 android_frameworks_native-a1a4f7a3e4a0e4d737671818600a5d77a28203ae.zip |
Themes: Port to CM12 [2/6]
Themes: Forward port installd
Id: I5c03bdca30d55f252d486ddac0355f41623ba8d5
Themes: Remove legacy theme support
Id: I6823a6f2735f07f8e4a25a9c0f6f297577a554ab
Access Themed ResTables from compiled theme apk [2/2]
Before this patch the ResTable for a theme/app was created and
accessed seperate from the compiled APK. Since the compiled APK
has its own copy of the resources.arsc, we can just reuse the table
in the APK instead
Id: Ib7916eba5663db5d077d33fc02623748e8a9f10c
Send target sdk version to aapt [2/2]
If vector drawables are used in a theme we must have a minSdkVersion of 21 passed
to aapt or else aapt will Segfault.
Id: Ib5ffa6d12c91d465f3a603e03b09ab03b02715c7
Change-Id: Ie14322b7efb40b270abd3d4ca1b7c5f97bf4b5ca
-rw-r--r-- | cmds/installd/commands.c | 208 | ||||
-rw-r--r-- | cmds/installd/installd.c | 16 | ||||
-rw-r--r-- | cmds/installd/installd.h | 6 |
3 files changed, 208 insertions, 22 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index fc3972e68..45a410fd3 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -1363,43 +1363,58 @@ out: return rc; } -static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) +static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd, + uint32_t target_hash, uint32_t overlay_hash) { static const char *IDMAP_BIN = "/system/bin/idmap"; static const size_t MAX_INT_LEN = 32; char idmap_str[MAX_INT_LEN]; + char target_hash_str[MAX_INT_LEN]; + char overlay_hash_str[MAX_INT_LEN]; snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); + snprintf(target_hash_str, sizeof(target_hash_str), "%d", target_hash); + snprintf(overlay_hash_str, sizeof(overlay_hash_str), "%d", overlay_hash); - execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); + execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, + target_hash_str, overlay_hash_str, (char*)NULL); ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); } -// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) -// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap +/* Prints to idmap_path (prefix)/(flat_target)@(flat_overerlay)@(suffix) + * Note: "Flat" is a string with '/' changed to @ + * Example input: + * prefix: /data/resource-cache/ + * suffix: idmap + * overlay_path: /data/app/com.theme.apk + * target_path: /data/app/com.target.apk + * Example output: + * idmap_path: /data/resource-cache/data@app@com.target.apk@data@app@theme.apk@idmap + */ static int flatten_path(const char *prefix, const char *suffix, - const char *overlay_path, char *idmap_path, size_t N) + const char *overlay_path, const char *target_path, char *idmap_path, size_t N) { - if (overlay_path == NULL || idmap_path == NULL) { + if (overlay_path == NULL || idmap_path == NULL || target_path == NULL) { return -1; } + + const size_t len_target_path = strlen(target_path); + if (len_target_path < 2 || *target_path != '/') { + return -1; + } + const size_t len_overlay_path = strlen(overlay_path); // will access overlay_path + 1 further below; requires absolute path if (len_overlay_path < 2 || *overlay_path != '/') { return -1; } const size_t len_idmap_root = strlen(prefix); - const size_t len_suffix = strlen(suffix); - if (SIZE_MAX - len_idmap_root < len_overlay_path || - SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { - // additions below would cause overflow - return -1; - } - if (N < len_idmap_root + len_overlay_path + len_suffix) { - return -1; - } + memset(idmap_path, 0, N); - snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); + int len = snprintf(idmap_path, N, "%s%s%s%s", prefix, target_path + 1, overlay_path, suffix); + if (len < 0 || (size_t)len >= N) { + return -1; // error or truncated + } char *ch = idmap_path + len_idmap_root; while (*ch != '\0') { if (*ch == '/') { @@ -1410,14 +1425,15 @@ static int flatten_path(const char *prefix, const char *suffix, return 0; } -int idmap(const char *target_apk, const char *overlay_apk, uid_t uid) +int idmap(const char *target_apk, const char *overlay_apk, uid_t uid, + uint32_t target_hash, uint32_t overlay_hash) { ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); int idmap_fd = -1; char idmap_path[PATH_MAX]; - if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, + if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, target_apk, idmap_path, sizeof(idmap_path)) == -1) { ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); goto fail; @@ -1455,7 +1471,7 @@ int idmap(const char *target_apk, const char *overlay_apk, uid_t uid) exit(1); } - run_idmap(target_apk, overlay_apk, idmap_fd); + run_idmap(target_apk, overlay_apk, idmap_fd, target_hash, overlay_hash); exit(1); /* only if exec call to idmap failed */ } else { int status = wait_child(pid); @@ -1475,6 +1491,160 @@ fail: return -1; } +static void run_aapt(const char *source_apk, const char *internal_path, + int resapk_fd, int pkgId, int min_sdk_version, const char *common_res_path) +{ + static const char *AAPT_BIN = "/system/bin/aapt"; + static const char *MANIFEST = "/data/app/AndroidManifest.xml"; + static const char *FRAMEWORK_RES = "/system/framework/framework-res.apk"; + + static const size_t MAX_INT_LEN = 32; + char restable_str[MAX_INT_LEN]; + char resapk_str[MAX_INT_LEN]; + char pkgId_str[MAX_INT_LEN]; + char minSdkVersion_str[MAX_INT_LEN]; + + snprintf(resapk_str, sizeof(resapk_str), "%d", resapk_fd); + snprintf(pkgId_str, sizeof(pkgId_str), "%d", pkgId); + snprintf(minSdkVersion_str, sizeof(minSdkVersion_str), "%d", min_sdk_version); + bool hasCommonResources = (common_res_path != NULL && common_res_path[0] != '\0'); + + if (hasCommonResources) { + execl(AAPT_BIN, AAPT_BIN, "package", + "--min-sdk-version", minSdkVersion_str, + "-M", MANIFEST, + "-S", source_apk, + "-X", internal_path, + "-I", FRAMEWORK_RES, + "-I", common_res_path, + "-r", resapk_str, + "-x", pkgId_str, + (char*)NULL); + } else { + execl(AAPT_BIN, AAPT_BIN, "package", + "--min-sdk-version", minSdkVersion_str, + "-M", MANIFEST, + "-S", source_apk, + "-X", internal_path, + "-I", FRAMEWORK_RES, + "-r", resapk_str, + "-x", pkgId_str, + (char*)NULL); + } + ALOGE("execl(%s) failed: %s\n", AAPT_BIN, strerror(errno)); +} + +int aapt(const char *source_apk, const char *internal_path, const char *out_restable, uid_t uid, + int pkgId, int min_sdk_version, const char *common_res_path) +{ + ALOGD("aapt source_apk=%s internal_path=%s out_restable=%s uid=%d, pkgId=%d, min_sdk_version=%d, common_res_path=%s", + source_apk, internal_path, out_restable, uid, pkgId, min_sdk_version, common_res_path); + static const int PARENT_READ_PIPE = 0; + static const int CHILD_WRITE_PIPE = 1; + + int resapk_fd = -1; + char restable_path[PATH_MAX]; + char resapk_path[PATH_MAX]; + + // get file descriptor for resources.arsc + snprintf(restable_path, PATH_MAX, "%s/resources.arsc", out_restable); + unlink(restable_path); + + // get file descriptor for resources.apk + snprintf(resapk_path, PATH_MAX, "%s/resources.apk", out_restable); + unlink(resapk_path); + resapk_fd = open(resapk_path, O_RDWR | O_CREAT | O_EXCL, 0644); + if (resapk_fd < 0) { + ALOGE("aapt cannot open '%s' for output: %s\n", resapk_path, strerror(errno)); + goto fail; + } + if (fchown(resapk_fd, AID_SYSTEM, uid) < 0) { + ALOGE("aapt cannot chown '%s'\n", resapk_path); + goto fail; + } + if (fchmod(resapk_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { + ALOGE("aapt cannot chmod '%s'\n", resapk_path); + goto fail; + } + + int pipefd[2]; + if (pipe(pipefd) != 0) { + pipefd[0] = pipefd[1] = -1; + } + pid_t pid = fork(); + if (pid == 0) { + /* child -- drop privileges before continuing */ + if (setgid(uid) != 0) { + ALOGE("setgid(%d) failed during aapt\n", uid); + exit(1); + } + if (setuid(uid) != 0) { + ALOGE("setuid(%d) failed during aapt\n", uid); + exit(1); + } + + if (flock(resapk_fd, LOCK_EX | LOCK_NB) != 0) { + ALOGE("flock(%s) failed during aapt: %s\n", out_restable, strerror(errno)); + exit(1); + } + + if (pipefd[PARENT_READ_PIPE] > 0 && pipefd[CHILD_WRITE_PIPE] > 0) { + close(pipefd[PARENT_READ_PIPE]); // close unused read end + if (dup2(pipefd[CHILD_WRITE_PIPE], STDERR_FILENO) != STDERR_FILENO) { + pipefd[CHILD_WRITE_PIPE] = -1; + } + } + + run_aapt(source_apk, internal_path, resapk_fd, pkgId, min_sdk_version, common_res_path); + + if (pipefd[CHILD_WRITE_PIPE] > 0) { + close(pipefd[CHILD_WRITE_PIPE]); + } + exit(1); /* only if exec call to idmap failed */ + } else { + int status, i; + char buffer[1024]; + ssize_t readlen; + + if (pipefd[CHILD_WRITE_PIPE] > 0) { + close(pipefd[CHILD_WRITE_PIPE]); // close unused write end + } + + if (pipefd[PARENT_READ_PIPE] > 0) { + while ((readlen = read(pipefd[PARENT_READ_PIPE], buffer, sizeof(buffer) - 1)) > 0) { + // in case buffer has more than one string in it, replace '\0' with '\n' + for (i = 0; i < readlen; i++) { + if (buffer[i] == '\0') buffer[i] = '\n'; + } + // null terminate buffer at readlen + buffer[readlen] = '\0'; + ALOG(LOG_ERROR, "InstallTheme", "%s", buffer); + } + waitpid(pid, &status, 0); + + if (pipefd[PARENT_READ_PIPE] > 0) { + close(pipefd[PARENT_READ_PIPE]); + } + } else { + status = wait_child(pid); + } + + if (status != 0) { + ALOGE("aapt failed, status=0x%04x\n", status); + goto fail; + } + } + + close(resapk_fd); + return 0; +fail: + if (resapk_fd >= 0) { + close(resapk_fd); + unlink(resapk_path); + } + return -1; +} + int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) { struct dirent *entry; diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 933338f90..db142a24b 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -136,7 +136,17 @@ static int do_linklib(char **arg, char reply[REPLY_MAX]) static int do_idmap(char **arg, char reply[REPLY_MAX]) { - return idmap(arg[0], arg[1], atoi(arg[2])); + return idmap(arg[0], arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4])); +} + +static int do_aapt(char **arg, char reply[REPLY_MAX]) +{ + return aapt(arg[0], arg[1], arg[2], atoi(arg[3]), atoi(arg[4]), atoi(arg[5]), ""); +} + +static int do_aapt_with_common(char **arg, char reply[REPLY_MAX]) +{ + return aapt(arg[0], arg[1], arg[2], atoi(arg[3]), atoi(arg[4]), atoi(arg[5]), arg[6]); } static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused))) @@ -175,9 +185,11 @@ struct cmdinfo cmds[] = { { "mkuserdata", 4, do_mk_user_data }, { "mkuserconfig", 1, do_mk_user_config }, { "rmuser", 1, do_rm_user }, - { "idmap", 3, do_idmap }, { "restorecondata", 3, do_restorecon_data }, { "patchoat", 5, do_patchoat }, + { "idmap", 5, do_idmap }, + { "aapt", 6, do_aapt }, + { "aapt_with_common", 7, do_aapt_with_common }, }; static int readx(int s, void *_buf, int count) diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 36c3e8c3f..f8be27ae0 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -223,5 +223,9 @@ 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); 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 idmap(const char *target_path, const char *overlay_path, uid_t uid, + uint32_t target_hash, uint32_t overlay_hash); +int aapt(const char *source_apk, const char *internal_path, const char *out_restable, uid_t uid, + int pkgId, int min_sdk_version, const char *common_res_path); + |