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, ¶m);
-
- 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});