Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d792118c authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

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
parent 7a6c5861
Loading
Loading
Loading
Loading
+137 −76
Original line number Diff line number Diff line
@@ -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 move_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;
@@ -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) {
        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) {
            LOG(WARNING) << "Failed to delete " << from;
        }
@@ -242,8 +281,14 @@ int move_user_data(const char *from_uuid, const char *to_uuid,

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 +334,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 +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)
{
    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();

    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 *instruction_set, int64_t *_codesize, int64_t *_datasize,
             int64_t *_cachesize, int64_t* _asecsize)
@@ -471,21 +516,29 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
    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.
         */
     * 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 */
    if (!create_cache_path(path, apkpath, instruction_set)) {
        if (stat(path, &s) == 0) {
@@ -503,20 +556,28 @@ 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));
    std::vector<userid_t> users;
    if (userid == -1) {
        users = get_known_users(uuid);
    } else {
        users.push_back(userid);
    }

    for (auto user : users) {
        std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
        const char* pkgdir = _pkgdir.c_str();

        d = opendir(pkgdir);
        if (d == NULL) {
        goto done;
            PLOG(WARNING) << "Failed to open " << pkgdir;
            continue;
        }
        dfd = dirfd(d);

@@ -564,7 +625,7 @@ int get_size(const char *uuid, const char *pkgname, userid_t userid, const char
            }
        }
        closedir(d);
done:
    }
    *_codesize = codesize;
    *_datasize = datasize;
    *_cachesize = cachesize;
@@ -1448,7 +1509,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 +1700,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;
+4 −4
Original line number Diff line number Diff line
@@ -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_mv_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 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)
@@ -200,7 +200,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 },
    { "mvcompleteapp",        6, do_mv_complete_app },
    { "movefiles",            0, do_movefiles },
    { "linklib",              4, do_linklib },
    { "mkuserdata",           5, do_mk_user_data },
+15 −9
Original line number Diff line number Diff line
@@ -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);
@@ -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 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 move_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 +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 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,
+19 −5
Original line number Diff line number Diff line
@@ -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"));
}

}
+26 −4
Original line number Diff line number Diff line
@@ -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
 * 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';
@@ -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.
 */