Make ReconcileSdkData more flexible

Instead of passing sdk package names and list of random strings to
installd, the client will pass the sub-directory name directly. The
client will be responsible for ensuring they don't create multiple
sub-directories for same sdk with different random suffixes.

Also, since "shared" sub-directory is just another type of sdk data
sub-directory, we no longer create it during sdk package path creation.
This directory should get created using ReconcileSdkData api by the
client.

Also cleaned up the tests and added SdkSandboxStorageHostTest in
TEST_MAPPING.

Bug: 211763739
Test: atest installd_service_test
Ignore-AOSP-First: Some of the cls are missing in AOSP. Will cherry-pick
this with rest of them together next week.

Change-Id: Ie9cdc2c41bcec64028008a79654f2d38c017b6d1
Merged-In: Ie9cdc2c41bcec64028008a79654f2d38c017b6d1
(cherry picked from commit 5288b055c114f0d765c284e50b9e0b3898305c80)
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index a92de4e..955d812 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -752,8 +752,7 @@
 
     if (flags & FLAG_STORAGE_SDK) {
         // Safe to ignore status since we can retry creating this by calling reconcileSdkData
-        auto ignore = createSdkSandboxDataPackageDirectory(uuid, packageName, userId, appId,
-                                                           previousAppId, seInfo, flags);
+        auto ignore = createSdkSandboxDataPackageDirectory(uuid, packageName, userId, appId, flags);
         if (!ignore.isOk()) {
             PLOG(WARNING) << "Failed to create sdk data package directory for " << packageName;
         }
@@ -772,7 +771,7 @@
  */
 binder::Status InstalldNativeService::createSdkSandboxDataPackageDirectory(
         const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
-        int32_t appId, int32_t previousAppId, const std::string& seInfo, int32_t flags) {
+        int32_t appId, int32_t flags) {
     int32_t sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
     if (sdkSandboxUid == -1) {
         // There no valid sdk sandbox process for this app. Skip creation of data directory
@@ -791,7 +790,7 @@
         // /data/misc_{ce,de}/<user-id>/sdksandbox directory gets created by vold
         // during user creation
 
-        // Prepare the app directory
+        // Prepare the package directory
         auto packagePath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId,
                                                                      packageName.c_str());
 #if SDK_DEBUG
@@ -801,27 +800,6 @@
         if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM, 0)) {
             return error("Failed to prepare " + packagePath);
         }
-
-        // Now prepare the shared directory which will be accessible by all codes
-        auto sharedPath = create_data_misc_sdk_sandbox_shared_path(uuid_, isCeData, userId,
-                                                                   packageName.c_str());
-
-        int32_t previousSdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, previousAppId);
-        int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
-        if (cacheGid == -1) {
-            return exception(binder::Status::EX_ILLEGAL_STATE,
-                             StringPrintf("cacheGid cannot be -1 for sdksandbox data"));
-        }
-        auto status = createAppDataDirs(sharedPath, sdkSandboxUid, AID_NOBODY,
-                                        &previousSdkSandboxUid, cacheGid, seInfo, 0700 | S_ISGID);
-        if (!status.isOk()) {
-            return status;
-        }
-
-        // TODO(b/211763739): We also need to handle art profile creations
-
-        // TODO(b/211763739): And return the CE inode of the sdksandbox root directory and
-        // app directory under it so we can clear contents while CE storage is locked
     }
 
     return ok();
@@ -874,8 +852,8 @@
         const android::os::ReconcileSdkDataArgs& args) {
     // Locking is performed depeer in the callstack.
 
-    return reconcileSdkData(args.uuid, args.packageName, args.sdkPackageNames, args.randomSuffixes,
-                            args.userId, args.appId, args.previousAppId, args.seInfo, args.flags);
+    return reconcileSdkData(args.uuid, args.packageName, args.subDirNames, args.userId, args.appId,
+                            args.previousAppId, args.seInfo, args.flags);
 }
 
 /**
@@ -889,17 +867,14 @@
  *   is to avoid having same per-sdk directory with different suffix.
  * - If a sdk level directory exist which is absent from sdkPackageNames, we remove it.
  */
-binder::Status InstalldNativeService::reconcileSdkData(
-        const std::optional<std::string>& uuid, const std::string& packageName,
-        const std::vector<std::string>& sdkPackageNames,
-        const std::vector<std::string>& randomSuffixes, int userId, int appId, int previousAppId,
-        const std::string& seInfo, int flags) {
+binder::Status InstalldNativeService::reconcileSdkData(const std::optional<std::string>& uuid,
+                                                       const std::string& packageName,
+                                                       const std::vector<std::string>& subDirNames,
+                                                       int userId, int appId, int previousAppId,
+                                                       const std::string& seInfo, int flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
-    for (const auto& sdkPackageName : sdkPackageNames) {
-        CHECK_ARGUMENT_PACKAGE_NAME(sdkPackageName);
-    }
     LOCK_PACKAGE_USER();
 
 #if SDK_DEBUG
@@ -908,16 +883,9 @@
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
 
-    // Validate we have enough randomSuffixStrings
-    if (randomSuffixes.size() != sdkPackageNames.size()) {
-        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
-                         StringPrintf("Not enough random suffix. Required %d, received %d.",
-                                      (int)sdkPackageNames.size(), (int)randomSuffixes.size()));
-    }
-
     // Prepare the sdk package directory in case it's missing
-    const auto status = createSdkSandboxDataPackageDirectory(uuid, packageName, userId, appId,
-                                                             previousAppId, seInfo, flags);
+    const auto status =
+            createSdkSandboxDataPackageDirectory(uuid, packageName, userId, appId, flags);
     if (!status.isOk()) {
         return status;
     }
@@ -931,37 +899,22 @@
         }
         const bool isCeData = (currentFlag == FLAG_STORAGE_CE);
 
-        // Since random suffix provided will be random every time, we need to ensure we don't end up
-        // creating multuple directories for same sdk package with different suffixes. This
-        // is ensured by fetching all the existing sub directories and storing them so that we can
-        // check for existence later. We also remove unconsumed sdk directories in this check.
         const auto packagePath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId,
                                                                            packageName.c_str());
-        const std::unordered_set<std::string> expectedSdkNames(sdkPackageNames.begin(),
-                                                               sdkPackageNames.end());
-        // Store paths of per-sdk directory for sdk that already exists
-        std::unordered_map<std::string, std::string> sdkNamesThatExist;
 
-        const auto subDirHandler = [&packagePath, &expectedSdkNames, &sdkNamesThatExist,
-                                    &res](const std::string& filename) {
-            auto filepath = packagePath + "/" + filename;
-            auto tokens = Split(filename, "@");
-            if (tokens.size() != 2) {
-                // Not a per-sdk directory with random suffix
-                return;
-            }
-            auto sdkName = tokens[0];
-
+        // Remove existing sub-directories not referred in subDirNames
+        const std::unordered_set<std::string> expectedSubDirNames(subDirNames.begin(),
+                                                                  subDirNames.end());
+        const auto subDirHandler = [&packagePath, &expectedSubDirNames,
+                                    &res](const std::string& subDirName) {
             // Remove the per-sdk directory if it is not referred in
-            // expectedSdkNames
-            if (expectedSdkNames.find(sdkName) == expectedSdkNames.end()) {
-                if (delete_dir_contents_and_dir(filepath) != 0) {
-                    res = error("Failed to delete " + filepath);
+            // expectedSubDirNames
+            if (expectedSubDirNames.find(subDirName) == expectedSubDirNames.end()) {
+                auto path = packagePath + "/" + subDirName;
+                if (delete_dir_contents_and_dir(path) != 0) {
+                    res = error("Failed to delete " + path);
                     return;
                 }
-            } else {
-                // Otherwise, store it as existing sdk level directory
-                sdkNamesThatExist[sdkName] = filepath;
             }
         };
         const int ec = foreach_subdir(packagePath, subDirHandler);
@@ -970,19 +923,11 @@
             continue;
         }
 
-        // Create sdksandbox data directory for each sdksandbox package
-        for (int i = 0, size = sdkPackageNames.size(); i < size; i++) {
-            const std::string& sdkName = sdkPackageNames[i];
-            const std::string& randomSuffix = randomSuffixes[i];
-            std::string path;
-            if (const auto& it = sdkNamesThatExist.find(sdkName); it != sdkNamesThatExist.end()) {
-                // Already exists. Use existing path instead of creating a new one
-                path = it->second;
-            } else {
-                path = create_data_misc_sdk_sandbox_sdk_path(uuid_, isCeData, userId,
-                                                             packageName.c_str(), sdkName.c_str(),
-                                                             randomSuffix.c_str());
-            }
+        // Now create the subDirNames
+        for (const auto& subDirName : subDirNames) {
+            const std::string path =
+                    create_data_misc_sdk_sandbox_sdk_path(uuid_, isCeData, userId,
+                                                          packageName.c_str(), subDirName.c_str());
 
             // Create the directory along with cache and code_cache
             const int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index f0fd867..95ac516 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -211,8 +211,7 @@
     binder::Status createSdkSandboxDataPackageDirectory(const std::optional<std::string>& uuid,
                                                         const std::string& packageName,
                                                         int32_t userId, int32_t appId,
-                                                        int32_t previousAppId,
-                                                        const std::string& seInfo, int32_t flags);
+                                                        int32_t flags);
     binder::Status clearSdkSandboxDataPackageDirectory(const std::optional<std::string>& uuid,
                                                        const std::string& packageName,
                                                        int32_t userId, int32_t flags);
@@ -221,8 +220,7 @@
                                                          int32_t userId, int32_t flags);
     binder::Status reconcileSdkData(const std::optional<std::string>& uuid,
                                     const std::string& packageName,
-                                    const std::vector<std::string>& sdkPackageNames,
-                                    const std::vector<std::string>& randomSuffixes, int32_t userId,
+                                    const std::vector<std::string>& subDirNames, int32_t userId,
                                     int32_t appId, int32_t previousAppId, const std::string& seInfo,
                                     int flags);
     binder::Status restoreconSdkDataLocked(const std::optional<std::string>& uuid,
diff --git a/cmds/installd/TEST_MAPPING b/cmds/installd/TEST_MAPPING
index 3f0fb6d..8ccab4c 100644
--- a/cmds/installd/TEST_MAPPING
+++ b/cmds/installd/TEST_MAPPING
@@ -30,6 +30,9 @@
     },
     {
       "name": "CtsCompilationTestCases"
+    },
+    {
+      "name": "SdkSandboxStorageHostTest"
     }
   ]
 }
diff --git a/cmds/installd/binder/android/os/ReconcileSdkDataArgs.aidl b/cmds/installd/binder/android/os/ReconcileSdkDataArgs.aidl
index 2f794b1..583a36d 100644
--- a/cmds/installd/binder/android/os/ReconcileSdkDataArgs.aidl
+++ b/cmds/installd/binder/android/os/ReconcileSdkDataArgs.aidl
@@ -20,8 +20,7 @@
 parcelable ReconcileSdkDataArgs {
     @nullable @utf8InCpp String uuid;
     @utf8InCpp String packageName;
-    @utf8InCpp List<String> sdkPackageNames;
-    @utf8InCpp List<String> randomSuffixes;
+    @utf8InCpp List<String> subDirNames;
     int userId;
     int appId;
     int previousAppId;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 65edc80..cf88856 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -45,7 +45,7 @@
 #include "utils.h"
 
 using android::base::StringPrintf;
-namespace fs = std::filesystem;
+using std::filesystem::is_empty;
 
 namespace android {
 std::string get_package_name(uid_t uid) {
@@ -79,12 +79,15 @@
 namespace installd {
 
 static constexpr const char* kTestUuid = "TEST";
-static constexpr const char* kTestPath = "/data/local/tmp";
+static const std::string kTestPath = "/data/local/tmp";
 static constexpr const uid_t kNobodyUid = 9999;
 static constexpr const uid_t kSystemUid = 1000;
 static constexpr const int32_t kTestUserId = 0;
 static constexpr const uid_t kTestAppId = 19999;
 static constexpr const int FLAG_STORAGE_SDK = InstalldNativeService::FLAG_STORAGE_SDK;
+static constexpr const int FLAG_CLEAR_CACHE_ONLY = InstalldNativeService::FLAG_CLEAR_CACHE_ONLY;
+static constexpr const int FLAG_CLEAR_CODE_CACHE_ONLY =
+        InstalldNativeService::FLAG_CLEAR_CODE_CACHE_ONLY;
 
 const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
 const gid_t kTestCacheGid = multiuser_get_cache_gid(kTestUserId, kTestAppId);
@@ -111,7 +114,7 @@
 }
 
 static std::string get_full_path(const std::string& path) {
-    return StringPrintf("%s/%s", kTestPath, path.c_str());
+    return StringPrintf("%s/%s", kTestPath.c_str(), path.c_str());
 }
 
 static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
@@ -169,10 +172,9 @@
 }
 
 static bool exists_renamed_deleted_dir(const std::string& rootDirectory) {
-    return find_file((std::string(kTestPath) + rootDirectory).c_str(),
-                     [](const std::string& name, bool is_dir) {
-                         return is_dir && is_renamed_deleted_dir(name);
-                     });
+    return find_file((kTestPath + rootDirectory).c_str(), [](const std::string& name, bool is_dir) {
+        return is_dir && is_renamed_deleted_dir(name);
+    });
 }
 
 class ServiceTest : public testing::Test {
@@ -1067,16 +1069,12 @@
     }
 
     android::os::ReconcileSdkDataArgs reconcileSdkDataArgs(
-            std::string packageName, std::vector<std::string> codeNames,
-            std::vector<std::string> randomSuffixes) {
+            const std::string& packageName, const std::vector<std::string>& subDirNames) {
         android::os::ReconcileSdkDataArgs args;
         args.uuid = kTestUuid;
         args.packageName = packageName;
-        for (const auto& codeName : codeNames) {
-            args.sdkPackageNames.push_back(codeName);
-        }
-        for (const auto& randomSuffix : randomSuffixes) {
-            args.randomSuffixes.push_back(randomSuffix);
+        for (const auto& subDirName : subDirNames) {
+            args.subDirNames.push_back(subDirName);
         }
         args.userId = kTestUserId;
         args.appId = kTestAppId;
@@ -1126,24 +1124,12 @@
 
     const std::string fooCePath = "misc_ce/0/sdksandbox/com.foo";
     CheckFileAccess(fooCePath, kSystemUid, kSystemUid, S_IFDIR | 0751);
-    CheckFileAccess(fooCePath + "/shared", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | S_ISGID | 0700);
-    CheckFileAccess(fooCePath + "/shared/cache", kTestSdkSandboxUid, kTestCacheGid,
-                    S_IFDIR | S_ISGID | 0771);
-    CheckFileAccess(fooCePath + "/shared/code_cache", kTestSdkSandboxUid, kTestCacheGid,
-                    S_IFDIR | S_ISGID | 0771);
 
     const std::string fooDePath = "misc_de/0/sdksandbox/com.foo";
     CheckFileAccess(fooDePath, kSystemUid, kSystemUid, S_IFDIR | 0751);
-    CheckFileAccess(fooDePath + "/shared", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | S_ISGID | 0700);
-    CheckFileAccess(fooDePath + "/shared/cache", kTestSdkSandboxUid, kTestCacheGid,
-                    S_IFDIR | S_ISGID | 0771);
-    CheckFileAccess(fooDePath + "/shared/code_cache", kTestSdkSandboxUid, kTestCacheGid,
-                    S_IFDIR | S_ISGID | 0771);
 }
 
-TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkAppLevelData_WithoutSdkFlag) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutSdkFlag) {
     android::os::CreateAppDataResult result;
     android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
     args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
@@ -1155,7 +1141,7 @@
     ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
 }
 
-TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkAppLevelData_WithoutSdkFlagDeletesExisting) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutSdkFlagDeletesExisting) {
     android::os::CreateAppDataResult result;
     android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
     // Create the app user data.
@@ -1169,7 +1155,7 @@
     ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
 }
 
-TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkAppLevelData_WithoutDeFlag) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutDeFlag) {
     android::os::CreateAppDataResult result;
     android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
     args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_SDK;
@@ -1184,7 +1170,7 @@
     ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
 }
 
-TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkAppLevelData_WithoutCeFlag) {
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSdkPackageData_WithoutCeFlag) {
     android::os::CreateAppDataResult result;
     android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
     args.flags = FLAG_STORAGE_DE | FLAG_STORAGE_SDK;
@@ -1201,7 +1187,7 @@
 
 TEST_F(SdkSandboxDataTest, ReconcileSdkData) {
     android::os::ReconcileSdkDataArgs args =
-            reconcileSdkDataArgs("com.foo", {"bar", "baz"}, {"random1", "random2"});
+            reconcileSdkDataArgs("com.foo", {"bar@random1", "baz@random2"});
 
     // Create the sdk data.
     ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
@@ -1235,59 +1221,15 @@
                     S_IFDIR | S_ISGID | 0771);
 }
 
-TEST_F(SdkSandboxDataTest, ReconcileSdkData_PackageNameCannotUseRandomSuffixSeparator) {
-    android::os::ReconcileSdkDataArgs args =
-            reconcileSdkDataArgs("com.foo", {"bar@illegal"}, {"random1"});
-
-    // Create the sdksandbox data.
-    auto status = service->reconcileSdkData(args);
-    ASSERT_EQ(status.exceptionCode(), binder::Status::EX_ILLEGAL_ARGUMENT);
-    ASSERT_EQ(status.exceptionMessage(), "Package name bar@illegal is malformed");
-}
-
-TEST_F(SdkSandboxDataTest, ReconcileSdkData_NotEnoughRandomSuffix) {
-    android::os::ReconcileSdkDataArgs args =
-            reconcileSdkDataArgs("com.foo", {"bar", "baz"}, {"random1"});
-
-    // Create the sdksandbox data.
-    auto status = service->reconcileSdkData(args);
-    ASSERT_EQ(status.exceptionCode(), binder::Status::EX_ILLEGAL_ARGUMENT);
-    ASSERT_EQ(status.exceptionMessage(), "Not enough random suffix. Required 2, received 1.");
-}
-
-TEST_F(SdkSandboxDataTest, ReconcileSdkData_DirectoryNotCreatedIfAlreadyExistsIgnoringSuffix) {
-    android::os::ReconcileSdkDataArgs args =
-            reconcileSdkDataArgs("com.foo", {"bar", "baz"}, {"random1", "random2"});
-
-    // Create the sdksandbox data.
-    ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
-
-    // Retry with different random suffix
-    args.randomSuffixes[0] = "r10";
-    args.randomSuffixes[1] = "r20";
-
-    // Create the sdksandbox data again
-    ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
-
-    // Previous directories from first attempt should exist
-    CheckFileAccess("misc_ce/0/sdksandbox/com.foo/bar@random1", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | S_ISGID | 0700);
-    CheckFileAccess("misc_ce/0/sdksandbox/com.foo/baz@random2", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | S_ISGID | 0700);
-    // No new directories should be created on second attempt
-    ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/bar@r10"));
-    ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo/bar@r20"));
-}
-
 TEST_F(SdkSandboxDataTest, ReconcileSdkData_ExtraCodeDirectoriesAreDeleted) {
     android::os::ReconcileSdkDataArgs args =
-            reconcileSdkDataArgs("com.foo", {"bar", "baz"}, {"random1", "random2"});
+            reconcileSdkDataArgs("com.foo", {"bar@random1", "baz@random2"});
 
     // Create the sdksandbox data.
     ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
 
     // Retry with different package name
-    args.sdkPackageNames[0] = "bar.diff";
+    args.subDirNames[0] = "bar.diff@random1";
 
     // Create the sdksandbox data again
     ASSERT_BINDER_SUCCESS(service->reconcileSdkData(args));
@@ -1347,130 +1289,90 @@
     void createTestSdkData(const std::string& packageName, std::vector<std::string> sdkNames) {
         const auto& cePackagePath = "/data/local/tmp/misc_ce/0/sdksandbox/" + packageName;
         const auto& dePackagePath = "/data/local/tmp/misc_de/0/sdksandbox/" + packageName;
-        ASSERT_TRUE(mkdirs(cePackagePath + "/shared/cache", 0700));
-        ASSERT_TRUE(mkdirs(cePackagePath + "shared/code_cache", 0700));
-        ASSERT_TRUE(mkdirs(dePackagePath + "/shared/cache", 0700));
-        ASSERT_TRUE(mkdirs(dePackagePath + "/shared/code_cache", 0700));
-        std::ofstream{cePackagePath + "/shared/cache/cachedTestData.txt"};
-        for (auto sdkName : sdkNames) {
-            ASSERT_TRUE(mkdirs(cePackagePath + "/" + sdkName + "/cache", 0700));
-            ASSERT_TRUE(mkdirs(dePackagePath + "/" + sdkName + "/cache", 0700));
-            ASSERT_TRUE(mkdirs(cePackagePath + "/" + sdkName + "/code_cache", 0700));
-            ASSERT_TRUE(mkdirs(dePackagePath + "/" + sdkName + "/code_cache", 0700));
-            std::ofstream{cePackagePath + "/" + sdkName + "/cache/cachedTestData.txt"};
-            std::ofstream{cePackagePath + "/" + sdkName + "/code_cache/cachedTestData.txt"};
-            std::ofstream{dePackagePath + "/" + sdkName + "/cache/cachedTestData.txt"};
-            std::ofstream{dePackagePath + "/" + sdkName + "/code_cache/cachedTestData.txt"};
+        ASSERT_TRUE(mkdirs(cePackagePath, 0700));
+        ASSERT_TRUE(mkdirs(dePackagePath, 0700));
+        const std::vector<std::string> packagePaths = {cePackagePath, dePackagePath};
+        for (const auto& packagePath : packagePaths) {
+            for (auto sdkName : sdkNames) {
+                ASSERT_TRUE(mkdirs(packagePath + "/" + sdkName + "/cache", 0700));
+                ASSERT_TRUE(mkdirs(packagePath + "/" + sdkName + "/code_cache", 0700));
+                std::ofstream{packagePath + "/" + sdkName + "/cache/cachedTestData.txt"};
+                std::ofstream{packagePath + "/" + sdkName + "/code_cache/cachedTestData.txt"};
+            }
         }
     }
 };
 
 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithCeAndClearCacheFlag) {
-    android::os::CreateAppDataResult result;
-    android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
-    args.packageName = "com.foo";
-    // Create the app user data.
-    ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
-    createTestSdkData("com.foo", {"sdk1", "sdk2"});
+    createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
     // Clear the app user data.
-    ASSERT_BINDER_SUCCESS(
-            service->clearAppData(args.uuid, args.packageName, args.userId,
-                                  FLAG_STORAGE_CE | (InstalldNativeService::FLAG_CLEAR_CACHE_ONLY),
-                                  result.ceDataInode));
-    ASSERT_TRUE(
-            fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/shared/cache")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/sdk1/cache")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/sdk2/cache")));
+    ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0,
+                                                FLAG_STORAGE_CE | FLAG_CLEAR_CACHE_ONLY, -1));
+
+    const std::string packagePath = kTestPath + "/misc_ce/0/sdksandbox/com.foo";
+    ASSERT_TRUE(is_empty(packagePath + "/shared/cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk1/cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk2/cache"));
 }
 
 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithCeAndClearCodeCacheFlag) {
-    android::os::CreateAppDataResult result;
-    android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
-    args.packageName = "com.foo";
-    // Create the app user data.
-    ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
-    createTestSdkData("com.foo", {"sdk1", "sdk2"});
+    createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
     // Clear the app user data.
-    ASSERT_BINDER_SUCCESS(
-            service->clearAppData(args.uuid, args.packageName, args.userId,
-                                  FLAG_STORAGE_CE |
-                                          (InstalldNativeService::FLAG_CLEAR_CODE_CACHE_ONLY),
-                                  result.ceDataInode));
-    ASSERT_TRUE(fs::is_empty(
-            fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/shared/code_cache")));
-    ASSERT_TRUE(
-            fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/sdk1/code_cache")));
-    ASSERT_TRUE(
-            fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/sdk2/code_cache")));
+    ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0,
+                                                FLAG_STORAGE_CE | FLAG_CLEAR_CODE_CACHE_ONLY, -1));
+
+    const std::string packagePath = kTestPath + "/misc_ce/0/sdksandbox/com.foo";
+    ASSERT_TRUE(is_empty(packagePath + "/shared/code_cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk1/code_cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk2/code_cache"));
 }
 
 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithDeAndClearCacheFlag) {
-    android::os::CreateAppDataResult result;
-    android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
-    args.packageName = "com.foo";
-    // Create the app user data.
-    ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
-    createTestSdkData("com.foo", {"sdk1", "sdk2"});
+    createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
     // Clear the app user data
     ASSERT_BINDER_SUCCESS(
-            service->clearAppData(args.uuid, args.packageName, args.userId,
+            service->clearAppData(kTestUuid, "com.foo", 0,
                                   FLAG_STORAGE_DE | (InstalldNativeService::FLAG_CLEAR_CACHE_ONLY),
-                                  result.ceDataInode));
-    ASSERT_TRUE(
-            fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/shared/cache")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/sdk1/cache")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/sdk2/cache")));
+                                  -1));
+
+    const std::string packagePath = kTestPath + "/misc_de/0/sdksandbox/com.foo";
+    ASSERT_TRUE(is_empty(packagePath + "/shared/cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk1/cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk2/cache"));
 }
 
 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithDeAndClearCodeCacheFlag) {
-    android::os::CreateAppDataResult result;
-    android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
-    args.packageName = "com.foo";
-    // Create the app user data.
-    ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
-    createTestSdkData("com.foo", {"sdk1", "sdk2"});
+    createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
     // Clear the app user data.
-    ASSERT_BINDER_SUCCESS(
-            service->clearAppData(args.uuid, args.packageName, args.userId,
-                                  FLAG_STORAGE_DE |
-                                          (InstalldNativeService::FLAG_CLEAR_CODE_CACHE_ONLY),
-                                  result.ceDataInode));
-    ASSERT_TRUE(fs::is_empty(
-            fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/shared/code_cache")));
-    ASSERT_TRUE(
-            fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/sdk1/code_cache")));
-    ASSERT_TRUE(
-            fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/sdk2/code_cache")));
+    ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0,
+                                                FLAG_STORAGE_DE | FLAG_CLEAR_CODE_CACHE_ONLY, -1));
+
+    const std::string packagePath = kTestPath + "/misc_de/0/sdksandbox/com.foo";
+    ASSERT_TRUE(is_empty(packagePath + "/shared/code_cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk1/code_cache"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk2/code_cache"));
 }
 
 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithCeAndWithoutAnyCacheFlag) {
-    android::os::CreateAppDataResult result;
-    android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
-    args.packageName = "com.foo";
-    // Create the app user data.
-    ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
-    createTestSdkData("com.foo", {"sdk1", "sdk2"});
+    createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
     // Clear the app user data.
-    ASSERT_BINDER_SUCCESS(service->clearAppData(args.uuid, args.packageName, args.userId,
-                                                FLAG_STORAGE_CE, result.ceDataInode));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/shared")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/sdk1")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/sdk2")));
+    ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0, FLAG_STORAGE_CE, -1));
+
+    const std::string packagePath = kTestPath + "/misc_ce/0/sdksandbox/com.foo";
+    ASSERT_TRUE(is_empty(packagePath + "/shared"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk1"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk2"));
 }
 
 TEST_F(ClearAppDataTest, ClearSdkSandboxDataDirectories_WithDeAndWithoutAnyCacheFlag) {
-    android::os::CreateAppDataResult result;
-    android::os::CreateAppDataArgs args = createAppDataArgs("com.foo");
-    args.packageName = "com.foo";
-    // Create the app user data.
-    ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
-    createTestSdkData("com.foo", {"sdk1", "sdk2"});
+    createTestSdkData("com.foo", {"shared", "sdk1", "sdk2"});
     // Clear the app user data.
-    ASSERT_BINDER_SUCCESS(service->clearAppData(args.uuid, args.packageName, args.userId,
-                                                FLAG_STORAGE_DE, result.ceDataInode));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/shared")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/sdk1")));
-    ASSERT_TRUE(fs::is_empty(fs::path("/data/local/tmp/misc_de/0/sdksandbox/com.foo/sdk2")));
+    ASSERT_BINDER_SUCCESS(service->clearAppData(kTestUuid, "com.foo", 0, FLAG_STORAGE_DE, -1));
+
+    const std::string packagePath = kTestPath + "/misc_de/0/sdksandbox/com.foo";
+    ASSERT_TRUE(is_empty(packagePath + "/shared"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk1"));
+    ASSERT_TRUE(is_empty(packagePath + "/sdk2"));
 }
 
 class DestroyUserDataTest : public SdkSandboxDataTest {};
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 38c1c05..910cd63 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -690,11 +690,11 @@
               create_data_misc_sdk_sandbox_package_path(nullptr, true, 10, "com.foo"));
 
     EXPECT_EQ("/data/misc_ce/0/sdksandbox/com.foo/shared",
-              create_data_misc_sdk_sandbox_shared_path(nullptr, true, 0, "com.foo"));
+              create_data_misc_sdk_sandbox_sdk_path(nullptr, true, 0, "com.foo", "shared"));
     EXPECT_EQ("/data/misc_ce/10/sdksandbox/com.foo/shared",
-              create_data_misc_sdk_sandbox_shared_path(nullptr, true, 10, "com.foo"));
+              create_data_misc_sdk_sandbox_sdk_path(nullptr, true, 10, "com.foo", "shared"));
     EXPECT_EQ("/data/misc_ce/10/sdksandbox/com.foo/bar@random",
-              create_data_misc_sdk_sandbox_sdk_path(nullptr, true, 10, "com.foo", "bar", "random"));
+              create_data_misc_sdk_sandbox_sdk_path(nullptr, true, 10, "com.foo", "bar@random"));
 
     // De data paths
     EXPECT_EQ("/data/misc_de/0/sdksandbox",
@@ -707,12 +707,11 @@
               create_data_misc_sdk_sandbox_package_path(nullptr, false, 10, "com.foo"));
 
     EXPECT_EQ("/data/misc_de/0/sdksandbox/com.foo/shared",
-              create_data_misc_sdk_sandbox_shared_path(nullptr, false, 0, "com.foo"));
+              create_data_misc_sdk_sandbox_sdk_path(nullptr, false, 0, "com.foo", "shared"));
     EXPECT_EQ("/data/misc_de/10/sdksandbox/com.foo/shared",
-              create_data_misc_sdk_sandbox_shared_path(nullptr, false, 10, "com.foo"));
+              create_data_misc_sdk_sandbox_sdk_path(nullptr, false, 10, "com.foo", "shared"));
     EXPECT_EQ("/data/misc_de/10/sdksandbox/com.foo/bar@random",
-              create_data_misc_sdk_sandbox_sdk_path(nullptr, false, 10, "com.foo", "bar",
-                                                    "random"));
+              create_data_misc_sdk_sandbox_sdk_path(nullptr, false, 10, "com.foo", "bar@random"));
 }
 
 TEST_F(UtilsTest, WaitChild) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index fd4d7bd..2ed971d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -224,28 +224,17 @@
 }
 
 /**
- * Create the path name where shared code data for a particular app will be stored.
- * 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) {
-    return StringPrintf("%s/shared",
-                        create_data_misc_sdk_sandbox_package_path(volume_uuid, isCeData, user,
-                                                                  package_name)
-                                .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>
+ * Create the path name where sdk data for a particular sdk will be stored.
+ * E.g. /data/misc_ce/0/sdksandbox/<package-name>/com.foo@randomstrings
  */
 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);
+                                                  const char* sub_dir_name) {
+    return StringPrintf("%s/%s",
+                        create_data_misc_sdk_sandbox_package_path(volume_uuid, isCeData, user,
+                                                                  package_name)
+                                .c_str(),
+                        sub_dir_name);
 }
 
 std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index dfc0bd5..ecea1d2 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -65,11 +65,9 @@
                                               userid_t userid);
 std::string create_data_misc_sdk_sandbox_package_path(const char* volume_uuid, bool isCeData,
                                                       userid_t userid, const char* package_name);
-std::string create_data_misc_sdk_sandbox_shared_path(const char* volume_uuid, bool isCeData,
-                                                     userid_t userid, const char* package_name);
 std::string create_data_misc_sdk_sandbox_sdk_path(const char* volume_uuid, bool isCeData,
                                                   userid_t userid, const char* package_name,
-                                                  const char* sdk_name, const char* randomSuffix);
+                                                  const char* sub_dir_name);
 
 std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user);
 std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user);