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

Commit 8ea0dc6a authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Shared OBB storage across users.

To avoid downloading large OBB files separately for each user,
provide a shared view of /sdcard/Android/obb to all apps.  Added
upgrade step to migrate the owners existing OBB files to become
the default view.

Bug: 7008879
Change-Id: I199321552fa7d4b97d5ed7fc3b3bc41f23618601
parent 0d43c567
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -241,7 +241,6 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
{
    char src_data_dir[PKG_PATH_MAX];
    char pkg_path[PKG_PATH_MAX];
    char media_path[PATH_MAX];
    DIR *d;
    struct dirent *de;
    struct stat s;
@@ -250,9 +249,6 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
    if (create_persona_path(src_data_dir, src_persona)) {
        return -1;
    }
    if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) {
        return -1;
    }

    d = opendir(src_data_dir);
    if (d != NULL) {
@@ -281,10 +277,10 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
        closedir(d);
    }

    // ensure /data/media/<user_id> exists
    if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
    if (ensure_media_user_dirs((userid_t) target_persona) == -1) {
        return -1;
    }

    return 0;
}

+49 −29
Original line number Diff line number Diff line
@@ -333,19 +333,16 @@ int initialize_globals() {

int initialize_directories() {
    int res = -1;
    int version = 0;
    FILE* file;

    // Read current filesystem layout version to handle upgrade paths
    char version_path[PATH_MAX];
    if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) {
        return -1;
    }
    file = fopen(version_path, "r");
    if (file != NULL) {
        fscanf(file, "%d", &version);
        fclose(file);
    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);

    int oldVersion;
    if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
        oldVersion = 0;
    }
    int version = oldVersion;

    // /data/user
    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
@@ -376,16 +373,12 @@ int initialize_directories() {
        }
    }

    // /data/media/0
    char owner_media_dir[PATH_MAX];
    create_persona_media_path(owner_media_dir, 0);

    if (version == 0) {
        // Introducing multi-user, so migrate /data/media contents into /data/media/0
        ALOGD("Migrating /data/media for multi-user");
        ALOGD("Upgrading /data/media for multi-user");

        // Ensure /data/media
        if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
            goto fail;
        }

@@ -402,10 +395,14 @@ int initialize_directories() {
        }

        // Create /data/media again
        if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
            goto fail;
        }

        // /data/media/0
        char owner_media_dir[PATH_MAX];
        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);

        // Move any owner data into place
        if (access(media_tmp_dir, F_OK) == 0) {
            if (rename(media_tmp_dir, owner_media_dir) == -1) {
@@ -433,8 +430,7 @@ int initialize_directories() {

                    // /data/media/<user_id>
                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
                    if (ensure_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
                        ALOGE("Failed to ensure %s: %s", user_media_dir, strerror(errno));
                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
                        goto fail;
                    }
                }
@@ -445,21 +441,45 @@ int initialize_directories() {
        version = 1;
    }

    // Ensure /data/media/0 is always ready
    if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
    // /data/media/obb
    char media_obb_dir[PATH_MAX];
    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);

    if (version == 1) {
        // Introducing /data/media/obb for sharing OBB across users; migrate
        // any existing OBB files from owner.
        ALOGD("Upgrading to shared /data/media/obb");

        // /data/media/0/Android/obb
        char owner_obb_path[PATH_MAX];
        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);

        // Only move if target doesn't already exist
        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
            if (rename(owner_obb_path, media_obb_dir) == -1) {
                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
                goto fail;
            }
        }

        version = 2;
    }

    if (ensure_media_user_dirs(0) == -1) {
        ALOGE("Failed to setup media for user 0");
        goto fail;
    }
    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
        goto fail;
    }

    // Persist our current version
    file = fopen(version_path, "w");
    if (file != NULL) {
        fprintf(file, "%d", version);
        fsync(fileno(file));
        fclose(file);
    } else {
    // Persist layout version if changed
    if (version != oldVersion) {
        if (fs_write_atomic_int(version_path, version) == -1) {
            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
            goto fail;
        }
    }

    // Success!
    res = 0;
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/wait.h>

#include <cutils/fs.h>
#include <cutils/sockets.h>
#include <cutils/log.h>
#include <cutils/properties.h>
+7 −32
Original line number Diff line number Diff line
@@ -991,39 +991,14 @@ char *build_string3(char *s1, char *s2, char *s3) {
    return result;
}

/* Ensure that directory exists with given mode and owners. */
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) {
    // Check if path needs to be created
    struct stat sb;
    if (stat(path, &sb) == -1) {
        if (errno == ENOENT) {
            goto create;
        } else {
            ALOGE("Failed to stat(%s): %s", path, strerror(errno));
            return -1;
        }
    }

    // Exists, verify status
    if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) {
        return 0;
    } else {
        goto fixup;
    }

create:
    if (mkdir(path, mode) == -1) {
        ALOGE("Failed to mkdir(%s): %s", path, strerror(errno));
        return -1;
    }
/* Ensure that /data/media directories are prepared for given user. */
int ensure_media_user_dirs(userid_t userid) {
    char media_user_path[PATH_MAX];
    char path[PATH_MAX];

fixup:
    if (chown(path, uid, gid) == -1) {
        ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno));
        return -1;
    }
    if (chmod(path, mode) == -1) {
        ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno));
    // Ensure /data/media/<userid> exists
    create_persona_media_path(media_user_path, userid);
    if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
        return -1;
    }