Merge "Tweak libtonemap's CPU interface to support batching." into tm-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 0e9ce89..24b201f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2418,7 +2418,7 @@
     // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
     // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
     // will kill the HAL and grab whatever it dumped in time.
-    constexpr size_t timeout_sec = 30;
+    constexpr size_t timeout_sec = 45;
 
     if (dumpstate_hal_handle_aidl != nullptr) {
         DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
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/BufferedTextOutput.h b/libs/binder/BufferedTextOutput.h
index fdd532a..57e03cb 100644
--- a/libs/binder/BufferedTextOutput.h
+++ b/libs/binder/BufferedTextOutput.h
@@ -18,8 +18,8 @@
 #define ANDROID_BUFFEREDTEXTOUTPUT_H
 
 #include <binder/TextOutput.h>
-#include <utils/threads.h>
 #include <sys/uio.h>
+#include <utils/Mutex.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 9c7ff97..c6b0cb7 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -31,7 +31,7 @@
 #include <binder/Parcel.h>
 #include <log/log.h>
 
-#include <utils/threads.h>
+#include <utils/Mutex.h>
 
 #include <map>
 
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index f79075d..3c97dca 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -27,7 +27,6 @@
 #include <utils/CallStack.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
-#include <utils/threads.h>
 
 #include <atomic>
 #include <errno.h>
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index c4475c7..03553f3 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -23,7 +23,6 @@
 #include <utils/Log.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
-#include <utils/threads.h>
 
 #include <stdint.h>
 #include <stdio.h>
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index e1cbc19..8132d46 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -18,10 +18,13 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/memfd.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -34,6 +37,24 @@
 
 // ---------------------------------------------------------------------------
 
+#ifdef __BIONIC__
+static int memfd_create_region(const char* name, size_t size) {
+    int fd = memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
+    if (fd == -1) {
+        ALOGE("%s: memfd_create(%s, %zd) failed: %s\n", __func__, name, size, strerror(errno));
+        return -1;
+    }
+
+    if (ftruncate(fd, size) == -1) {
+        ALOGE("%s, ftruncate(%s, %zd) failed for memfd creation: %s\n", __func__, name, size,
+              strerror(errno));
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+#endif
+
 MemoryHeapBase::MemoryHeapBase()
     : mFD(-1), mSize(0), mBase(MAP_FAILED),
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
@@ -45,15 +66,36 @@
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
 {
     const size_t pagesize = getpagesize();
-    size = ((size + pagesize-1) & ~(pagesize-1));
-    int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size);
-    ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno));
-    if (fd >= 0) {
-        if (mapfd(fd, true, size) == NO_ERROR) {
-            if (flags & READ_ONLY) {
-                ashmem_set_prot_region(fd, PROT_READ);
-            }
+    size = ((size + pagesize - 1) & ~(pagesize - 1));
+    int fd = -1;
+    if (mFlags & FORCE_MEMFD) {
+#ifdef __BIONIC__
+        ALOGV("MemoryHeapBase: Attempting to force MemFD");
+        fd = memfd_create_region(name ? name : "MemoryHeapBase", size);
+        if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
+        const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) |
+                ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL);
+        if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) {
+            ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error  %s", name,
+                  SEAL_FLAGS, strerror(errno));
+            munmap(mBase, mSize);
+            mBase = nullptr;
+            mSize = 0;
+            close(fd);
         }
+        return;
+#else
+        mFlags &= ~(FORCE_MEMFD | MEMFD_ALLOW_SEALING);
+#endif
+    }
+    if (mFlags & MEMFD_ALLOW_SEALING) {
+      LOG_ALWAYS_FATAL("Invalid Flags. MEMFD_ALLOW_SEALING only valid with FORCE_MEMFD.");
+    }
+    fd = ashmem_create_region(name ? name : "MemoryHeapBase", size);
+    ALOGE_IF(fd < 0, "MemoryHeapBase: error creating ashmem region: %s", strerror(errno));
+    if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
+    if (mFlags & READ_ONLY) {
+        ashmem_set_prot_region(fd, PROT_READ);
     }
 }
 
@@ -61,6 +103,9 @@
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
 {
+    if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+        LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
+    }
     int open_flags = O_RDWR;
     if (flags & NO_CACHING)
         open_flags |= O_SYNC;
@@ -80,6 +125,9 @@
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
 {
+    if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+        LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
+    }
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
     mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), false, size, offset);
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/ProcessState.cpp b/libs/binder/ProcessState.cpp
index b14a838..4a01d81 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -25,9 +25,10 @@
 #include <binder/IServiceManager.h>
 #include <binder/Stability.h>
 #include <cutils/atomic.h>
+#include <utils/AndroidThreads.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
-#include <utils/threads.h>
+#include <utils/Thread.h>
 
 #include "Static.h"
 #include "binder_module.h"
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index e79cb86..d40778a 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -853,10 +853,16 @@
         }
 
         if (session->mConnections.mOutgoing.size() == 0) {
-            ALOGE("Session has no client connections. This is required for an RPC server to make "
-                  "any non-nested (e.g. oneway or on another thread) calls. Use: %d. Server "
-                  "connections: %zu",
-                  static_cast<int>(use), session->mConnections.mIncoming.size());
+            ALOGE("Session has no outgoing connections. This is required for an RPC server to make "
+                  "any non-nested (e.g. oneway or on another thread) calls. Use code request "
+                  "reason: %d. Incoming connections: %zu. %s.",
+                  static_cast<int>(use), session->mConnections.mIncoming.size(),
+                  (session->server()
+                           ? "This is a server session, so see RpcSession::setMaxIncomingThreads "
+                             "for the corresponding client"
+                           : "This is a client session, so see RpcSession::setMaxOutgoingThreads "
+                             "for this client or RpcServer::setMaxThreads for the corresponding "
+                             "server"));
             return WOULD_BLOCK;
         }
 
diff --git a/libs/binder/Static.h b/libs/binder/Static.h
index 83524e8..8444fe7 100644
--- a/libs/binder/Static.h
+++ b/libs/binder/Static.h
@@ -17,8 +17,6 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
-#include <utils/threads.h>
-
 #include <binder/IBinder.h>
 #include <binder/ProcessState.h>
 
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 8deb2fe..19ad5e6 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -18,7 +18,6 @@
 
 #include <binder/IBinder.h>
 #include <utils/Mutex.h>
-#include <utils/threads.h>
 
 #include <map>
 #include <unordered_map>
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index dd76943..15dd28f 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -34,7 +34,21 @@
         // memory won't be mapped locally, but will be mapped in the remote
         // process.
         DONT_MAP_LOCALLY = 0x00000100,
-        NO_CACHING = 0x00000200
+        NO_CACHING = 0x00000200,
+        // Bypass ashmem-libcutils to create a memfd shared region.
+        // Ashmem-libcutils will eventually migrate to memfd.
+        // Memfd has security benefits and supports file sealing.
+        // Calling process will need to modify selinux permissions to
+        // open access to tmpfs files. See audioserver for examples.
+        // This is only valid for size constructor.
+        // For host compilation targets, memfd is stubbed in favor of /tmp
+        // files so sealing is not enforced.
+        FORCE_MEMFD = 0x00000400,
+        // Default opt-out of sealing behavior in memfd to avoid potential DOS.
+        // Clients of shared files can seal at anytime via syscall, leading to
+        // TOC/TOU issues if additional seals prevent access from the creating
+        // process. Alternatively, seccomp fcntl().
+        MEMFD_ALLOW_SEALING = 0x00000800
     };
 
     /*
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
index e658574..6f9eb5e 100644
--- a/libs/binder/include/binder/PermissionController.h
+++ b/libs/binder/include/binder/PermissionController.h
@@ -19,8 +19,7 @@
 #ifndef __ANDROID_VNDK__
 
 #include <binder/IPermissionController.h>
-
-#include <utils/threads.h>
+#include <utils/Mutex.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 0deee73..675585e 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -18,11 +18,10 @@
 
 #include <binder/IBinder.h>
 #include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
 
-#include <utils/threads.h>
-
 #include <pthread.h>
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/include_activitymanager/binder/ActivityManager.h b/libs/binder/include_activitymanager/binder/ActivityManager.h
index b772b80..abc7f1d 100644
--- a/libs/binder/include_activitymanager/binder/ActivityManager.h
+++ b/libs/binder/include_activitymanager/binder/ActivityManager.h
@@ -18,10 +18,9 @@
 
 #ifndef __ANDROID_VNDK__
 
-#include <binder/IActivityManager.h>
 #include <android/app/ProcessStateEnum.h>
-
-#include <utils/threads.h>
+#include <binder/IActivityManager.h>
+#include <utils/Mutex.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
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/Android.bp b/libs/binder/tests/Android.bp
index ff55d6e..a3533d8 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -99,6 +99,7 @@
         "binderParcelUnitTest.cpp",
         "binderBinderUnitTest.cpp",
         "binderStatusUnitTest.cpp",
+        "binderMemoryHeapBaseUnitTest.cpp",
     ],
     shared_libs: [
         "libbinder",
diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
new file mode 100644
index 0000000..21cb70b
--- /dev/null
+++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 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 <binder/MemoryHeapBase.h>
+#include <cutils/ashmem.h>
+#include <fcntl.h>
+
+#include <gtest/gtest.h>
+using namespace android;
+#ifdef __BIONIC__
+TEST(MemoryHeapBase, ForceMemfdRespected) {
+    auto mHeap = sp<MemoryHeapBase>::make(10, MemoryHeapBase::FORCE_MEMFD, "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_FALSE(ashmem_valid(fd));
+    EXPECT_NE(fcntl(fd, F_GET_SEALS), -1);
+}
+
+TEST(MemoryHeapBase, MemfdSealed) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL);
+}
+
+TEST(MemoryHeapBase, MemfdUnsealed) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::MEMFD_ALLOW_SEALING,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0);
+}
+
+TEST(MemoryHeapBase, MemfdSealedProtected) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::READ_ONLY,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE);
+}
+
+TEST(MemoryHeapBase, MemfdUnsealedProtected) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::READ_ONLY |
+                                          MemoryHeapBase::MEMFD_ALLOW_SEALING,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE);
+}
+
+#else
+TEST(MemoryHeapBase, HostMemfdExpected) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::READ_ONLY,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    void* ptr = mHeap->getBase();
+    EXPECT_NE(ptr, MAP_FAILED);
+    EXPECT_TRUE(ashmem_valid(fd));
+    EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
+}
+
+TEST(MemoryHeapBase,HostMemfdException) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::READ_ONLY |
+                                          MemoryHeapBase::MEMFD_ALLOW_SEALING,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    void* ptr = mHeap->getBase();
+    EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
+    EXPECT_TRUE(ashmem_valid(fd));
+    EXPECT_NE(ptr, MAP_FAILED);
+}
+
+#endif
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/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
index 749bf21..633626c 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
@@ -19,13 +19,18 @@
 #include <binder/Parcel.h>
 #include <fuzzer/FuzzedDataProvider.h>
 
+#include <functional>
+
 namespace android {
 /**
  * Fill parcel data, including some random binder objects and FDs
+ *
+ * p - the Parcel to fill
+ * provider - takes ownership and completely consumes provider
+ * writeHeader - optional function to write a specific header once the format of the parcel is
+ *     picked (for instance, to write an interface header)
  */
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
-/**
- * Fill parcel data, but don't fill any objects.
- */
-void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider);
+void fillRandomParcel(
+        Parcel* p, FuzzedDataProvider&& provider,
+        std::function<void(Parcel* p, FuzzedDataProvider& provider)> writeHeader = nullptr);
 } // 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..be39bb9
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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()),
+                         [&binder](Parcel* p, FuzzedDataProvider& provider) {
+                             // most code will be behind checks that the head of the Parcel
+                             // is exactly this, so make it easier for fuzzers to reach this
+                             if (provider.ConsumeBool()) {
+                                 p->writeInterfaceToken(binder->getInterfaceDescriptor());
+                             }
+                         });
+
+        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/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 8bf04cc..cfabc1e 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -34,15 +34,26 @@
     String16 mDescriptor;
 };
 
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider) {
+static void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) {
+    std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes());
+    CHECK(OK == p->write(data.data(), data.size()));
+}
+
+void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider,
+                      std::function<void(Parcel* p, FuzzedDataProvider& provider)> writeHeader) {
     if (provider.ConsumeBool()) {
         auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
         CHECK_EQ(OK, session->addNullDebuggingClient());
         p->markForRpc(session);
+
+        writeHeader(p, provider);
+
         fillRandomParcelData(p, std::move(provider));
         return;
     }
 
+    writeHeader(p, provider);
+
     while (provider.remaining_bytes() > 0) {
         auto fillFunc = provider.PickValueInArray<const std::function<void()>>({
                 // write data
@@ -85,9 +96,4 @@
     }
 }
 
-void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) {
-    std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes());
-    CHECK(OK == p->write(data.data(), data.size()));
-}
-
 } // namespace android
diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
index 741987f..5079431 100644
--- a/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
+++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
@@ -30,7 +30,6 @@
 #include <utils/KeyedVector.h>
 #include <utils/Log.h>
 #include <utils/Mutex.h>
-#include <utils/threads.h>
 
 #include <stdio.h>
 
diff --git a/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
index 4a0aeba..bf7c613 100644
--- a/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
+++ b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
@@ -27,7 +27,6 @@
 #include <utils/KeyedVector.h>
 #include <utils/Log.h>
 #include <utils/Mutex.h>
-#include <utils/threads.h>
 
 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/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
index 1100cad..6e5e14d 100644
--- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -66,13 +66,13 @@
     sp<IPower> hal = waitForVintfService<IPower>();
 
     if (hal == nullptr) {
-        ALOGI("Power HAL not available, skipping test...");
+        ALOGV("Power HAL not available, skipping test...");
         return;
     }
 
     binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...);
     if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
-        ALOGI("Power HAL does not support this operation, skipping test...");
+        ALOGV("Power HAL does not support this operation, skipping test...");
         return;
     }
 
@@ -93,7 +93,7 @@
     sp<IPower> pwHal = waitForVintfService<IPower>();
 
     if (pwHal == nullptr) {
-        ALOGI("Power HAL not available, skipping test...");
+        ALOGV("Power HAL not available, skipping test...");
         return;
     }
 
@@ -105,13 +105,13 @@
     auto status = pwHal->createHintSession(1, 0, threadIds, durationNanos, &hal);
 
     if (hal == nullptr) {
-        ALOGI("Power HAL doesn't support session, skipping test...");
+        ALOGV("Power HAL doesn't support session, skipping test...");
         return;
     }
 
     binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...);
     if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
-        ALOGI("Power HAL does not support this operation, skipping test...");
+        ALOGV("Power HAL does not support this operation, skipping test...");
         return;
     }
 
@@ -159,13 +159,13 @@
     sp<IPower> hal = waitForVintfService<IPower>();
 
     if (hal == nullptr) {
-        ALOGI("Power HAL not available, skipping test...");
+        ALOGV("Power HAL not available, skipping test...");
         return;
     }
 
     binder::Status ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
     if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
-        ALOGI("Power HAL does not support this operation, skipping test...");
+        ALOGV("Power HAL does not support this operation, skipping test...");
         return;
     }
 
diff --git a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
index 97e026b..167f3a6 100644
--- a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
@@ -51,7 +51,7 @@
     sp<I> hal = I::getService();
 
     if (hal == nullptr) {
-        ALOGI("Power HAL HIDL not available, skipping test...");
+        ALOGV("Power HAL HIDL not available, skipping test...");
         return;
     }
 
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 0aca24a..0b23a5a 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -362,6 +362,8 @@
     // composition.
     if (!mBufferInfo.mFrameLatencyNeeded) return;
 
+    mAlreadyDisplayedThisCompose = false;
+
     // Update mFrameEventHistory.
     {
         Mutex::Autolock lock(mFrameEventHistoryMutex);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index e6a76e8..bcae8d9 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -75,17 +75,15 @@
 // -----------------------------------------------------------------------
 void BufferStateLayer::onLayerDisplayed(
         std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) {
-    // If a layer has been displayed again we may need to clear
-    // the mLastClientComposition fence that we use for early release in setBuffer
-    // (as we now have a new fence which won't pass through the client composition path in some cases
-    //  e.g. screenshot). We expect one call to onLayerDisplayed after receiving the GL comp fence
-    // from a single composition cycle, and want to clear on the second call
-    // (which we track with mLastClientCompositionDisplayed)
-   if (mLastClientCompositionDisplayed) {
+    // If we are displayed on multiple displays in a single composition cycle then we would
+    // need to do careful tracking to enable the use of the mLastClientCompositionFence.
+    //  For example we can only use it if all the displays are client comp, and we need
+    //  to merge all the client comp fences. We could do this, but for now we just
+    // disable the optimization when a layer is composed on multiple displays.
+    if (mAlreadyDisplayedThisCompose) {
         mLastClientCompositionFence = nullptr;
-        mLastClientCompositionDisplayed = false;
-    } else if (mLastClientCompositionFence) {
-        mLastClientCompositionDisplayed = true;
+    } else {
+        mAlreadyDisplayedThisCompose = true;
     }
 
     // The previous release fence notifies the client that SurfaceFlinger is done with the previous
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 9302b7b..aefc014 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -41,10 +41,6 @@
         "libtonemap",
         "libtrace_proto",
         "libaidlcommonsupport",
-        "libprocessgroup",
-        "libcgrouprc",
-        "libjsoncpp",
-        "libcgrouprc_format",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
@@ -72,7 +68,6 @@
         "src/DisplayColorProfile.cpp",
         "src/DisplaySurface.cpp",
         "src/DumpHelpers.cpp",
-        "src/HwcAsyncWorker.cpp",
         "src/HwcBufferCache.cpp",
         "src/LayerFECompositionState.cpp",
         "src/Output.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index ca86f4c..c553fce 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -72,9 +72,6 @@
     virtual void resizeBuffers(const ui::Size&) = 0;
 
     virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
-
-    // Returns true if the render surface supports client composition prediction.
-    virtual bool supportsCompositionStrategyPrediction() const;
 };
 
 } // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 1555102..d8644a4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -35,7 +35,6 @@
 #include <utils/Vector.h>
 
 #include <ui/DisplayIdentification.h>
-#include "DisplayHardware/HWComposer.h"
 
 namespace android {
 
@@ -55,7 +54,6 @@
 
 namespace impl {
 struct OutputCompositionState;
-struct GpuCompositionResult;
 } // namespace impl
 
 /**
@@ -264,9 +262,6 @@
     // Latches the front-end layer state for each output layer
     virtual void updateLayerStateFromFE(const CompositionRefreshArgs&) const = 0;
 
-    // Enables predicting composition strategy to run client composition earlier
-    virtual void setPredictCompositionStrategy(bool) = 0;
-
 protected:
     virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
     virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;
@@ -283,22 +278,13 @@
     virtual void updateColorProfile(const CompositionRefreshArgs&) = 0;
     virtual void beginFrame() = 0;
     virtual void prepareFrame() = 0;
-
-    using GpuCompositionResult = compositionengine::impl::GpuCompositionResult;
-    // Runs prepare frame in another thread while running client composition using
-    // the previous frame's composition strategy.
-    virtual GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) = 0;
     virtual void devOptRepaintFlash(const CompositionRefreshArgs&) = 0;
-    virtual void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) = 0;
+    virtual void finishFrame(const CompositionRefreshArgs&) = 0;
     virtual std::optional<base::unique_fd> composeSurfaces(
-            const Region&, const compositionengine::CompositionRefreshArgs&,
-            std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&) = 0;
+            const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) = 0;
     virtual void postFramebuffer() = 0;
     virtual void renderCachedSets(const CompositionRefreshArgs&) = 0;
-    virtual std::optional<android::HWComposer::DeviceRequestedChanges>
-    chooseCompositionStrategy() = 0;
-    virtual void applyCompositionStrategy(
-            const std::optional<android::HWComposer::DeviceRequestedChanges>& changes) = 0;
+    virtual void chooseCompositionStrategy() = 0;
     virtual bool getSkipColorTransform() const = 0;
     virtual FrameFences presentAndGetFrameFences() = 0;
     virtual std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
@@ -309,7 +295,6 @@
             std::vector<LayerFE::LayerSettings>& clientCompositionLayers) = 0;
     virtual void setExpensiveRenderingExpected(bool enabled) = 0;
     virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0;
-    virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0;
 };
 
 } // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index 9ee779c..daee83b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -100,9 +100,6 @@
 
     // Debugging - gets the page flip count for the RenderSurface
     virtual std::uint32_t getPageFlipCount() const = 0;
-
-    // Returns true if the render surface supports client composition prediction.
-    virtual bool supportsCompositionStrategyPrediction() const = 0;
 };
 
 } // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 3b8b06f..58d2530 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -22,7 +22,6 @@
 #include <compositionengine/DisplayColorProfile.h>
 #include <compositionengine/DisplayCreationArgs.h>
 #include <compositionengine/RenderSurface.h>
-#include <compositionengine/impl/GpuCompositionResult.h>
 #include <compositionengine/impl/Output.h>
 #include <ui/PixelFormat.h>
 #include <ui/Size.h>
@@ -52,14 +51,11 @@
     void setReleasedLayers(const CompositionRefreshArgs&) override;
     void setColorTransform(const CompositionRefreshArgs&) override;
     void setColorProfile(const ColorProfile&) override;
-
-    using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges;
-    std::optional<DeviceRequestedChanges> chooseCompositionStrategy() override;
-    void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override;
+    void chooseCompositionStrategy() override;
     bool getSkipColorTransform() const override;
     compositionengine::Output::FrameFences presentAndGetFrameFences() override;
     void setExpensiveRenderingExpected(bool) override;
-    void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override;
+    void finishFrame(const CompositionRefreshArgs&) override;
 
     // compositionengine::Display overrides
     DisplayId getId() const override;
@@ -77,6 +73,7 @@
     using DisplayRequests = android::HWComposer::DeviceRequestedChanges::DisplayRequests;
     using LayerRequests = android::HWComposer::DeviceRequestedChanges::LayerRequests;
     using ClientTargetProperty = android::HWComposer::DeviceRequestedChanges::ClientTargetProperty;
+    virtual bool anyLayersRequireClientComposition() const;
     virtual bool allLayersRequireClientComposition() const;
     virtual void applyChangedTypesToLayers(const ChangedTypes&);
     virtual void applyDisplayRequests(const DisplayRequests&);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h
deleted file mode 100644
index ed1ddc1..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 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-base/unique_fd.h>
-#include <ui/GraphicBuffer.h>
-
-namespace android::compositionengine::impl {
-
-struct GpuCompositionResult {
-    // True if composition strategy was predicted successfully.
-    bool succeeded = false;
-
-    // Composition ready fence.
-    base::unique_fd fence{};
-
-    // Buffer to be used for gpu composition. If gpu composition was not successful,
-    // then we want to reuse the buffer instead of dequeuing another buffer.
-    std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
-
-    bool bufferAvailable() const { return buffer != nullptr; };
-};
-
-} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h
deleted file mode 100644
index 11c0054..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 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-base/thread_annotations.h>
-#include <future>
-#include <optional>
-#include <thread>
-
-#include "DisplayHardware/HWComposer.h"
-
-namespace android::compositionengine::impl {
-
-// HWC Validate call may take multiple milliseconds to complete and can account for
-// a signification amount of time in the display hotpath. This helper class allows
-// us to run the hwc validate function on a real time thread if we can predict what
-// the composition strategy will be and if composition includes client composition.
-// While the hwc validate runs, client composition is kicked off with the prediction.
-// When the worker returns with a value, the composition continues if the prediction
-// was successful otherwise the client composition is re-executed.
-//
-// Note: This does not alter the sequence between HWC and surfaceflinger.
-class HwcAsyncWorker final {
-public:
-    HwcAsyncWorker();
-    ~HwcAsyncWorker();
-    // Runs the provided function which calls hwc validate and returns the requested
-    // device changes as a future.
-    std::future<std::optional<android::HWComposer::DeviceRequestedChanges>> send(
-            std::function<std::optional<android::HWComposer::DeviceRequestedChanges>()>);
-
-private:
-    std::mutex mMutex;
-    std::condition_variable mCv GUARDED_BY(mMutex);
-    bool mDone GUARDED_BY(mMutex) = false;
-    bool mTaskRequested GUARDED_BY(mMutex) = false;
-    std::packaged_task<std::optional<android::HWComposer::DeviceRequestedChanges>()> mTask
-            GUARDED_BY(mMutex);
-    std::thread mThread;
-    void run();
-};
-
-} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 0be5d01..a7a8e97 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -17,13 +17,9 @@
 #pragma once
 
 #include <compositionengine/CompositionEngine.h>
-#include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/Output.h>
 #include <compositionengine/impl/ClientCompositionRequestCache.h>
-#include <compositionengine/impl/GpuCompositionResult.h>
-#include <compositionengine/impl/HwcAsyncWorker.h>
 #include <compositionengine/impl/OutputCompositionState.h>
-#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <compositionengine/impl/planner/Planner.h>
 #include <renderengine/DisplaySettings.h>
 #include <renderengine/LayerSettings.h>
@@ -96,38 +92,25 @@
     void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
     void beginFrame() override;
     void prepareFrame() override;
-    GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) override;
     void devOptRepaintFlash(const CompositionRefreshArgs&) override;
-    void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override;
-    std::optional<base::unique_fd> composeSurfaces(const Region&,
-                                                   const compositionengine::CompositionRefreshArgs&,
-                                                   std::shared_ptr<renderengine::ExternalTexture>,
-                                                   base::unique_fd&) override;
+    void finishFrame(const CompositionRefreshArgs&) override;
+    std::optional<base::unique_fd> composeSurfaces(
+            const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) override;
     void postFramebuffer() override;
     void renderCachedSets(const CompositionRefreshArgs&) override;
     void cacheClientCompositionRequests(uint32_t) override;
-    bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override;
-    void setPredictCompositionStrategy(bool) override;
 
     // Testing
     const ReleasedLayers& getReleasedLayersForTest() const;
     void setDisplayColorProfileForTest(std::unique_ptr<compositionengine::DisplayColorProfile>);
     void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
     bool plannerEnabled() const { return mPlanner != nullptr; }
-    virtual bool anyLayersRequireClientComposition() const;
-    virtual void updateProtectedContentState();
-    virtual bool dequeueRenderBuffer(base::unique_fd*,
-                                     std::shared_ptr<renderengine::ExternalTexture>*);
-    virtual std::future<std::optional<android::HWComposer::DeviceRequestedChanges>>
-    chooseCompositionStrategyAsync();
 
 protected:
     std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
     std::optional<size_t> findCurrentOutputLayerForLayer(
             const sp<compositionengine::LayerFE>&) const;
-    using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges;
-    std::optional<DeviceRequestedChanges> chooseCompositionStrategy() override;
-    void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override{};
+    void chooseCompositionStrategy() override;
     bool getSkipColorTransform() const override;
     compositionengine::Output::FrameFences presentAndGetFrameFences() override;
     std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
@@ -148,7 +131,6 @@
 private:
     void dirtyEntireOutput();
     compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const;
-    void finishPrepareFrame();
     ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const;
     compositionengine::Output::ColorProfile pickColorProfile(
             const compositionengine::CompositionRefreshArgs&) const;
@@ -162,7 +144,6 @@
     OutputLayer* mLayerRequestingBackgroundBlur = nullptr;
     std::unique_ptr<ClientCompositionRequestCache> mClientCompositionRequestCache;
     std::unique_ptr<planner::Planner> mPlanner;
-    std::unique_ptr<HwcAsyncWorker> mHwComposerAsyncWorker;
 };
 
 // This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 92f22b6..66dd825 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -37,8 +37,6 @@
 #include <ui/Region.h>
 #include <ui/Transform.h>
 
-#include "DisplayHardware/HWComposer.h"
-
 namespace android {
 
 namespace compositionengine::impl {
@@ -116,8 +114,6 @@
     // Current target dataspace
     ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN};
 
-    std::optional<android::HWComposer::DeviceRequestedChanges> previousDeviceRequestedChanges{};
-
     // The earliest time to send the present command to the HAL
     std::chrono::steady_clock::time_point earliestPresentTime;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index e4cb113..a8a5380 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -63,7 +63,6 @@
     void queueBuffer(base::unique_fd readyFence) override;
     void onPresentDisplayCompleted() override;
     void flip() override;
-    bool supportsCompositionStrategyPrediction() const override;
 
     // Debugging
     void dump(std::string& result) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
index 72e6f3b..d90cc90 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
@@ -41,7 +41,6 @@
     MOCK_METHOD1(createDisplayColorProfile, void(const DisplayColorProfileCreationArgs&));
     MOCK_METHOD1(createRenderSurface, void(const RenderSurfaceCreationArgs&));
     MOCK_METHOD1(createClientCompositionCache, void(uint32_t));
-    MOCK_METHOD1(setPredictCompositionStrategy, void(bool));
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 27303a8..b68b95d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -22,7 +22,6 @@
 #include <compositionengine/Output.h>
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/RenderSurface.h>
-#include <compositionengine/impl/GpuCompositionResult.h>
 #include <compositionengine/impl/OutputCompositionState.h>
 #include <gmock/gmock.h>
 
@@ -100,22 +99,16 @@
     MOCK_METHOD0(beginFrame, void());
 
     MOCK_METHOD0(prepareFrame, void());
-    MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&));
-    MOCK_METHOD0(chooseCompositionStrategy,
-                 std::optional<android::HWComposer::DeviceRequestedChanges>());
-    MOCK_METHOD1(applyCompositionStrategy,
-                 void(const std::optional<android::HWComposer::DeviceRequestedChanges>&));
+    MOCK_METHOD0(chooseCompositionStrategy, void());
 
     MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
 
-    MOCK_METHOD2(finishFrame,
-                 void(const compositionengine::CompositionRefreshArgs&, GpuCompositionResult&&));
+    MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
 
-    MOCK_METHOD4(composeSurfaces,
+    MOCK_METHOD2(composeSurfaces,
                  std::optional<base::unique_fd>(
                          const Region&,
-                         const compositionengine::CompositionRefreshArgs& refreshArgs,
-                         std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
+                         const compositionengine::CompositionRefreshArgs& refreshArgs));
     MOCK_CONST_METHOD0(getSkipColorTransform, bool());
 
     MOCK_METHOD0(postFramebuffer, void());
@@ -128,8 +121,6 @@
                  void(const Region&, std::vector<LayerFE::LayerSettings>&));
     MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
     MOCK_METHOD1(cacheClientCompositionRequests, void(uint32_t));
-    MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
-    MOCK_METHOD1(setPredictCompositionStrategy, void(bool));
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index e12aebb..fe858c2 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -45,7 +45,6 @@
     MOCK_METHOD0(flip, void());
     MOCK_CONST_METHOD1(dump, void(std::string& result));
     MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t());
-    MOCK_CONST_METHOD0(supportsCompositionStrategyPrediction, bool());
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 09648c3..6a75283 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -221,12 +221,12 @@
     setReleasedLayers(std::move(releasedLayers));
 }
 
-std::optional<android::HWComposer::DeviceRequestedChanges> Display::chooseCompositionStrategy() {
+void Display::chooseCompositionStrategy() {
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
     if (mIsDisconnected) {
-        return {};
+        return;
     }
 
     // Default to the base settings -- client composition only.
@@ -235,7 +235,7 @@
     // If we don't have a HWC display, then we are done.
     const auto halDisplayId = HalDisplayId::tryCast(mId);
     if (!halDisplayId) {
-        return {};
+        return;
     }
 
     // Get any composition changes requested by the HWC device, and apply them.
@@ -260,13 +260,8 @@
         result != NO_ERROR) {
         ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
               strerror(-result));
-        return {};
+        return;
     }
-
-    return changes;
-}
-
-void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChanges>& changes) {
     if (changes) {
         applyChangedTypesToLayers(changes->changedTypes);
         applyDisplayRequests(changes->displayRequests);
@@ -292,6 +287,12 @@
     return hwc.hasCapability(Capability::SKIP_CLIENT_COLOR_TRANSFORM);
 }
 
+bool Display::anyLayersRequireClientComposition() const {
+    const auto layers = getOutputLayersOrderedByZ();
+    return std::any_of(layers.begin(), layers.end(),
+                       [](const auto& layer) { return layer->requiresClientComposition(); });
+}
+
 bool Display::allLayersRequireClientComposition() const {
     const auto layers = getOutputLayersOrderedByZ();
     return std::all_of(layers.begin(), layers.end(),
@@ -389,8 +390,7 @@
     }
 }
 
-void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs,
-                          GpuCompositionResult&& result) {
+void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
     // We only need to actually compose the display if:
     // 1) It is being handled by hardware composer, which may need this to
     //    keep its virtual display state machine in sync, or
@@ -400,7 +400,7 @@
         return;
     }
 
-    impl::Output::finishFrame(refreshArgs, std::move(result));
+    impl::Output::finishFrame(refreshArgs);
 }
 
 } // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp
index 28900af..db6d4f2 100644
--- a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp
@@ -20,8 +20,4 @@
 
 DisplaySurface::~DisplaySurface() = default;
 
-bool DisplaySurface::supportsCompositionStrategyPrediction() const {
-    return true;
-}
-
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
deleted file mode 100644
index 497424a..0000000
--- a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 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 <compositionengine/impl/HwcAsyncWorker.h>
-#include <processgroup/sched_policy.h>
-#include <pthread.h>
-#include <sched.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <system/thread_defs.h>
-
-#include <android-base/thread_annotations.h>
-#include <cutils/sched_policy.h>
-
-namespace android::compositionengine::impl {
-
-HwcAsyncWorker::HwcAsyncWorker() {
-    mThread = std::thread(&HwcAsyncWorker::run, this);
-    pthread_setname_np(mThread.native_handle(), "HwcAsyncWorker");
-}
-
-HwcAsyncWorker::~HwcAsyncWorker() {
-    {
-        std::scoped_lock lock(mMutex);
-        mDone = true;
-        mCv.notify_all();
-    }
-    if (mThread.joinable()) {
-        mThread.join();
-    }
-}
-std::future<std::optional<android::HWComposer::DeviceRequestedChanges>> HwcAsyncWorker::send(
-        std::function<std::optional<android::HWComposer::DeviceRequestedChanges>()> task) {
-    std::unique_lock<std::mutex> lock(mMutex);
-    android::base::ScopedLockAssertion assumeLock(mMutex);
-    mTask = std::packaged_task<std::optional<android::HWComposer::DeviceRequestedChanges>()>(
-            [task = std::move(task)]() { return task(); });
-    mTaskRequested = true;
-    mCv.notify_one();
-    return mTask.get_future();
-}
-
-void HwcAsyncWorker::run() {
-    set_sched_policy(0, SP_FOREGROUND);
-    struct sched_param param = {0};
-    param.sched_priority = 2;
-    sched_setscheduler(gettid(), SCHED_FIFO, &param);
-
-    std::unique_lock<std::mutex> lock(mMutex);
-    android::base::ScopedLockAssertion assumeLock(mMutex);
-    while (!mDone) {
-        mCv.wait(lock);
-        if (mTaskRequested && mTask.valid()) {
-            mTask();
-            mTaskRequested = false;
-        }
-    }
-}
-
-} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index cd10bc1..aef55d4 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -22,7 +22,6 @@
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/RenderSurface.h>
-#include <compositionengine/impl/HwcAsyncWorker.h>
 #include <compositionengine/impl/Output.h>
 #include <compositionengine/impl/OutputCompositionState.h>
 #include <compositionengine/impl/OutputLayer.h>
@@ -435,17 +434,9 @@
     writeCompositionState(refreshArgs);
     setColorTransform(refreshArgs);
     beginFrame();
-
-    GpuCompositionResult result;
-    const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
-    if (predictCompositionStrategy) {
-        result = prepareFrameAsync(refreshArgs);
-    } else {
-        prepareFrame();
-    }
-
+    prepareFrame();
     devOptRepaintFlash(refreshArgs);
-    finishFrame(refreshArgs, std::move(result));
+    finishFrame(refreshArgs);
     postFramebuffer();
     renderCachedSets(refreshArgs);
 }
@@ -960,62 +951,19 @@
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
-    auto& outputState = editState();
+    const auto& outputState = getState();
     if (!outputState.isEnabled) {
         return;
     }
 
-    auto changes = chooseCompositionStrategy();
-    outputState.previousDeviceRequestedChanges = changes;
-    if (changes) {
-        applyCompositionStrategy(changes);
-    }
-    finishPrepareFrame();
-}
+    chooseCompositionStrategy();
 
-std::future<std::optional<android::HWComposer::DeviceRequestedChanges>>
-Output::chooseCompositionStrategyAsync() {
-    return mHwComposerAsyncWorker->send([&]() { return chooseCompositionStrategy(); });
-}
-
-GpuCompositionResult Output::prepareFrameAsync(const CompositionRefreshArgs& refreshArgs) {
-    ATRACE_CALL();
-    ALOGV(__FUNCTION__);
-    auto& state = editState();
-    const auto& previousChanges = state.previousDeviceRequestedChanges;
-    auto hwcResult = chooseCompositionStrategyAsync();
-    applyCompositionStrategy(previousChanges);
-    finishPrepareFrame();
-
-    base::unique_fd bufferFence;
-    std::shared_ptr<renderengine::ExternalTexture> buffer;
-    updateProtectedContentState();
-    const bool dequeueSucceeded = dequeueRenderBuffer(&bufferFence, &buffer);
-    GpuCompositionResult compositionResult;
-    if (dequeueSucceeded) {
-        std::optional<base::unique_fd> optFd =
-                composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence);
-        if (optFd) {
-            compositionResult.fence = std::move(*optFd);
-        }
+    if (mPlanner) {
+        mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
     }
 
-    auto changes = hwcResult.valid() ? hwcResult.get() : std::nullopt;
-    const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges;
-    compositionResult.succeeded = predictionSucceeded;
-    if (!predictionSucceeded) {
-        ATRACE_NAME("CompositionStrategyPredictionMiss");
-        if (changes) {
-            applyCompositionStrategy(changes);
-        }
-        finishPrepareFrame();
-        // Track the dequeued buffer to reuse so we don't need to dequeue another one.
-        compositionResult.buffer = buffer;
-    } else {
-        ATRACE_NAME("CompositionStrategyPredictionHit");
-    }
-    state.previousDeviceRequestedChanges = std::move(changes);
-    return compositionResult;
+    mRenderSurface->prepareFrame(outputState.usesClientComposition,
+                                 outputState.usesDeviceComposition);
 }
 
 void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
@@ -1025,11 +973,7 @@
 
     if (getState().isEnabled) {
         if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) {
-            base::unique_fd bufferFence;
-            std::shared_ptr<renderengine::ExternalTexture> buffer;
-            updateProtectedContentState();
-            dequeueRenderBuffer(&bufferFence, &buffer);
-            static_cast<void>(composeSurfaces(dirtyRegion, refreshArgs, buffer, bufferFence));
+            static_cast<void>(composeSurfaces(dirtyRegion, refreshArgs));
             mRenderSurface->queueBuffer(base::unique_fd());
         }
     }
@@ -1041,7 +985,7 @@
     prepareFrame();
 }
 
-void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositionResult&& result) {
+void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
@@ -1049,25 +993,9 @@
         return;
     }
 
-    std::optional<base::unique_fd> optReadyFence;
-    std::shared_ptr<renderengine::ExternalTexture> buffer;
-    base::unique_fd bufferFence;
-    if (result.succeeded) {
-        optReadyFence = std::move(result.fence);
-    } else {
-        if (result.bufferAvailable()) {
-            buffer = std::move(result.buffer);
-            bufferFence = std::move(result.fence);
-        } else {
-            updateProtectedContentState();
-            if (!dequeueRenderBuffer(&bufferFence, &buffer)) {
-                return;
-            }
-        }
-        // Repaint the framebuffer (if needed), getting the optional fence for when
-        // the composition completes.
-        optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence);
-    }
+    // Repaint the framebuffer (if needed), getting the optional fence for when
+    // the composition completes.
+    auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
     if (!optReadyFence) {
         return;
     }
@@ -1076,8 +1004,16 @@
     mRenderSurface->queueBuffer(std::move(*optReadyFence));
 }
 
-void Output::updateProtectedContentState() {
+std::optional<base::unique_fd> Output::composeSurfaces(
+        const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
     const auto& outputState = getState();
+    OutputCompositionState& outputCompositionState = editState();
+    const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
+                                                      outputState.usesClientComposition};
+
     auto& renderEngine = getCompositionEngine().getRenderEngine();
     const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
 
@@ -1099,48 +1035,29 @@
     } else if (!outputState.isSecure && renderEngine.isProtected()) {
         renderEngine.useProtectedContext(false);
     }
-}
 
-bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence,
-                                 std::shared_ptr<renderengine::ExternalTexture>* tex) {
-    const auto& outputState = getState();
+    base::unique_fd fd;
+
+    std::shared_ptr<renderengine::ExternalTexture> tex;
 
     // If we aren't doing client composition on this output, but do have a
     // flipClientTarget request for this frame on this output, we still need to
     // dequeue a buffer.
-    if (outputState.usesClientComposition || outputState.flipClientTarget) {
-        *tex = mRenderSurface->dequeueBuffer(bufferFence);
-        if (*tex == nullptr) {
+    if (hasClientComposition || outputState.flipClientTarget) {
+        tex = mRenderSurface->dequeueBuffer(&fd);
+        if (tex == nullptr) {
             ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
                   "client composition for this frame",
                   mName.c_str());
-            return false;
+            return {};
         }
     }
-    return true;
-}
 
-std::optional<base::unique_fd> Output::composeSurfaces(
-        const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs,
-        std::shared_ptr<renderengine::ExternalTexture> tex, base::unique_fd& fd) {
-    ATRACE_CALL();
-    ALOGV(__FUNCTION__);
-
-    const auto& outputState = getState();
-    const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
-                                                      outputState.usesClientComposition};
     if (!hasClientComposition) {
         setExpensiveRenderingExpected(false);
         return base::unique_fd();
     }
 
-    if (tex == nullptr) {
-        ALOGW("Buffer not valid for display [%s], bailing out of "
-              "client composition for this frame",
-              mName.c_str());
-        return {};
-    }
-
     ALOGV("hasClientComposition");
 
     renderengine::DisplaySettings clientCompositionDisplay;
@@ -1168,8 +1085,6 @@
             outputState.usesDeviceComposition || getSkipColorTransform();
 
     // Generate the client composition requests for the layers on this output.
-    auto& renderEngine = getCompositionEngine().getRenderEngine();
-    const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
     std::vector<LayerFE*> clientCompositionLayersFE;
     std::vector<LayerFE::LayerSettings> clientCompositionLayers =
             generateClientCompositionRequests(supportsProtectedContent,
@@ -1177,19 +1092,16 @@
                                               clientCompositionLayersFE);
     appendRegionFlashRequests(debugRegion, clientCompositionLayers);
 
-    OutputCompositionState& outputCompositionState = editState();
     // Check if the client composition requests were rendered into the provided graphic buffer. If
     // so, we can reuse the buffer and avoid client composition.
     if (mClientCompositionRequestCache) {
         if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(),
                                                    clientCompositionDisplay,
                                                    clientCompositionLayers)) {
-            ATRACE_NAME("ClientCompositionCacheHit");
             outputCompositionState.reusedClientComposition = true;
             setExpensiveRenderingExpected(false);
             return base::unique_fd();
         }
-        ATRACE_NAME("ClientCompositionCacheMiss");
         mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay,
                                             clientCompositionLayers);
     }
@@ -1441,13 +1353,12 @@
     outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect());
 }
 
-std::optional<android::HWComposer::DeviceRequestedChanges> Output::chooseCompositionStrategy() {
+void Output::chooseCompositionStrategy() {
     // The base output implementation can only do client composition
     auto& outputState = editState();
     outputState.usesClientComposition = true;
     outputState.usesDeviceComposition = false;
     outputState.reusedClientComposition = false;
-    return {};
 }
 
 bool Output::getSkipColorTransform() const {
@@ -1462,63 +1373,5 @@
     return result;
 }
 
-void Output::setPredictCompositionStrategy(bool predict) {
-    if (predict) {
-        mHwComposerAsyncWorker = std::make_unique<HwcAsyncWorker>();
-    } else {
-        mHwComposerAsyncWorker.reset(nullptr);
-    }
-}
-
-bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) {
-    if (!getState().isEnabled || !mHwComposerAsyncWorker) {
-        ALOGV("canPredictCompositionStrategy disabled");
-        return false;
-    }
-
-    if (!getState().previousDeviceRequestedChanges) {
-        ALOGV("canPredictCompositionStrategy previous changes not available");
-        return false;
-    }
-
-    if (!mRenderSurface->supportsCompositionStrategyPrediction()) {
-        ALOGV("canPredictCompositionStrategy surface does not support");
-        return false;
-    }
-
-    if (refreshArgs.devOptFlashDirtyRegionsDelay) {
-        ALOGV("canPredictCompositionStrategy devOptFlashDirtyRegionsDelay");
-        return false;
-    }
-
-    // If no layer uses clientComposition, then don't predict composition strategy
-    // because we have less work to do in parallel.
-    if (!anyLayersRequireClientComposition()) {
-        ALOGV("canPredictCompositionStrategy no layer uses clientComposition");
-        return false;
-    }
-
-    if (!refreshArgs.updatingOutputGeometryThisFrame) {
-        return true;
-    }
-
-    ALOGV("canPredictCompositionStrategy updatingOutputGeometryThisFrame");
-    return false;
-}
-
-bool Output::anyLayersRequireClientComposition() const {
-    const auto layers = getOutputLayersOrderedByZ();
-    return std::any_of(layers.begin(), layers.end(),
-                       [](const auto& layer) { return layer->requiresClientComposition(); });
-}
-
-void Output::finishPrepareFrame() {
-    const auto& state = getState();
-    if (mPlanner) {
-        mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
-    }
-    mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition);
-}
-
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 5a3af7b..12c2c8e 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -289,9 +289,5 @@
     return mTexture;
 }
 
-bool RenderSurface::supportsCompositionStrategyPrediction() const {
-    return mDisplaySurface->supportsCompositionStrategyPrediction();
-}
-
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 36b04d9..cd03235 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -30,9 +30,7 @@
 #include <compositionengine/mock/OutputLayer.h>
 #include <compositionengine/mock/RenderSurface.h>
 #include <gtest/gtest.h>
-#include <renderengine/mock/FakeExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
-
 #include <ui/Rect.h>
 #include <ui/StaticDisplayInfo.h>
 
@@ -200,22 +198,6 @@
     std::shared_ptr<Display> mDisplay =
             createPartialMockDisplay<Display>(mCompositionEngine,
                                               getDisplayCreationArgsForPhysicalDisplay());
-
-    android::HWComposer::DeviceRequestedChanges mDeviceRequestedChanges{
-            {{nullptr, Composition::CLIENT}},
-            hal::DisplayRequest::FLIP_CLIENT_TARGET,
-            {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
-            {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
-            -1.f,
-    };
-
-    void chooseCompositionStrategy(Display* display) {
-        std::optional<android::HWComposer::DeviceRequestedChanges> changes =
-                display->chooseCompositionStrategy();
-        if (changes) {
-            display->applyCompositionStrategy(changes);
-        }
-    }
 };
 
 struct FullDisplayImplTestCommon : public DisplayTestCommon {
@@ -232,11 +214,6 @@
                 std::unique_ptr<compositionengine::OutputLayer>(mLayer2.outputLayer));
         mDisplay->injectOutputLayerForTest(
                 std::unique_ptr<compositionengine::OutputLayer>(mLayer3.outputLayer));
-        mResultWithBuffer.buffer = std::make_shared<
-                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
-                                                         1ULL /* bufferId */,
-                                                         HAL_PIXEL_FORMAT_RGBA_8888,
-                                                         0ULL /*usage*/);
     }
 
     Layer mLayer1;
@@ -245,8 +222,6 @@
     StrictMock<HWC2::mock::Layer> hwc2LayerUnknown;
     std::shared_ptr<Display> mDisplay =
             createDisplay<Display>(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay());
-    impl::GpuCompositionResult mResultWithBuffer;
-    impl::GpuCompositionResult mResultWithoutBuffer;
 };
 
 /*
@@ -579,7 +554,7 @@
             createPartialMockDisplay<Display>(mCompositionEngine, args);
     EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId()));
 
-    chooseCompositionStrategy(gpuDisplay.get());
+    gpuDisplay->chooseCompositionStrategy();
 
     auto& state = gpuDisplay->getState();
     EXPECT_TRUE(state.usesClientComposition);
@@ -592,12 +567,11 @@
                 getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _, _))
             .WillOnce(Return(INVALID_OPERATION));
 
-    chooseCompositionStrategy(mDisplay.get());
+    mDisplay->chooseCompositionStrategy();
 
     auto& state = mDisplay->getState();
     EXPECT_TRUE(state.usesClientComposition);
     EXPECT_FALSE(state.usesDeviceComposition);
-    EXPECT_FALSE(state.previousDeviceRequestedChanges.has_value());
 }
 
 TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) {
@@ -614,16 +588,10 @@
 
     EXPECT_CALL(mHwComposer,
                 getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
-            .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges),
-                                     Return(NO_ERROR)));
-    EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes))
-            .Times(1);
-    EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1);
-    EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests))
-            .Times(1);
+            .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
 
-    chooseCompositionStrategy(mDisplay.get());
+    mDisplay->chooseCompositionStrategy();
 
     auto& state = mDisplay->getState();
     EXPECT_FALSE(state.usesClientComposition);
@@ -650,17 +618,11 @@
 
     EXPECT_CALL(mHwComposer,
                 getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
-            .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges),
-                                     Return(NO_ERROR)));
-    EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes))
-            .Times(1);
-    EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1);
-    EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests))
-            .Times(1);
+            .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
 
     mDisplay->setNextBrightness(kDisplayBrightness);
-    chooseCompositionStrategy(mDisplay.get());
+    mDisplay->chooseCompositionStrategy();
 
     auto& state = mDisplay->getState();
     EXPECT_FALSE(state.usesClientComposition);
@@ -669,6 +631,14 @@
 }
 
 TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) {
+    android::HWComposer::DeviceRequestedChanges changes{
+            {{nullptr, Composition::CLIENT}},
+            hal::DisplayRequest::FLIP_CLIENT_TARGET,
+            {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
+            {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
+            -1.f,
+    };
+
     // Since two calls are made to anyLayersRequireClientComposition with different return
     // values, use a Sequence to control the matching so the values are returned in a known
     // order.
@@ -682,15 +652,13 @@
 
     EXPECT_CALL(mHwComposer,
                 getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
-            .WillOnce(DoAll(SetArgPointee<5>(mDeviceRequestedChanges), Return(NO_ERROR)));
-    EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes))
-            .Times(1);
-    EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1);
-    EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests))
-            .Times(1);
+            .WillOnce(DoAll(SetArgPointee<5>(changes), Return(NO_ERROR)));
+    EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1);
+    EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1);
+    EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1);
     EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
 
-    chooseCompositionStrategy(mDisplay.get());
+    mDisplay->chooseCompositionStrategy();
 
     auto& state = mDisplay->getState();
     EXPECT_FALSE(state.usesClientComposition);
@@ -954,7 +922,7 @@
     mDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1));
     mDisplay->editState().dirtyRegion = Region::INVALID_REGION;
 
-    mDisplay->finishFrame({}, std::move(mResultWithBuffer));
+    mDisplay->finishFrame({});
 }
 
 TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) {
@@ -972,7 +940,7 @@
     gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1));
     gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION;
 
-    gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer));
+    gpuDisplay->finishFrame({});
 }
 
 TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) {
@@ -989,7 +957,7 @@
     gpuDisplay->editState().usesClientComposition = false;
     gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1));
     gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1));
-    gpuDisplay->finishFrame({}, std::move(mResultWithBuffer));
+    gpuDisplay->finishFrame({});
 }
 
 /*
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 719f15c..1f1dd1a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -133,6 +133,8 @@
                  status_t(PhysicalDisplayId,
                           std::optional<aidl::android::hardware::graphics::common::
                                                 DisplayDecorationSupport>* support));
+    MOCK_METHOD2(setIdleTimerEnabled, status_t(PhysicalDisplayId, std::chrono::milliseconds));
+    MOCK_METHOD1(hasDisplayIdleTimerCapability, bool(PhysicalDisplayId displayId));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index af172d8..54eb8f8 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -28,7 +28,6 @@
 #include <gtest/gtest.h>
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/impl/ExternalTexture.h>
-#include <renderengine/mock/FakeExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -990,7 +989,7 @@
     struct OutputPartialMock : public OutputPartialMockBase {
         // Sets up the helper functions called by the function under test to use
         // mock implementations.
-        MOCK_METHOD0(chooseCompositionStrategy, std::optional<DeviceRequestedChanges>());
+        MOCK_METHOD0(chooseCompositionStrategy, void());
     };
 
     OutputPrepareFrameTest() {
@@ -1038,133 +1037,6 @@
     EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
 }
 
-struct OutputPrepareFrameAsyncTest : public testing::Test {
-    struct OutputPartialMock : public OutputPartialMockBase {
-        // Sets up the helper functions called by the function under test to use
-        // mock implementations.
-        MOCK_METHOD0(chooseCompositionStrategy, std::optional<DeviceRequestedChanges>());
-        MOCK_METHOD0(updateProtectedContentState, void());
-        MOCK_METHOD2(dequeueRenderBuffer,
-                     bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
-        MOCK_METHOD0(chooseCompositionStrategyAsync,
-                     std::future<std::optional<android::HWComposer::DeviceRequestedChanges>>());
-        MOCK_METHOD4(composeSurfaces,
-                     std::optional<base::unique_fd>(
-                             const Region&, const compositionengine::CompositionRefreshArgs&,
-                             std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
-    };
-
-    OutputPrepareFrameAsyncTest() {
-        mOutput.setDisplayColorProfileForTest(
-                std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
-        mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
-    }
-
-    StrictMock<mock::CompositionEngine> mCompositionEngine;
-    mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
-    mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
-    StrictMock<OutputPartialMock> mOutput;
-    CompositionRefreshArgs mRefreshArgs;
-};
-
-TEST_F(OutputPrepareFrameAsyncTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
-    mOutput.editState().isEnabled = true;
-    mOutput.editState().usesClientComposition = false;
-    mOutput.editState().usesDeviceComposition = true;
-    mOutput.editState().previousDeviceRequestedChanges =
-            std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
-    std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
-    p.set_value(mOutput.editState().previousDeviceRequestedChanges);
-
-    EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
-    EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
-    EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
-    EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _));
-
-    impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
-    EXPECT_TRUE(result.succeeded);
-    EXPECT_FALSE(result.bufferAvailable());
-}
-
-TEST_F(OutputPrepareFrameAsyncTest, skipCompositionOnDequeueFailure) {
-    mOutput.editState().isEnabled = true;
-    mOutput.editState().usesClientComposition = false;
-    mOutput.editState().usesDeviceComposition = true;
-    mOutput.editState().previousDeviceRequestedChanges =
-            std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
-    std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
-    p.set_value(mOutput.editState().previousDeviceRequestedChanges);
-
-    EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(false));
-    EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2);
-    EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
-
-    impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
-    EXPECT_FALSE(result.succeeded);
-    EXPECT_FALSE(result.bufferAvailable());
-}
-
-// Tests that in the event of hwc error when choosing composition strategy, we would fall back
-// client composition
-TEST_F(OutputPrepareFrameAsyncTest, chooseCompositionStrategyFailureCallsPrepareFrame) {
-    mOutput.editState().isEnabled = true;
-    mOutput.editState().usesClientComposition = false;
-    mOutput.editState().usesDeviceComposition = true;
-    mOutput.editState().previousDeviceRequestedChanges =
-            std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
-    std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
-    p.set_value({});
-    std::shared_ptr<renderengine::ExternalTexture> tex =
-            std::make_shared<renderengine::mock::FakeExternalTexture>(1, 1,
-                                                                      HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                                      2);
-
-    EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _))
-            .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true)));
-    EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2);
-    EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
-    EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _));
-
-    impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
-    EXPECT_FALSE(result.succeeded);
-    EXPECT_TRUE(result.bufferAvailable());
-}
-
-TEST_F(OutputPrepareFrameAsyncTest, predictionMiss) {
-    mOutput.editState().isEnabled = true;
-    mOutput.editState().usesClientComposition = false;
-    mOutput.editState().usesDeviceComposition = true;
-    mOutput.editState().previousDeviceRequestedChanges =
-            std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
-    auto newDeviceRequestedChanges =
-            std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
-    newDeviceRequestedChanges->clientTargetBrightness = 5.f;
-    std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
-    p.set_value(newDeviceRequestedChanges);
-    std::shared_ptr<renderengine::ExternalTexture> tex =
-            std::make_shared<renderengine::mock::FakeExternalTexture>(1, 1,
-                                                                      HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                                      2);
-
-    EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _))
-            .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true)));
-    EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2);
-    EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
-    EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _));
-
-    impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
-    EXPECT_FALSE(result.succeeded);
-    EXPECT_TRUE(result.bufferAvailable());
-}
-
 /*
  * Output::prepare()
  */
@@ -1923,14 +1795,10 @@
         MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
         MOCK_METHOD0(beginFrame, void());
         MOCK_METHOD0(prepareFrame, void());
-        MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&));
         MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
-        MOCK_METHOD2(finishFrame,
-                     void(const compositionengine::CompositionRefreshArgs&,
-                          GpuCompositionResult&&));
+        MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
         MOCK_METHOD0(postFramebuffer, void());
         MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&));
-        MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
     };
 
     StrictMock<OutputPartialMock> mOutput;
@@ -1946,30 +1814,9 @@
     EXPECT_CALL(mOutput, writeCompositionState(Ref(args)));
     EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
     EXPECT_CALL(mOutput, beginFrame());
-    EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(false));
     EXPECT_CALL(mOutput, prepareFrame());
     EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
-    EXPECT_CALL(mOutput, finishFrame(Ref(args), _));
-    EXPECT_CALL(mOutput, postFramebuffer());
-    EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
-
-    mOutput.present(args);
-}
-
-TEST_F(OutputPresentTest, predictingCompositionStrategyInvokesPrepareFrameAsync) {
-    CompositionRefreshArgs args;
-
-    InSequence seq;
-    EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
-    EXPECT_CALL(mOutput, updateCompositionState(Ref(args)));
-    EXPECT_CALL(mOutput, planComposition());
-    EXPECT_CALL(mOutput, writeCompositionState(Ref(args)));
-    EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
-    EXPECT_CALL(mOutput, beginFrame());
-    EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(true));
-    EXPECT_CALL(mOutput, prepareFrameAsync(Ref(args)));
-    EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
-    EXPECT_CALL(mOutput, finishFrame(Ref(args), _));
+    EXPECT_CALL(mOutput, finishFrame(Ref(args)));
     EXPECT_CALL(mOutput, postFramebuffer());
     EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
 
@@ -2867,15 +2714,11 @@
         // Sets up the helper functions called by the function under test to use
         // mock implementations.
         MOCK_METHOD(Region, getDirtyRegion, (), (const));
-        MOCK_METHOD4(composeSurfaces,
+        MOCK_METHOD2(composeSurfaces,
                      std::optional<base::unique_fd>(
-                             const Region&, const compositionengine::CompositionRefreshArgs&,
-                             std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
+                             const Region&, const compositionengine::CompositionRefreshArgs&));
         MOCK_METHOD0(postFramebuffer, void());
         MOCK_METHOD0(prepareFrame, void());
-        MOCK_METHOD0(updateProtectedContentState, void());
-        MOCK_METHOD2(dequeueRenderBuffer,
-                     bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
     };
 
     OutputDevOptRepaintFlashTest() {
@@ -2932,9 +2775,7 @@
 
     InSequence seq;
     EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kNotEmptyRegion));
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _));
-    EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs), _, _));
+    EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs)));
     EXPECT_CALL(*mRenderSurface, queueBuffer(_));
     EXPECT_CALL(mOutput, postFramebuffer());
     EXPECT_CALL(mOutput, prepareFrame());
@@ -2950,14 +2791,10 @@
     struct OutputPartialMock : public OutputPartialMockBase {
         // Sets up the helper functions called by the function under test to use
         // mock implementations.
-        MOCK_METHOD4(composeSurfaces,
+        MOCK_METHOD2(composeSurfaces,
                      std::optional<base::unique_fd>(
-                             const Region&, const compositionengine::CompositionRefreshArgs&,
-                             std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
+                             const Region&, const compositionengine::CompositionRefreshArgs&));
         MOCK_METHOD0(postFramebuffer, void());
-        MOCK_METHOD0(updateProtectedContentState, void());
-        MOCK_METHOD2(dequeueRenderBuffer,
-                     bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
     };
 
     OutputFinishFrameTest() {
@@ -2975,63 +2812,27 @@
 TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
     mOutput.mState.isEnabled = false;
 
-    impl::GpuCompositionResult result;
-    mOutput.finishFrame(mRefreshArgs, std::move(result));
+    mOutput.finishFrame(mRefreshArgs);
 }
 
 TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
     mOutput.mState.isEnabled = true;
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
-    EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _));
 
-    impl::GpuCompositionResult result;
-    mOutput.finishFrame(mRefreshArgs, std::move(result));
+    InSequence seq;
+    EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _));
+
+    mOutput.finishFrame(mRefreshArgs);
 }
 
 TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
     mOutput.mState.isEnabled = true;
 
     InSequence seq;
-    EXPECT_CALL(mOutput, updateProtectedContentState());
-    EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
-    EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _))
+    EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _))
             .WillOnce(Return(ByMove(base::unique_fd())));
     EXPECT_CALL(*mRenderSurface, queueBuffer(_));
 
-    impl::GpuCompositionResult result;
-    mOutput.finishFrame(mRefreshArgs, std::move(result));
-}
-
-TEST_F(OutputFinishFrameTest, predictionSucceeded) {
-    mOutput.mState.isEnabled = true;
-
-    InSequence seq;
-    EXPECT_CALL(*mRenderSurface, queueBuffer(_));
-
-    impl::GpuCompositionResult result;
-    result.succeeded = true;
-    mOutput.finishFrame(mRefreshArgs, std::move(result));
-}
-
-TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) {
-    mOutput.mState.isEnabled = true;
-
-    InSequence seq;
-
-    impl::GpuCompositionResult result;
-    result.succeeded = false;
-    result.buffer =
-            std::make_shared<renderengine::mock::FakeExternalTexture>(1, 1,
-                                                                      HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                                      2);
-
-    EXPECT_CALL(mOutput,
-                composeSurfaces(RegionEq(Region::INVALID_REGION), _, result.buffer,
-                                Eq(ByRef(result.fence))))
-            .WillOnce(Return(ByMove(base::unique_fd())));
-    EXPECT_CALL(*mRenderSurface, queueBuffer(_));
-    mOutput.finishFrame(mRefreshArgs, std::move(result));
+    mOutput.finishFrame(mRefreshArgs);
 }
 
 /*
@@ -3278,15 +3079,8 @@
 
     struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
         auto execute() {
-            base::unique_fd fence;
-            std::shared_ptr<renderengine::ExternalTexture> externalTexture;
-            const bool success =
-                    getInstance()->mOutput.dequeueRenderBuffer(&fence, &externalTexture);
-            if (success) {
-                getInstance()->mReadyFence =
-                        getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs,
-                                                               externalTexture, fence);
-            }
+            getInstance()->mReadyFence =
+                    getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
             return nextState<FenceCheckState>();
         }
     };
@@ -3847,11 +3641,7 @@
     EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
     EXPECT_CALL(mRenderEngine, useProtectedContext(false));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
@@ -3859,11 +3649,7 @@
     mLayer2.mLayerFEState.hasProtectedContent = true;
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
@@ -3875,11 +3661,7 @@
     EXPECT_CALL(mRenderEngine, useProtectedContext(false));
     EXPECT_CALL(*mRenderSurface, setProtected(false));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
@@ -3901,11 +3683,7 @@
             .WillOnce(Return(ByMove(
                     futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
@@ -3915,11 +3693,7 @@
     EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
     EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
@@ -3930,11 +3704,7 @@
     EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
     EXPECT_CALL(mRenderEngine, useProtectedContext(true));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
@@ -3945,11 +3715,7 @@
     EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
     EXPECT_CALL(*mRenderSurface, setProtected(true));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
@@ -3960,11 +3726,7 @@
     EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
     EXPECT_CALL(mRenderEngine, useProtectedContext(true));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
@@ -3994,11 +3756,7 @@
             .WillOnce(Return(ByMove(
                     futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
 
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
 
 struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur
@@ -4033,12 +3791,7 @@
     mOutput.writeCompositionState(mRefreshArgs);
 
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
-
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, mRefreshArgs);
 }
 
 TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotExpensive) {
@@ -4048,12 +3801,7 @@
     mOutput.writeCompositionState(mRefreshArgs);
 
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(0);
-
-    base::unique_fd fd;
-    std::shared_ptr<renderengine::ExternalTexture> tex;
-    mOutput.updateProtectedContentState();
-    mOutput.dequeueRenderBuffer(&fd, &tex);
-    mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd);
+    mOutput.composeSurfaces(kDebugRegion, mRefreshArgs);
 }
 
 /*
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 610d86f..45b98bb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -91,7 +91,6 @@
                 static_cast<uint32_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers));
     }
 
-    mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy);
     mCompositionDisplay->createDisplayColorProfile(
             compositionengine::DisplayColorProfileCreationArgsBuilder()
                     .setHasWideColorGamut(args.hasWideColorGamut)
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 80e2d99..92592f7 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -248,6 +248,7 @@
         case OptionalFeature::ExpectedPresentTime:
         case OptionalFeature::DisplayBrightnessCommand:
         case OptionalFeature::BootDisplayConfig:
+        case OptionalFeature::KernelIdleTimer:
             return true;
     }
 }
@@ -475,6 +476,19 @@
     return Error::NONE;
 }
 
+Error AidlComposer::hasDisplayIdleTimerCapability(Display display, bool* outSupport) {
+    std::vector<AidlDisplayCapability> capabilities;
+    const auto status =
+            mAidlComposerClient->getDisplayCapabilities(translate<int64_t>(display), &capabilities);
+    if (!status.isOk()) {
+        ALOGE("getDisplayCapabilities failed %s", status.getDescription().c_str());
+        return static_cast<Error>(status.getServiceSpecificError());
+    }
+    *outSupport = std::find(capabilities.begin(), capabilities.end(),
+                            AidlDisplayCapability::DISPLAY_IDLE_TIMER) != capabilities.end();
+    return Error::NONE;
+}
+
 Error AidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
                                        float* outMaxLuminance, float* outMaxAverageLuminance,
                                        float* outMinLuminance) {
@@ -1100,5 +1114,17 @@
     }
     return Error::NONE;
 }
+
+Error AidlComposer::setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) {
+    const auto status =
+            mAidlComposerClient->setIdleTimerEnabled(translate<int64_t>(displayId),
+                                                     translate<int32_t>(timeout.count()));
+    if (!status.isOk()) {
+        ALOGE("setIdleTimerEnabled failed %s", status.getDescription().c_str());
+        return static_cast<Error>(status.getServiceSpecificError());
+    }
+    return Error::NONE;
+}
+
 } // namespace Hwc2
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 80ca8da..6c0f636 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -100,6 +100,7 @@
                              std::vector<uint32_t>* outLayerRequestMasks) override;
 
     Error getDozeSupport(Display display, bool* outSupport) override;
+    Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
     Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
                              float* outMaxAverageLuminance, float* outMinLuminance) override;
 
@@ -220,6 +221,7 @@
     Error getPreferredBootDisplayConfig(Display displayId, Config*) override;
     Error getDisplayDecorationSupport(Display display,
                                       std::optional<DisplayDecorationSupport>* support) override;
+    Error setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) override;
 
 private:
     // Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 23886d4..6abe7d1 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -93,6 +93,7 @@
         // Whether setDisplayBrightness is able to be applied as part of a display command.
         DisplayBrightnessCommand,
         BootDisplayConfig,
+        KernelIdleTimer,
     };
 
     virtual bool isSupported(OptionalFeature) const = 0;
@@ -134,6 +135,7 @@
                                      std::vector<uint32_t>* outLayerRequestMasks) = 0;
 
     virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
+    virtual Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) = 0;
     virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
                                      float* outMaxLuminance, float* outMaxAverageLuminance,
                                      float* outMinLuminance) = 0;
@@ -274,6 +276,7 @@
             Display display,
             std::optional<::aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
                     support) = 0;
+    virtual Error setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) = 0;
 };
 
 } // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index a1b663c..6501276 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -148,6 +148,12 @@
     return mComposer.isSupported(android::Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
 }
 
+bool Display::hasDisplayIdleTimerCapability() const {
+    bool isCapabilitySupported = false;
+    return mComposer.hasDisplayIdleTimerCapability(mId, &isCapabilitySupported) == Error::NONE &&
+            isCapabilitySupported;
+}
+
 Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
     std::vector<Hwc2::Layer> layerIds;
     std::vector<Composition> types;
@@ -588,6 +594,11 @@
     return static_cast<Error>(error);
 }
 
+Error Display::setIdleTimerEnabled(std::chrono::milliseconds timeout) {
+    const auto error = mComposer.setIdleTimerEnabled(mId, timeout);
+    return static_cast<Error>(error);
+}
+
 // For use by Device
 
 void Display::setConnected(bool connected) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 334d6ec..c03cede 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -91,6 +91,7 @@
     virtual bool hasCapability(
             aidl::android::hardware::graphics::composer3::DisplayCapability) const = 0;
     virtual bool isVsyncPeriodSwitchSupported() const = 0;
+    virtual bool hasDisplayIdleTimerCapability() const = 0;
     virtual void onLayerDestroyed(hal::HWLayerId layerId) = 0;
 
     [[clang::warn_unused_result]] virtual hal::Error acceptChanges() = 0;
@@ -166,6 +167,8 @@
     [[clang::warn_unused_result]] virtual hal::Error getDisplayDecorationSupport(
             std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
                     support) = 0;
+    [[clang::warn_unused_result]] virtual hal::Error setIdleTimerEnabled(
+            std::chrono::milliseconds timeout) = 0;
 };
 
 namespace impl {
@@ -242,6 +245,7 @@
     hal::Error getDisplayDecorationSupport(
             std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
                     support) override;
+    hal::Error setIdleTimerEnabled(std::chrono::milliseconds timeout) override;
 
     // Other Display methods
     hal::HWDisplayId getId() const override { return mId; }
@@ -250,6 +254,7 @@
     bool hasCapability(aidl::android::hardware::graphics::composer3::DisplayCapability)
             const override EXCLUDES(mDisplayCapabilitiesMutex);
     bool isVsyncPeriodSwitchSupported() const override;
+    bool hasDisplayIdleTimerCapability() const override;
     void onLayerDestroyed(hal::HWLayerId layerId) override;
 
 private:
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index ed6e4b0..02b3772 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -971,6 +971,26 @@
     }
 }
 
+status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
+                                         std::chrono::milliseconds timeout) {
+    ATRACE_CALL();
+    RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+    const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout);
+    if (error == hal::Error::UNSUPPORTED) {
+        RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+    }
+    if (error == hal::Error::BAD_PARAMETER) {
+        RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+    }
+    RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+    return NO_ERROR;
+}
+
+bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) {
+    RETURN_IF_INVALID_DISPLAY(displayId, false);
+    return mDisplayData[displayId].hwcDisplay->hasDisplayIdleTimerCapability();
+}
+
 void HWComposer::loadLayerMetadataSupport() {
     mSupportedLayerGenericMetadata.clear();
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a8d439b..f9637f0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -267,16 +267,10 @@
             PhysicalDisplayId,
             std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
                     support) = 0;
+    virtual status_t setIdleTimerEnabled(PhysicalDisplayId, std::chrono::milliseconds timeout) = 0;
+    virtual bool hasDisplayIdleTimerCapability(PhysicalDisplayId) = 0;
 };
 
-static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs,
-                              const android::HWComposer::DeviceRequestedChanges& rhs) {
-    return lhs.changedTypes == rhs.changedTypes && lhs.displayRequests == rhs.displayRequests &&
-            lhs.layerRequests == rhs.layerRequests &&
-            lhs.clientTargetProperty == rhs.clientTargetProperty &&
-            lhs.clientTargetBrightness == rhs.clientTargetBrightness;
-}
-
 namespace impl {
 
 class HWComposer final : public android::HWComposer {
@@ -410,6 +404,8 @@
             PhysicalDisplayId,
             std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
                     support) override;
+    status_t setIdleTimerEnabled(PhysicalDisplayId, std::chrono::milliseconds timeout) override;
+    bool hasDisplayIdleTimerCapability(PhysicalDisplayId) override;
 
     // for debugging ----------------------------------------------------------
     void dump(std::string& out) const override;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index f735bba..33adceb 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -236,6 +236,7 @@
         case OptionalFeature::ExpectedPresentTime:
         case OptionalFeature::DisplayBrightnessCommand:
         case OptionalFeature::BootDisplayConfig:
+        case OptionalFeature::KernelIdleTimer:
             return false;
     }
 }
@@ -487,6 +488,11 @@
     return error;
 }
 
+Error HidlComposer::hasDisplayIdleTimerCapability(Display, bool*) {
+    LOG_ALWAYS_FATAL("hasDisplayIdleTimerCapability should have never been called on this as "
+                     "OptionalFeature::KernelIdleTimer is not supported on HIDL");
+}
+
 Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
                                        float* outMaxLuminance, float* outMaxAverageLuminance,
                                        float* outMinLuminance) {
@@ -1320,6 +1326,11 @@
     return Error::UNSUPPORTED;
 }
 
+Error HidlComposer::setIdleTimerEnabled(Display, std::chrono::milliseconds) {
+    LOG_ALWAYS_FATAL("setIdleTimerEnabled should have never been called on this as "
+                     "OptionalFeature::KernelIdleTimer is not supported on HIDL");
+}
+
 void HidlComposer::registerCallback(ComposerCallback& callback) {
     const bool vsyncSwitchingSupported =
             isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index c2b60cb..a1ea4f2 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -208,6 +208,7 @@
                              std::vector<uint32_t>* outLayerRequestMasks) override;
 
     Error getDozeSupport(Display display, bool* outSupport) override;
+    Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
     Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
                              float* outMaxAverageLuminance, float* outMinLuminance) override;
 
@@ -331,6 +332,7 @@
             Display display,
             std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
                     support) override;
+    Error setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) override;
 
 private:
     class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index e21095a..307da41 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -89,9 +89,6 @@
     virtual void dumpAsString(String8& result) const;
     virtual void resizeBuffers(const ui::Size&) override;
     virtual const sp<Fence>& getClientTargetAcquireFence() const override;
-    // Virtual display surface needs to prepare the frame based on composition type. Skip
-    // any client composition prediction.
-    virtual bool supportsCompositionStrategyPrediction() const override { return false; };
 
 private:
     enum Source : size_t {
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/Layer.h b/services/surfaceflinger/Layer.h
index 2b5e337..48a9bc5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2007 The Android Open Source Project
  *
@@ -1049,7 +1048,7 @@
     mutable bool mDrawingStateModified = false;
 
     sp<Fence> mLastClientCompositionFence;
-    bool mLastClientCompositionDisplayed = false;
+    bool mAlreadyDisplayedThisCompose = false;
 private:
     virtual void setTransformHint(ui::Transform::RotationFlags) {}
 
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index a1e1455..896f254 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -26,18 +26,12 @@
 namespace android {
 namespace {
 
-struct ReparentForDrawing {
-    const sp<Layer>& oldParent;
-
-    ReparentForDrawing(const sp<Layer>& oldParent, const sp<Layer>& newParent,
-                       const Rect& drawingBounds)
-          : oldParent(oldParent) {
+void reparentForDrawing(const sp<Layer>& oldParent, const sp<Layer>& newParent,
+                   const Rect& drawingBounds) {
         // Compute and cache the bounds for the new parent layer.
         newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform(),
-                                 0.f /* shadowRadius */);
+            0.f /* shadowRadius */);
         oldParent->setChildrenDrawingParent(newParent);
-    }
-    ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); }
 };
 
 } // namespace
@@ -114,11 +108,19 @@
     } else {
         // In the "childrenOnly" case we reparent the children to a screenshot
         // layer which has no properties set and which does not draw.
+        //  We hold the statelock as the reparent-for-drawing operation modifies the
+        //  hierarchy and there could be readers on Binder threads, like dump.
         sp<ContainerLayer> screenshotParentLayer = mFlinger.getFactory().createContainerLayer(
-                {&mFlinger, nullptr, "Screenshot Parent"s, 0, LayerMetadata()});
-
-        ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
+                  {&mFlinger, nullptr, "Screenshot Parent"s, 0, LayerMetadata()});
+        {
+            Mutex::Autolock _l(mFlinger.mStateLock);
+            reparentForDrawing(mLayer, screenshotParentLayer, sourceCrop);
+        }
         drawLayers();
+        {
+            Mutex::Autolock _l(mFlinger.mStateLock);
+            mLayer->setChildrenDrawingParent(mLayer);
+        }
     }
 }
 
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
index 6a90694..41273e0 100644
--- a/services/surfaceflinger/LayerRenderArea.h
+++ b/services/surfaceflinger/LayerRenderArea.h
@@ -46,6 +46,7 @@
     Rect getSourceCrop() const override;
 
     void render(std::function<void()> drawLayers) override;
+    virtual sp<Layer> getParentLayer() const { return mLayer; }
 
 private:
     const sp<Layer> mLayer;
@@ -58,4 +59,4 @@
     const bool mChildrenOnly;
 };
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index c9f7f46..387364c 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -4,6 +4,7 @@
 #include <ui/Transform.h>
 
 #include <functional>
+#include "Layer.h"
 
 namespace android {
 
@@ -85,6 +86,10 @@
     // Returns the source display viewport.
     const Rect& getLayerStackSpaceRect() const { return mLayerStackSpaceRect; }
 
+    // If this is a LayerRenderArea, return the root layer of the
+    // capture operation.
+    virtual sp<Layer> getParentLayer() const { return nullptr; }
+
 protected:
     const bool mAllowSecureLayers;
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 15e30b3..65c8613 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -670,9 +670,9 @@
 }
 
 void RefreshRateConfigs::initializeIdleTimer() {
-    if (mConfig.idleTimerTimeoutMs > 0) {
+    if (mConfig.idleTimerTimeout > 0ms) {
         mIdleTimer.emplace(
-                "IdleTimer", std::chrono::milliseconds(mConfig.idleTimerTimeoutMs),
+                "IdleTimer", mConfig.idleTimerTimeout,
                 [this] {
                     std::scoped_lock lock(mIdleTimerCallbacksMutex);
                     if (const auto callbacks = getIdleTimerCallbacks()) {
@@ -963,12 +963,24 @@
 
     base::StringAppendF(&result, "Supports Frame Rate Override By Content: %s\n",
                         mSupportsFrameRateOverrideByContent ? "yes" : "no");
-    base::StringAppendF(&result, "Idle timer: (%s) %s\n",
-                        mConfig.supportKernelIdleTimer ? "kernel" : "platform",
-                        mIdleTimer ? mIdleTimer->dump().c_str() : "off");
+    base::StringAppendF(&result, "Idle timer: ");
+    if (mConfig.kernelIdleTimerController.has_value()) {
+        if (mConfig.kernelIdleTimerController == KernelIdleTimerController::Sysprop) {
+            base::StringAppendF(&result, "(kernel(sysprop))");
+        } else {
+            base::StringAppendF(&result, "(kernel(hwc))");
+        }
+    } else {
+        base::StringAppendF(&result, "(platform)");
+    }
+    base::StringAppendF(&result, " %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off");
     result.append("\n");
 }
 
+std::chrono::milliseconds RefreshRateConfigs::getIdleTimerTimeout() {
+    return mConfig.idleTimerTimeout;
+}
+
 } // namespace android::scheduler
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 14583e3..30d3edd 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -272,6 +272,8 @@
     // Returns a known frame rate that is the closest to frameRate
     Fps findClosestKnownFrameRate(Fps frameRate) const;
 
+    enum class KernelIdleTimerController { Sysprop, HwcApi };
+
     // Configuration flags.
     struct Config {
         bool enableFrameRateOverride = false;
@@ -282,17 +284,18 @@
         int frameRateMultipleThreshold = 0;
 
         // The Idle Timer timeout. 0 timeout means no idle timer.
-        int32_t idleTimerTimeoutMs = 0;
+        std::chrono::milliseconds idleTimerTimeout = 0ms;
 
-        // Whether to use idle timer callbacks that support the kernel timer.
-        bool supportKernelIdleTimer = false;
+        // The controller representing how the kernel idle timer will be configured
+        // either on the HWC api or sysprop.
+        std::optional<KernelIdleTimerController> kernelIdleTimerController;
     };
 
     RefreshRateConfigs(const DisplayModes&, DisplayModeId,
                        Config config = {.enableFrameRateOverride = false,
                                         .frameRateMultipleThreshold = 0,
-                                        .idleTimerTimeoutMs = 0,
-                                        .supportKernelIdleTimer = false});
+                                        .idleTimerTimeout = 0ms,
+                                        .kernelIdleTimerController = {}});
 
     RefreshRateConfigs(const RefreshRateConfigs&) = delete;
     RefreshRateConfigs& operator=(const RefreshRateConfigs&) = delete;
@@ -310,6 +313,7 @@
         TurnOff,  // Turn off the idle timer.
         TurnOn    // Turn on the idle timer.
     };
+
     // Checks whether kernel idle timer should be active depending the policy decisions around
     // refresh rates.
     KernelIdleTimerAction getIdleTimerAction() const;
@@ -332,7 +336,9 @@
                                                  Fps displayFrameRate, GlobalSignals) const
             EXCLUDES(mLock);
 
-    bool supportsKernelIdleTimer() const { return mConfig.supportKernelIdleTimer; }
+    std::optional<KernelIdleTimerController> kernelIdleTimerController() {
+        return mConfig.kernelIdleTimerController;
+    }
 
     struct IdleTimerCallbacks {
         struct Callbacks {
@@ -370,7 +376,7 @@
         if (!mIdleTimer) {
             return;
         }
-        if (kernelOnly && !mConfig.supportKernelIdleTimer) {
+        if (kernelOnly && !mConfig.kernelIdleTimerController.has_value()) {
             return;
         }
         mIdleTimer->reset();
@@ -378,6 +384,8 @@
 
     void dump(std::string& result) const EXCLUDES(mLock);
 
+    std::chrono::milliseconds getIdleTimerTimeout();
+
 private:
     friend struct TestableRefreshRateConfigs;
 
@@ -437,8 +445,8 @@
     std::optional<IdleTimerCallbacks::Callbacks> getIdleTimerCallbacks() const
             REQUIRES(mIdleTimerCallbacksMutex) {
         if (!mIdleTimerCallbacks) return {};
-        return mConfig.supportKernelIdleTimer ? mIdleTimerCallbacks->kernel
-                                              : mIdleTimerCallbacks->platform;
+        return mConfig.kernelIdleTimerController.has_value() ? mIdleTimerCallbacks->kernel
+                                                             : mIdleTimerCallbacks->platform;
     }
 
     // The list of refresh rates, indexed by display modes ID. This may change after this
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index efaa975..268036c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -169,6 +169,8 @@
 using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
 using aidl::android::hardware::graphics::composer3::Capability;
 using aidl::android::hardware::graphics::composer3::DisplayCapability;
+using KernelIdleTimerController =
+        ::android::scheduler::RefreshRateConfigs::KernelIdleTimerController;
 
 namespace android {
 
@@ -270,39 +272,33 @@
     return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3;
 }
 
-
-struct IdleTimerConfig {
-    int32_t timeoutMs;
-    bool supportKernelIdleTimer;
-};
-
-IdleTimerConfig getIdleTimerConfiguration(DisplayId displayId) {
-    // TODO(adyabr): use ro.surface_flinger.* namespace
-
+std::chrono::milliseconds getIdleTimerTimeout(DisplayId displayId) {
     const auto displayIdleTimerMsKey = [displayId] {
         std::stringstream ss;
         ss << "debug.sf.set_idle_timer_ms_" << displayId.value;
         return ss.str();
     }();
 
+    const int32_t displayIdleTimerMs = base::GetIntProperty(displayIdleTimerMsKey, 0);
+    if (displayIdleTimerMs > 0) {
+        return std::chrono::milliseconds(displayIdleTimerMs);
+    }
+
+    const int32_t setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms", 0);
+    const int32_t millis = setIdleTimerMs ? setIdleTimerMs : sysprop::set_idle_timer_ms(0);
+    return std::chrono::milliseconds(millis);
+}
+
+bool getKernelIdleTimerSyspropConfig(DisplayId displayId) {
     const auto displaySupportKernelIdleTimerKey = [displayId] {
         std::stringstream ss;
         ss << "debug.sf.support_kernel_idle_timer_" << displayId.value;
         return ss.str();
     }();
 
-    const int32_t displayIdleTimerMs = base::GetIntProperty(displayIdleTimerMsKey, 0);
     const auto displaySupportKernelIdleTimer =
             base::GetBoolProperty(displaySupportKernelIdleTimerKey, false);
-
-    if (displayIdleTimerMs > 0) {
-        return {displayIdleTimerMs, displaySupportKernelIdleTimer};
-    }
-
-    const int32_t setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms", 0);
-    const int32_t millis = setIdleTimerMs ? setIdleTimerMs : sysprop::set_idle_timer_ms(0);
-
-    return {millis, sysprop::support_kernel_idle_timer(false)};
+    return displaySupportKernelIdleTimer || sysprop::support_kernel_idle_timer(false);
 }
 
 }  // namespace anonymous
@@ -480,9 +476,6 @@
     property_get("debug.sf.disable_client_composition_cache", value, "0");
     mDisableClientCompositionCache = atoi(value);
 
-    property_get("debug.sf.predict_hwc_composition_strategy", value, "0");
-    mPredictCompositionStrategy = atoi(value);
-
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
     // comes online to attempt to read the property. The property is
@@ -2832,14 +2825,15 @@
         creationArgs.connectionType = physical->type;
         creationArgs.supportedModes = physical->supportedModes;
         creationArgs.activeModeId = physical->activeMode->getId();
-        const auto [idleTimerTimeoutMs, supportKernelIdleTimer] =
-                getIdleTimerConfiguration(compositionDisplay->getId());
+        const auto [kernelIdleTimerController, idleTimerTimeoutMs] =
+                getKernelIdleTimerProperties(compositionDisplay->getId());
+
         scheduler::RefreshRateConfigs::Config config =
                 {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
                  .frameRateMultipleThreshold =
                          base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0),
-                 .idleTimerTimeoutMs = idleTimerTimeoutMs,
-                 .supportKernelIdleTimer = supportKernelIdleTimer};
+                 .idleTimerTimeout = idleTimerTimeoutMs,
+                 .kernelIdleTimerController = kernelIdleTimerController};
         creationArgs.refreshRateConfigs =
                 std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
                                                                 creationArgs.activeModeId, config);
@@ -3413,7 +3407,7 @@
                                                         features);
     {
         auto configs = display->holdRefreshRateConfigs();
-        if (configs->supportsKernelIdleTimer()) {
+        if (configs->kernelIdleTimerController().has_value()) {
             features |= Feature::kKernelIdleTimer;
         }
 
@@ -6151,6 +6145,47 @@
     }));
 }
 
+std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
+SurfaceFlinger::getKernelIdleTimerProperties(DisplayId displayId) {
+    const bool isKernelIdleTimerHwcSupported = getHwComposer().getComposer()->isSupported(
+            android::Hwc2::Composer::OptionalFeature::KernelIdleTimer);
+    const auto timeout = getIdleTimerTimeout(displayId);
+    if (isKernelIdleTimerHwcSupported) {
+        if (const auto id = PhysicalDisplayId::tryCast(displayId);
+            getHwComposer().hasDisplayIdleTimerCapability(*id)) {
+            // In order to decide if we can use the HWC api for idle timer
+            // we query DisplayCapability::DISPLAY_IDLE_TIMER directly on the composer
+            // without relying on hasDisplayCapability.
+            // hasDisplayCapability relies on DisplayCapabilities
+            // which are updated after we set the PowerMode::ON.
+            // DISPLAY_IDLE_TIMER is a display driver property
+            // and is available before the PowerMode::ON
+            return {KernelIdleTimerController::HwcApi, timeout};
+        }
+        return {std::nullopt, timeout};
+    }
+    if (getKernelIdleTimerSyspropConfig(displayId)) {
+        return {KernelIdleTimerController::Sysprop, timeout};
+    }
+
+    return {std::nullopt, timeout};
+}
+
+void SurfaceFlinger::updateKernelIdleTimer(std::chrono::milliseconds timeout,
+                                           KernelIdleTimerController controller,
+                                           PhysicalDisplayId displayId) {
+    switch (controller) {
+        case KernelIdleTimerController::HwcApi: {
+            getHwComposer().setIdleTimerEnabled(displayId, timeout);
+            break;
+        }
+        case KernelIdleTimerController::Sysprop: {
+            base::SetProperty(KERNEL_IDLE_TIMER_PROP, timeout > 0ms ? "true" : "false");
+            break;
+        }
+    }
+}
+
 void SurfaceFlinger::toggleKernelIdleTimer() {
     using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
 
@@ -6162,23 +6197,31 @@
 
     // If the support for kernel idle timer is disabled for the active display,
     // don't do anything.
-    if (!display->refreshRateConfigs().supportsKernelIdleTimer()) {
+    const std::optional<KernelIdleTimerController> kernelIdleTimerController =
+            display->refreshRateConfigs().kernelIdleTimerController();
+    if (!kernelIdleTimerController.has_value()) {
         return;
     }
 
     const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();
+
     switch (action) {
         case KernelIdleTimerAction::TurnOff:
             if (mKernelIdleTimerEnabled) {
                 ATRACE_INT("KernelIdleTimer", 0);
-                base::SetProperty(KERNEL_IDLE_TIMER_PROP, "false");
+                std::chrono::milliseconds constexpr kTimerDisabledTimeout = 0ms;
+                updateKernelIdleTimer(kTimerDisabledTimeout, kernelIdleTimerController.value(),
+                                      display->getPhysicalId());
                 mKernelIdleTimerEnabled = false;
             }
             break;
         case KernelIdleTimerAction::TurnOn:
             if (!mKernelIdleTimerEnabled) {
                 ATRACE_INT("KernelIdleTimer", 1);
-                base::SetProperty(KERNEL_IDLE_TIMER_PROP, "true");
+                const std::chrono::milliseconds timeout =
+                        display->refreshRateConfigs().getIdleTimerTimeout();
+                updateKernelIdleTimer(timeout, kernelIdleTimerController.value(),
+                                      display->getPhysicalId());
                 mKernelIdleTimerEnabled = true;
             }
             break;
@@ -6456,19 +6499,6 @@
         // and failed if display is not in native mode. This provide a way to force using native
         // colors when capture.
         dataspace = args.dataspace;
-        if (dataspace == ui::Dataspace::UNKNOWN) {
-            auto display = findDisplay([layerStack = parent->getLayerStack()](const auto& display) {
-                return display.getLayerStack() == layerStack;
-            });
-            if (!display) {
-                // If the layer is not on a display, use the dataspace for the default display.
-                display = getDefaultDisplayDeviceLocked();
-            }
-
-            const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode;
-            dataspace = pickDataspaceFromColorMode(colorMode);
-        }
-
     } // mStateLock
 
     // really small crop or frameScale
@@ -6597,7 +6627,7 @@
 
         renderArea->render([&] {
             renderEngineResultFuture =
-                    renderScreenImplLocked(*renderArea, traverseLayers, buffer,
+                    renderScreenImpl(*renderArea, traverseLayers, buffer,
                                            canCaptureBlackoutContent, regionSampling, grayscale,
                                            captureResults);
         });
@@ -6630,7 +6660,7 @@
     }
 }
 
-std::shared_future<renderengine::RenderEngineResult> SurfaceFlinger::renderScreenImplLocked(
+std::shared_future<renderengine::RenderEngineResult> SurfaceFlinger::renderScreenImpl(
         const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
         const std::shared_ptr<renderengine::ExternalTexture>& buffer,
         bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
@@ -6654,7 +6684,22 @@
     }
 
     captureResults.buffer = buffer->getBuffer();
-    captureResults.capturedDataspace = renderArea.getReqDataSpace();
+    auto dataspace = renderArea.getReqDataSpace();
+    auto parent = renderArea.getParentLayer();
+    if ((dataspace == ui::Dataspace::UNKNOWN) && (parent != nullptr)) {
+        Mutex::Autolock lock(mStateLock);
+        auto display = findDisplay([layerStack = parent->getLayerStack()](const auto& display) {
+            return display.getLayerStack() == layerStack;
+        });
+        if (!display) {
+            // If the layer is not on a display, use the dataspace for the default display.
+            display = getDefaultDisplayDeviceLocked();
+        }
+
+        const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode;
+        dataspace = pickDataspaceFromColorMode(colorMode);
+    }
+    captureResults.capturedDataspace = dataspace;
 
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
@@ -6672,7 +6717,7 @@
     clientCompositionDisplay.clip = sourceCrop;
     clientCompositionDisplay.orientation = rotation;
 
-    clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
+    clientCompositionDisplay.outputDataspace = dataspace;
     clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
 
     const float colorSaturation = grayscale ? 0 : 1;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 86c8333..81afa9b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -344,11 +344,6 @@
     void disableExpensiveRendering();
     FloatRect getMaxDisplayBounds();
 
-    // If set, composition engine tries to predict the composition strategy provided by HWC
-    // based on the previous frame. If the strategy can be predicted, gpu composition will
-    // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect.
-    bool mPredictCompositionStrategy = false;
-
 protected:
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
@@ -380,6 +375,7 @@
     friend class MonitoredProducer;
     friend class RefreshRateOverlay;
     friend class RegionSamplingThread;
+    friend class LayerRenderArea;
     friend class LayerTracing;
 
     // For unit tests
@@ -467,6 +463,8 @@
     };
 
     using ActiveModeInfo = DisplayDevice::ActiveModeInfo;
+    using KernelIdleTimerController =
+            ::android::scheduler::RefreshRateConfigs::KernelIdleTimerController;
 
     enum class BootStage {
         BOOTLOADER,
@@ -690,6 +688,14 @@
     void triggerOnFrameRateOverridesChanged() override;
     // Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
     void toggleKernelIdleTimer() REQUIRES(mStateLock);
+    // Get the controller and timeout that will help decide how the kernel idle timer will be
+    // configured and what value to use as the timeout.
+    std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
+            getKernelIdleTimerProperties(DisplayId) REQUIRES(mStateLock);
+    // Updates the kernel idle timer either through HWC or through sysprop
+    // depending on which controller is provided
+    void updateKernelIdleTimer(std::chrono::milliseconds timeoutMs, KernelIdleTimerController,
+                               PhysicalDisplayId) REQUIRES(mStateLock);
     // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
     // make calls to sys prop each time.
     bool mKernelIdleTimerEnabled = false;
@@ -858,10 +864,10 @@
             RenderAreaFuture, TraverseLayersFunction,
             const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
             bool grayscale, const sp<IScreenCaptureListener>&);
-    std::shared_future<renderengine::RenderEngineResult> renderScreenImplLocked(
+    std::shared_future<renderengine::RenderEngineResult> renderScreenImpl(
             const RenderArea&, TraverseLayersFunction,
             const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent,
-            bool regionSampling, bool grayscale, ScreenCaptureResults&);
+            bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock);
 
     // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a
     // matching ownerUid
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 1669075..15c9d19 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -244,8 +244,8 @@
                                                                       HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                                                       usage);
 
-    auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer,
-                                                  forSystem, regionSampling);
+    auto result = mFlinger.renderScreenImpl(*renderArea, traverseLayers, mCaptureScreenBuffer,
+                                            forSystem, regionSampling);
     EXPECT_TRUE(result.valid());
 
     auto& [status, drawFence] = result.get();
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/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index fe0564e..6780108 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -400,12 +400,12 @@
         return mFlinger->setPowerModeInternal(display, mode);
     }
 
-    auto renderScreenImplLocked(const RenderArea& renderArea,
+    auto renderScreenImpl(const RenderArea& renderArea,
                                 SurfaceFlinger::TraverseLayersFunction traverseLayers,
                                 const std::shared_ptr<renderengine::ExternalTexture>& buffer,
                                 bool forSystem, bool regionSampling) {
         ScreenCaptureResults captureResults;
-        return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem,
+        return mFlinger->renderScreenImpl(renderArea, traverseLayers, buffer, forSystem,
                                                 regionSampling, false /* grayscale */,
                                                 captureResults);
     }
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index a1aa7e8..996f835 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -76,6 +76,7 @@
     MOCK_METHOD4(getDisplayRequests,
                  Error(Display, uint32_t*, std::vector<Layer>*, std::vector<uint32_t>*));
     MOCK_METHOD2(getDozeSupport, Error(Display, bool*));
+    MOCK_METHOD2(getKernelIdleTimerSupport, Error(Display, bool*));
     MOCK_METHOD5(getHdrCapabilities, Error(Display, std::vector<Hdr>*, float*, float*, float*));
     MOCK_METHOD1(getPerFrameMetadataKeys,
                  std::vector<IComposerClient::PerFrameMetadataKey>(Display));
@@ -157,6 +158,8 @@
                  Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
     MOCK_METHOD2(getDisplayDecorationSupport,
                  Error(Display, std::optional<DisplayDecorationSupport>*));
+    MOCK_METHOD2(setIdleTimerEnabled, Error(Display, std::chrono::milliseconds));
+    MOCK_METHOD2(hasDisplayIdleTimerCapability, Error(Display, bool*));
 };
 
 } // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 570ffeb..d9faa06 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -99,6 +99,8 @@
             hal::Error, getDisplayDecorationSupport,
             (std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> *),
             (override));
+    MOCK_METHOD(hal::Error, setIdleTimerEnabled, (std::chrono::milliseconds), (override));
+    MOCK_METHOD(bool, hasDisplayIdleTimerCapability, (), (const override));
 };
 
 class Layer : public HWC2::Layer {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 60c0cb5..7664518 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -924,9 +924,8 @@
     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_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});
@@ -936,9 +935,9 @@
     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_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});
 
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 0be4403..72696ad 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -719,8 +719,6 @@
 
     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 =
@@ -748,7 +746,9 @@
 
         consumer_usage = surface.consumer_usage;
     }
-    wide_color_support = wide_color_support && swapchain_ext;
+    wide_color_support =
+        wide_color_support &&
+        instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
 
     AHardwareBuffer_Desc desc = {};
     desc.width = 1;
@@ -762,11 +762,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});