diff options
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/atrace/atrace.cpp | 5 | ||||
-rw-r--r-- | cmds/bugreport/bugreport.cpp | 2 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.c | 192 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 17 | ||||
-rw-r--r-- | cmds/dumpstate/utils.c | 87 | ||||
-rw-r--r-- | cmds/installd/commands.cpp | 307 | ||||
-rw-r--r-- | cmds/installd/installd.cpp | 17 | ||||
-rw-r--r-- | cmds/installd/installd.h | 26 | ||||
-rw-r--r-- | cmds/installd/tests/installd_utils_test.cpp | 24 | ||||
-rw-r--r-- | cmds/installd/utils.cpp | 54 | ||||
-rw-r--r-- | cmds/service/service.cpp | 34 | ||||
-rw-r--r-- | cmds/servicemanager/service_manager.c | 1 |
12 files changed, 605 insertions, 161 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 515d761..9def406 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -137,6 +137,9 @@ static const TracingCategory k_categories[] = { { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable" }, { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable" }, } }, + { "regulators", "Voltage and Current Regulators", 0, { + { REQ, "/sys/kernel/debug/tracing/events/regulator/enable" }, + } }, }; /* Command line options */ @@ -897,7 +900,7 @@ int main(int argc, char **argv) g_traceOverwrite = true; } else if (!strcmp(long_options[option_index].name, "async_stop")) { async = true; - traceStop = false; + traceStart = false; } else if (!strcmp(long_options[option_index].name, "async_dump")) { async = true; traceStart = false; diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp index b606406..6892b57 100644 --- a/cmds/bugreport/bugreport.cpp +++ b/cmds/bugreport/bugreport.cpp @@ -86,6 +86,6 @@ int main() { } while (bytes_written != 0 && bytes_to_send > 0); } - TEMP_FAILURE_RETRY(close(s)); + close(s); return 0; } diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index a33dcf3..ef8db06 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -18,6 +18,7 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -99,8 +100,170 @@ static void dump_dev_files(const char *title, const char *driverpath, const char closedir(d); } +static bool skip_not_stat(const char *path) { + static const char stat[] = "/stat"; + size_t len = strlen(path); + if (path[len - 1] == '/') { /* Directory? */ + return false; + } + return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ +} + +static const char mmcblk0[] = "/sys/block/mmcblk0/"; +unsigned long worst_write_perf = 20000; /* in KB/s */ + +static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) { + unsigned long fields[11], read_perf, write_perf; + bool z; + char *cp, *buffer = NULL; + size_t i = 0; + FILE *fp = fdopen(fd, "rb"); + getline(&buffer, &i, fp); + fclose(fp); + if (!buffer) { + return -errno; + } + i = strlen(buffer); + while ((i > 0) && (buffer[i - 1] == '\n')) { + buffer[--i] = '\0'; + } + if (!*buffer) { + free(buffer); + return 0; + } + z = true; + for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) { + fields[i] = strtol(cp, &cp, 0); + if (fields[i] != 0) { + z = false; + } + } + if (z) { /* never accessed */ + free(buffer); + return 0; + } + + if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) { + path += sizeof(mmcblk0) - 1; + } + + printf("%s: %s\n", path, buffer); + free(buffer); + + read_perf = 0; + if (fields[3]) { + read_perf = 512 * fields[2] / fields[3]; + } + write_perf = 0; + if (fields[7]) { + write_perf = 512 * fields[6] / fields[7]; + } + printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf); + if ((write_perf > 1) && (write_perf < worst_write_perf)) { + worst_write_perf = write_perf; + } + return 0; +} + +/* Copied policy from system/core/logd/LogBuffer.cpp */ + +#define LOG_BUFFER_SIZE (256 * 1024) +#define LOG_BUFFER_MIN_SIZE (64 * 1024UL) +#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL) + +static bool valid_size(unsigned long value) { + if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) { + return false; + } + + long pages = sysconf(_SC_PHYS_PAGES); + if (pages < 1) { + return true; + } + + long pagesize = sysconf(_SC_PAGESIZE); + if (pagesize <= 1) { + pagesize = PAGE_SIZE; + } + + // maximum memory impact a somewhat arbitrary ~3% + pages = (pages + 31) / 32; + unsigned long maximum = pages * pagesize; + + if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) { + return true; + } + + return value <= maximum; +} + +static unsigned long property_get_size(const char *key) { + unsigned long value; + char *cp, property[PROPERTY_VALUE_MAX]; + + property_get(key, property, ""); + value = strtoul(property, &cp, 10); + + switch(*cp) { + case 'm': + case 'M': + value *= 1024; + /* FALLTHRU */ + case 'k': + case 'K': + value *= 1024; + /* FALLTHRU */ + case '\0': + break; + + default: + value = 0; + } + + if (!valid_size(value)) { + value = 0; + } + + return value; +} + +/* timeout in ms */ +static unsigned long logcat_timeout(char *name) { + static const char global_tuneable[] = "persist.logd.size"; // Settings App + static const char global_default[] = "ro.logd.size"; // BoardConfig.mk + char key[PROP_NAME_MAX]; + unsigned long property_size, default_size; + + default_size = property_get_size(global_tuneable); + if (!default_size) { + default_size = property_get_size(global_default); + } + + snprintf(key, sizeof(key), "%s.%s", global_tuneable, name); + property_size = property_get_size(key); + + if (!property_size) { + snprintf(key, sizeof(key), "%s.%s", global_default, name); + property_size = property_get_size(key); + } + + if (!property_size) { + property_size = default_size; + } + + if (!property_size) { + property_size = LOG_BUFFER_SIZE; + } + + /* Engineering margin is ten-fold our guess */ + return 10 * (property_size + worst_write_perf) / worst_write_perf; +} + +/* End copy from system/core/logd/LogBuffer.cpp */ + /* dumps the current system state to stdout */ static void dumpstate() { + unsigned long timeout; time_t now = time(NULL); char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX]; char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX]; @@ -133,7 +296,7 @@ static void dumpstate() { dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version"); run_command("UPTIME", 10, "uptime", NULL); - dump_file("MMC PERF", "/sys/block/mmcblk0/stat"); + dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd); dump_file("MEMORY INFO", "/proc/meminfo"); run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL); run_command("PROCRANK", 20, "procrank", NULL); @@ -149,7 +312,6 @@ static void dumpstate() { dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources"); dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); dump_file("KERNEL SYNC", "/d/sync"); - dump_file("KERNEL BLUEDROID", "/d/bluedroid"); run_command("PROCESSES", 10, "ps", "-P", NULL); run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL); @@ -169,9 +331,24 @@ static void dumpstate() { } // dump_file("EVENT LOG TAGS", "/etc/event-log-tags"); - run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL); - run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL); - run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL); + // calculate timeout + timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash"); + if (timeout < 20000) { + timeout = 20000; + } + run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL); + timeout = logcat_timeout("events"); + if (timeout < 20000) { + timeout = 20000; + } + run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL); + timeout = logcat_timeout("radio"); + if (timeout < 20000) { + timeout = 20000; + } + run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL); + + run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL); /* show the traces we collected in main(), if that was done */ if (dump_traces_path != NULL) { @@ -242,8 +419,6 @@ static void dumpstate() { run_command("LAST LOGCAT", 10, "logcat", "-L", "-v", "threadtime", "-b", "all", "-d", "*:v", NULL); - for_each_userid(do_dump_settings, NULL); - /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */ run_command("NETWORK INTERFACES", 10, "ip", "link", NULL); @@ -259,6 +434,8 @@ static void dumpstate() { run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL); run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL); + run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL); + run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL); run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL); run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL); @@ -362,6 +539,7 @@ static void dumpstate() { run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL); run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL); run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL); + run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL); printf("========================================================\n"); printf("== Running Application Activities\n"); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index d17a677..c5d3044 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -26,7 +26,6 @@ typedef void (for_each_pid_func)(int, const char *); typedef void (for_each_tid_func)(int, int, const char *); -typedef void (for_each_userid_func)(int); /* prints the contents of a file */ int dump_file(const char *title, const char *path); @@ -36,6 +35,16 @@ int dump_file(const char *title, const char *path); */ int dump_file_from_fd(const char *title, const char *path, int fd); +/* calls skip to gate calling dump_from_fd recursively + * in the specified directory. dump_from_fd defaults to + * dump_file_from_fd above when set to NULL. skip defaults + * to false when set to NULL. dump_from_fd will always be + * called with title NULL. + */ +int dump_files(const char *title, const char *dir, + bool (*skip)(const char *path), + int (*dump_from_fd)(const char *title, const char *path, int fd)); + /* forks a command and waits for it to finish -- terminate args with NULL */ int run_command(const char *title, int timeout_seconds, const char *command, ...); @@ -57,9 +66,6 @@ void for_each_pid(for_each_pid_func func, const char *header); /* for each thread in the system, run the specified function */ void for_each_tid(for_each_tid_func func, const char *header); -/* for each user id in the system, run the specified function */ -void for_each_userid(for_each_userid_func func, const char *header); - /* Displays a blocked processes in-kernel wait channel */ void show_wchan(int pid, int tid, const char *name); @@ -69,9 +75,6 @@ void do_showmap(int pid, const char *name); /* Gets the dmesg output for the kernel */ void do_dmesg(); -/* Dumps settings for a given user id */ -void do_dump_settings(int userid); - /* Prints the contents of all the routing tables, both IPv4 and IPv6. */ void dump_route_tables(); diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index cf14c8b..d679787 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -206,22 +206,6 @@ out_close: return; } -void do_dump_settings(int userid) { - char title[255]; - char dbpath[255]; - char sql[255]; - sprintf(title, "SYSTEM SETTINGS (user %d)", userid); - if (userid == 0) { - strcpy(dbpath, "/data/data/com.android.providers.settings/databases/settings.db"); - strcpy(sql, "pragma user_version; select * from system; select * from secure; select * from global;"); - } else { - sprintf(dbpath, "/data/system/users/%d/settings.db", userid); - strcpy(sql, "pragma user_version; select * from system; select * from secure;"); - } - run_command(title, 20, SU_PATH, "root", "sqlite3", dbpath, sql, NULL); - return; -} - void do_dmesg() { printf("------ KERNEL LOG (dmesg) ------\n"); /* Get size of kernel buffer */ @@ -306,7 +290,7 @@ static int _dump_file_from_fd(const char *title, const char *path, int fd) { } } } - TEMP_FAILURE_RETRY(close(fd)); + close(fd); if (!newline) printf("\n"); if (title) printf("\n"); @@ -326,6 +310,75 @@ int dump_file(const char *title, const char *path) { return _dump_file_from_fd(title, path, fd); } +/* calls skip to gate calling dump_from_fd recursively + * in the specified directory. dump_from_fd defaults to + * dump_file_from_fd above when set to NULL. skip defaults + * to false when set to NULL. dump_from_fd will always be + * called with title NULL. + */ +int dump_files(const char *title, const char *dir, + bool (*skip)(const char *path), + int (*dump_from_fd)(const char *title, const char *path, int fd)) { + DIR *dirp; + struct dirent *d; + char *newpath = NULL; + char *slash = "/"; + int fd, retval = 0; + + if (title) { + printf("------ %s (%s) ------\n", title, dir); + } + + if (dir[strlen(dir) - 1] == '/') { + ++slash; + } + dirp = opendir(dir); + if (dirp == NULL) { + retval = -errno; + fprintf(stderr, "%s: %s\n", dir, strerror(errno)); + return retval; + } + + if (!dump_from_fd) { + dump_from_fd = dump_file_from_fd; + } + for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) { + if ((d->d_name[0] == '.') + && (((d->d_name[1] == '.') && (d->d_name[2] == '\0')) + || (d->d_name[1] == '\0'))) { + continue; + } + asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name, + (d->d_type == DT_DIR) ? "/" : ""); + if (!newpath) { + retval = -errno; + continue; + } + if (skip && (*skip)(newpath)) { + continue; + } + if (d->d_type == DT_DIR) { + int ret = dump_files(NULL, newpath, skip, dump_from_fd); + if (ret < 0) { + retval = ret; + } + continue; + } + fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)); + if (fd < 0) { + retval = fd; + printf("*** %s: %s\n", newpath, strerror(errno)); + continue; + } + (*dump_from_fd)(NULL, newpath, fd); + } + closedir(dirp); + if (title) { + printf("\n"); + } + return retval; +} + /* fd must have been opened with the flag O_NONBLOCK. With this flag set, * it's possible to avoid issues where opening the file itself can get * stuck. diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp index de6fd96..7090b36 100644 --- a/cmds/installd/commands.cpp +++ b/cmds/installd/commands.cpp @@ -50,7 +50,7 @@ int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const c return -1; } - std::string _pkgdir(create_package_data_path(uuid, pkgname, 0)); + std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname)); const char* pkgdir = _pkgdir.c_str(); if (mkdir(pkgdir, 0751) < 0) { @@ -80,7 +80,7 @@ int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const c int uninstall(const char *uuid, const char *pkgname, userid_t userid) { - std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); const char* pkgdir = _pkgdir.c_str(); remove_profile_file(pkgname); @@ -115,7 +115,7 @@ int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid) return -1; } - std::string _pkgdir(create_package_data_path(uuid, pkgname, 0)); + std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname)); const char* pkgdir = _pkgdir.c_str(); if (stat(pkgdir, &s) < 0) return -1; @@ -141,7 +141,7 @@ int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid) int delete_user_data(const char *uuid, const char *pkgname, userid_t userid) { - std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); const char* pkgdir = _pkgdir.c_str(); return delete_dir_contents(pkgdir, 0, NULL); @@ -149,7 +149,7 @@ int delete_user_data(const char *uuid, const char *pkgname, userid_t userid) int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) { - std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); const char* pkgdir = _pkgdir.c_str(); if (mkdir(pkgdir, 0751) < 0) { @@ -177,15 +177,48 @@ int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t us return 0; } -int move_user_data(const char *from_uuid, const char *to_uuid, - const char *package_name, appid_t appid, const char* seinfo) { +int copy_complete_app(const char *from_uuid, const char *to_uuid, + const char *package_name, const char *data_app_name, appid_t appid, + const char* seinfo) { std::vector<userid_t> users = get_known_users(from_uuid); - // Copy package private data for all known users + // Copy app + { + std::string from(create_data_app_package_path(from_uuid, data_app_name)); + std::string to(create_data_app_package_path(to_uuid, data_app_name)); + std::string to_parent(create_data_app_path(to_uuid)); + + char *argv[] = { + (char*) kCpPath, + (char*) "-F", /* delete any existing destination file first (--remove-destination) */ + (char*) "-p", /* preserve timestamps, ownership, and permissions */ + (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ + (char*) "-P", /* Do not follow symlinks [default] */ + (char*) "-d", /* don't dereference symlinks */ + (char*) from.c_str(), + (char*) to_parent.c_str() + }; + + LOG(DEBUG) << "Copying " << from << " to " << to; + int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); + + if (rc != 0) { + LOG(ERROR) << "Failed copying " << from << " to " << to + << ": status " << rc; + goto fail; + } + + if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) { + LOG(ERROR) << "Failed to restorecon " << to; + goto fail; + } + } + + // Copy private data for all known users for (auto user : users) { - std::string from(create_package_data_path(from_uuid, package_name, user)); - std::string to(create_package_data_path(to_uuid, package_name, user)); - std::string to_user(create_data_user_path(to_uuid, user)); + std::string from(create_data_user_package_path(from_uuid, user, package_name)); + std::string to(create_data_user_package_path(to_uuid, user, package_name)); + std::string to_parent(create_data_user_path(to_uuid, user)); // Data source may not exist for all users; that's okay if (access(from.c_str(), F_OK) != 0) { @@ -213,7 +246,7 @@ int move_user_data(const char *from_uuid, const char *to_uuid, (char*) "-P", /* Do not follow symlinks [default] */ (char*) "-d", /* don't dereference symlinks */ (char*) from.c_str(), - (char*) to_user.c_str() + (char*) to_parent.c_str() }; LOG(DEBUG) << "Copying " << from << " to " << to; @@ -224,26 +257,28 @@ int move_user_data(const char *from_uuid, const char *to_uuid, << ": status " << rc; goto fail; } - - if (restorecon_data(to_uuid, package_name, seinfo, uid) != 0) { - LOG(ERROR) << "Failed to restorecon " << to; - goto fail; - } } - // Copy successful, so delete old data - for (auto user : users) { - std::string from(create_package_data_path(from_uuid, package_name, user)); - if (delete_dir_contents(from.c_str(), 1, NULL) != 0) { - LOG(WARNING) << "Failed to delete " << from; - } + if (restorecon_data(to_uuid, package_name, seinfo, multiuser_get_uid(0, appid)) != 0) { + LOG(ERROR) << "Failed to restorecon"; + goto fail; } + + // We let the framework scan the new location and persist that before + // deleting the data in the old location; this ordering ensures that + // we can recover from things like battery pulls. return 0; fail: // Nuke everything we might have already copied + { + std::string to(create_data_app_package_path(to_uuid, data_app_name)); + if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { + LOG(WARNING) << "Failed to rollback " << to; + } + } for (auto user : users) { - std::string to(create_package_data_path(to_uuid, package_name, user)); + std::string to(create_data_user_package_path(to_uuid, user, package_name)); if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { LOG(WARNING) << "Failed to rollback " << to; } @@ -289,7 +324,7 @@ int delete_user(const char *uuid, userid_t userid) int delete_cache(const char *uuid, const char *pkgname, userid_t userid) { std::string _cachedir( - create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); + create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX); const char* cachedir = _cachedir.c_str(); /* delete contents, not the directory, no exceptions */ @@ -299,7 +334,7 @@ int delete_cache(const char *uuid, const char *pkgname, userid_t userid) int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid) { std::string _codecachedir( - create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); + create_data_user_package_path(uuid, userid, pkgname) + CODE_CACHE_DIR_POSTFIX); const char* codecachedir = _codecachedir.c_str(); struct stat s; @@ -454,7 +489,7 @@ int rm_dex(const char *path, const char *instruction_set) } } -int get_size(const char *uuid, const char *pkgname, userid_t userid, const char *apkpath, +int get_size(const char *uuid, const char *pkgname, int userid, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int64_t* _asecsize) @@ -470,30 +505,38 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char int64_t cachesize = 0; int64_t asecsize = 0; - /* count the source apk as code -- but only if it's not - * on the /system partition and its not on the sdcard. - */ + /* count the source apk as code -- but only if it's not + * on the /system partition and its not on the sdcard. */ if (validate_system_app_path(apkpath) && strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { if (stat(apkpath, &s) == 0) { codesize += stat_size(&s); + if (S_ISDIR(s.st_mode)) { + d = opendir(apkpath); + if (d != NULL) { + dfd = dirfd(d); + codesize += calculate_dir_size(dfd); + closedir(d); + } + } } } - /* count the forward locked apk as code if it is given - */ + + /* count the forward locked apk as code if it is given */ if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { if (stat(fwdlock_apkpath, &s) == 0) { codesize += stat_size(&s); } } - /* count the cached dexfile as code */ + + /* count the cached dexfile as code */ if (!create_cache_path(path, apkpath, instruction_set)) { if (stat(path, &s) == 0) { codesize += stat_size(&s); } } - /* add in size of any libraries */ + /* add in size of any libraries */ if (libdirpath != NULL && libdirpath[0] != '!') { d = opendir(libdirpath); if (d != NULL) { @@ -503,68 +546,76 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char } } - /* compute asec size if it is given - */ + /* compute asec size if it is given */ if (asecpath != NULL && asecpath[0] != '!') { if (stat(asecpath, &s) == 0) { asecsize += stat_size(&s); } } - std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); - const char* pkgdir = _pkgdir.c_str(); - - d = opendir(pkgdir); - if (d == NULL) { - goto done; + std::vector<userid_t> users; + if (userid == -1) { + users = get_known_users(uuid); + } else { + users.push_back(userid); } - dfd = dirfd(d); - /* most stuff in the pkgdir is data, except for the "cache" - * directory and below, which is cache, and the "lib" directory - * and below, which is code... - */ - while ((de = readdir(d))) { - const char *name = de->d_name; + for (auto user : users) { + std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname)); + const char* pkgdir = _pkgdir.c_str(); - if (de->d_type == DT_DIR) { - int subfd; - int64_t statsize = 0; - int64_t dirsize = 0; - /* always skip "." and ".." */ - if (name[0] == '.') { - if (name[1] == 0) continue; - if ((name[1] == '.') && (name[2] == 0)) continue; - } - if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { - statsize = stat_size(&s); - } - subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); - if (subfd >= 0) { - dirsize = calculate_dir_size(subfd); - } - if(!strcmp(name,"lib")) { - codesize += dirsize + statsize; - } else if(!strcmp(name,"cache")) { - cachesize += dirsize + statsize; + d = opendir(pkgdir); + if (d == NULL) { + PLOG(WARNING) << "Failed to open " << pkgdir; + continue; + } + dfd = dirfd(d); + + /* most stuff in the pkgdir is data, except for the "cache" + * directory and below, which is cache, and the "lib" directory + * and below, which is code... + */ + while ((de = readdir(d))) { + const char *name = de->d_name; + + if (de->d_type == DT_DIR) { + int subfd; + int64_t statsize = 0; + int64_t dirsize = 0; + /* always skip "." and ".." */ + if (name[0] == '.') { + if (name[1] == 0) continue; + if ((name[1] == '.') && (name[2] == 0)) continue; + } + if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { + statsize = stat_size(&s); + } + subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); + if (subfd >= 0) { + dirsize = calculate_dir_size(subfd); + } + if(!strcmp(name,"lib")) { + codesize += dirsize + statsize; + } else if(!strcmp(name,"cache")) { + cachesize += dirsize + statsize; + } else { + datasize += dirsize + statsize; + } + } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) { + // This is the symbolic link to the application's library + // code. We'll count this as code instead of data, since + // it is not something that the app creates. + if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { + codesize += stat_size(&s); + } } else { - datasize += dirsize + statsize; - } - } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) { - // This is the symbolic link to the application's library - // code. We'll count this as code instead of data, since - // it is not something that the app creates. - if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { - codesize += stat_size(&s); - } - } else { - if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { - datasize += stat_size(&s); + if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { + datasize += stat_size(&s); + } } } + closedir(d); } - closedir(d); -done: *_codesize = codesize; *_datasize = datasize; *_cachesize = cachesize; @@ -684,6 +735,15 @@ static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); } +static bool check_boolean_property(const char* property_name, bool default_value = false) { + char tmp_property_value[PROPERTY_VALUE_MAX]; + bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0; + if (!have_property) { + return default_value; + } + return strcmp(tmp_property_value, "true") == 0; +} + static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set, bool vm_safe_mode, bool debuggable) @@ -744,9 +804,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 || (strcmp(vold_decrypt, "1") == 0))); - char use_jit_property[PROPERTY_VALUE_MAX]; - bool have_jit_property = property_get("debug.usejit", use_jit_property, NULL) > 0; - bool use_jit = have_jit_property && strcmp(use_jit_property, "true") == 0; + bool use_jit = check_boolean_property("debug.usejit"); + bool generate_debug_info = check_boolean_property("debug.generate-debug-info"); static const char* DEX2OAT_BIN = "/system/bin/dex2oat"; @@ -839,6 +898,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, + (have_dex2oat_threads_flag ? 1 : 0) + (have_dex2oat_swap_fd ? 1 : 0) + (have_dex2oat_relocation_skip_flag ? 2 : 0) + + (generate_debug_info ? 1 : 0) + (debuggable ? 1 : 0) + dex2oat_flags_count]; int i = 0; @@ -877,6 +937,9 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, if (have_dex2oat_swap_fd) { argv[i++] = dex2oat_swap_fd; } + if (generate_debug_info) { + argv[i++] = "--generate-debug-info"; + } if (debuggable) { argv[i++] = "--debuggable"; } @@ -921,20 +984,49 @@ static int wait_child(pid_t pid) } /* - * Whether dexopt should use a swap file when compiling an APK. If kAlwaysProvideSwapFile, do this - * on all devices (dex2oat will make a more informed decision itself, anyways). Otherwise, only do - * this on a low-mem device. + * Whether dexopt should use a swap file when compiling an APK. + * + * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision + * itself, anyways). + * + * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true". + * + * Otherwise, return true if this is a low-mem device. + * + * Otherwise, return default value. */ -static bool kAlwaysProvideSwapFile = true; +static bool kAlwaysProvideSwapFile = false; +static bool kDefaultProvideSwapFile = true; static bool ShouldUseSwapFileForDexopt() { if (kAlwaysProvideSwapFile) { return true; } - char low_mem_buf[PROPERTY_VALUE_MAX]; - property_get("ro.config.low_ram", low_mem_buf, ""); - return (strcmp(low_mem_buf, "true") == 0); + // Check the "override" property. If it exists, return value == "true". + char dex2oat_prop_buf[PROPERTY_VALUE_MAX]; + if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) { + if (strcmp(dex2oat_prop_buf, "true") == 0) { + return true; + } else { + return false; + } + } + + // Shortcut for default value. This is an implementation optimization for the process sketched + // above. If the default value is true, we can avoid to check whether this is a low-mem device, + // as low-mem is never returning false. The compiler will optimize this away if it can. + if (kDefaultProvideSwapFile) { + return true; + } + + bool is_low_mem = check_boolean_property("ro.config.low_ram"); + if (is_low_mem) { + return true; + } + + // Default value must be false here. + return kDefaultProvideSwapFile; } /* @@ -1448,7 +1540,7 @@ int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int u struct stat s, libStat; int rc = 0; - std::string _pkgdir(create_package_data_path(uuid, pkgname, userId)); + std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname)); std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); const char* pkgdir = _pkgdir.c_str(); @@ -1639,7 +1731,7 @@ int restorecon_data(const char* uuid, const char* pkgName, // Special case for owner on internal storage if (uuid == nullptr) { - std::string path(create_package_data_path(nullptr, pkgName, 0)); + std::string path(create_data_user_package_path(nullptr, 0, pkgName)); if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) { PLOG(ERROR) << "restorecon failed for " << path; @@ -1717,6 +1809,31 @@ int rm_package_dir(const char* apk_path) return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */); } +int link_file(const char* relative_path, const char* from_base, const char* to_base) { + char from_path[PKG_PATH_MAX]; + char to_path[PKG_PATH_MAX]; + snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path); + snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path); + + if (validate_apk_path_subdirs(from_path)) { + ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path); + return -1; + } + + if (validate_apk_path_subdirs(to_path)) { + ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path); + return -1; + } + + const int ret = link(from_path, to_path); + if (ret < 0) { + ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno)); + return -1; + } + + return 0; +} + 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; diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp index 3a86181..13e3168 100644 --- a/cmds/installd/installd.cpp +++ b/cmds/installd/installd.cpp @@ -124,10 +124,10 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused) return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } -static int do_mv_user_data(char **arg, char reply[REPLY_MAX] __unused) +static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] __unused) { - // from_uuid, to_uuid, pkgname, appid, seinfo - return move_user_data(parse_null(arg[0]), parse_null(arg[1]), arg[2], atoi(arg[3]), arg[4]); + // from_uuid, to_uuid, package_name, data_app_name, appid, seinfo + return copy_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]); } static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused) @@ -179,6 +179,12 @@ static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] __unused) return rm_package_dir(arg[0]); } +static int do_link_file(char **arg, char reply[REPLY_MAX] __unused) +{ + /* relative_path, from_base, to_base */ + return link_file(arg[0], arg[1], arg[2]); +} + struct cmdinfo { const char *name; unsigned numargs; @@ -200,7 +206,7 @@ struct cmdinfo cmds[] = { { "rmcodecache", 3, do_rm_code_cache }, { "getsize", 8, do_get_size }, { "rmuserdata", 3, do_rm_user_data }, - { "mvuserdata", 5, do_mv_user_data }, + { "cpcompleteapp", 6, do_cp_complete_app }, { "movefiles", 0, do_movefiles }, { "linklib", 4, do_linklib }, { "mkuserdata", 5, do_mk_user_data }, @@ -209,7 +215,8 @@ struct cmdinfo cmds[] = { { "idmap", 3, do_idmap }, { "restorecondata", 4, do_restorecon_data }, { "createoatdir", 2, do_create_oat_dir }, - { "rmpackagedir", 1, do_rm_package_dir}, + { "rmpackagedir", 1, do_rm_package_dir }, + { "linkfile", 3, do_link_file } }; static int readx(int s, void *_buf, int count) diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index f31bf4f..7ec5793 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -142,10 +142,6 @@ typedef struct { /* util.c */ -// TODO: rename to create_data_user_package_path -std::string create_package_data_path(const char* volume_uuid, - const char* package_name, userid_t user); - int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, const char *postfix, @@ -153,8 +149,15 @@ int create_pkg_path(char path[PKG_PATH_MAX], std::string create_data_path(const char* volume_uuid); +std::string create_data_app_path(const char* volume_uuid); + +std::string create_data_app_package_path(const char* volume_uuid, const char* package_name); + std::string create_data_user_path(const char* volume_uuid, userid_t userid); +std::string create_data_user_package_path(const char* volume_uuid, + userid_t user, const char* package_name); + std::string create_data_media_path(const char* volume_uuid, userid_t userid); std::vector<userid_t> get_known_users(const char* volume_uuid); @@ -200,6 +203,7 @@ int get_path_from_string(dir_rec_t* rec, const char* path); int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix); int validate_apk_path(const char *path); +int validate_apk_path_subdirs(const char *path); int append_and_increment(char** dst, const char* src, size_t* dst_size); @@ -221,8 +225,9 @@ int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid); int delete_user_data(const char *uuid, const char *pkgname, userid_t userid); int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo); -int move_user_data(const char* from_uuid, const char *to_uuid, - const char *package_name, appid_t appid, const char* seinfo); +int copy_complete_app(const char* from_uuid, const char *to_uuid, + const char *package_name, const char *data_app_name, appid_t appid, + const char* seinfo); int make_user_config(userid_t userid); int delete_user(const char *uuid, userid_t userid); int delete_cache(const char *uuid, const char *pkgname, userid_t userid); @@ -230,9 +235,11 @@ int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid); int move_dex(const char *src, const char *dst, const char *instruction_set); int rm_dex(const char *path, const char *instruction_set); int protect(char *pkgname, gid_t gid); -int get_size(const char *uuid, const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath, - const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, - int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); +int get_size(const char *uuid, const char *pkgname, int userid, + const char *apkpath, const char *libdirpath, + const char *fwdlock_apkpath, const char *asecpath, + const char *instruction_set, int64_t *codesize, int64_t *datasize, + int64_t *cachesize, int64_t *asecsize); int free_cache(const char *uuid, int64_t free_size); int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName, const char *instruction_set, int dexopt_needed, bool vm_safe_mode, @@ -248,3 +255,4 @@ int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const const char *instruction_set); int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, const char *instruction_set); +int link_file(const char *relative_path, const char *from_base, const char *to_base); diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index 4ce559d..5e397f9 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -455,6 +455,13 @@ TEST_F(UtilsTest, CreateDataPath) { create_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b")); } +TEST_F(UtilsTest, CreateDataAppPath) { + EXPECT_EQ("/data/app", create_data_app_path(nullptr)); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app", + create_data_app_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b")); +} + TEST_F(UtilsTest, CreateDataUserPath) { EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0)); EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10)); @@ -475,14 +482,21 @@ TEST_F(UtilsTest, CreateDataMediaPath) { create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); } -TEST_F(UtilsTest, CreatePackageDataPath) { - EXPECT_EQ("/data/data/com.example", create_package_data_path(nullptr, "com.example", 0)); - EXPECT_EQ("/data/user/10/com.example", create_package_data_path(nullptr, "com.example", 10)); +TEST_F(UtilsTest, CreateDataAppPackagePath) { + EXPECT_EQ("/data/app/com.example", create_data_app_package_path(nullptr, "com.example")); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app/com.example", + create_data_app_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example")); +} + +TEST_F(UtilsTest, CreateDataUserPackagePath) { + EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example")); + EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example", - create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 0)); + create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example", - create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 10)); + create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example")); } } diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index ba411cd..7db3fb9 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -37,16 +37,31 @@ static bool is_valid_filename(const std::string& name) { } /** + * Create the path name where package app contents should be stored for + * the given volume UUID and package name. An empty UUID is assumed to + * be internal storage. + */ +std::string create_data_app_package_path(const char* volume_uuid, + const char* package_name) { + CHECK(is_valid_filename(package_name)); + CHECK(is_valid_package_name(package_name) == 0); + + return StringPrintf("%s/%s", + create_data_app_path(volume_uuid).c_str(), package_name); +} + +/** * Create the path name where package data should be stored for the given * volume UUID, package name, and user ID. An empty UUID is assumed to be * internal storage. */ -std::string create_package_data_path(const char* volume_uuid, - const char* package_name, userid_t user) { +std::string create_data_user_package_path(const char* volume_uuid, + userid_t user, const char* package_name) { CHECK(is_valid_filename(package_name)); CHECK(is_valid_package_name(package_name) == 0); - return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name); + return StringPrintf("%s/%s", + create_data_user_path(volume_uuid, user).c_str(), package_name); } int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, @@ -56,7 +71,7 @@ int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, return -1; } - std::string _tmp(create_package_data_path(nullptr, pkgname, userid) + postfix); + std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix); const char* tmp = _tmp.c_str(); if (strlen(tmp) >= PKG_PATH_MAX) { path[0] = '\0'; @@ -77,6 +92,13 @@ std::string create_data_path(const char* volume_uuid) { } /** + * Create the path name for app data. + */ +std::string create_data_app_path(const char* volume_uuid) { + return StringPrintf("%s/app", create_data_path(volume_uuid).c_str()); +} + +/** * Create the path name for user data for a certain userid. */ std::string create_data_user_path(const char* volume_uuid, userid_t userid) { @@ -1021,15 +1043,13 @@ int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { } /** - * Check whether path points to a valid path for an APK file. Only one level of - * subdirectory names is allowed. Returns -1 when an invalid path is encountered - * and 0 when a valid path is encountered. + * Check whether path points to a valid path for an APK file. The path must + * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within + * that path. Returns -1 when an invalid path is encountered and 0 when a valid path + * is encountered. */ -int validate_apk_path(const char *path) -{ +static int validate_apk_path_internal(const char *path, int maxSubdirs) { const dir_rec_t* dir = NULL; - int maxSubdirs = 1; - if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { dir = &android_app_dir; } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) { @@ -1038,7 +1058,9 @@ int validate_apk_path(const char *path) dir = &android_asec_dir; } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) { dir = &android_mnt_expand_dir; - maxSubdirs = 2; + if (maxSubdirs < 2) { + maxSubdirs = 2; + } } else { return -1; } @@ -1046,6 +1068,14 @@ int validate_apk_path(const char *path) return validate_path(dir, path, maxSubdirs); } +int validate_apk_path(const char* path) { + return validate_apk_path_internal(path, 1 /* maxSubdirs */); +} + +int validate_apk_path_subdirs(const char* path) { + return validate_apk_path_internal(path, 3 /* maxSubdirs */); +} + int append_and_increment(char** dst, const char* src, size_t* dst_size) { ssize_t ret = strlcpy(*dst, src, *dst_size); if (ret < 0 || (size_t) ret >= *dst_size) { diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp index 97fc47c..428b87c 100644 --- a/cmds/service/service.cpp +++ b/cmds/service/service.cpp @@ -146,6 +146,15 @@ int main(int argc, char* const argv[]) break; } data.writeInt32(atoi(argv[optind++])); + } else if (strcmp(argv[optind], "i64") == 0) { + optind++; + if (optind >= argc) { + aerr << "service: no integer supplied for 'i64'" << endl; + wantsUsage = true; + result = 10; + break; + } + data.writeInt64(atoll(argv[optind++])); } else if (strcmp(argv[optind], "s16") == 0) { optind++; if (optind >= argc) { @@ -155,6 +164,24 @@ int main(int argc, char* const argv[]) break; } data.writeString16(String16(argv[optind++])); + } else if (strcmp(argv[optind], "f") == 0) { + optind++; + if (optind >= argc) { + aerr << "service: no number supplied for 'f'" << endl; + wantsUsage = true; + result = 10; + break; + } + data.writeFloat(atof(argv[optind++])); + } else if (strcmp(argv[optind], "d") == 0) { + optind++; + if (optind >= argc) { + aerr << "service: no number supplied for 'd'" << endl; + wantsUsage = true; + result = 10; + break; + } + data.writeDouble(atof(argv[optind++])); } else if (strcmp(argv[optind], "null") == 0) { optind++; data.writeStrongBinder(NULL); @@ -272,9 +299,12 @@ int main(int argc, char* const argv[]) aout << "Usage: service [-h|-?]\n" " service list\n" " service check SERVICE\n" - " service call SERVICE CODE [i32 INT | s16 STR] ...\n" + " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n" "Options:\n" - " i32: Write the integer INT into the send parcel.\n" + " i32: Write the 32-bit integer N into the send parcel.\n" + " i64: Write the 64-bit integer N into the send parcel.\n" + " f: Write the 32-bit single-precision number N into the send parcel.\n" + " d: Write the 64-bit double-precision number N into the send parcel.\n" " s16: Write the UTF-16 string STR into the send parcel.\n"; // " intent: Write and Intent int the send parcel. ARGS can be\n" // " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n"; diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index cacfe14..7fa9a39 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -361,6 +361,7 @@ int main(int argc, char **argv) selinux_enabled = is_selinux_enabled(); sehandle = selinux_android_service_context_handle(); + selinux_status_open(true); if (selinux_enabled > 0) { if (sehandle == NULL) { |