Offer to move both code and data together.

We now move code under /data/app/com.example when a complete move
is requested.  This really only works for new cluster-style installs
that also have native libraries and OAT contained inside.

Teach measuring code about cluster-style installs when measuring
app footprint.  Also offer to measure private data space for all
users.

Bug: 19993667, 20275578
Change-Id: I6df7b947cb5cc8a4552f56f4b64a661e8512389f
This commit is contained in:
Jeff Sharkey 2015-04-30 15:58:19 -07:00
parent 7a6c586161
commit d792118c49
5 changed files with 201 additions and 98 deletions

View File

@ -50,7 +50,7 @@ int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const c
return -1; 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(); const char* pkgdir = _pkgdir.c_str();
if (mkdir(pkgdir, 0751) < 0) { 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) 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(); const char* pkgdir = _pkgdir.c_str();
remove_profile_file(pkgname); 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; 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(); const char* pkgdir = _pkgdir.c_str();
if (stat(pkgdir, &s) < 0) return -1; 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) 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(); const char* pkgdir = _pkgdir.c_str();
return delete_dir_contents(pkgdir, 0, NULL); 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) 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(); const char* pkgdir = _pkgdir.c_str();
if (mkdir(pkgdir, 0751) < 0) { 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; return 0;
} }
int move_user_data(const char *from_uuid, const char *to_uuid, int move_complete_app(const char *from_uuid, const char *to_uuid,
const char *package_name, appid_t appid, const char* seinfo) { 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); 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) { for (auto user : users) {
std::string from(create_package_data_path(from_uuid, package_name, user)); std::string from(create_data_user_package_path(from_uuid, user, package_name));
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));
std::string to_user(create_data_user_path(to_uuid, user)); std::string to_parent(create_data_user_path(to_uuid, user));
// Data source may not exist for all users; that's okay // Data source may not exist for all users; that's okay
if (access(from.c_str(), F_OK) != 0) { 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*) "-P", /* Do not follow symlinks [default] */
(char*) "-d", /* don't dereference symlinks */ (char*) "-d", /* don't dereference symlinks */
(char*) from.c_str(), (char*) from.c_str(),
(char*) to_user.c_str() (char*) to_parent.c_str()
}; };
LOG(DEBUG) << "Copying " << from << " to " << to; LOG(DEBUG) << "Copying " << from << " to " << to;
@ -231,9 +264,15 @@ int move_user_data(const char *from_uuid, const char *to_uuid,
} }
} }
// Copy successful, so delete old data // Delete old app and data
{
std::string from(create_data_app_package_path(from_uuid, data_app_name));
if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
LOG(WARNING) << "Failed to delete " << from;
}
}
for (auto user : users) { for (auto user : users) {
std::string from(create_package_data_path(from_uuid, package_name, user)); std::string from(create_data_user_package_path(from_uuid, user, package_name));
if (delete_dir_contents(from.c_str(), 1, NULL) != 0) { if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
LOG(WARNING) << "Failed to delete " << from; LOG(WARNING) << "Failed to delete " << from;
} }
@ -242,8 +281,14 @@ int move_user_data(const char *from_uuid, const char *to_uuid,
fail: fail:
// Nuke everything we might have already copied // 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) { 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) { if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
LOG(WARNING) << "Failed to rollback " << to; LOG(WARNING) << "Failed to rollback " << to;
} }
@ -289,7 +334,7 @@ int delete_user(const char *uuid, userid_t userid)
int delete_cache(const char *uuid, const char *pkgname, userid_t userid) int delete_cache(const char *uuid, const char *pkgname, userid_t userid)
{ {
std::string _cachedir( 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(); const char* cachedir = _cachedir.c_str();
/* delete contents, not the directory, no exceptions */ /* delete contents, not the directory, no exceptions */
@ -299,7 +344,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) int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid)
{ {
std::string _codecachedir( std::string _codecachedir(
create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX);
const char* codecachedir = _codecachedir.c_str(); const char* codecachedir = _codecachedir.c_str();
struct stat s; struct stat s;
@ -454,7 +499,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 *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
const char *instruction_set, int64_t *_codesize, int64_t *_datasize, const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
int64_t *_cachesize, int64_t* _asecsize) int64_t *_cachesize, int64_t* _asecsize)
@ -470,30 +515,38 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
int64_t cachesize = 0; int64_t cachesize = 0;
int64_t asecsize = 0; int64_t asecsize = 0;
/* count the source apk as code -- but only if it's not /* count the source apk as code -- but only if it's not
* on the /system partition and its not on the sdcard. * on the /system partition and its not on the sdcard. */
*/
if (validate_system_app_path(apkpath) && if (validate_system_app_path(apkpath) &&
strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
if (stat(apkpath, &s) == 0) { if (stat(apkpath, &s) == 0) {
codesize += stat_size(&s); 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 (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
if (stat(fwdlock_apkpath, &s) == 0) { if (stat(fwdlock_apkpath, &s) == 0) {
codesize += stat_size(&s); 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 (!create_cache_path(path, apkpath, instruction_set)) {
if (stat(path, &s) == 0) { if (stat(path, &s) == 0) {
codesize += stat_size(&s); codesize += stat_size(&s);
} }
} }
/* add in size of any libraries */ /* add in size of any libraries */
if (libdirpath != NULL && libdirpath[0] != '!') { if (libdirpath != NULL && libdirpath[0] != '!') {
d = opendir(libdirpath); d = opendir(libdirpath);
if (d != NULL) { if (d != NULL) {
@ -503,68 +556,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 (asecpath != NULL && asecpath[0] != '!') {
if (stat(asecpath, &s) == 0) { if (stat(asecpath, &s) == 0) {
asecsize += stat_size(&s); asecsize += stat_size(&s);
} }
} }
std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); std::vector<userid_t> users;
const char* pkgdir = _pkgdir.c_str(); if (userid == -1) {
users = get_known_users(uuid);
d = opendir(pkgdir); } else {
if (d == NULL) { users.push_back(userid);
goto done;
} }
dfd = dirfd(d);
/* most stuff in the pkgdir is data, except for the "cache" for (auto user : users) {
* directory and below, which is cache, and the "lib" directory std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
* and below, which is code... const char* pkgdir = _pkgdir.c_str();
*/
while ((de = readdir(d))) {
const char *name = de->d_name;
if (de->d_type == DT_DIR) { d = opendir(pkgdir);
int subfd; if (d == NULL) {
int64_t statsize = 0; PLOG(WARNING) << "Failed to open " << pkgdir;
int64_t dirsize = 0; continue;
/* always skip "." and ".." */ }
if (name[0] == '.') { dfd = dirfd(d);
if (name[1] == 0) continue;
if ((name[1] == '.') && (name[2] == 0)) continue; /* most stuff in the pkgdir is data, except for the "cache"
} * directory and below, which is cache, and the "lib" directory
if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { * and below, which is code...
statsize = stat_size(&s); */
} while ((de = readdir(d))) {
subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); const char *name = de->d_name;
if (subfd >= 0) {
dirsize = calculate_dir_size(subfd); if (de->d_type == DT_DIR) {
} int subfd;
if(!strcmp(name,"lib")) { int64_t statsize = 0;
codesize += dirsize + statsize; int64_t dirsize = 0;
} else if(!strcmp(name,"cache")) { /* always skip "." and ".." */
cachesize += dirsize + statsize; 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 { } else {
datasize += dirsize + statsize; if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
} datasize += stat_size(&s);
} 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);
} }
} }
closedir(d);
} }
closedir(d);
done:
*_codesize = codesize; *_codesize = codesize;
*_datasize = datasize; *_datasize = datasize;
*_cachesize = cachesize; *_cachesize = cachesize;
@ -1448,7 +1509,7 @@ int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int u
struct stat s, libStat; struct stat s, libStat;
int rc = 0; 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); std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
const char* pkgdir = _pkgdir.c_str(); const char* pkgdir = _pkgdir.c_str();
@ -1639,7 +1700,7 @@ int restorecon_data(const char* uuid, const char* pkgName,
// Special case for owner on internal storage // Special case for owner on internal storage
if (uuid == nullptr) { 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) { if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) {
PLOG(ERROR) << "restorecon failed for " << path; PLOG(ERROR) << "restorecon failed for " << path;

View File

@ -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 */ 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_mv_complete_app(char **arg, char reply[REPLY_MAX] __unused)
{ {
// from_uuid, to_uuid, pkgname, appid, seinfo // from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
return move_user_data(parse_null(arg[0]), parse_null(arg[1]), arg[2], atoi(arg[3]), arg[4]); return move_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) static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused)
@ -200,7 +200,7 @@ struct cmdinfo cmds[] = {
{ "rmcodecache", 3, do_rm_code_cache }, { "rmcodecache", 3, do_rm_code_cache },
{ "getsize", 8, do_get_size }, { "getsize", 8, do_get_size },
{ "rmuserdata", 3, do_rm_user_data }, { "rmuserdata", 3, do_rm_user_data },
{ "mvuserdata", 5, do_mv_user_data }, { "mvcompleteapp", 6, do_mv_complete_app },
{ "movefiles", 0, do_movefiles }, { "movefiles", 0, do_movefiles },
{ "linklib", 4, do_linklib }, { "linklib", 4, do_linklib },
{ "mkuserdata", 5, do_mk_user_data }, { "mkuserdata", 5, do_mk_user_data },

View File

@ -142,10 +142,6 @@ typedef struct {
/* util.c */ /* 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], int create_pkg_path(char path[PKG_PATH_MAX],
const char *pkgname, const char *pkgname,
const char *postfix, 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_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_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::string create_data_media_path(const char* volume_uuid, userid_t userid);
std::vector<userid_t> get_known_users(const char* volume_uuid); std::vector<userid_t> get_known_users(const char* volume_uuid);
@ -221,8 +224,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 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, int make_user_data(const char *uuid, const char *pkgname, uid_t uid,
userid_t userid, const char* seinfo); userid_t userid, const char* seinfo);
int move_user_data(const char* from_uuid, const char *to_uuid, int move_complete_app(const char* from_uuid, const char *to_uuid,
const char *package_name, appid_t appid, const char* seinfo); const char *package_name, const char *data_app_name, appid_t appid,
const char* seinfo);
int make_user_config(userid_t userid); int make_user_config(userid_t userid);
int delete_user(const char *uuid, userid_t userid); int delete_user(const char *uuid, userid_t userid);
int delete_cache(const char *uuid, const char *pkgname, userid_t userid); int delete_cache(const char *uuid, const char *pkgname, userid_t userid);
@ -230,9 +234,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 move_dex(const char *src, const char *dst, const char *instruction_set);
int rm_dex(const char *path, const char *instruction_set); int rm_dex(const char *path, const char *instruction_set);
int protect(char *pkgname, gid_t gid); 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, int get_size(const char *uuid, const char *pkgname, int userid,
const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, const char *apkpath, const char *libdirpath,
int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); 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 free_cache(const char *uuid, int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName, 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, const char *instruction_set, int dexopt_needed, bool vm_safe_mode,

View File

@ -455,6 +455,13 @@ TEST_F(UtilsTest, CreateDataPath) {
create_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b")); 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) { TEST_F(UtilsTest, CreateDataUserPath) {
EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0)); EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10)); 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)); create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
} }
TEST_F(UtilsTest, CreatePackageDataPath) { TEST_F(UtilsTest, CreateDataAppPackagePath) {
EXPECT_EQ("/data/data/com.example", create_package_data_path(nullptr, "com.example", 0)); EXPECT_EQ("/data/app/com.example", create_data_app_package_path(nullptr, "com.example"));
EXPECT_EQ("/data/user/10/com.example", create_package_data_path(nullptr, "com.example", 10));
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", 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", 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"));
} }
} }

View File

@ -36,17 +36,32 @@ 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 * 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 * volume UUID, package name, and user ID. An empty UUID is assumed to be
* internal storage. * internal storage.
*/ */
std::string create_package_data_path(const char* volume_uuid, std::string create_data_user_package_path(const char* volume_uuid,
const char* package_name, userid_t user) { userid_t user, const char* package_name) {
CHECK(is_valid_filename(package_name)); CHECK(is_valid_filename(package_name));
CHECK(is_valid_package_name(package_name) == 0); 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, 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; 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(); const char* tmp = _tmp.c_str();
if (strlen(tmp) >= PKG_PATH_MAX) { if (strlen(tmp) >= PKG_PATH_MAX) {
path[0] = '\0'; path[0] = '\0';
@ -76,6 +91,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. * Create the path name for user data for a certain userid.
*/ */