From bbfb6ea1ac459116512b34db94c647092dc99140 Mon Sep 17 00:00:00 2001 From: Ricky Wai Date: Thu, 3 Dec 2020 15:32:52 +0000 Subject: [PATCH] Check if storage app data and obb directories exist in vold As storage is not mounted in system server, we use vold to check if storage app data and obb directories exist instead. We add a method in vold so it only creates app data and obb dirs if dirs do not exist to speed up app starting time. Bug: 160336374 Test: Data and obb directories are created when a new app is started Change-Id: I1bd784d9c9e05463f71433fc782ac4e0c831cbf1 --- VoldNativeService.cpp | 8 ++++++++ VoldNativeService.h | 1 + VolumeManager.cpp | 29 +++++++++++++++++++++++++++-- VolumeManager.h | 9 ++++++++- binder/android/os/IVold.aidl | 1 + 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 674a721..864a6f0 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -394,6 +394,14 @@ binder::Status VoldNativeService::setupAppDir(const std::string& path, int32_t a return translate(VolumeManager::Instance()->setupAppDir(path, appUid)); } +binder::Status VoldNativeService::ensureAppDirsCreated(const std::vector& paths, + int32_t appUid) { + ENFORCE_SYSTEM_OR_ROOT; + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->ensureAppDirsCreated(paths, appUid)); +} + binder::Status VoldNativeService::fixupAppDir(const std::string& path, int32_t appUid) { ENFORCE_SYSTEM_OR_ROOT; CHECK_ARGUMENT_PATH(path); diff --git a/VoldNativeService.h b/VoldNativeService.h index 390e9fc..0a55af4 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -67,6 +67,7 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status remountAppStorageDirs(int uid, int pid, const std::vector& packageNames); + binder::Status ensureAppDirsCreated(const std::vector& paths, int32_t appUid); binder::Status setupAppDir(const std::string& path, int32_t appUid); binder::Status fixupAppDir(const std::string& path, int32_t appUid); diff --git a/VolumeManager.cpp b/VolumeManager.cpp index f0fc388..714122d 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -984,7 +984,25 @@ int VolumeManager::unmountAll() { return 0; } -int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly) { +int VolumeManager::ensureAppDirsCreated(const std::vector& paths, int32_t appUid) { + if (IsSdcardfsUsed()) { + // sdcardfs magically does this for us + return OK; + } + + int size = paths.size(); + for (int i = 0; i < size; i++) { + int result = setupAppDir(paths[i], appUid, false /* fixupExistingOnly */, + true /* skipIfDirExists */); + if (result != OK) { + return result; + } + } + return OK; +} + +int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly, + bool skipIfDirExists) { // Only offer to create directories for paths managed by vold if (!StartsWith(path, "/storage/")) { LOG(ERROR) << "Failed to find mounted volume for " << path; @@ -1029,11 +1047,18 @@ int VolumeManager::setupAppDir(const std::string& path, int32_t appUid, bool fix const std::string volumeRoot = volume->getRootPath(); // eg /data/media/0 - if (fixupExistingOnly && (access(lowerPath.c_str(), F_OK) != 0)) { + const int access_result = access(lowerPath.c_str(), F_OK); + if (fixupExistingOnly && access_result != 0) { // Nothing to fixup return OK; } + if (skipIfDirExists && access_result == 0) { + // It's safe to assume it's ok as it will be used for zygote to bind mount dir only, + // which the dir doesn't need to have correct permission for now yet. + return OK; + } + if (volume->getType() == VolumeBase::Type::kPublic) { // On public volumes, we don't need to setup permissions, as everything goes through // FUSE; just create the dirs and be done with it. diff --git a/VolumeManager.h b/VolumeManager.h index 54a2443..932b81c 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -165,12 +165,16 @@ class VolumeManager { * files in the passed in path, but only if that path exists; if it doesn't * exist, this function doesn't create them. * + * If skipIfDirExists is set, we will not fix any existing dirs, we will + * only create app dirs if it doesn't exist. + * * Validates that given paths are absolute and that they contain no relative * "." or ".." paths or symlinks. Last path segment is treated as filename * and ignored, unless the path ends with "/". Also ensures that path * belongs to a volume managed by vold. */ - int setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly = false); + int setupAppDir(const std::string& path, int32_t appUid, bool fixupExistingOnly = false, + bool skipIfDirExists = false); /** * Fixes up an existing application directory, as if it was created with @@ -179,6 +183,9 @@ class VolumeManager { */ int fixupAppDir(const std::string& path, int32_t appUid); + // Called before zygote starts to ensure dir exists so zygote can bind mount them. + int ensureAppDirsCreated(const std::vector& paths, int32_t appUid); + int createObb(const std::string& path, const std::string& key, int32_t ownerGid, std::string* outVolId); int destroyObb(const std::string& volId); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index bb284b8..ef4f89a 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -57,6 +57,7 @@ interface IVold { void setupAppDir(@utf8InCpp String path, int appUid); void fixupAppDir(@utf8InCpp String path, int appUid); + void ensureAppDirsCreated(in @utf8InCpp String[] paths, int appUid); @utf8InCpp String createObb(@utf8InCpp String sourcePath, @utf8InCpp String sourceKey, int ownerGid);