Merge "ART profiler"
This commit is contained in:
commit
1649c77ed2
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2008, The Android Open Source Project
|
** Copyright 2008, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -115,6 +115,8 @@ int uninstall(const char *pkgname, userid_t userid)
|
|||||||
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
|
if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
remove_profile_file(pkgname);
|
||||||
|
|
||||||
/* delete contents AND directory, no exceptions */
|
/* delete contents AND directory, no exceptions */
|
||||||
return delete_dir_contents(pkgdir, 1, NULL);
|
return delete_dir_contents(pkgdir, 1, NULL);
|
||||||
}
|
}
|
||||||
@ -557,9 +559,9 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
|
dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
|
||||||
strlen(DALVIK_CACHE_POSTFIX) + 1;
|
strlen(DALVIK_CACHE_POSTFIX) + 1;
|
||||||
|
|
||||||
if (dstlen > PKG_PATH_MAX) {
|
if (dstlen > PKG_PATH_MAX) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -568,7 +570,7 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src)
|
|||||||
DALVIK_CACHE_PREFIX,
|
DALVIK_CACHE_PREFIX,
|
||||||
src + 1, /* skip the leading / */
|
src + 1, /* skip the leading / */
|
||||||
DALVIK_CACHE_POSTFIX);
|
DALVIK_CACHE_POSTFIX);
|
||||||
|
|
||||||
for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
|
for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
|
||||||
if (*tmp == '/') {
|
if (*tmp == '/') {
|
||||||
*tmp = '@';
|
*tmp = '@';
|
||||||
@ -601,7 +603,7 @@ static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
const char* output_file_name, const char *pkgname)
|
||||||
{
|
{
|
||||||
char dex2oat_flags[PROPERTY_VALUE_MAX];
|
char dex2oat_flags[PROPERTY_VALUE_MAX];
|
||||||
property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, "");
|
property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, "");
|
||||||
@ -613,17 +615,25 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
|
|||||||
char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
|
char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
|
||||||
char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
|
char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
|
||||||
char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];
|
char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];
|
||||||
|
char profile_file[strlen("--profile-file=") + PKG_PATH_MAX];
|
||||||
|
|
||||||
sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
|
sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
|
||||||
sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
|
sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
|
||||||
sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
|
sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
|
||||||
sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
|
sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
|
||||||
|
if (strcmp(pkgname, "*") != 0) {
|
||||||
|
snprintf(profile_file, sizeof(profile_file), "--profile-file=%s/%s",
|
||||||
|
DALVIK_CACHE_PREFIX "profiles", pkgname);
|
||||||
|
} else {
|
||||||
|
strcpy(profile_file, "--no-profile-file");
|
||||||
|
}
|
||||||
|
|
||||||
ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
|
ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
|
||||||
execl(DEX2OAT_BIN, DEX2OAT_BIN,
|
execl(DEX2OAT_BIN, DEX2OAT_BIN,
|
||||||
zip_fd_arg, zip_location_arg,
|
zip_fd_arg, zip_location_arg,
|
||||||
oat_fd_arg, oat_location_arg,
|
oat_fd_arg, oat_location_arg,
|
||||||
strlen(dex2oat_flags) > 0 ? dex2oat_flags : NULL,
|
strlen(dex2oat_flags) > 0 ? dex2oat_flags : NULL,
|
||||||
|
profile_file,
|
||||||
(char*) NULL);
|
(char*) NULL);
|
||||||
ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
|
ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
|
||||||
}
|
}
|
||||||
@ -654,7 +664,8 @@ static int wait_child(pid_t pid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dexopt(const char *apk_path, uid_t uid, int is_public)
|
int dexopt(const char *apk_path, uid_t uid, int is_public,
|
||||||
|
const char *pkgname)
|
||||||
{
|
{
|
||||||
struct utimbuf ut;
|
struct utimbuf ut;
|
||||||
struct stat apk_stat, dex_stat;
|
struct stat apk_stat, dex_stat;
|
||||||
@ -708,6 +719,12 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create profile file if there is a package name present.
|
||||||
|
if (strcmp(pkgname, "*") != 0) {
|
||||||
|
create_profile_file(pkgname, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
|
ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@ -740,7 +757,7 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
|
|||||||
if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
|
if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
|
||||||
run_dexopt(zip_fd, out_fd, apk_path, out_path);
|
run_dexopt(zip_fd, out_fd, apk_path, out_path);
|
||||||
} else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
|
} else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
|
||||||
run_dex2oat(zip_fd, out_fd, apk_path, out_path);
|
run_dex2oat(zip_fd, out_fd, apk_path, out_path, pkgname);
|
||||||
} else {
|
} else {
|
||||||
exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */
|
exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */
|
||||||
}
|
}
|
||||||
@ -804,12 +821,12 @@ int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
|
|||||||
|
|
||||||
int srcend = strlen(srcpath);
|
int srcend = strlen(srcpath);
|
||||||
int dstend = strlen(dstpath);
|
int dstend = strlen(dstpath);
|
||||||
|
|
||||||
if (lstat(srcpath, statbuf) < 0) {
|
if (lstat(srcpath, statbuf) < 0) {
|
||||||
ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
|
ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((statbuf->st_mode&S_IFDIR) == 0) {
|
if ((statbuf->st_mode&S_IFDIR) == 0) {
|
||||||
mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
|
mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
|
||||||
dstuid, dstgid, statbuf);
|
dstuid, dstgid, statbuf);
|
||||||
@ -835,7 +852,7 @@ int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
||||||
while ((de = readdir(d))) {
|
while ((de = readdir(d))) {
|
||||||
const char *name = de->d_name;
|
const char *name = de->d_name;
|
||||||
/* always skip "." and ".." */
|
/* always skip "." and ".." */
|
||||||
@ -843,32 +860,32 @@ int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
|
|||||||
if (name[1] == 0) continue;
|
if (name[1] == 0) continue;
|
||||||
if ((name[1] == '.') && (name[2] == 0)) continue;
|
if ((name[1] == '.') && (name[2] == 0)) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
|
if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
|
||||||
ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
|
ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
|
if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
|
||||||
ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
|
ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
srcpath[srcend] = dstpath[dstend] = '/';
|
srcpath[srcend] = dstpath[dstend] = '/';
|
||||||
strcpy(srcpath+srcend+1, name);
|
strcpy(srcpath+srcend+1, name);
|
||||||
strcpy(dstpath+dstend+1, name);
|
strcpy(dstpath+dstend+1, name);
|
||||||
|
|
||||||
if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
|
if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
|
||||||
res = 1;
|
res = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: we will be leaving empty directories behind in srcpath,
|
// Note: we will be leaving empty directories behind in srcpath,
|
||||||
// but that is okay, the package manager will be erasing all of the
|
// but that is okay, the package manager will be erasing all of the
|
||||||
// data associated with .apks that disappear.
|
// data associated with .apks that disappear.
|
||||||
|
|
||||||
srcpath[srcend] = dstpath[dstend] = 0;
|
srcpath[srcend] = dstpath[dstend] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(d);
|
closedir(d);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -910,7 +927,7 @@ int movefiles()
|
|||||||
UPDATE_COMMANDS_DIR_PREFIX, name);
|
UPDATE_COMMANDS_DIR_PREFIX, name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufp = 0;
|
bufp = 0;
|
||||||
bufe = 0;
|
bufe = 0;
|
||||||
buf[PKG_PATH_MAX] = 0;
|
buf[PKG_PATH_MAX] = 0;
|
||||||
|
@ -38,8 +38,8 @@ static int do_install(char **arg, char reply[REPLY_MAX])
|
|||||||
|
|
||||||
static int do_dexopt(char **arg, char reply[REPLY_MAX])
|
static int do_dexopt(char **arg, char reply[REPLY_MAX])
|
||||||
{
|
{
|
||||||
/* apk_path, uid, is_public */
|
/* apk_path, uid, is_public, pkgname */
|
||||||
return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
|
return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_move_dex(char **arg, char reply[REPLY_MAX])
|
static int do_move_dex(char **arg, char reply[REPLY_MAX])
|
||||||
@ -138,7 +138,7 @@ struct cmdinfo {
|
|||||||
struct cmdinfo cmds[] = {
|
struct cmdinfo cmds[] = {
|
||||||
{ "ping", 0, do_ping },
|
{ "ping", 0, do_ping },
|
||||||
{ "install", 4, do_install },
|
{ "install", 4, do_install },
|
||||||
{ "dexopt", 3, do_dexopt },
|
{ "dexopt", 4, do_dexopt },
|
||||||
{ "movedex", 2, do_move_dex },
|
{ "movedex", 2, do_move_dex },
|
||||||
{ "rmdex", 1, do_rm_dex },
|
{ "rmdex", 1, do_rm_dex },
|
||||||
{ "remove", 2, do_remove },
|
{ "remove", 2, do_remove },
|
||||||
|
@ -189,6 +189,8 @@ char *build_string3(char *s1, char *s2, char *s3);
|
|||||||
|
|
||||||
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
|
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
|
||||||
int ensure_media_user_dirs(userid_t userid);
|
int ensure_media_user_dirs(userid_t userid);
|
||||||
|
int create_profile_file(const char *pkgname, gid_t gid);
|
||||||
|
void remove_profile_file(const char *pkgname);
|
||||||
|
|
||||||
/* commands.c */
|
/* commands.c */
|
||||||
|
|
||||||
@ -207,7 +209,7 @@ int get_size(const char *pkgname, userid_t userid, const char *apkpath, const ch
|
|||||||
const char *fwdlock_apkpath, const char *asecpath, int64_t *codesize,
|
const char *fwdlock_apkpath, const char *asecpath, int64_t *codesize,
|
||||||
int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
|
int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
|
||||||
int free_cache(int64_t free_size);
|
int free_cache(int64_t free_size);
|
||||||
int dexopt(const char *apk_path, uid_t uid, int is_public);
|
int dexopt(const char *apk_path, uid_t uid, int is_public, const char *pkgName);
|
||||||
int movefiles();
|
int movefiles();
|
||||||
int linklib(const char* target, const char* source, int userId);
|
int linklib(const char* target, const char* source, int userId);
|
||||||
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
|
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2008, The Android Open Source Project
|
** Copyright 2008, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1005,3 +1005,59 @@ int ensure_media_user_dirs(userid_t userid) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int create_profile_file(const char *pkgname, gid_t gid) {
|
||||||
|
const char *profile_dir = DALVIK_CACHE_PREFIX "profiles";
|
||||||
|
struct stat profileStat;
|
||||||
|
char profile_file[PKG_PATH_MAX];
|
||||||
|
|
||||||
|
// If we don't have a profile directory under dalvik-cache we need to create one.
|
||||||
|
if (stat(profile_dir, &profileStat) < 0) {
|
||||||
|
// Create the profile directory under dalvik-cache.
|
||||||
|
if (mkdir(profile_dir, 0711) < 0) {
|
||||||
|
ALOGE("cannot make profile dir '%s': %s\n", profile_dir, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the profile directory write-only for group and other. Owner can rwx it.
|
||||||
|
if (chmod(profile_dir, 0711) < 0) {
|
||||||
|
ALOGE("cannot chown profile dir '%s': %s\n", profile_dir, strerror(errno));
|
||||||
|
unlink(profile_dir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(profile_file, sizeof(profile_file), "%s/%s", profile_dir, pkgname);
|
||||||
|
|
||||||
|
// The 'system' user needs to be able to read the profile to determine if dex2oat
|
||||||
|
// needs to be run. This is done in dalvik.system.DexFile.isDexOptNeededInternal(). So
|
||||||
|
// we make it world readable. Not a problem since the dalvik cache is world
|
||||||
|
// readable anyway.
|
||||||
|
|
||||||
|
int fd = open(profile_file, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0664);
|
||||||
|
|
||||||
|
// Open will fail if the file already exists. We want to ignore that.
|
||||||
|
if (fd >= 0) {
|
||||||
|
if (fchown(fd, -1, gid) < 0) {
|
||||||
|
ALOGE("cannot chown profile file '%s': %s\n", profile_file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
unlink(profile_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fchmod(fd, 0664) < 0) {
|
||||||
|
ALOGE("cannot chmod profile file '%s': %s\n", profile_file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
unlink(profile_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_profile_file(const char *pkgname) {
|
||||||
|
char profile_file[PKG_PATH_MAX];
|
||||||
|
snprintf(profile_file, sizeof(profile_file), "%s/%s", DALVIK_CACHE_PREFIX "profiles", pkgname);
|
||||||
|
unlink(profile_file);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user