Installd: Allow different behavior before bootcomplete

Check dev.bootcomplete in dex2oat(). Use the information for
two changes.

Only switch to the background when we're post bootcomplete.
This will ensure better utilization after upgrades.

Add a second dex2oat-threads property that is used pre
bootcomplete. A separation of these phases allows using less
cores when the device is up, freeing up resources for other
purposes, e.g., avoid jank. The precedence during boot is the
boot property, or the image property if the former doesn't
exist, or the default property as a fallback.

Bug: 23898216
Bug: 24004256
Change-Id: I5063f3fc4b437cbe88c4e94584e01c1c78eccc4d
This commit is contained in:
Andreas Gampe 2015-09-14 16:33:11 -07:00
parent 624408eecb
commit 21948005f0

View File

@ -746,7 +746,7 @@ static bool check_boolean_property(const char* property_name, bool default_value
static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, 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, const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
bool vm_safe_mode, bool debuggable) bool vm_safe_mode, bool debuggable, bool post_bootcomplete)
{ {
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@ -770,8 +770,24 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
dex2oat_compiler_filter_flag, NULL) > 0; dex2oat_compiler_filter_flag, NULL) > 0;
char dex2oat_threads_buf[PROPERTY_VALUE_MAX]; char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
bool have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", dex2oat_threads_buf, bool have_dex2oat_threads_flag = false;
NULL) > 0; if (!post_bootcomplete) {
have_dex2oat_threads_flag = property_get("dalvik.vm.boot-dex2oat-threads",
dex2oat_threads_buf,
NULL) > 0;
// If there's no boot property, fall back to the image property.
if (!have_dex2oat_threads_flag) {
have_dex2oat_threads_flag = property_get("dalvik.vm.image-dex2oat-threads",
dex2oat_threads_buf,
NULL) > 0;
}
// If there's neither, fall back to the default property.
}
if (!have_dex2oat_threads_flag) {
have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads",
dex2oat_threads_buf,
NULL) > 0;
}
char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2]; char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
if (have_dex2oat_threads_flag) { if (have_dex2oat_threads_flag) {
sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf); sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
@ -1065,6 +1081,27 @@ static bool calculate_odex_file_path(char path[PKG_PATH_MAX],
return true; return true;
} }
static bool IsPostBootComplete() {
char dev_bootcomplete_prop_buf[PROPERTY_VALUE_MAX];
if (property_get("dev.bootcomplete", dev_bootcomplete_prop_buf, "0") > 0) {
return (strcmp(dev_bootcomplete_prop_buf, "1") == 0);
}
return false;
}
static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
if (set_to_bg) {
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
ALOGE("set_sched_policy failed: %s\n", strerror(errno));
exit(70);
}
if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
ALOGE("setpriority failed: %s\n", strerror(errno));
exit(71);
}
}
}
int dexopt(const char *apk_path, uid_t uid, bool is_public, int dexopt(const char *apk_path, uid_t uid, bool is_public,
const char *pkgname, const char *instruction_set, int dexopt_needed, const char *pkgname, const char *instruction_set, int dexopt_needed,
bool vm_safe_mode, bool debuggable, const char* oat_dir) bool vm_safe_mode, bool debuggable, const char* oat_dir)
@ -1076,6 +1113,7 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public,
const char *input_file; const char *input_file;
char in_odex_path[PKG_PATH_MAX]; char in_odex_path[PKG_PATH_MAX];
int res, input_fd=-1, out_fd=-1, swap_fd=-1; int res, input_fd=-1, out_fd=-1, swap_fd=-1;
bool post_bootcomplete = IsPostBootComplete();
// Early best-effort check whether we can fit the the path into our buffers. // 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 // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
@ -1198,14 +1236,7 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public,
ALOGE("capset failed: %s\n", strerror(errno)); ALOGE("capset failed: %s\n", strerror(errno));
exit(66); exit(66);
} }
if (set_sched_policy(0, SP_BACKGROUND) < 0) { SetDex2OatAndPatchOatScheduling(post_bootcomplete);
ALOGE("set_sched_policy failed: %s\n", strerror(errno));
exit(70);
}
if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
ALOGE("setpriority failed: %s\n", strerror(errno));
exit(71);
}
if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) { if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno)); ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
exit(67); exit(67);
@ -1222,7 +1253,7 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public,
input_file_name++; input_file_name++;
} }
run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname, run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
instruction_set, vm_safe_mode, debuggable); instruction_set, vm_safe_mode, debuggable, post_bootcomplete);
} else { } else {
ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
exit(73); exit(73);