Create separate api for reconciling per-sdk storage
Sdks should get their own storage area under the sdk package path
at: `/data/misc_ce/0/sdksandbox/<package>/<sdk-name>@<random-suffix>`
The random suffix is to prevent sdks from guessing each others storage
paths. It is separated by '@' which is an illegal character for package
names.
The new API prepares the sdk-level directories as follows:
- creates them if they do not exist.
- on occasssions where they already exist, it skips creating them.
- on occasssions where it finds an per-sdk directory that shouldn't be
there, it deletes them.
- it also creates the package path if its missing for any reason.
Additional Changes:
- For package-level sdk data directory, we now delete it if FLAG_STORAGE_SDK
flag is not passed. This is done so that we clean up properly when an
app that consumes sdk updates to a state where it no longer consumes
sdks.
Bug: 211763739
Test: atest installd_service_tes
Test: atest SdkSandboxStorageHostTest
Ignore-AOSP-First: Feature is being developed in internal branch
Change-Id: I7f144f5da4c4e10851f78d731de5dfb429fbac4d
Merged-In: I7f144f5da4c4e10851f78d731de5dfb429fbac4d
(cherry picked from commit 92f5cf0d0b943315d475dfbe9273a6118095bdbf)
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 992425d..8cfd123 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -212,7 +212,7 @@
/**
* Create the path name where code data for all codes in a particular app will be stored.
- * E.g. /data/misc_ce/0/sdksandbox/<app-name>
+ * E.g. /data/misc_ce/0/sdksandbox/<package-name>
*/
std::string create_data_misc_sdk_sandbox_package_path(const char* volume_uuid, bool isCeData,
userid_t user, const char* package_name) {
@@ -224,7 +224,7 @@
/**
* Create the path name where shared code data for a particular app will be stored.
- * E.g. /data/misc_ce/0/sdksandbox/<app-name>/shared
+ * E.g. /data/misc_ce/0/sdksandbox/<package-name>/shared
*/
std::string create_data_misc_sdk_sandbox_shared_path(const char* volume_uuid, bool isCeData,
userid_t user, const char* package_name) {
@@ -234,6 +234,19 @@
.c_str());
}
+/**
+ * Create the path name where per-code level data for a particular app will be stored.
+ * E.g. /data/misc_ce/0/sdksandbox/<package-name>/<sdk-name>-<random-suffix>
+ */
+std::string create_data_misc_sdk_sandbox_sdk_path(const char* volume_uuid, bool isCeData,
+ userid_t user, const char* package_name,
+ const char* sdk_name, const char* randomSuffix) {
+ check_package_name(sdk_name);
+ auto package_path =
+ create_data_misc_sdk_sandbox_package_path(volume_uuid, isCeData, user, package_name);
+ return StringPrintf("%s/%s@%s", package_path.c_str(), sdk_name, randomSuffix);
+}
+
std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
}
@@ -696,6 +709,34 @@
return std::unique_ptr<DIR, DirCloser>(::opendir(dir));
}
+// Collects filename of subdirectories of given directory and passes it to the function
+int foreach_subdir(const std::string& pathname, const std::function<void(const std::string&)> fn) {
+ auto dir = open_dir(pathname.c_str());
+ if (!dir) return -1;
+
+ int dfd = dirfd(dir.get());
+ if (dfd < 0) {
+ ALOGE("Couldn't dirfd %s: %s\n", pathname.c_str(), strerror(errno));
+ return -1;
+ }
+
+ struct dirent* de;
+ while ((de = readdir(dir.get()))) {
+ if (de->d_type != DT_DIR) {
+ continue;
+ }
+
+ std::string name{de->d_name};
+ // always skip "." and ".."
+ if (name == "." || name == "..") {
+ continue;
+ }
+ fn(name);
+ }
+
+ return 0;
+}
+
void cleanup_invalid_package_dirs_under_path(const std::string& pathname) {
auto dir = open_dir(pathname.c_str());
if (!dir) {