Merge "CaptureLayers: Avoid promoting parent on binder thread" into tm-dev
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 77bed0e..f32bb24 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -726,8 +726,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;
         }
@@ -746,7 +745,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
@@ -765,7 +764,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
@@ -775,27 +774,6 @@
         if (prepare_app_dir(packagePath, 0751, AID_SYSTEM, AID_SYSTEM)) {
             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);
-        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();
@@ -848,8 +826,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);
 }
 
 /**
@@ -863,17 +841,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
@@ -882,16 +857,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;
     }
@@ -905,37 +873,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);
@@ -944,19 +897,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);
@@ -967,7 +912,7 @@
             const int32_t sandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
             int32_t previousSandboxUid = multiuser_get_sdk_sandbox_uid(userId, previousAppId);
             auto status = createAppDataDirs(path, sandboxUid, AID_NOBODY, &previousSandboxUid,
-                                            cacheGid, seInfo, 0700);
+                                            cacheGid, seInfo, 0700 | S_ISGID);
             if (!status.isOk()) {
                 res = status;
                 continue;
@@ -2152,6 +2097,13 @@
             stats->dataSize += space;
         }
 
+        int sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
+        if (sdkSandboxUid != -1) {
+            if ((space = GetOccupiedSpaceForUid(uuid, sdkSandboxUid)) != -1) {
+                stats->dataSize += space;
+            }
+        }
+
         int cacheGid = multiuser_get_cache_gid(userId, appId);
         if (cacheGid != -1) {
             if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
@@ -2259,8 +2211,17 @@
     closedir(d);
 }
 
+void collectManualStatsForSubDirectories(const std::string& path, struct stats* stats) {
+    const auto subDirHandler = [&path, &stats](const std::string& subDir) {
+        auto fullpath = path + "/" + subDir;
+        collectManualStats(fullpath, stats);
+    };
+    foreach_subdir(path, subDirHandler);
+}
+
 static void collectManualStatsForUser(const std::string& path, struct stats* stats,
-        bool exclude_apps = false) {
+                                      bool exclude_apps = false,
+                                      bool is_sdk_sandbox_storage = false) {
     DIR *d;
     int dfd;
     struct dirent *de;
@@ -2285,6 +2246,11 @@
                 continue;
             } else if (exclude_apps && (user_uid >= AID_APP_START && user_uid <= AID_APP_END)) {
                 continue;
+            } else if (is_sdk_sandbox_storage) {
+                // In case of sdk sandbox storage (e.g. /data/misc_ce/0/sdksandbox/<package-name>),
+                // collect individual stats of each subdirectory (shared, storage of each sdk etc.)
+                collectManualStatsForSubDirectories(StringPrintf("%s/%s", path.c_str(), name),
+                                                    stats);
             } else {
                 collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
             }
@@ -2427,6 +2393,19 @@
             collectManualStats(dePath, &stats);
             ATRACE_END();
 
+            // In case of sdk sandbox storage (e.g. /data/misc_ce/0/sdksandbox/<package-name>),
+            // collect individual stats of each subdirectory (shared, storage of each sdk etc.)
+            if (appId >= AID_APP_START && appId <= AID_APP_END) {
+                ATRACE_BEGIN("sdksandbox");
+                auto sdkSandboxCePath =
+                        create_data_misc_sdk_sandbox_package_path(uuid_, true, userId, pkgname);
+                collectManualStatsForSubDirectories(sdkSandboxCePath, &stats);
+                auto sdkSandboxDePath =
+                        create_data_misc_sdk_sandbox_package_path(uuid_, false, userId, pkgname);
+                collectManualStatsForSubDirectories(sdkSandboxDePath, &stats);
+                ATRACE_END();
+            }
+
             if (!uuid) {
                 ATRACE_BEGIN("profiles");
                 calculate_tree_size(
@@ -2663,6 +2642,13 @@
         collectManualStatsForUser(dePath, &stats);
         ATRACE_END();
 
+        ATRACE_BEGIN("sdksandbox");
+        auto sdkSandboxCePath = create_data_misc_sdk_sandbox_path(uuid_, true, userId);
+        collectManualStatsForUser(sdkSandboxCePath, &stats, false, true);
+        auto sdkSandboxDePath = create_data_misc_sdk_sandbox_path(uuid_, false, userId);
+        collectManualStatsForUser(sdkSandboxDePath, &stats, false, true);
+        ATRACE_END();
+
         if (!uuid) {
             ATRACE_BEGIN("profile");
             auto userProfilePath = create_primary_cur_profile_dir_path(userId);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 1f0fc9c..5c21842 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 04558d5..38cb370 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 {
@@ -992,16 +994,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;
@@ -1051,22 +1049,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 | 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 | 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;
@@ -1078,7 +1066,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.
@@ -1092,7 +1080,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;
@@ -1107,7 +1095,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;
@@ -1124,102 +1112,58 @@
 
 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));
 
     const std::string barCePath = "misc_ce/0/sdksandbox/com.foo/bar@random1";
-    CheckFileAccess(barCePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | 0700);
+    CheckFileAccess(barCePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
     CheckFileAccess(barCePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
     CheckFileAccess(barCePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
 
     const std::string bazCePath = "misc_ce/0/sdksandbox/com.foo/baz@random2";
-    CheckFileAccess(bazCePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | 0700);
+    CheckFileAccess(bazCePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
     CheckFileAccess(bazCePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
     CheckFileAccess(bazCePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
 
     const std::string barDePath = "misc_de/0/sdksandbox/com.foo/bar@random1";
-    CheckFileAccess(barDePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | 0700);
+    CheckFileAccess(barDePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
     CheckFileAccess(barDePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
     CheckFileAccess(barDePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
 
     const std::string bazDePath = "misc_de/0/sdksandbox/com.foo/baz@random2";
-    CheckFileAccess(bazDePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | 0700);
+    CheckFileAccess(bazDePath, kTestSdkSandboxUid, kNobodyUid, S_IFDIR | S_ISGID | 0700);
     CheckFileAccess(bazDePath + "/cache", kTestSdkSandboxUid, kTestCacheGid,
                     S_IFDIR | S_ISGID | 0771);
     CheckFileAccess(bazDePath + "/code_cache", kTestSdkSandboxUid, kTestCacheGid,
                     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 | 0700);
-    CheckFileAccess("misc_ce/0/sdksandbox/com.foo/baz@random2", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | 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));
 
     // New directoris should exist
     CheckFileAccess("misc_ce/0/sdksandbox/com.foo/bar.diff@random1", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | 0700);
+                    S_IFDIR | S_ISGID | 0700);
     CheckFileAccess("misc_ce/0/sdksandbox/com.foo/baz@random2", kTestSdkSandboxUid, kNobodyUid,
-                    S_IFDIR | 0700);
+                    S_IFDIR | S_ISGID | 0700);
     // Directory for old unreferred sdksandbox package name should be removed
     ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo/bar@random1"));
 }
@@ -1270,130 +1214,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 8cfd123..123e3d4 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -223,28 +223,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 54d77f9..cb30993 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);
diff --git a/include/android/storage_manager.h b/include/android/storage_manager.h
index 7f2ee08..270570e 100644
--- a/include/android/storage_manager.h
+++ b/include/android/storage_manager.h
@@ -124,6 +124,12 @@
 
 /**
  * Attempts to mount an OBB file. This is an asynchronous operation.
+ *
+ * Since API level 33, this function can only be used to mount unencrypted OBBs,
+ * i.e. the {@code key} parameter must be {@code null} or an empty string. Note
+ * that even before API level 33, mounting encrypted OBBs didn't work on many
+ * Android device implementations. Applications should not assume any particular
+ * behavior when {@code key} is nonempty.
  */
 void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
         AStorageManager_obbCallbackFunc cb, void* data);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 504c6c2..a217a15 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1862,6 +1862,7 @@
 {
     status_t status = readNullableStrongBinder(val);
     if (status == OK && !val->get()) {
+        ALOGW("Expecting binder but got null!");
         status = UNEXPECTED_NULL;
     }
     return status;
diff --git a/libs/binder/ParcelableHolder.cpp b/libs/binder/ParcelableHolder.cpp
index 2e86b74..3cf94e3 100644
--- a/libs/binder/ParcelableHolder.cpp
+++ b/libs/binder/ParcelableHolder.cpp
@@ -52,7 +52,10 @@
 }
 
 status_t ParcelableHolder::readFromParcel(const Parcel* p) {
-    this->mStability = static_cast<Stability>(p->readInt32());
+    int32_t wireStability;
+    if (status_t status = p->readInt32(&wireStability); status != OK) return status;
+    if (static_cast<int32_t>(this->mStability) != wireStability) return BAD_VALUE;
+
     this->mParcelable = nullptr;
     this->mParcelableName = std::nullopt;
     int32_t rawDataSize;
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
index 28819bb..f45aa76 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -101,7 +101,12 @@
             return STATUS_INVALID_OPERATION;
         }
 
-        RETURN_ON_FAILURE(AParcel_readInt32(parcel, &this->mStability));
+        parcelable_stability_t wireStability;
+        RETURN_ON_FAILURE(AParcel_readInt32(parcel, &wireStability));
+        if (this->mStability != wireStability) {
+            return STATUS_BAD_VALUE;
+        }
+
         int32_t dataSize;
         binder_status_t status = AParcel_readInt32(parcel, &dataSize);
 
diff --git a/libs/binder/rust/src/parcel/parcelable_holder.rs b/libs/binder/rust/src/parcel/parcelable_holder.rs
index d58e839..432da5d 100644
--- a/libs/binder/rust/src/parcel/parcelable_holder.rs
+++ b/libs/binder/rust/src/parcel/parcelable_holder.rs
@@ -233,7 +233,9 @@
     }
 
     fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode> {
-        self.stability = parcel.read()?;
+        if self.stability != parcel.read()? {
+            return Err(StatusCode::BAD_VALUE);
+        }
 
         let data_size: i32 = parcel.read()?;
         if data_size < 0 {
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index 38bde3a..57d496d 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -66,10 +66,13 @@
     srcs: [
         "random_fd.cpp",
         "random_parcel.cpp",
+        "libbinder_driver.cpp",
+        "libbinder_ndk_driver.cpp",
     ],
     shared_libs: [
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libutils",
     ],
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
new file mode 100644
index 0000000..a9a6197
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/IBinder.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+/**
+ * Based on the random data in provider, construct an arbitrary number of
+ * Parcel objects and send them to the service in serial.
+ *
+ * Usage:
+ *
+ *   extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ *       FuzzedDataProvider provider = FuzzedDataProvider(data, size);
+ *       // can use provider here to create a service with different options
+ *       sp<IFoo> myService = sp<IFoo>::make(...);
+ *       fuzzService(myService, std::move(provider));
+ *   }
+ */
+void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider);
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
new file mode 100644
index 0000000..f2b7823
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_parcel.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+/**
+ * Based on the random data in provider, construct an arbitrary number of
+ * Parcel objects and send them to the service in serial.
+ *
+ * Usage:
+ *
+ *   extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ *       FuzzedDataProvider provider = FuzzedDataProvider(data, size);
+ *       // can use provider here to create a service with different options
+ *       std::shared_ptr<IFoo> myService = ndk::SharedRefBase<IFoo>::make(...);
+ *       fuzzService(myService->asBinder().get(), std::move(provider));
+ *   }
+ */
+void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider);
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
new file mode 100644
index 0000000..e849c9b
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include <fuzzbinder/random_parcel.h>
+
+namespace android {
+
+void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) {
+    while (provider.remaining_bytes() > 0) {
+        uint32_t code = provider.ConsumeIntegral<uint32_t>();
+        uint32_t flags = provider.ConsumeIntegral<uint32_t>();
+        Parcel data;
+
+        std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>(
+                provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
+        fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()));
+
+        Parcel reply;
+        (void)binder->transact(code, data, &reply, flags);
+    }
+}
+
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
new file mode 100644
index 0000000..462ef9a
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+
+#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzbinder/random_parcel.h>
+
+// libbinder_ndk doesn't export this header which breaks down its API for NDK
+// and APEX users, but we need access to it to fuzz.
+#include "../../ndk/ibinder_internal.h"
+
+namespace android {
+
+void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider) {
+    fuzzService(binder->getBinder(), std::move(provider));
+}
+
+} // namespace android
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 606fe2a..18fb7c1 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -112,7 +112,7 @@
                 "frameworks/native/libs/arect/include",
             ],
         },
-        linux_glibc: {
+        host_linux: {
             srcs: [
                 "InputTransport.cpp",
                 "android/os/IInputConstants.aidl",
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 81747d5..ec59888 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -618,15 +618,15 @@
     }
 }
 
-void SurfaceFrame::tracePredictions(int64_t displayFrameToken) const {
+void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
     int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
 
     // Expected timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
-        packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+        packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
 
         auto* event = packet->set_frame_timeline_event();
         auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
@@ -644,8 +644,8 @@
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
-        packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+        packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
 
         auto* event = packet->set_frame_timeline_event();
         auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
@@ -654,14 +654,14 @@
     });
 }
 
-void SurfaceFrame::traceActuals(int64_t displayFrameToken) const {
+void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
     int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
 
     // Actual timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
         // Actual start time is not yet available, so use expected start instead
         if (mPredictionState == PredictionState::Expired) {
             // If prediction is expired, we can't use the predicted start time. Instead, just use a
@@ -669,11 +669,12 @@
             // frame in the trace.
             nsecs_t endTime =
                     (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
-            packet->set_timestamp(
-                    static_cast<uint64_t>(endTime - kPredictionExpiredStartTimeDelta));
+            packet->set_timestamp(static_cast<uint64_t>(endTime - kPredictionExpiredStartTimeDelta +
+                                                        monoBootOffset));
         } else {
-            packet->set_timestamp(static_cast<uint64_t>(
-                    mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime));
+            packet->set_timestamp(static_cast<uint64_t>(monoBootOffset + mActuals.startTime == 0
+                                                                ? mPredictions.startTime
+                                                                : mActuals.startTime));
         }
 
         auto* event = packet->set_frame_timeline_event();
@@ -706,11 +707,11 @@
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         std::scoped_lock lock(mMutex);
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
         if (mPresentState == PresentState::Dropped) {
-            packet->set_timestamp(static_cast<uint64_t>(mDropTime));
+            packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
         } else {
-            packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
+            packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
         }
 
         auto* event = packet->set_frame_timeline_event();
@@ -723,7 +724,7 @@
 /**
  * TODO(b/178637512): add inputEventId to the perfetto trace.
  */
-void SurfaceFrame::trace(int64_t displayFrameToken) const {
+void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
     if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
         displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
         // No packets can be traced with a missing token.
@@ -732,9 +733,9 @@
     if (getPredictionState() != PredictionState::Expired) {
         // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
         // a trace.
-        tracePredictions(displayFrameToken);
+        tracePredictions(displayFrameToken, monoBootOffset);
     }
-    traceActuals(displayFrameToken);
+    traceActuals(displayFrameToken, monoBootOffset);
 }
 
 namespace impl {
@@ -760,8 +761,9 @@
 }
 
 FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
-                             JankClassificationThresholds thresholds)
-      : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
+                             JankClassificationThresholds thresholds, bool useBootTimeClock)
+      : mUseBootTimeClock(useBootTimeClock),
+        mMaxDisplayFrames(kDefaultMaxDisplayFrames),
         mTimeStats(std::move(timeStats)),
         mSurfaceFlingerPid(surfaceFlingerPid),
         mJankClassificationThresholds(thresholds) {
@@ -1016,14 +1018,16 @@
     }
 }
 
-void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid) const {
+void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
+                                                   nsecs_t monoBootOffset) const {
     int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
 
     // Expected timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
-        packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime));
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+        packet->set_timestamp(
+                static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
 
         auto* event = packet->set_frame_timeline_event();
         auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
@@ -1037,8 +1041,9 @@
     // Expected timeline end
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
-        packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime));
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+        packet->set_timestamp(
+                static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
 
         auto* event = packet->set_frame_timeline_event();
         auto* expectedDisplayFrameEndEvent = event->set_frame_end();
@@ -1047,14 +1052,16 @@
     });
 }
 
-void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid) const {
+void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
+                                               nsecs_t monoBootOffset) const {
     int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
 
     // Actual timeline start
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
-        packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.startTime));
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+        packet->set_timestamp(
+                static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
 
         auto* event = packet->set_frame_timeline_event();
         auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
@@ -1075,8 +1082,9 @@
     // Actual timeline end
     FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
         auto packet = ctx.NewTracePacket();
-        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
-        packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime));
+        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+        packet->set_timestamp(
+                static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
 
         auto* event = packet->set_frame_timeline_event();
         auto* actualDisplayFrameEndEvent = event->set_frame_end();
@@ -1085,7 +1093,7 @@
     });
 }
 
-void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const {
+void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const {
     if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
         // DisplayFrame should not have an invalid token.
         ALOGE("Cannot trace DisplayFrame with invalid token");
@@ -1095,12 +1103,12 @@
     if (mPredictionState == PredictionState::Valid) {
         // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
         // meaningful way in a trace.
-        tracePredictions(surfaceFlingerPid);
+        tracePredictions(surfaceFlingerPid, monoBootOffset);
     }
-    traceActuals(surfaceFlingerPid);
+    traceActuals(surfaceFlingerPid, monoBootOffset);
 
     for (auto& surfaceFrame : mSurfaceFrames) {
-        surfaceFrame->trace(mToken);
+        surfaceFrame->trace(mToken, monoBootOffset);
     }
 }
 
@@ -1164,6 +1172,12 @@
 }
 
 void FrameTimeline::flushPendingPresentFences() {
+    // Perfetto is using boottime clock to void drifts when the device goes
+    // to suspend.
+    const auto monoBootOffset = mUseBootTimeClock
+            ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
+            : 0;
+
     for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
         const auto& pendingPresentFence = mPendingPresentFences[i];
         nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
@@ -1175,7 +1189,7 @@
         }
         auto& displayFrame = pendingPresentFence.second;
         displayFrame->onPresent(signalTime, mPreviousPresentTime);
-        displayFrame->trace(mSurfaceFlingerPid);
+        displayFrame->trace(mSurfaceFlingerPid, monoBootOffset);
         mPreviousPresentTime = signalTime;
 
         mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 36d6290..a2305af 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -204,8 +204,9 @@
     std::string miniDump() const;
     // Emits a packet for perfetto tracing. The function body will be executed only if tracing is
     // enabled. The displayFrameToken is needed to link the SurfaceFrame to the corresponding
-    // DisplayFrame at the trace processor side.
-    void trace(int64_t displayFrameToken) const;
+    // DisplayFrame at the trace processor side. monoBootOffset is the difference
+    // between SYSTEM_TIME_BOOTTIME and SYSTEM_TIME_MONOTONIC.
+    void trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
 
     // Getter functions used only by FrameTimelineTests and SurfaceFrame internally
     TimelineItem getActuals() const;
@@ -225,8 +226,8 @@
             std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
 
 private:
-    void tracePredictions(int64_t displayFrameToken) const;
-    void traceActuals(int64_t displayFrameToken) const;
+    void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
+    void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
     void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
                             nsecs_t& deadlineDelta) REQUIRES(mMutex);
 
@@ -369,8 +370,9 @@
         // Dumpsys interface - dumps all data irrespective of jank
         void dumpAll(std::string& result, nsecs_t baseTime) const;
         // Emits a packet for perfetto tracing. The function body will be executed only if tracing
-        // is enabled.
-        void trace(pid_t surfaceFlingerPid) const;
+        // is enabled. monoBootOffset is the difference between SYSTEM_TIME_BOOTTIME
+        // and SYSTEM_TIME_MONOTONIC.
+        void trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
         // Sets the token, vsyncPeriod, predictions and SF start time.
         void onSfWakeUp(int64_t token, Fps refreshRate, std::optional<TimelineItem> predictions,
                         nsecs_t wakeUpTime);
@@ -401,8 +403,8 @@
 
     private:
         void dump(std::string& result, nsecs_t baseTime) const;
-        void tracePredictions(pid_t surfaceFlingerPid) const;
-        void traceActuals(pid_t surfaceFlingerPid) const;
+        void tracePredictions(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
+        void traceActuals(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
         void classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
                           nsecs_t previousPresentTime);
 
@@ -442,7 +444,7 @@
     };
 
     FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
-                  JankClassificationThresholds thresholds = {});
+                  JankClassificationThresholds thresholds = {}, bool useBootTimeClock = true);
     ~FrameTimeline() = default;
 
     frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
@@ -484,6 +486,7 @@
     TokenManager mTokenManager;
     TraceCookieCounter mTraceCookieCounter;
     mutable std::mutex mMutex;
+    const bool mUseBootTimeClock;
     uint32_t mMaxDisplayFrames;
     std::shared_ptr<TimeStats> mTimeStats;
     const pid_t mSurfaceFlingerPid;
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 834a560..f1efa92 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -66,9 +66,10 @@
     }
 
     void SetUp() override {
+        constexpr bool kUseBootTimeClock = true;
         mTimeStats = std::make_shared<mock::TimeStats>();
         mFrameTimeline = std::make_unique<impl::FrameTimeline>(mTimeStats, kSurfaceFlingerPid,
-                                                               kTestThresholds);
+                                                               kTestThresholds, !kUseBootTimeClock);
         mFrameTimeline->registerDataSource();
         mTokenManager = &mFrameTimeline->mTokenManager;
         mTraceCookieCounter = &mFrameTimeline->mTraceCookieCounter;
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 60c0cb5..6e54d6c 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -632,10 +632,8 @@
         switch (ext_bit) {
             case ProcHook::KHR_android_surface:
             case ProcHook::KHR_surface:
-            case ProcHook::KHR_surface_protected_capabilities:
             case ProcHook::EXT_swapchain_colorspace:
             case ProcHook::KHR_get_surface_capabilities2:
-            case ProcHook::GOOGLE_surfaceless_query:
                 hook_extensions_.set(ext_bit);
                 // return now as these extensions do not require HAL support
                 return;
@@ -712,10 +710,8 @@
             case ProcHook::KHR_external_fence_capabilities:
             case ProcHook::KHR_get_surface_capabilities2:
             case ProcHook::KHR_surface:
-            case ProcHook::KHR_surface_protected_capabilities:
             case ProcHook::EXT_debug_report:
             case ProcHook::EXT_swapchain_colorspace:
-            case ProcHook::GOOGLE_surfaceless_query:
             case ProcHook::ANDROID_native_buffer:
             case ProcHook::EXTENSION_CORE_1_0:
             case ProcHook::EXTENSION_CORE_1_1:
@@ -924,23 +920,17 @@
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
     std::vector<VkExtensionProperties> loader_extensions;
-    loader_extensions.push_back({
-        VK_KHR_SURFACE_EXTENSION_NAME,
-        VK_KHR_SURFACE_SPEC_VERSION});
     loader_extensions.push_back(
-        {VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
-         VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION});
+        {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION});
     loader_extensions.push_back({
         VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
         VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
     loader_extensions.push_back({
         VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
         VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
-    loader_extensions.push_back({
-        VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
-        VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
-    loader_extensions.push_back({VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME,
-                                 VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION});
+    loader_extensions.push_back(
+        {VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+         VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
 
     static const VkExtensionProperties loader_debug_report_extension = {
         VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index b436db1..5f37a50 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -565,13 +565,11 @@
     if (strcmp(name, "VK_EXT_hdr_metadata") == 0) return ProcHook::EXT_hdr_metadata;
     if (strcmp(name, "VK_EXT_swapchain_colorspace") == 0) return ProcHook::EXT_swapchain_colorspace;
     if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
-    if (strcmp(name, "VK_GOOGLE_surfaceless_query") == 0) return ProcHook::GOOGLE_surfaceless_query;
     if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
     if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
     if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
     if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
     if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
-    if (strcmp(name, "VK_KHR_surface_protected_capabilities") == 0) return ProcHook::KHR_surface_protected_capabilities;
     if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
     if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
     if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 079f9cc..819f6b2 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -41,13 +41,11 @@
         EXT_hdr_metadata,
         EXT_swapchain_colorspace,
         GOOGLE_display_timing,
-        GOOGLE_surfaceless_query,
         KHR_android_surface,
         KHR_get_surface_capabilities2,
         KHR_incremental_present,
         KHR_shared_presentable_image,
         KHR_surface,
-        KHR_surface_protected_capabilities,
         KHR_swapchain,
         ANDROID_external_memory_android_hardware_buffer,
         KHR_bind_memory2,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 0be4403..6dce394 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -619,65 +619,43 @@
 
 VKAPI_ATTR
 VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
-    VkPhysicalDevice pdev,
+    VkPhysicalDevice /*pdev*/,
     VkSurfaceKHR surface,
     VkSurfaceCapabilitiesKHR* capabilities) {
     ATRACE_CALL();
 
     int err;
+    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
     int width, height;
+    err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
+    if (err != android::OK) {
+        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
+    if (err != android::OK) {
+        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+
     int transform_hint;
+    err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
+    if (err != android::OK) {
+        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+
     int max_buffer_count;
-    if (surface == VK_NULL_HANDLE) {
-        const InstanceData& instance_data = GetData(pdev);
-        ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
-        bool surfaceless_enabled =
-            instance_data.hook_extensions.test(surfaceless);
-        if (!surfaceless_enabled) {
-            // It is an error to pass a surface==VK_NULL_HANDLE unless the
-            // VK_GOOGLE_surfaceless_query extension is enabled
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        // Support for VK_GOOGLE_surfaceless_query.  The primary purpose of this
-        // extension for this function is for
-        // VkSurfaceProtectedCapabilitiesKHR::supportsProtected.  The following
-        // four values cannot be known without a surface.  Default values will
-        // be supplied anyway, but cannot be relied upon.
-        width = 1000;
-        height = 1000;
-        transform_hint = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        max_buffer_count = 10;
-    } else {
-        ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
-
-        err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
-        if (err != android::OK) {
-            ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
-                  strerror(-err), err);
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
-        if (err != android::OK) {
-            ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
-                  strerror(-err), err);
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-
-        err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
-                            &transform_hint);
-        if (err != android::OK) {
-            ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
-                  strerror(-err), err);
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-
-        err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT,
-                            &max_buffer_count);
-        if (err != android::OK) {
-            ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
-                  strerror(-err), err);
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
+    err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT,
+                        &max_buffer_count);
+    if (err != android::OK) {
+        ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     capabilities->minImageCount = std::min(max_buffer_count, 3);
     capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
@@ -718,43 +696,23 @@
     const InstanceData& instance_data = GetData(pdev);
 
     bool wide_color_support = false;
-    uint64_t consumer_usage = 0;
-    bool swapchain_ext =
-        instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
-    if (surface_handle == VK_NULL_HANDLE) {
-        ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
-        bool surfaceless_enabled =
-            instance_data.hook_extensions.test(surfaceless);
-        if (!surfaceless_enabled) {
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        // Support for VK_GOOGLE_surfaceless_query.  The EGL loader
-        // unconditionally supports wide color formats, even if they will cause
-        // a SurfaceFlinger fallback.  Based on that, wide_color_support will be
-        // set to true in this case.
-        wide_color_support = true;
-
-        // TODO(b/203826952): research proper value; temporarily use the
-        // values seen on Pixel
-        consumer_usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
-    } else {
-        Surface& surface = *SurfaceFromHandle(surface_handle);
-        int err = native_window_get_wide_color_support(surface.window.get(),
-                                                       &wide_color_support);
-        if (err) {
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        ALOGV("wide_color_support is: %d", wide_color_support);
-
-        consumer_usage = surface.consumer_usage;
+    Surface& surface = *SurfaceFromHandle(surface_handle);
+    int err = native_window_get_wide_color_support(surface.window.get(),
+                                                   &wide_color_support);
+    if (err) {
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
-    wide_color_support = wide_color_support && swapchain_ext;
+    ALOGV("wide_color_support is: %d", wide_color_support);
+    wide_color_support =
+        wide_color_support &&
+        instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
 
     AHardwareBuffer_Desc desc = {};
     desc.width = 1;
     desc.height = 1;
     desc.layers = 1;
-    desc.usage = consumer_usage | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+    desc.usage = surface.consumer_usage |
+                 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
                  AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
 
     // We must support R8G8B8A8
@@ -762,11 +720,6 @@
         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
         {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
 
-    if (swapchain_ext) {
-        all_formats.emplace_back(VkSurfaceFormatKHR{
-            VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_BT709_LINEAR_EXT});
-    }
-
     if (wide_color_support) {
         all_formats.emplace_back(VkSurfaceFormatKHR{
             VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
@@ -774,10 +727,6 @@
             VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
     }
 
-    // NOTE: Any new formats that are added must be coordinated across different
-    // Android users.  This includes the ANGLE team (a layered implementation of
-    // OpenGL-ES).
-
     desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
     if (AHardwareBuffer_isSupported(&desc)) {
         all_formats.emplace_back(VkSurfaceFormatKHR{
@@ -865,12 +814,6 @@
                         .supportedUsageFlags;
             } break;
 
-            case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
-                VkSurfaceProtectedCapabilitiesKHR* protected_caps =
-                    reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(caps);
-                protected_caps->supportsProtected = VK_TRUE;
-            } break;
-
             default:
                 // Ignore all other extension structs
                 break;
@@ -922,51 +865,31 @@
 
     int err;
     int query_value;
-    std::vector<VkPresentModeKHR> present_modes;
-    if (surface == VK_NULL_HANDLE) {
-        const InstanceData& instance_data = GetData(pdev);
-        ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
-        bool surfaceless_enabled =
-            instance_data.hook_extensions.test(surfaceless);
-        if (!surfaceless_enabled) {
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        // Support for VK_GOOGLE_surfaceless_query.  The primary purpose of this
-        // extension for this function is for
-        // VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and
-        // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR.  We technically cannot
-        // know if VK_PRESENT_MODE_SHARED_MAILBOX_KHR is supported without a
-        // surface, and that cannot be relied upon.
-        present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
-        present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
-    } else {
-        ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
 
-        err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-                            &query_value);
-        if (err != android::OK || query_value < 0) {
-            ALOGE(
-                "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
-                "value=%d",
-                strerror(-err), err, query_value);
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
-
-        err =
-            window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
-        if (err != android::OK || query_value < 0) {
-            ALOGE(
-                "NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
-                strerror(-err), err, query_value);
-            return VK_ERROR_SURFACE_LOST_KHR;
-        }
-        uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
-
-        if (min_undequeued_buffers + 1 < max_buffer_count)
-            present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
-        present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+    err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                        &query_value);
+    if (err != android::OK || query_value < 0) {
+        ALOGE(
+            "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
+            "value=%d",
+            strerror(-err), err, query_value);
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
+    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
+
+    err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
+    if (err != android::OK || query_value < 0) {
+        ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
+              strerror(-err), err, query_value);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+    uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
+
+    std::vector<VkPresentModeKHR> present_modes;
+    if (min_undequeued_buffers + 1 < max_buffer_count)
+        present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
+    present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
 
     VkPhysicalDevicePresentationPropertiesANDROID present_properties;
     QueryPresentationProperties(pdev, &present_properties);
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index af56764..6a73023 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -27,13 +27,11 @@
     'VK_EXT_hdr_metadata',
     'VK_EXT_swapchain_colorspace',
     'VK_GOOGLE_display_timing',
-    'VK_GOOGLE_surfaceless_query',
     'VK_KHR_android_surface',
     'VK_KHR_get_surface_capabilities2',
     'VK_KHR_incremental_present',
     'VK_KHR_shared_presentable_image',
     'VK_KHR_surface',
-    'VK_KHR_surface_protected_capabilities',
     'VK_KHR_swapchain',
 ]