Merge "[SF] Rename variables to match style" into rvc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 8637a31..28fdaa4 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -237,6 +237,7 @@
{ OPT, "events/kmem/rss_stat/enable" },
{ OPT, "events/kmem/ion_heap_grow/enable" },
{ OPT, "events/kmem/ion_heap_shrink/enable" },
+ { OPT, "events/ion/ion_stat/enable" },
} },
};
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 040ddde..9b2f4a8 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -107,6 +107,8 @@
chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_grow/enable
chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink/enable
chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_shrink/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/ion/ion_stat/enable
+ chmod 0666 /sys/kernel/tracing/events/ion/ion_stat/enable
chmod 0666 /sys/kernel/debug/tracing/events/mm_event/mm_event_record/enable
chmod 0666 /sys/kernel/tracing/events/mm_event/mm_event_record/enable
chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_generate/enable
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 8ff4ca6..a5e6c68 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -68,4 +68,9 @@
* Called when screenshot is taken.
*/
oneway void onScreenshotTaken(boolean success);
+
+ /**
+ * Called when ui intensive bugreport dumps are finished.
+ */
+ oneway void onUiIntensiveBugreportDumpsFinished(String callingPackage);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index c85c7cf..9ba4819 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -169,6 +169,7 @@
#define OTA_METADATA_DIR "/metadata/ota"
#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
#define LINKERCONFIG_DIR "/linkerconfig"
+#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -1612,6 +1613,7 @@
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(PROFILE_DATA_DIR_CUR, true);
ds.AddDir(PROFILE_DATA_DIR_REF, true);
+ ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
}
ds.AddDir(PREREBOOT_DATA_DIR, false);
add_mountinfo();
@@ -2630,11 +2632,13 @@
if (options_->telephony_only) {
MaybeTakeEarlyScreenshot();
+ onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
DumpstateTelephonyOnly(calling_package);
DumpstateBoard();
} else if (options_->wifi_only) {
MaybeTakeEarlyScreenshot();
+ onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
DumpstateWifiOnly();
} else {
@@ -2643,6 +2647,7 @@
// Take screenshot and get consent only after critical dumpsys has finished.
MaybeTakeEarlyScreenshot();
+ onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
// Dump state for the default case. This also drops root.
@@ -2732,6 +2737,19 @@
TakeScreenshot();
}
+void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
+ const std::string& calling_package) {
+ if (calling_uid == AID_SHELL || !CalledByApi()) {
+ return;
+ }
+ if (listener_ != nullptr) {
+ // Let listener know ui intensive bugreport dumps are finished, then it can do event
+ // handling if required.
+ android::String16 package(calling_package.c_str());
+ listener_->onUiIntensiveBugreportDumpsFinished(package);
+ }
+}
+
void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
if (calling_uid == AID_SHELL || !CalledByApi()) {
// No need to get consent for shell triggered dumpstates, or not through
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 498f338..28d8936 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -509,6 +509,9 @@
void MaybeTakeEarlyScreenshot();
+ void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
+ const std::string& calling_package);
+
void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package);
// Removes the in progress files output files (tmp file, zip/txt file, screenshot),
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 047a1c3..6f2d754 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -173,6 +173,15 @@
return binder::Status::ok();
}
+ binder::Status onUiIntensiveBugreportDumpsFinished(const android::String16& callingpackage)
+ override {
+ std::lock_guard <std::mutex> lock(lock_);
+ std::string callingpackageUtf8 = std::string(String8(callingpackage).string());
+ dprintf(out_fd_, "\rCalling package of ui intensive bugreport dumps finished: %s",
+ callingpackageUtf8.c_str());
+ return binder::Status::ok();
+ }
+
bool getIsFinished() {
std::lock_guard<std::mutex> lock(lock_);
return is_finished_;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2efb130..9871a3b 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -66,6 +66,8 @@
MOCK_METHOD1(onError, binder::Status(int32_t error_code));
MOCK_METHOD0(onFinished, binder::Status());
MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
+ MOCK_METHOD1(onUiIntensiveBugreportDumpsFinished,
+ binder::Status(const android::String16& callingpackage));
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index ae44d38..7d1c1ad 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -420,6 +420,32 @@
return true;
}
+binder::Status InstalldNativeService::createAppDataBatched(
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& uuids,
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& packageNames,
+ int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+ const std::vector<std::string>& seInfos, const std::vector<int32_t>& targetSdkVersions,
+ int64_t* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ ATRACE_BEGIN("createAppDataBatched");
+ binder::Status ret;
+ for (size_t i = 0; i < uuids->size(); i++) {
+ if (!packageNames->at(i)) {
+ continue;
+ }
+ ret = createAppData(uuids->at(i), *packageNames->at(i), userId, flags, appIds[i],
+ seInfos[i], targetSdkVersions[i], _aidl_return);
+ if (!ret.isOk()) {
+ ATRACE_END();
+ return ret;
+ }
+ }
+ ATRACE_END();
+ return ok();
+}
+
binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index eb151ca..8e7d98b 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -44,7 +44,12 @@
int32_t userSerial, int32_t flags);
binder::Status destroyUserData(const std::unique_ptr<std::string>& uuid, int32_t userId,
int32_t flags);
-
+ binder::Status createAppDataBatched(
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& uuids,
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& packageNames,
+ int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+ const std::vector<std::string>& seInfos, const std::vector<int32_t>& targetSdkVersions,
+ int64_t* _aidl_return);
binder::Status createAppData(const std::unique_ptr<std::string>& uuid,
const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 5e5af73..eeda6c5 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -23,6 +23,9 @@
long createAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
int userId, int flags, int appId, in @utf8InCpp String seInfo, int targetSdkVersion);
+ long createAppDataBatched(in @nullable @utf8InCpp String[] uuids,
+ in @nullable @utf8InCpp String[] packageNames, in int userId, int flags, in int[] appIds,
+ in @utf8InCpp String[] seInfos, in int[] targetSdkVersions);
void restoreconAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, int flags, int appId, @utf8InCpp String seInfo);
void migrateAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 5ee6a9f..ffa8724 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -262,6 +262,17 @@
return "";
}
+static std::string MapPropertyToArgWithBackup(const std::string& property,
+ const std::string& backupProperty,
+ const std::string& format,
+ const std::string& default_value = "") {
+ std::string value = GetProperty(property, default_value);
+ if (!value.empty()) {
+ return StringPrintf(format.c_str(), value.c_str());
+ }
+ return MapPropertyToArg(backupProperty, format, default_value);
+}
+
// Determines which binary we should use for execution (the debug or non-debug version).
// e.g. dex2oatd vs dex2oat
static const char* select_execution_binary(const char* binary, const char* debug_binary,
@@ -307,6 +318,16 @@
// Phenotype property name for enabling profiling the boot class path.
static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath";
+static bool IsBootClassPathProfilingEnable() {
+ std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
+ profile_boot_class_path =
+ server_configurable_flags::GetServerConfigurableFlag(
+ RUNTIME_NATIVE_BOOT_NAMESPACE,
+ PROFILE_BOOT_CLASS_PATH,
+ /*default_value=*/ profile_boot_class_path);
+ return profile_boot_class_path == "true";
+}
+
class RunDex2Oat : public ExecVHelper {
public:
RunDex2Oat(int zip_fd,
@@ -321,6 +342,7 @@
const char* compiler_filter,
bool debuggable,
bool post_bootcomplete,
+ bool for_restore,
bool background_job_compile,
int profile_fd,
const char* class_loader_context,
@@ -336,14 +358,24 @@
std::string dex2oat_Xms_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xms", "-Xms%s");
std::string dex2oat_Xmx_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xmx", "-Xmx%s");
- const char* threads_property = post_bootcomplete
- ? "dalvik.vm.dex2oat-threads"
- : "dalvik.vm.boot-dex2oat-threads";
- std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
- const char* cpu_set_property = post_bootcomplete
- ? "dalvik.vm.dex2oat-cpu-set"
- : "dalvik.vm.boot-dex2oat-cpu-set";
- std::string dex2oat_cpu_set_arg = MapPropertyToArg(cpu_set_property, "--cpu-set=%s");
+ std::string threads_format = "-j%s";
+ std::string dex2oat_threads_arg = post_bootcomplete
+ ? (for_restore
+ ? MapPropertyToArgWithBackup(
+ "dalvik.vm.restore-dex2oat-threads",
+ "dalvik.vm.dex2oat-threads",
+ threads_format)
+ : MapPropertyToArg("dalvik.vm.dex2oat-threads", threads_format))
+ : MapPropertyToArg("dalvik.vm.boot-dex2oat-threads", threads_format);
+ std::string cpu_set_format = "--cpu-set=%s";
+ std::string dex2oat_cpu_set_arg = post_bootcomplete
+ ? (for_restore
+ ? MapPropertyToArgWithBackup(
+ "dalvik.vm.restore-dex2oat-cpu-set",
+ "dalvik.vm.dex2oat-cpu-set",
+ cpu_set_format)
+ : MapPropertyToArg("dalvik.vm.dex2oat-cpu-set", cpu_set_format))
+ : MapPropertyToArg("dalvik.vm.boot-dex2oat-cpu-set", cpu_set_format);
std::string bootclasspath;
char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
@@ -407,8 +439,17 @@
MapPropertyToArg("dalvik.vm.dex2oat-very-large", "--very-large-app-threshold=%s");
+
+ // Decide whether to use dex2oat64.
+ bool use_dex2oat64 = false;
+ // Check whether the device even supports 64-bit ABIs.
+ if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
+ use_dex2oat64 = GetBoolProperty("dalvik.vm.dex2oat64.enabled", false);
+ }
const char* dex2oat_bin = select_execution_binary(
- kDex2oatPath, kDex2oatDebugPath, background_job_compile);
+ (use_dex2oat64 ? kDex2oat64Path : kDex2oat32Path),
+ (use_dex2oat64 ? kDex2oatDebug64Path : kDex2oatDebug32Path),
+ background_job_compile);
bool generate_minidebug_info = kEnableMinidebugInfo &&
GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
@@ -419,14 +460,7 @@
ENABLE_JITZYGOTE_IMAGE,
/*default_value=*/ "");
- std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
- profile_boot_class_path =
- server_configurable_flags::GetServerConfigurableFlag(
- RUNTIME_NATIVE_BOOT_NAMESPACE,
- PROFILE_BOOT_CLASS_PATH,
- /*default_value=*/ profile_boot_class_path);
-
- if (use_jitzygote_image == "true" || profile_boot_class_path == "true") {
+ if (use_jitzygote_image == "true" || IsBootClassPathProfilingEnable()) {
boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
} else {
boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
@@ -865,7 +899,15 @@
}
RunProfman profman_merge;
- profman_merge.SetupMerge(profiles_fd, reference_profile_fd);
+ const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>();
+ const std::vector<std::string>& dex_locations = std::vector<std::string>();
+ profman_merge.SetupMerge(
+ profiles_fd,
+ reference_profile_fd,
+ apk_fds,
+ dex_locations,
+ /* for_snapshot= */ false,
+ IsBootClassPathProfilingEnable());
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -2075,6 +2117,7 @@
bool enable_hidden_api_checks = (dexopt_flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) != 0;
bool generate_compact_dex = (dexopt_flags & DEXOPT_GENERATE_COMPACT_DEX) != 0;
bool generate_app_image = (dexopt_flags & DEXOPT_GENERATE_APP_IMAGE) != 0;
+ bool for_restore = (dexopt_flags & DEXOPT_FOR_RESTORE) != 0;
// Check if we're dealing with a secondary dex file and if we need to compile it.
std::string oat_dir_str;
@@ -2191,6 +2234,7 @@
compiler_filter,
debuggable,
boot_complete,
+ for_restore,
background_job_compile,
reference_profile_fd.get(),
class_loader_context,
@@ -2777,7 +2821,13 @@
}
RunProfman args;
- args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations, /*for_snapshot=*/true);
+ // This is specifically a snapshot for an app, so don't use boot image profiles.
+ args.SetupMerge(profiles_fd,
+ snapshot_fd,
+ apk_fds,
+ dex_locations,
+ /* for_snapshot= */ true,
+ /* for_boot_image= */ false);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index ef739ba..cc44873 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -34,8 +34,10 @@
#define ANDROID_ART_APEX_BIN "/apex/com.android.art/bin"
// Location of binaries in the Android Runtime APEX.
-static constexpr const char* kDex2oatPath = ANDROID_ART_APEX_BIN "/dex2oat";
-static constexpr const char* kDex2oatDebugPath = ANDROID_ART_APEX_BIN "/dex2oatd";
+static constexpr const char* kDex2oat32Path = ANDROID_ART_APEX_BIN "/dex2oat32";
+static constexpr const char* kDex2oat64Path = ANDROID_ART_APEX_BIN "/dex2oat64";
+static constexpr const char* kDex2oatDebug32Path = ANDROID_ART_APEX_BIN "/dex2oatd32";
+static constexpr const char* kDex2oatDebug64Path = ANDROID_ART_APEX_BIN "/dex2oatd64";
static constexpr const char* kProfmanPath = ANDROID_ART_APEX_BIN "/profman";
static constexpr const char* kProfmanDebugPath = ANDROID_ART_APEX_BIN "/profmand";
static constexpr const char* kDexoptanalyzerPath = ANDROID_ART_APEX_BIN "/dexoptanalyzer";
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index c928631..b5ee481 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -55,6 +55,7 @@
constexpr int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
constexpr int DEXOPT_GENERATE_COMPACT_DEX = 1 << 11;
constexpr int DEXOPT_GENERATE_APP_IMAGE = 1 << 12;
+constexpr int DEXOPT_FOR_RESTORE = 1 << 13; // TODO(b/135202722): remove
/* all known values for dexopt flags */
constexpr int DEXOPT_MASK =
@@ -69,7 +70,8 @@
| DEXOPT_IDLE_BACKGROUND_JOB
| DEXOPT_ENABLE_HIDDEN_API_CHECKS
| DEXOPT_GENERATE_COMPACT_DEX
- | DEXOPT_GENERATE_APP_IMAGE;
+ | DEXOPT_GENERATE_APP_IMAGE
+ | DEXOPT_FOR_RESTORE;
// NOTE: keep in sync with StorageManager
constexpr int FLAG_STORAGE_DE = 1 << 0;
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index d773790..18f8268 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -83,7 +83,7 @@
static_assert(DEXOPT_GENERATE_COMPACT_DEX == 1 << 11, "DEXOPT_GENERATE_COMPACT_DEX unexpected");
static_assert(DEXOPT_GENERATE_APP_IMAGE == 1 << 12, "DEXOPT_GENERATE_APP_IMAGE unexpected");
-static_assert(DEXOPT_MASK == (0x1dfe | DEXOPT_IDLE_BACKGROUND_JOB),
+static_assert(DEXOPT_MASK == (0x3dfe | DEXOPT_IDLE_BACKGROUND_JOB),
"DEXOPT_MASK unexpected.");
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 69fefa1..16e4055 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -653,6 +653,15 @@
DEX2OAT_FROM_SCRATCH);
}
+TEST_F(DexoptTest, DexoptPrimaryPublicRestore) {
+ LOG(INFO) << "DexoptPrimaryPublicRestore";
+ CompilePrimaryDexOk("verify",
+ DEXOPT_FOR_RESTORE | DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+}
+
TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
binder::Status status;
@@ -750,6 +759,36 @@
EXPECT_TRUE(found_enable);
}
+TEST_F(DexoptTest, DexoptDex2oat64Enabled) {
+ LOG(INFO) << "DexoptDex2oat64Enabled";
+ const std::string property = "dalvik.vm.dex2oat64.enabled";
+ const std::string previous_value = android::base::GetProperty(property, "");
+ auto restore_property = android::base::make_scope_guard([=]() {
+ android::base::SetProperty(property, previous_value);
+ });
+ std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex");
+ // Disable the property and use dex2oat32.
+ ASSERT_TRUE(android::base::SetProperty(property, "false")) << property;
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+ DEXOPT_GENERATE_APP_IMAGE,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH,
+ /*binder_result=*/nullptr,
+ empty_dm_file_.c_str());
+ // Enable the property and use dex2oat64.
+ ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+ DEXOPT_GENERATE_APP_IMAGE,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH,
+ /*binder_result=*/nullptr,
+ empty_dm_file_.c_str());
+}
+
class PrimaryDexReCompilationTest : public DexoptTest {
public:
virtual void SetUp() {
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index cbbea12..1f9892a 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -49,14 +49,28 @@
const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
const std::string instance = name.substr(firstSlash+1);
- for (const auto& manifest : {
- vintf::VintfObject::GetDeviceHalManifest(),
- vintf::VintfObject::GetFrameworkHalManifest()
+ struct ManifestWithDescription {
+ std::shared_ptr<const vintf::HalManifest> manifest;
+ const char* description;
+ };
+ for (const ManifestWithDescription& mwd : {
+ ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
+ ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
}) {
- if (manifest != nullptr && manifest->hasAidlInstance(package, iface, instance)) {
+ if (mwd.manifest == nullptr) {
+ LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description;
+ // note, we explicitly do not retry here, so that we can detect VINTF
+ // or other bugs (b/151696835)
+ continue;
+ }
+ if (mwd.manifest->hasAidlInstance(package, iface, instance)) {
+ LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
return true;
}
}
+
+ // Although it is tested, explicitly rebuilding qualified name, in case it
+ // becomes something unexpected.
LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
<< " in the VINTF manifest.";
return false;
@@ -72,13 +86,20 @@
#endif // !VENDORSERVICEMANAGER
ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {
-#ifndef VENDORSERVICEMANAGER
- // can process these at any times, don't want to delay first VINTF client
- std::thread([] {
- vintf::VintfObject::GetDeviceHalManifest();
- vintf::VintfObject::GetFrameworkHalManifest();
- }).detach();
-#endif // !VENDORSERVICEMANAGER
+// TODO(b/151696835): reenable performance hack when we solve bug, since with
+// this hack and other fixes, it is unlikely we will see even an ephemeral
+// failure when the manifest parse fails. The goal is that the manifest will
+// be read incorrectly and cause the process trying to register a HAL to
+// fail. If this is in fact an early boot kernel contention issue, then we
+// will get no failure, and by its absence, be signalled to invest more
+// effort in re-adding this performance hack.
+// #ifndef VENDORSERVICEMANAGER
+// // can process these at any times, don't want to delay first VINTF client
+// std::thread([] {
+// vintf::VintfObject::GetDeviceHalManifest();
+// vintf::VintfObject::GetFrameworkHalManifest();
+// }).detach();
+// #endif // !VENDORSERVICEMANAGER
}
ServiceManager::~ServiceManager() {
// this should only happen in tests
@@ -547,4 +568,4 @@
return Status::ok();
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/data/etc/android.hardware.camera.concurrent.xml b/data/etc/android.hardware.camera.concurrent.xml
new file mode 100644
index 0000000..2cbb263
--- /dev/null
+++ b/data/etc/android.hardware.camera.concurrent.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<!-- This is the set of features required for a camera2 device that supports concurrent operation
+ of front and back cameras -->
+<permissions>
+ <feature name="android.hardware.camera.front" />
+ <feature name="android.hardware.camera.concurrent" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.hinge_angle.xml b/data/etc/android.hardware.sensor.hinge_angle.xml
new file mode 100644
index 0000000..d744305
--- /dev/null
+++ b/data/etc/android.hardware.sensor.hinge_angle.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<!-- Feature for devices with a hinge angle sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.hinge_angle" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.software.controls.xml b/data/etc/android.software.controls.xml
new file mode 100644
index 0000000..2cba34b
--- /dev/null
+++ b/data/etc/android.software.controls.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<!-- This is the standard feature indicating device controls support on the device,
+ as specified in the CDD. ONLY devices that meet the CDD's requirements may
+ declare this feature. -->
+<permissions>
+ <feature name="android.software.controls" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 619d017..dc6963f 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -59,6 +59,9 @@
<!-- Feature to specify if the device support managed users. -->
<feature name="android.software.managed_users" notLowRam="true"/>
+ <!-- Feature to specify if the device supports controls. -->
+ <feature name="android.software.controls" />
+
<!-- Devices with all optimizations required to support VR Mode and
pass all CDD requirements for this feature may include
android.hardware.vr.high_performance -->
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 52524ca..e878f86 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -59,6 +59,9 @@
<!-- Feature to specify if the device support managed users. -->
<feature name="android.software.managed_users" />
+ <!-- Feature to specify if the device supports controls. -->
+ <feature name="android.software.controls" />
+
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with a rear-facing camera must include one of these as appropriate:
android.hardware.camera.xml or
diff --git a/headers/Android.bp b/headers/Android.bp
index 82bc8a1..5337235 100644
--- a/headers/Android.bp
+++ b/headers/Android.bp
@@ -17,4 +17,5 @@
"libutils_headers",
"libstagefright_foundation_headers",
],
+ min_sdk_version: "29",
}
diff --git a/headers/media_plugin/media/openmax/OMX_IndexExt.h b/headers/media_plugin/media/openmax/OMX_IndexExt.h
index bbb3193..a427db7 100644
--- a/headers/media_plugin/media/openmax/OMX_IndexExt.h
+++ b/headers/media_plugin/media/openmax/OMX_IndexExt.h
@@ -89,6 +89,7 @@
OMX_IndexParamVideoVp9, /**< reference: OMX_VIDEO_PARAM_VP9TYPE */
OMX_IndexParamVideoAndroidVp9Encoder, /**< reference: OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE */
OMX_IndexParamVideoAndroidImageGrid, /**< reference: OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE */
+ OMX_IndexParamVideoAndroidRequiresSwRenderer, /**< reference: OMX_PARAM_U32TYPE */
OMX_IndexExtVideoEndUnused,
/* Image & Video common configurations */
diff --git a/libs/nativedisplay/include/android/choreographer.h b/include/android/choreographer.h
similarity index 88%
rename from libs/nativedisplay/include/android/choreographer.h
rename to include/android/choreographer.h
index 5fd3de9..c1c4a72 100644
--- a/libs/nativedisplay/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -75,14 +75,16 @@
* Deprecated: Use AChoreographer_postFrameCallback64 instead.
*/
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
- AChoreographer_frameCallback callback, void* data) __INTRODUCED_IN(24) __DEPRECATED_IN(29);
+ AChoreographer_frameCallback callback, void* data)
+ __INTRODUCED_IN(24) __DEPRECATED_IN(29);
/**
* Deprecated: Use AChoreographer_postFrameCallbackDelayed64 instead.
*/
void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
- AChoreographer_frameCallback callback, void* data,
- long delayMillis) __INTRODUCED_IN(24) __DEPRECATED_IN(29);
+ AChoreographer_frameCallback callback, void* data,
+ long delayMillis) __INTRODUCED_IN(24)
+ __DEPRECATED_IN(29);
#endif /* __ANDROID_API__ >= 24 */
@@ -95,7 +97,8 @@
* Available since API level 29.
*/
void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
- AChoreographer_frameCallback64 callback, void* data) __INTRODUCED_IN(29);
+ AChoreographer_frameCallback64 callback, void* data)
+ __INTRODUCED_IN(29);
/**
* Post a callback to be run on the frame following the specified delay. The
@@ -105,7 +108,8 @@
* Available since API level 29.
*/
void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
- AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) __INTRODUCED_IN(29);
+ AChoreographer_frameCallback64 callback, void* data,
+ uint32_t delayMillis) __INTRODUCED_IN(29);
#endif /* __ANDROID_API__ >= 29 */
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index c44db51..c5e56fd 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -68,46 +68,48 @@
// Window types from WindowManager.LayoutParams
enum {
FIRST_APPLICATION_WINDOW = 1,
- TYPE_BASE_APPLICATION = 1,
- TYPE_APPLICATION = 2,
+ TYPE_BASE_APPLICATION = 1,
+ TYPE_APPLICATION = 2,
TYPE_APPLICATION_STARTING = 3,
LAST_APPLICATION_WINDOW = 99,
- FIRST_SUB_WINDOW = 1000,
- TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
- TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
- TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
- TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
- TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
- LAST_SUB_WINDOW = 1999,
- FIRST_SYSTEM_WINDOW = 2000,
- TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
- TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
- TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
- TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
- TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
- TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
- TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
- TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
- TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
- TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
- TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
- TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
- TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
- TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
- TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
- TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17,
- TYPE_POINTER = FIRST_SYSTEM_WINDOW+18,
- TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19,
- TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
- TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
- TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22,
- TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24,
- TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27,
- TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32,
- TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34,
- LAST_SYSTEM_WINDOW = 2999,
+ FIRST_SUB_WINDOW = 1000,
+ TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
+ TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1,
+ TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2,
+ TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3,
+ TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4,
+ LAST_SUB_WINDOW = 1999,
+ FIRST_SYSTEM_WINDOW = 2000,
+ TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
+ TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1,
+ TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2,
+ TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3,
+ TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4,
+ TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5,
+ TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6,
+ TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7,
+ TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8,
+ TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9,
+ TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10,
+ TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11,
+ TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12,
+ TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13,
+ TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14,
+ TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15,
+ TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16,
+ TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17,
+ TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18,
+ TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19,
+ TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20,
+ TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21,
+ TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22,
+ TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24,
+ TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27,
+ TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32,
+ TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34,
+ TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40,
+ TYPE_TRUSTED_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 42,
+ LAST_SYSTEM_WINDOW = 2999,
};
enum {
@@ -123,17 +125,17 @@
// input windows that have the same token.
sp<IBinder> token;
// This uniquely identifies the input window.
- int32_t id = 0;
+ int32_t id = -1;
std::string name;
- int32_t layoutParamsFlags;
- int32_t layoutParamsType;
- nsecs_t dispatchingTimeout;
+ int32_t layoutParamsFlags = 0;
+ int32_t layoutParamsType = 0;
+ nsecs_t dispatchingTimeout = -1;
/* These values are filled in by SurfaceFlinger. */
- int32_t frameLeft;
- int32_t frameTop;
- int32_t frameRight;
- int32_t frameBottom;
+ int32_t frameLeft = -1;
+ int32_t frameTop = -1;
+ int32_t frameRight = -1;
+ int32_t frameBottom = -1;
/*
* SurfaceFlinger consumes this value to shrink the computed frame. This is
@@ -145,7 +147,7 @@
// A global scaling factor for all windows. Unlike windowScaleX/Y this results
// in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis.
- float globalScaleFactor;
+ float globalScaleFactor = 1.0f;
// Scaling factors applied to individual windows.
float windowXScale = 1.0f;
@@ -156,18 +158,18 @@
* to absolute coordinates by SurfaceFlinger once the frame is computed.
*/
Region touchableRegion;
- bool visible;
- bool canReceiveKeys;
- bool hasFocus;
- bool hasWallpaper;
- bool paused;
- int32_t ownerPid;
- int32_t ownerUid;
- int32_t inputFeatures;
- int32_t displayId;
+ bool visible = false;
+ bool canReceiveKeys = false;
+ bool hasFocus = false;
+ bool hasWallpaper = false;
+ bool paused = false;
+ int32_t ownerPid = -1;
+ int32_t ownerUid = -1;
+ int32_t inputFeatures = 0;
+ int32_t displayId = ADISPLAY_ID_NONE;
int32_t portalToDisplayId = ADISPLAY_ID_NONE;
InputApplicationInfo applicationInfo;
- bool replaceTouchableRegionWithCrop;
+ bool replaceTouchableRegionWithCrop = false;
wp<IBinder> touchableRegionCropHandle;
void addTouchableRegion(const Rect& region);
@@ -213,7 +215,7 @@
}
inline std::string getName() const {
- return mInfo.token ? mInfo.name : "<invalid>";
+ return !mInfo.name.empty() ? mInfo.name : "<invalid>";
}
inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h
new file mode 120000
index 0000000..c2047c0
--- /dev/null
+++ b/include/ui/FatVector.h
@@ -0,0 +1 @@
+../../libs/ui/include/ui/FatVector.h
\ No newline at end of file
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 2518b14..f66673f 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -35,4 +35,5 @@
enabled: true,
},
},
+ min_sdk_version: "29",
}
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 4f2709d..5e4c98f 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -98,15 +98,6 @@
return PROCESS_STATE_UNKNOWN;
}
-bool ActivityManager::isUidActiveOrForeground(const uid_t uid, const String16& callingPackage)
-{
- sp<IActivityManager> service = getService();
- if (service != nullptr) {
- return service->isUidActiveOrForeground(uid, callingPackage);
- }
- return false;
-}
-
status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
sp<IActivityManager> service = getService();
if (service != nullptr) {
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index e6cfeb4..db4aba8 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -28,6 +28,7 @@
"libcutils_headers",
"libutils_headers",
],
+ min_sdk_version: "29",
}
// These interfaces are android-specific implementation unrelated to binder
@@ -152,6 +153,7 @@
sanitize: {
misc_undefined: ["integer"],
},
+ min_sdk_version: "29",
}
// AIDL interface between libbinder and framework.jar
@@ -170,6 +172,7 @@
aidl_interface {
name: "libbinder_aidl_test_stub",
+ unstable: true,
local_include_dir: "aidl",
srcs: [":libbinder_aidl"],
vendor_available: true,
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 9e1249b..1eb5363 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -104,18 +104,6 @@
}
return reply.readInt32();
}
-
- virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
- data.writeInt32(uid);
- data.writeString16(callingPackage);
- remote()->transact(IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION, data, &reply);
- // fail on exception
- if (reply.readExceptionCode() != 0) return false;
- return reply.readInt32() == 1;
- }
};
// ------------------------------------------------------------------------------------
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 9e89c57..d67ce15 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -997,7 +997,11 @@
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
- LOG_ALWAYS_FATAL("Driver did not consume write buffer");
+ LOG_ALWAYS_FATAL("Driver did not consume write buffer. "
+ "err: %s consumed: %zu of %zu",
+ statusToString(err).c_str(),
+ (size_t)bwr.write_consumed,
+ mOut.dataSize());
else {
mOut.setDataSize(0);
processPostWriteDerefs();
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index 74aece8..6f49aa1 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -82,12 +82,12 @@
return false;
}
- if (!manager->registerClientCallback(name, service, this).isOk()) {
- ALOGE("Failed to add client callback for service %s", name.c_str());
- return false;
- }
-
if (!reRegister) {
+ if (!manager->registerClientCallback(name, service, this).isOk()) {
+ ALOGE("Failed to add client callback for service %s", name.c_str());
+ return false;
+ }
+
// Only add this when a service is added for the first time, as it is not removed
mRegisteredServices[name] = {service, allowIsolated, dumpFlags};
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index beab270..9642a87 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -987,12 +987,22 @@
status_t Parcel::writeString8(const String8& str)
{
- status_t err = writeInt32(str.bytes());
- // only write string if its length is more than zero characters,
- // as readString8 will only read if the length field is non-zero.
- // this is slightly different from how writeString16 works.
- if (str.bytes() > 0 && err == NO_ERROR) {
- err = write(str.string(), str.bytes()+1);
+ return writeString8(str.string(), str.size());
+}
+
+status_t Parcel::writeString8(const char* str, size_t len)
+{
+ if (str == nullptr) return writeInt32(-1);
+
+ status_t err = writeInt32(len);
+ if (err == NO_ERROR) {
+ uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char));
+ if (data) {
+ memcpy(data, str, len);
+ *reinterpret_cast<char*>(data+len) = 0;
+ return NO_ERROR;
+ }
+ err = mError;
}
return err;
}
@@ -1832,37 +1842,39 @@
String8 Parcel::readString8() const
{
- String8 retString;
- status_t status = readString8(&retString);
- if (status != OK) {
- // We don't care about errors here, so just return an empty string.
- return String8();
- }
- return retString;
+ size_t len;
+ const char* str = readString8Inplace(&len);
+ if (str) return String8(str, len);
+ ALOGE("Reading a NULL string not supported here.");
+ return String8();
}
status_t Parcel::readString8(String8* pArg) const
{
- int32_t size;
- status_t status = readInt32(&size);
- if (status != OK) {
- return status;
- }
- // watch for potential int overflow from size+1
- if (size < 0 || size >= INT32_MAX) {
- return BAD_VALUE;
- }
- // |writeString8| writes nothing for empty string.
- if (size == 0) {
+ size_t len;
+ const char* str = readString8Inplace(&len);
+ if (str) {
+ pArg->setTo(str, len);
+ return 0;
+ } else {
*pArg = String8();
- return OK;
+ return UNEXPECTED_NULL;
}
- const char* str = (const char*)readInplace(size + 1);
- if (str == nullptr) {
- return BAD_VALUE;
+}
+
+const char* Parcel::readString8Inplace(size_t* outLen) const
+{
+ int32_t size = readInt32();
+ // watch for potential int overflow from size+1
+ if (size >= 0 && size < INT32_MAX) {
+ *outLen = size;
+ const char* str = (const char*)readInplace(size+1);
+ if (str != nullptr) {
+ return str;
+ }
}
- pArg->setTo(str, size);
- return OK;
+ *outLen = 0;
+ return nullptr;
}
String16 Parcel::readString16() const
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 0bb6d28..9108e31 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -46,24 +46,25 @@
PROCESS_STATE_PERSISTENT = 0,
PROCESS_STATE_PERSISTENT_UI = 1,
PROCESS_STATE_TOP = 2,
- PROCESS_STATE_BOUND_TOP = 3,
- PROCESS_STATE_FOREGROUND_SERVICE = 4,
- PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5,
- PROCESS_STATE_IMPORTANT_FOREGROUND = 6,
- PROCESS_STATE_IMPORTANT_BACKGROUND = 7,
- PROCESS_STATE_TRANSIENT_BACKGROUND = 8,
- PROCESS_STATE_BACKUP = 9,
- PROCESS_STATE_SERVICE = 10,
- PROCESS_STATE_RECEIVER = 11,
- PROCESS_STATE_TOP_SLEEPING = 12,
- PROCESS_STATE_HEAVY_WEIGHT = 13,
- PROCESS_STATE_HOME = 14,
- PROCESS_STATE_LAST_ACTIVITY = 15,
- PROCESS_STATE_CACHED_ACTIVITY = 16,
- PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17,
- PROCESS_STATE_CACHED_RECENT = 18,
- PROCESS_STATE_CACHED_EMPTY = 19,
- PROCESS_STATE_NONEXISTENT = 20,
+ PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3,
+ PROCESS_STATE_BOUND_TOP = 4,
+ PROCESS_STATE_FOREGROUND_SERVICE = 5,
+ PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6,
+ PROCESS_STATE_IMPORTANT_FOREGROUND = 7,
+ PROCESS_STATE_IMPORTANT_BACKGROUND = 8,
+ PROCESS_STATE_TRANSIENT_BACKGROUND = 9,
+ PROCESS_STATE_BACKUP = 10,
+ PROCESS_STATE_SERVICE = 11,
+ PROCESS_STATE_RECEIVER = 12,
+ PROCESS_STATE_TOP_SLEEPING = 13,
+ PROCESS_STATE_HEAVY_WEIGHT = 14,
+ PROCESS_STATE_HOME = 15,
+ PROCESS_STATE_LAST_ACTIVITY = 16,
+ PROCESS_STATE_CACHED_ACTIVITY = 17,
+ PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18,
+ PROCESS_STATE_CACHED_RECENT = 19,
+ PROCESS_STATE_CACHED_EMPTY = 20,
+ PROCESS_STATE_NONEXISTENT = 21,
};
ActivityManager();
@@ -76,7 +77,6 @@
void unregisterUidObserver(const sp<IUidObserver>& observer);
bool isUidActive(const uid_t uid, const String16& callingPackage);
int getUidProcessState(const uid_t uid, const String16& callingPackage);
- bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage);
status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index 1815ecc..e0248f6 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -39,15 +39,13 @@
virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0;
virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0;
virtual int32_t getUidProcessState(const uid_t uid, const String16& callingPackage) = 0;
- virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) = 0;
enum {
OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
REGISTER_UID_OBSERVER_TRANSACTION,
UNREGISTER_UID_OBSERVER_TRANSACTION,
IS_UID_ACTIVE_TRANSACTION,
- GET_UID_PROCESS_STATE_TRANSACTION,
- IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION,
+ GET_UID_PROCESS_STATE_TRANSACTION
};
};
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 4b1a758..c1f64fb 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -119,6 +119,7 @@
status_t writeDouble(double val);
status_t writeCString(const char* str);
status_t writeString8(const String8& str);
+ status_t writeString8(const char* str, size_t len);
status_t writeString16(const String16& str);
status_t writeString16(const std::unique_ptr<String16>& str);
status_t writeString16(const char16_t* str, size_t len);
@@ -283,6 +284,7 @@
const char* readCString() const;
String8 readString8() const;
status_t readString8(String8* pArg) const;
+ const char* readString8Inplace(size_t* outLen) const;
String16 readString16() const;
status_t readString16(String16* pArg) const;
status_t readString16(std::unique_ptr<String16>* pArg) const;
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index cb4b20f..5f5265c 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -92,6 +92,7 @@
aidl_interface {
name: "IBinderVendorDoubleLoadTest",
+ unstable: true,
vendor: true,
srcs: [
"IBinderVendorDoubleLoadTest.aidl",
@@ -100,6 +101,7 @@
aidl_interface {
name: "IBinderNdkUnitTest",
+ unstable: true,
srcs: [
"IBinderNdkUnitTest.aidl",
"IEmpty.aidl",
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index c7b7551..c0da2cd 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -27,7 +27,9 @@
defaults: ["binder_test_defaults"],
srcs: ["binderDriverInterfaceTest.cpp"],
compile_multilib: "32",
+ multilib: { lib32: { suffix: "" } },
cflags: ["-DBINDER_IPC_32BIT=1"],
+ test_suites: ["vts"],
}
cc_test {
@@ -52,7 +54,10 @@
"libutils",
],
compile_multilib: "32",
+ multilib: { lib32: { suffix: "" } },
cflags: ["-DBINDER_IPC_32BIT=1"],
+ test_suites: ["vts"],
+ require_root: true,
}
cc_test {
@@ -137,6 +142,7 @@
aidl_interface {
name: "binderStabilityTestIface",
+ unstable: true,
srcs: [
"IBinderStabilityTest.aidl",
],
diff --git a/libs/binder/tests/binderAbiHelper.h b/libs/binder/tests/binderAbiHelper.h
new file mode 100644
index 0000000..369b55d
--- /dev/null
+++ b/libs/binder/tests/binderAbiHelper.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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 <stdlib.h>
+#include <iostream>
+
+#ifdef BINDER_IPC_32BIT
+static constexpr bool kBuild32Abi = true;
+#else
+static constexpr bool kBuild32Abi = false;
+#endif
+
+// TODO: remove when CONFIG_ANDROID_BINDER_IPC_32BIT is no longer supported
+static inline bool ReadKernelConfigIs32BitAbi() {
+ // failure case implies we run with standard ABI
+ return 0 == system("zcat /proc/config.gz | grep -E \"^CONFIG_ANDROID_BINDER_IPC_32BIT=y$\"");
+}
+
+static inline void ExitIfWrongAbi() {
+ bool runtime32Abi = ReadKernelConfigIs32BitAbi();
+
+ if (kBuild32Abi != runtime32Abi) {
+ std::cout << "[==========] Running 1 test from 1 test suite." << std::endl;
+ std::cout << "[----------] Global test environment set-up." << std::endl;
+ std::cout << "[----------] 1 tests from BinderLibTest" << std::endl;
+ std::cout << "[ RUN ] BinderTest.AbortForWrongAbi" << std::endl;
+ std::cout << "[ INFO ] test build abi 32: " << kBuild32Abi << " runtime abi 32: " << runtime32Abi << " so, skipping tests " << std::endl;
+ std::cout << "[ OK ] BinderTest.AbortForWrongAbi (0 ms) " << std::endl;
+ std::cout << "[----------] 1 tests from BinderTest (0 ms total)" << std::endl;
+ std::cout << "" << std::endl;
+ std::cout << "[----------] Global test environment tear-down" << std::endl;
+ std::cout << "[==========] 1 test from 1 test suite ran. (0 ms total)" << std::endl;
+ std::cout << "[ PASSED ] 1 tests." << std::endl;
+ exit(0);
+ }
+}
+
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index f3ed6a6..8cc3054 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -25,6 +25,8 @@
#include <sys/mman.h>
#include <poll.h>
+#include "binderAbiHelper.h"
+
#define BINDER_DEV_NAME "/dev/binder"
testing::Environment* binder_env;
@@ -361,6 +363,7 @@
}
int main(int argc, char **argv) {
+ ExitIfWrongAbi();
::testing::InitGoogleTest(&argc, argv);
binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv());
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index e343df7..40de2db 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -32,6 +32,8 @@
#include <sys/epoll.h>
#include <sys/prctl.h>
+#include "binderAbiHelper.h"
+
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
using namespace android;
@@ -1451,6 +1453,8 @@
}
int main(int argc, char **argv) {
+ ExitIfWrongAbi();
+
if (argc == 4 && !strcmp(argv[1], "--servername")) {
binderservername = argv[2];
} else {
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index c186110..88752ee 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -22,7 +22,7 @@
shared_libs: [
"libbinder",
- "libhidlbase", // libhwbinder is in here
+ "libhidlbase", // libhwbinder is in here
],
export_include_dirs: ["include"],
@@ -31,6 +31,7 @@
"-Wall",
"-Werror",
],
+ min_sdk_version: "29",
}
hidl_package_root {
@@ -39,6 +40,7 @@
aidl_interface {
name: "binderthreadstateutilstest.aidl",
+ unstable: true,
srcs: ["IAidlStuff.aidl"],
}
diff --git a/libs/gralloc/types/include/gralloctypes/Gralloc4.h b/libs/gralloc/types/include/gralloctypes/Gralloc4.h
index 5ec4d0d..8d12754 100644
--- a/libs/gralloc/types/include/gralloctypes/Gralloc4.h
+++ b/libs/gralloc/types/include/gralloctypes/Gralloc4.h
@@ -25,6 +25,7 @@
#include <aidl/android/hardware/graphics/common/Interlaced.h>
#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
+#include <aidl/android/hardware/graphics/common/Rect.h>
#include <aidl/android/hardware/graphics/common/Smpte2086.h>
#include <aidl/android/hardware/graphics/common/StandardMetadataType.h>
#include <aidl/android/hardware/graphics/common/XyColor.h>
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 7f57f5d..7976ecb 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -27,6 +27,7 @@
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
],
+ min_sdk_version: "29",
}
cc_library_shared {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index a8384ac..56591bd 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -19,8 +19,6 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <cutils/properties.h>
-
#include <gui/BLASTBufferQueue.h>
#include <gui/BufferItemConsumer.h>
#include <gui/GLConsumer.h>
@@ -95,7 +93,8 @@
if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
}
-BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
+BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height,
+ bool enableTripleBuffering)
: mSurfaceControl(surface),
mWidth(width),
mHeight(height),
@@ -105,8 +104,7 @@
// explicitly so that dequeueBuffer will block
mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
- int8_t disableTripleBuffer = property_get_bool("ro.sf.disable_triple_buffer", 0);
- if (!disableTripleBuffer) {
+ if (enableTripleBuffering) {
mProducer->setMaxDequeuedBufferCount(2);
}
mBufferItemConsumer =
@@ -189,13 +187,13 @@
mPendingReleaseItem.item = std::move(mSubmitted.front());
mSubmitted.pop();
- processNextBufferLocked();
+ processNextBufferLocked(false);
mCallbackCV.notify_all();
decStrong((void*)transactionCallbackThunk);
}
-void BLASTBufferQueue::processNextBufferLocked() {
+void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
ATRACE_CALL();
if (mNumFrameAvailable == 0 || mNumAcquired == MAX_ACQUIRED_BUFFERS + 1) {
return;
@@ -209,7 +207,7 @@
SurfaceComposerClient::Transaction localTransaction;
bool applyTransaction = true;
SurfaceComposerClient::Transaction* t = &localTransaction;
- if (mNextTransaction != nullptr && mUseNextTransaction) {
+ if (mNextTransaction != nullptr && useNextTransaction) {
t = mNextTransaction;
mNextTransaction = nullptr;
applyTransaction = false;
@@ -274,16 +272,14 @@
while (mNumFrameAvailable > 0 || mNumAcquired == MAX_ACQUIRED_BUFFERS + 1) {
mCallbackCV.wait(_lock);
}
- mUseNextTransaction = true;
}
// add to shadow queue
mNumFrameAvailable++;
- processNextBufferLocked();
+ processNextBufferLocked(true);
}
void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
std::lock_guard _lock{mMutex};
- mUseNextTransaction = false;
mNextTransaction = t;
}
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 4be014f..489f3c3 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -19,7 +19,6 @@
#include <inttypes.h>
#include <log/log.h>
#include <system/window.h>
-#include <ui/BufferHubBuffer.h>
namespace android {
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index a1803d8..8d80833 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -28,7 +28,6 @@
#include <inttypes.h>
-#include <cutils/properties.h>
#include <cutils/atomic.h>
#include <gui/BufferItem.h>
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 3f4c5da..a7cf39a 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -655,8 +655,9 @@
}
listener = mCore->mConsumerListener;
- if (listener != nullptr) {
- listener->onFrameDetached(mSlots[slot].mGraphicBuffer->getId());
+ auto gb = mSlots[slot].mGraphicBuffer;
+ if (listener != nullptr && gb != nullptr) {
+ listener->onFrameDetached(gb->getId());
}
mSlots[slot].mBufferState.detachProducer();
mCore->mActiveBuffers.erase(slot);
@@ -1120,8 +1121,9 @@
mCore->mFreeBuffers.push_back(slot);
}
- if (mCore->mConsumerListener != nullptr) {
- mCore->mConsumerListener->onFrameCancelled(mSlots[slot].mGraphicBuffer->getId());
+ auto gb = mSlots[slot].mGraphicBuffer;
+ if (mCore->mConsumerListener != nullptr && gb != nullptr) {
+ mCore->mConsumerListener->onFrameCancelled(gb->getId());
}
mSlots[slot].mFence = fence;
mCore->mDequeueCondition.notify_all();
diff --git a/libs/gui/DebugEGLImageTracker.cpp b/libs/gui/DebugEGLImageTracker.cpp
index ab6f364..5762dab 100644
--- a/libs/gui/DebugEGLImageTracker.cpp
+++ b/libs/gui/DebugEGLImageTracker.cpp
@@ -14,13 +14,14 @@
* limitations under the License.
*/
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
-#include <cutils/properties.h>
#include <gui/DebugEGLImageTracker.h>
#include <cinttypes>
#include <unordered_map>
+using android::base::GetBoolProperty;
using android::base::StringAppendF;
std::mutex DebugEGLImageTracker::mInstanceLock;
@@ -57,10 +58,7 @@
DebugEGLImageTracker *DebugEGLImageTracker::getInstance() {
std::lock_guard lock(mInstanceLock);
if (mInstance == nullptr) {
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.enable_egl_image_tracker", value, "0");
- const bool enabled = static_cast<bool>(atoi(value));
-
+ const bool enabled = GetBoolProperty("debug.sf.enable_egl_image_tracker", false);
if (enabled) {
mInstance = new DebugEGLImageTrackerImpl();
} else {
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 15f966d..b33bc9e 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -36,10 +36,7 @@
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::ConfigChanged configChanged)
- : mLooper(looper),
- mReceiver(vsyncSource, configChanged),
- mWaitingForVsync(false),
- mConfigChangeFlag(configChanged) {
+ : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
@@ -92,16 +89,12 @@
return OK;
}
-void DisplayEventDispatcher::toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) {
- if (mConfigChangeFlag == configChangeFlag) {
- return;
- }
- status_t status = mReceiver.toggleConfigEvents(configChangeFlag);
+void DisplayEventDispatcher::requestLatestConfig() {
+ status_t status = mReceiver.requestLatestConfig();
if (status) {
ALOGW("Failed enable config events, status=%d", status);
return;
}
- mConfigChangeFlag = configChangeFlag;
}
int DisplayEventDispatcher::getFd() const {
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index fd6aaf8..1fed509 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -79,10 +79,9 @@
return NO_INIT;
}
-status_t DisplayEventReceiver::toggleConfigEvents(
- ISurfaceComposer::ConfigChanged configChangeFlag) {
+status_t DisplayEventReceiver::requestLatestConfig() {
if (mEventConnection != nullptr) {
- mEventConnection->toggleConfigEvents(configChangeFlag);
+ mEventConnection->requestLatestConfig();
return NO_ERROR;
}
return NO_INIT;
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index dda5acf..aa74bfd 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -26,8 +26,8 @@
STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
SET_VSYNC_RATE,
REQUEST_NEXT_VSYNC,
- TOGGLE_CONFIG_EVENTS,
- LAST = TOGGLE_CONFIG_EVENTS,
+ REQUEST_LATEST_CONFIG,
+ LAST = REQUEST_LATEST_CONFIG,
};
} // Anonymous namespace
@@ -55,10 +55,9 @@
Tag::REQUEST_NEXT_VSYNC);
}
- void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) override {
- callRemoteAsync<decltype(
- &IDisplayEventConnection::toggleConfigEvents)>(Tag::TOGGLE_CONFIG_EVENTS,
- configChangeFlag);
+ void requestLatestConfig() override {
+ callRemoteAsync<decltype(&IDisplayEventConnection::requestLatestConfig)>(
+ Tag::REQUEST_LATEST_CONFIG);
}
};
@@ -81,8 +80,8 @@
return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate);
case Tag::REQUEST_NEXT_VSYNC:
return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync);
- case Tag::TOGGLE_CONFIG_EVENTS:
- return callLocalAsync(data, reply, &IDisplayEventConnection::toggleConfigEvents);
+ case Tag::REQUEST_LATEST_CONFIG:
+ return callLocalAsync(data, reply, &IDisplayEventConnection::requestLatestConfig);
}
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index bd4d62c..2a27a9a 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -795,8 +795,7 @@
}
virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask,
- uint64_t maxFrames) const {
+ uint8_t componentMask, uint64_t maxFrames) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -932,8 +931,11 @@
}
virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, float minRefreshRate,
- float maxRefreshRate) {
+ int32_t defaultConfig,
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -950,14 +952,26 @@
ALOGE("setDesiredDisplayConfigSpecs failed to write defaultConfig: %d", result);
return result;
}
- result = data.writeFloat(minRefreshRate);
+ result = data.writeFloat(primaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write minRefreshRate: %d", result);
+ ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMin: %d", result);
return result;
}
- result = data.writeFloat(maxRefreshRate);
+ result = data.writeFloat(primaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write maxRefreshRate: %d", result);
+ ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMax: %d", result);
+ return result;
+ }
+ result = data.writeFloat(appRequestRefreshRateMin);
+ if (result != NO_ERROR) {
+ ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMin: %d",
+ result);
+ return result;
+ }
+ result = data.writeFloat(appRequestRefreshRateMax);
+ if (result != NO_ERROR) {
+ ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMax: %d",
+ result);
return result;
}
@@ -972,9 +986,14 @@
virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t* outDefaultConfig,
- float* outMinRefreshRate,
- float* outMaxRefreshRate) {
- if (!outDefaultConfig || !outMinRefreshRate || !outMaxRefreshRate) return BAD_VALUE;
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) {
+ if (!outDefaultConfig || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax ||
+ !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) {
+ return BAD_VALUE;
+ }
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -997,14 +1016,26 @@
ALOGE("getDesiredDisplayConfigSpecs failed to read defaultConfig: %d", result);
return result;
}
- result = reply.readFloat(outMinRefreshRate);
+ result = reply.readFloat(outPrimaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read minRefreshRate: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMin: %d", result);
return result;
}
- result = reply.readFloat(outMaxRefreshRate);
+ result = reply.readFloat(outPrimaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read maxRefreshRate: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMax: %d", result);
+ return result;
+ }
+ result = reply.readFloat(outAppRequestRefreshRateMin);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMin: %d",
+ result);
+ return result;
+ }
+ result = reply.readFloat(outAppRequestRefreshRateMax);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMax: %d",
+ result);
return result;
}
return reply.readInt32();
@@ -1038,7 +1069,7 @@
return NO_ERROR;
}
- virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) const {
+ virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1836,20 +1867,38 @@
ALOGE("setDesiredDisplayConfigSpecs: failed to read defaultConfig: %d", result);
return result;
}
- float minRefreshRate;
- result = data.readFloat(&minRefreshRate);
+ float primaryRefreshRateMin;
+ result = data.readFloat(&primaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read minRefreshRate: %d", result);
+ ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMin: %d",
+ result);
return result;
}
- float maxRefreshRate;
- result = data.readFloat(&maxRefreshRate);
+ float primaryRefreshRateMax;
+ result = data.readFloat(&primaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read maxRefreshRate: %d", result);
+ ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMax: %d",
+ result);
return result;
}
- result = setDesiredDisplayConfigSpecs(displayToken, defaultConfig, minRefreshRate,
- maxRefreshRate);
+ float appRequestRefreshRateMin;
+ result = data.readFloat(&appRequestRefreshRateMin);
+ if (result != NO_ERROR) {
+ ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMin: %d",
+ result);
+ return result;
+ }
+ float appRequestRefreshRateMax;
+ result = data.readFloat(&appRequestRefreshRateMax);
+ if (result != NO_ERROR) {
+ ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMax: %d",
+ result);
+ return result;
+ }
+ result =
+ setDesiredDisplayConfigSpecs(displayToken, defaultConfig, primaryRefreshRateMin,
+ primaryRefreshRateMax, appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
if (result != NO_ERROR) {
ALOGE("setDesiredDisplayConfigSpecs: failed to call setDesiredDisplayConfigSpecs: "
"%d",
@@ -1863,11 +1912,16 @@
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> displayToken = data.readStrongBinder();
int32_t defaultConfig;
- float minRefreshRate;
- float maxRefreshRate;
+ float primaryRefreshRateMin;
+ float primaryRefreshRateMax;
+ float appRequestRefreshRateMin;
+ float appRequestRefreshRateMax;
- status_t result = getDesiredDisplayConfigSpecs(displayToken, &defaultConfig,
- &minRefreshRate, &maxRefreshRate);
+ status_t result =
+ getDesiredDisplayConfigSpecs(displayToken, &defaultConfig,
+ &primaryRefreshRateMin, &primaryRefreshRateMax,
+ &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax);
if (result != NO_ERROR) {
ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: "
"%d",
@@ -1880,14 +1934,28 @@
ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultConfig: %d", result);
return result;
}
- result = reply->writeFloat(minRefreshRate);
+ result = reply->writeFloat(primaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write minRefreshRate: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMin: %d",
+ result);
return result;
}
- result = reply->writeFloat(maxRefreshRate);
+ result = reply->writeFloat(primaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write maxRefreshRate: %d", result);
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMax: %d",
+ result);
+ return result;
+ }
+ result = reply->writeFloat(appRequestRefreshRateMin);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMin: %d",
+ result);
+ return result;
+ }
+ result = reply->writeFloat(appRequestRefreshRateMax);
+ if (result != NO_ERROR) {
+ ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMax: %d",
+ result);
return result;
}
reply->writeInt32(result);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index f7158d0..e43446a 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -116,6 +116,7 @@
output.writeInt32(frameRateSelectionPriority);
output.writeFloat(frameRate);
output.writeByte(frameRateCompatibility);
+ output.writeUint32(fixedTransformHint);
return NO_ERROR;
}
@@ -198,6 +199,7 @@
frameRateSelectionPriority = input.readInt32();
frameRate = input.readFloat();
frameRateCompatibility = input.readByte();
+ fixedTransformHint = static_cast<ui::Transform::RotationFlags>(input.readUint32());
return NO_ERROR;
}
@@ -433,6 +435,10 @@
frameRate = other.frameRate;
frameRateCompatibility = other.frameRateCompatibility;
}
+ if (other.what & eFixedTransformHintChanged) {
+ what |= eFixedTransformHintChanged;
+ fixedTransformHint = other.fixedTransformHint;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index f911e70..2bf8ff7 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -57,7 +57,8 @@
return op == NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR ||
op == NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR ||
op == NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR ||
- op == NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR;
+ op == NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR ||
+ op == NATIVE_WINDOW_SET_QUERY_INTERCEPTOR;
}
} // namespace
@@ -501,6 +502,19 @@
int Surface::hook_query(const ANativeWindow* window, int what, int* value) {
const Surface* c = getSelf(window);
+ {
+ std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex);
+ if (c->mQueryInterceptor != nullptr) {
+ auto interceptor = c->mQueryInterceptor;
+ auto data = c->mQueryInterceptorData;
+ return interceptor(window, Surface::queryInternal, data, what, value);
+ }
+ }
+ return c->query(what, value);
+}
+
+int Surface::queryInternal(const ANativeWindow* window, int what, int* value) {
+ const Surface* c = getSelf(window);
return c->query(what, value);
}
@@ -1177,6 +1191,9 @@
case NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR:
res = dispatchAddQueueInterceptor(args);
break;
+ case NATIVE_WINDOW_SET_QUERY_INTERCEPTOR:
+ res = dispatchAddQueryInterceptor(args);
+ break;
case NATIVE_WINDOW_ALLOCATE_BUFFERS:
allocateBuffers();
res = NO_ERROR;
@@ -1457,6 +1474,15 @@
return NO_ERROR;
}
+int Surface::dispatchAddQueryInterceptor(va_list args) {
+ ANativeWindow_queryInterceptor interceptor = va_arg(args, ANativeWindow_queryInterceptor);
+ void* data = va_arg(args, void*);
+ std::lock_guard<std::shared_mutex> lock(mInterceptorMutex);
+ mQueryInterceptor = interceptor;
+ mQueryInterceptorData = data;
+ return NO_ERROR;
+}
+
int Surface::dispatchGetLastQueuedBuffer(va_list args) {
AHardwareBuffer** buffer = va_arg(args, AHardwareBuffer**);
int* fence = va_arg(args, int*);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 605c2e8..5922f3a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -241,8 +241,31 @@
// ---------------------------------------------------------------------------
-void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId);
+void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId);
+/**
+ * We use the BufferCache to reduce the overhead of exchanging GraphicBuffers with
+ * the server. If we were to simply parcel the GraphicBuffer we would pay two overheads
+ * 1. Cost of sending the FD
+ * 2. Cost of importing the GraphicBuffer with the mapper in the receiving process.
+ * To ease this cost we implement the following scheme of caching buffers to integers,
+ * or said-otherwise, naming them with integers. This is the scheme known as slots in
+ * the legacy BufferQueue system.
+ * 1. When sending Buffers to SurfaceFlinger we look up the Buffer in the cache.
+ * 2. If there is a cache-hit we remove the Buffer from the Transaction and instead
+ * send the cached integer.
+ * 3. If there is a cache miss, we cache the new buffer and send the integer
+ * along with the Buffer, SurfaceFlinger on it's side creates a new cache
+ * entry, and we use the integer for further communication.
+ * A few details about lifetime:
+ * 1. The cache evicts by LRU. The server side cache is keyed by BufferCache::getToken
+ * which is per process Unique. The server side cache is larger than the client side
+ * cache so that the server will never evict entries before the client.
+ * 2. When the client evicts an entry it notifies the server via an uncacheBuffer
+ * transaction.
+ * 3. The client only references the Buffers by ID, and uses buffer->addDeathCallback
+ * to auto-evict destroyed buffers.
+ */
class BufferCache : public Singleton<BufferCache> {
public:
BufferCache() : token(new BBinder()) {}
@@ -270,7 +293,7 @@
evictLeastRecentlyUsedBuffer();
}
- buffer->addDeathCallback(bufferCacheCallback, nullptr);
+ buffer->addDeathCallback(removeDeadBufferCallback, nullptr);
mBuffers[buffer->getId()] = getCounter();
return buffer->getId();
@@ -318,7 +341,7 @@
ANDROID_SINGLETON_STATIC_INSTANCE(BufferCache);
-void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId) {
+void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId) {
// GraphicBuffer id's are used as the cache ids.
BufferCache::getInstance().uncache(graphicBufferId);
}
@@ -576,9 +599,11 @@
uint64_t cacheId = 0;
status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId);
if (ret == NO_ERROR) {
+ // Cache-hit. Strip the buffer and send only the id.
s->what &= ~static_cast<uint64_t>(layer_state_t::eBufferChanged);
s->buffer = nullptr;
} else {
+ // Cache-miss. Include the buffer and send the new cacheId.
cacheId = BufferCache::getInstance().cache(s->buffer);
}
s->what |= layer_state_t::eCachedBufferChanged;
@@ -1412,6 +1437,22 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixedTransformHint(
+ const sp<SurfaceControl>& sc, int32_t fixedTransformHint) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ const ui::Transform::RotationFlags transform = fixedTransformHint == -1
+ ? ui::Transform::ROT_INVALID
+ : ui::Transform::toRotationFlags(static_cast<ui::Rotation>(fixedTransformHint));
+ s->what |= layer_state_t::eFixedTransformHintChanged;
+ s->fixedTransformHint = transform;
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
@@ -1673,22 +1714,26 @@
status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t defaultConfig,
- float minRefreshRate,
- float maxRefreshRate) {
- return ComposerService::getComposerService()->setDesiredDisplayConfigSpecs(displayToken,
- defaultConfig,
- minRefreshRate,
- maxRefreshRate);
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) {
+ return ComposerService::getComposerService()
+ ->setDesiredDisplayConfigSpecs(displayToken, defaultConfig, primaryRefreshRateMin,
+ primaryRefreshRateMax, appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
}
status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t* outDefaultConfig,
- float* outMinRefreshRate,
- float* outMaxRefreshRate) {
- return ComposerService::getComposerService()->getDesiredDisplayConfigSpecs(displayToken,
- outDefaultConfig,
- outMinRefreshRate,
- outMaxRefreshRate);
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) {
+ return ComposerService::getComposerService()
+ ->getDesiredDisplayConfigSpecs(displayToken, outDefaultConfig, outPrimaryRefreshRateMin,
+ outPrimaryRefreshRateMax, outAppRequestRefreshRateMin,
+ outAppRequestRefreshRateMax);
}
status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 64c21e0..2320771 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -66,7 +66,9 @@
: public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener
{
public:
- BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height);
+ BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height,
+ bool enableTripleBuffering = true);
+
sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
return mProducer;
}
@@ -90,7 +92,7 @@
BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
BLASTBufferQueue(const BLASTBufferQueue& rhs);
- void processNextBufferLocked() REQUIRES(mMutex);
+ void processNextBufferLocked(bool useNextTransaction) REQUIRES(mMutex);
Rect computeCrop(const BufferItem& item);
sp<SurfaceControl> mSurfaceControl;
@@ -123,8 +125,6 @@
sp<BLASTBufferItemConsumer> mBufferItemConsumer;
SurfaceComposerClient::Transaction* mNextTransaction GUARDED_BY(mMutex);
-
- bool mUseNextTransaction = false;
};
} // namespace android
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index fcdf6bf..f210c34 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -31,7 +31,7 @@
status_t initialize();
void dispose();
status_t scheduleVsync();
- void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag);
+ void requestLatestConfig();
int getFd() const;
virtual int handleEvent(int receiveFd, int events, void* data);
@@ -42,7 +42,6 @@
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
bool mWaitingForVsync;
- ISurfaceComposer::ConfigChanged mConfigChangeFlag;
virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0;
virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 109e28b..8d49184 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -65,6 +65,7 @@
struct VSync {
uint32_t count;
+ nsecs_t expectedVSyncTimestamp;
};
struct Hotplug {
@@ -146,9 +147,10 @@
status_t requestNextVsync();
/*
- * toggleConfigEvents() toggles delivery of config change events.
+ * requestLatestConfig() force-requests the current config for the primary
+ * display.
*/
- status_t toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag);
+ status_t requestLatestConfig();
private:
sp<IDisplayEventConnection> mEventConnection;
diff --git a/libs/gui/include/gui/IDisplayEventConnection.h b/libs/gui/include/gui/IDisplayEventConnection.h
index 8b35ef6..674aafd 100644
--- a/libs/gui/include/gui/IDisplayEventConnection.h
+++ b/libs/gui/include/gui/IDisplayEventConnection.h
@@ -53,11 +53,9 @@
virtual void requestNextVsync() = 0; // Asynchronous
/*
- * togglesConfigEvents() configures whether or not display config changes
- * should be propagated.
+ * requestLatestConfig() requests the config for the primary display.
*/
- virtual void toggleConfigEvents(
- ISurfaceComposer::ConfigChanged configChangeFlag) = 0; // Asynchronous
+ virtual void requestLatestConfig() = 0; // Asynchronous
};
class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3cef256..0d33b3f 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -383,7 +383,7 @@
*/
virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
uint8_t componentMask,
- uint64_t maxFrames) const = 0;
+ uint64_t maxFrames) = 0;
/* Returns statistics on the color profile of the last frame displayed for a given display
*
@@ -426,19 +426,36 @@
*/
virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) = 0;
- /*
- * Sets the refresh rate boundaries for display configuration.
- * For all other parameters, default configuration is used. The index for the default is
- * corresponding to the configs returned from getDisplayConfigs().
+ /* Sets the refresh rate boundaries for the display.
+ *
+ * The primary refresh rate range represents display manager's general guidance on the display
+ * configs we'll consider when switching refresh rates. Unless we get an explicit signal from an
+ * app, we should stay within this range.
+ *
+ * The app request refresh rate range allows us to consider more display configs when switching
+ * refresh rates. Although we should generally stay within the primary range, specific
+ * considerations, such as layer frame rate settings specified via the setFrameRate() api, may
+ * cause us to go outside the primary range. We never go outside the app request range. The app
+ * request range will be greater than or equal to the primary refresh rate range, never smaller.
+ *
+ * defaultConfig is used to narrow the list of display configs SurfaceFlinger will consider
+ * switching between. Only configs with a config group and resolution matching defaultConfig
+ * will be considered for switching. The defaultConfig index corresponds to the list of configs
+ * returned from getDisplayConfigs().
*/
virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, float minRefreshRate,
- float maxRefreshRate) = 0;
+ int32_t defaultConfig,
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) = 0;
virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t* outDefaultConfig,
- float* outMinRefreshRate,
- float* outMaxRefreshRate) = 0;
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) = 0;
/*
* Gets whether brightness operations are supported on a display.
*
@@ -468,8 +485,7 @@
* BAD_VALUE if the brightness is invalid, or
* INVALID_OPERATION if brightness operations are not supported.
*/
- virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken,
- float brightness) const = 0;
+ virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) = 0;
/*
* Sends a power hint to the composer. This function is asynchronous.
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 2b2f773..e60f677 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -35,6 +35,7 @@
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Rotation.h>
+#include <ui/Transform.h>
#include <utils/Errors.h>
namespace android {
@@ -103,6 +104,7 @@
eFrameRateChanged = 0x40'00000000,
eBackgroundBlurRadiusChanged = 0x80'00000000,
eProducerDisconnect = 0x100'00000000,
+ eFixedTransformHintChanged = 0x200'00000000,
};
layer_state_t()
@@ -136,7 +138,8 @@
shadowRadius(0.0f),
frameRateSelectionPriority(-1),
frameRate(0.0f),
- frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT) {
+ frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
+ fixedTransformHint(ui::Transform::ROT_INVALID) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -225,6 +228,15 @@
// Layer frame rate and compatibility. See ANativeWindow_setFrameRate().
float frameRate;
int8_t frameRateCompatibility;
+
+ // Set by window manager indicating the layer and all its children are
+ // in a different orientation than the display. The hint suggests that
+ // the graphic producers should receive a transform hint as if the
+ // display was in this orientation. When the display changes to match
+ // the layer orientation, the graphic producer may not need to allocate
+ // a buffer of a different size. -1 means the transform hint is not set,
+ // otherwise the value will be a valid ui::Rotation.
+ ui::Transform::RotationFlags fixedTransformHint;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 917c0d4..49c83da 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -209,6 +209,7 @@
int* fenceFd);
static int performInternal(ANativeWindow* window, int operation, va_list args);
static int queueBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd);
+ static int queryInternal(const ANativeWindow* window, int what, int* value);
static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer* buffer);
@@ -261,6 +262,7 @@
int dispatchAddDequeueInterceptor(va_list args);
int dispatchAddPerformInterceptor(va_list args);
int dispatchAddQueueInterceptor(va_list args);
+ int dispatchAddQueryInterceptor(va_list args);
int dispatchGetLastQueuedBuffer(va_list args);
bool transformToDisplayInverse();
@@ -468,7 +470,7 @@
mutable Mutex mMutex;
// mInterceptorMutex is the mutex guarding interceptors.
- std::shared_mutex mInterceptorMutex;
+ mutable std::shared_mutex mInterceptorMutex;
ANativeWindow_cancelBufferInterceptor mCancelInterceptor = nullptr;
void* mCancelInterceptorData = nullptr;
@@ -478,6 +480,8 @@
void* mPerformInterceptorData = nullptr;
ANativeWindow_queueBufferInterceptor mQueueInterceptor = nullptr;
void* mQueueInterceptorData = nullptr;
+ ANativeWindow_queryInterceptor mQueryInterceptor = nullptr;
+ void* mQueryInterceptorData = nullptr;
// must be used from the lock/unlock thread
sp<GraphicBuffer> mLockedBuffer;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 2fb9538..e981a39 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -118,21 +118,19 @@
// Shorthand for getDisplayConfigs element at getActiveConfig index.
static status_t getActiveDisplayConfig(const sp<IBinder>& display, DisplayConfig*);
- // Sets the refresh rate boundaries for display configuration.
- // For all other parameters, default configuration is used. The index for the default is
- // corresponting to the configs returned from getDisplayConfigs().
+ // Sets the refresh rate boundaries for the display.
static status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, float minRefreshRate,
- float maxRefreshRate);
- // Gets the refresh rate boundaries for display configuration.
- // For all other parameters, default configuration is used. The index for the default is
- // corresponting to the configs returned from getDisplayConfigs().
- // The reason is passed in for telemetry tracking, and it corresponds to the list of all
- // the policy rules that were used.
+ int32_t defaultConfig, float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax);
+ // Gets the refresh rate boundaries for the display.
static status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t* outDefaultConfig,
- float* outMinRefreshRate,
- float* outMaxRefreshRate);
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax);
// Gets the list of supported color modes for the given display
static status_t getDisplayColorModes(const sp<IBinder>& display,
@@ -521,6 +519,14 @@
Transaction& setFrameRate(const sp<SurfaceControl>& sc, float frameRate,
int8_t compatibility);
+ // Set by window manager indicating the layer and all its children are
+ // in a different orientation than the display. The hint suggests that
+ // the graphic producers should receive a transform hint as if the
+ // display was in this orientation. When the display changes to match
+ // the layer orientation, the graphic producer may not need to allocate
+ // a buffer of a different size.
+ Transaction& setFixedTransformHint(const sp<SurfaceControl>& sc, int32_t transformHint);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
index e7f7c1f..64b1eac 100644
--- a/libs/gui/sysprop/Android.bp
+++ b/libs/gui/sysprop/Android.bp
@@ -4,4 +4,7 @@
api_packages: ["android.sysprop"],
property_owner: "Platform",
vendor_available: true,
+ cpp: {
+ min_sdk_version: "29",
+ },
}
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 7f960ab..a6bcd10 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -39,6 +39,7 @@
shared_libs: [
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
+ "libSurfaceFlingerProp",
"libbase",
"liblog",
"libEGL",
@@ -53,6 +54,8 @@
"libutils",
"libnativewindow"
],
+
+ header_libs: ["libsurfaceflinger_headers"],
}
// Build a separate binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index a87ccd6..d929a59 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -722,5 +722,8 @@
ASSERT_EQ(2, events->frameNumber);
ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
ASSERT_GE(events->postedTime, postedTimeB);
+
+ // wait for any callbacks that have not been received
+ adapter.waitForCallbacks();
}
} // namespace android
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index c59afba..5188a09 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -178,7 +178,7 @@
mInputInfo.name = "Test info";
mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
- mInputInfo.dispatchingTimeout = 100000;
+ mInputInfo.dispatchingTimeout = seconds_to_nanoseconds(5);
mInputInfo.globalScaleFactor = 1.0;
mInputInfo.canReceiveKeys = true;
mInputInfo.hasFocus = true;
@@ -196,7 +196,7 @@
InputApplicationInfo aInfo;
aInfo.token = new BBinder();
aInfo.name = "Test app info";
- aInfo.dispatchingTimeout = 100000;
+ aInfo.dispatchingTimeout = seconds_to_nanoseconds(5);
mInputInfo.applicationInfo = aInfo;
}
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index dbd4ef9..6746b0a 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -240,6 +240,19 @@
float const luma_gray = 0.50;
};
+TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) {
+ sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<Listener> listener = new Listener();
+ const Rect sampleArea{100, 100, 200, 200};
+ // Passing in composer service as the layer handle should not crash, we'll
+ // treat it as a layer that no longer exists and silently allow sampling to
+ // occur.
+ status_t status = composer->addRegionSamplingListener(sampleArea,
+ IInterface::asBinder(composer), listener);
+ ASSERT_EQ(NO_ERROR, status);
+ composer->removeRegionSamplingListener(listener);
+}
+
TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) {
fill_render(rgba_green);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ef1fd02..a1d12a5 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -18,17 +18,17 @@
#include <gtest/gtest.h>
+#include <SurfaceFlingerProperties.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <binder/ProcessState.h>
#include <configstore/Utils.h>
-#include <cutils/properties.h>
-#include <inttypes.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
+#include <inttypes.h>
#include <private/gui/ComposerService.h>
#include <ui/Rect.h>
#include <utils/String8.h>
@@ -46,11 +46,9 @@
using Transaction = SurfaceComposerClient::Transaction;
-static bool hasWideColorDisplay =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+static bool hasWideColorDisplay = android::sysprop::has_wide_color_display(false);
-static bool hasHdrDisplay =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+static bool hasHdrDisplay = android::sysprop::has_HDR_display(false);
class FakeSurfaceComposer;
class FakeProducerFrameEventHistory;
@@ -804,7 +802,7 @@
}
status_t setDisplayContentSamplingEnabled(const sp<IBinder>& /*display*/, bool /*enable*/,
uint8_t /*componentMask*/,
- uint64_t /*maxFrames*/) const override {
+ uint64_t /*maxFrames*/) override {
return NO_ERROR;
}
status_t getDisplayedContentSample(const sp<IBinder>& /*display*/, uint64_t /*maxFrames*/,
@@ -822,7 +820,7 @@
return NO_ERROR;
}
status_t setDisplayBrightness(const sp<IBinder>& /*displayToken*/,
- float /*brightness*/) const override {
+ float /*brightness*/) override {
return NO_ERROR;
}
@@ -836,14 +834,19 @@
return NO_ERROR;
}
status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/,
- int32_t /*defaultConfig*/, float /*minRefreshRate*/,
- float /*maxRefreshRate*/) {
+ int32_t /*defaultConfig*/,
+ float /*primaryRefreshRateMin*/,
+ float /*primaryRefreshRateMax*/,
+ float /*appRequestRefreshRateMin*/,
+ float /*appRequestRefreshRateMax*/) {
return NO_ERROR;
}
status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/,
int32_t* /*outDefaultConfig*/,
- float* /*outMinRefreshRate*/,
- float* /*outMaxRefreshRate*/) override {
+ float* /*outPrimaryRefreshRateMin*/,
+ float* /*outPrimaryRefreshRateMax*/,
+ float* /*outAppRequestRefreshRateMin*/,
+ float* /*outAppRequestRefreshRateMax*/) override {
return NO_ERROR;
};
status_t notifyPowerHint(int32_t /*hintId*/) override { return NO_ERROR; }
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index ef7cc7d..11af23e 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -468,7 +468,7 @@
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.displayId = displayId;
- msg.body.key.hmac = hmac;
+ msg.body.key.hmac = std::move(hmac);
msg.body.key.action = action;
msg.body.key.flags = flags;
msg.body.key.keyCode = keyCode;
@@ -526,7 +526,7 @@
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.displayId = displayId;
- msg.body.motion.hmac = hmac;
+ msg.body.motion.hmac = std::move(hmac);
msg.body.motion.action = action;
msg.body.motion.actionButton = actionButton;
msg.body.motion.flags = flags;
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 03ca459..85a2015 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -42,17 +42,18 @@
&& y >= frameTop && y < frameBottom;
}
+// TODO(b/155781676): Remove and replace call points with trustedOverlay when that is ready.
bool InputWindowInfo::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
- || layoutParamsType == TYPE_STATUS_BAR
- || layoutParamsType == TYPE_NAVIGATION_BAR
- || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
- || layoutParamsType == TYPE_DOCK_DIVIDER
- || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
- || layoutParamsType == TYPE_INPUT_CONSUMER;
+ return layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG ||
+ layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_STATUS_BAR ||
+ layoutParamsType == TYPE_NOTIFICATION_SHADE ||
+ layoutParamsType == TYPE_NAVIGATION_BAR ||
+ layoutParamsType == TYPE_NAVIGATION_BAR_PANEL ||
+ layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY ||
+ layoutParamsType == TYPE_DOCK_DIVIDER ||
+ layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY ||
+ layoutParamsType == TYPE_INPUT_CONSUMER ||
+ layoutParamsType == TYPE_TRUSTED_APPLICATION_OVERLAY;
}
bool InputWindowInfo::supportsSplitTouch() const {
@@ -65,7 +66,7 @@
}
status_t InputWindowInfo::write(Parcel& output) const {
- if (token == nullptr) {
+ if (name.empty()) {
output.writeInt32(0);
return OK;
}
@@ -110,12 +111,7 @@
return ret;
}
- sp<IBinder> token = from.readStrongBinder();
- if (token == nullptr) {
- return ret;
- }
-
- ret.token = token;
+ ret.token = from.readStrongBinder();
ret.id = from.readInt32();
ret.name = from.readString8().c_str();
ret.layoutParamsFlags = from.readInt32();
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
index 7375a2b..9e7e4a2 100644
--- a/libs/nativebase/Android.bp
+++ b/libs/nativebase/Android.bp
@@ -25,5 +25,6 @@
windows: {
enabled: true,
},
- }
+ },
+ min_sdk_version: "29",
}
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 0ff33ac..e458b2e 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -17,24 +17,63 @@
#define LOG_TAG "Choreographer"
//#define LOG_NDEBUG 0
-#include <apex/choreographer.h>
+#include <android-base/thread_annotations.h>
#include <gui/DisplayEventDispatcher.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
+#include <private/android/choreographer.h>
#include <utils/Looper.h>
-#include <utils/Mutex.h>
#include <utils/Timers.h>
#include <cinttypes>
+#include <mutex>
#include <optional>
#include <queue>
#include <thread>
-namespace android {
+namespace {
+struct {
+ // Global JVM that is provided by zygote
+ JavaVM* jvm = nullptr;
+ struct {
+ jclass clazz;
+ jmethodID getInstance;
+ jmethodID registerNativeChoreographerForRefreshRateCallbacks;
+ jmethodID unregisterNativeChoreographerForRefreshRateCallbacks;
+ } displayManagerGlobal;
+} gJni;
-static inline const char* toString(bool value) {
+// Gets the JNIEnv* for this thread, and performs one-off initialization if we
+// have never retrieved a JNIEnv* pointer before.
+JNIEnv* getJniEnv() {
+ if (gJni.jvm == nullptr) {
+ ALOGW("AChoreographer: No JVM provided!");
+ return nullptr;
+ }
+
+ JNIEnv* env = nullptr;
+ if (gJni.jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGD("Attaching thread to JVM for AChoreographer");
+ JavaVMAttachArgs args = {JNI_VERSION_1_4, "AChoreographer_env", NULL};
+ jint attachResult = gJni.jvm->AttachCurrentThreadAsDaemon(&env, (void*)&args);
+ if (attachResult != JNI_OK) {
+ ALOGE("Unable to attach thread. Error: %d", attachResult);
+ return nullptr;
+ }
+ }
+ if (env == nullptr) {
+ ALOGW("AChoreographer: No JNI env available!");
+ }
+ return env;
+}
+
+inline const char* toString(bool value) {
return value ? "true" : "false";
}
+} // namespace
+
+namespace android {
struct FrameCallback {
AChoreographer_frameCallback callback;
@@ -52,24 +91,43 @@
struct RefreshRateCallback {
AChoreographer_refreshRateCallback callback;
void* data;
+ bool firstCallbackFired = false;
};
+class Choreographer;
+
+struct {
+ std::mutex lock;
+ std::vector<Choreographer*> ptrs GUARDED_BY(lock);
+ bool registeredToDisplayManager GUARDED_BY(lock) = false;
+
+ std::atomic<nsecs_t> mLastKnownVsync = -1;
+} gChoreographers;
+
class Choreographer : public DisplayEventDispatcher, public MessageHandler {
public:
- explicit Choreographer(const sp<Looper>& looper);
+ explicit Choreographer(const sp<Looper>& looper) EXCLUDES(gChoreographers.lock);
void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay);
- void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
+ void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data)
+ EXCLUDES(gChoreographers.lock);
void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
+ // Drains the queue of pending vsync periods and dispatches refresh rate
+ // updates to callbacks.
+ // The assumption is that this method is only called on a single
+ // processing thread, either by looper or by AChoreographer_handleEvents
+ void handleRefreshRateUpdates();
+ void scheduleLatestConfigRequest();
enum {
MSG_SCHEDULE_CALLBACKS = 0,
- MSG_SCHEDULE_VSYNC = 1
+ MSG_SCHEDULE_VSYNC = 1,
+ MSG_HANDLE_REFRESH_RATE_UPDATES = 2,
};
virtual void handleMessage(const Message& message) override;
static Choreographer* getForThread();
- virtual ~Choreographer() = default;
+ virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
private:
Choreographer(const Choreographer&) = delete;
@@ -81,21 +139,17 @@
void scheduleCallbacks();
+ std::mutex mLock;
// Protected by mLock
std::priority_queue<FrameCallback> mFrameCallbacks;
-
- // Protected by mLock
std::vector<RefreshRateCallback> mRefreshRateCallbacks;
- nsecs_t mVsyncPeriod = 0;
- mutable Mutex mLock;
+ nsecs_t mLatestVsyncPeriod = -1;
const sp<Looper> mLooper;
const std::thread::id mThreadId;
- const std::optional<PhysicalDisplayId> mInternalDisplayId;
};
-
static thread_local Choreographer* gChoreographer;
Choreographer* Choreographer::getForThread() {
if (gChoreographer == nullptr) {
@@ -115,17 +169,47 @@
}
Choreographer::Choreographer(const sp<Looper>& looper)
- : DisplayEventDispatcher(looper),
+ : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp,
+ ISurfaceComposer::ConfigChanged::eConfigChangedDispatch),
mLooper(looper),
- mThreadId(std::this_thread::get_id()),
- mInternalDisplayId(SurfaceComposerClient::getInternalDisplayId()) {}
+ mThreadId(std::this_thread::get_id()) {
+ std::lock_guard<std::mutex> _l(gChoreographers.lock);
+ gChoreographers.ptrs.push_back(this);
+}
+
+Choreographer::~Choreographer() {
+ std::lock_guard<std::mutex> _l(gChoreographers.lock);
+ gChoreographers.ptrs.erase(std::remove_if(gChoreographers.ptrs.begin(),
+ gChoreographers.ptrs.end(),
+ [=](Choreographer* c) { return c == this; }),
+ gChoreographers.ptrs.end());
+ // Only poke DisplayManagerGlobal to unregister if we previously registered
+ // callbacks.
+ if (gChoreographers.ptrs.empty() && gChoreographers.registeredToDisplayManager) {
+ JNIEnv* env = getJniEnv();
+ if (env == nullptr) {
+ ALOGW("JNI environment is unavailable, skipping choreographer cleanup");
+ return;
+ }
+ jobject dmg = env->CallStaticObjectMethod(gJni.displayManagerGlobal.clazz,
+ gJni.displayManagerGlobal.getInstance);
+ if (dmg == nullptr) {
+ ALOGW("DMS is not initialized yet, skipping choreographer cleanup");
+ } else {
+ env->CallVoidMethod(dmg,
+ gJni.displayManagerGlobal
+ .unregisterNativeChoreographerForRefreshRateCallbacks);
+ env->DeleteLocalRef(dmg);
+ }
+ }
+}
void Choreographer::postFrameCallbackDelayed(
AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
FrameCallback callback{cb, cb64, data, now + delay};
{
- AutoMutex _l{mLock};
+ std::lock_guard<std::mutex> _l{mLock};
mFrameCallbacks.push(callback);
}
if (callback.dueTime <= now) {
@@ -150,37 +234,68 @@
}
void Choreographer::registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data) {
+ std::lock_guard<std::mutex> _l{mLock};
+ for (const auto& callback : mRefreshRateCallbacks) {
+ // Don't re-add callbacks.
+ if (cb == callback.callback && data == callback.data) {
+ return;
+ }
+ }
+ mRefreshRateCallbacks.emplace_back(
+ RefreshRateCallback{.callback = cb, .data = data, .firstCallbackFired = false});
+ bool needsRegistration = false;
{
- AutoMutex _l{mLock};
- for (const auto& callback : mRefreshRateCallbacks) {
- // Don't re-add callbacks.
- if (cb == callback.callback && data == callback.data) {
- return;
+ std::lock_guard<std::mutex> _l2(gChoreographers.lock);
+ needsRegistration = !gChoreographers.registeredToDisplayManager;
+ }
+ if (needsRegistration) {
+ JNIEnv* env = getJniEnv();
+ if (env == nullptr) {
+ ALOGW("JNI environment is unavailable, skipping registration");
+ return;
+ }
+ jobject dmg = env->CallStaticObjectMethod(gJni.displayManagerGlobal.clazz,
+ gJni.displayManagerGlobal.getInstance);
+ if (dmg == nullptr) {
+ ALOGW("DMS is not initialized yet: skipping registration");
+ return;
+ } else {
+ env->CallVoidMethod(dmg,
+ gJni.displayManagerGlobal
+ .registerNativeChoreographerForRefreshRateCallbacks,
+ reinterpret_cast<int64_t>(this));
+ env->DeleteLocalRef(dmg);
+ {
+ std::lock_guard<std::mutex> _l2(gChoreographers.lock);
+ gChoreographers.registeredToDisplayManager = true;
}
}
- mRefreshRateCallbacks.emplace_back(RefreshRateCallback{cb, data});
- toggleConfigEvents(ISurfaceComposer::ConfigChanged::eConfigChangedDispatch);
+ } else {
+ scheduleLatestConfigRequest();
}
}
void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb,
void* data) {
- {
- AutoMutex _l{mLock};
- mRefreshRateCallbacks.erase(std::remove_if(mRefreshRateCallbacks.begin(),
- mRefreshRateCallbacks.end(),
- [&](const RefreshRateCallback& callback) {
- return cb == callback.callback &&
- data == callback.data;
- }),
- mRefreshRateCallbacks.end());
- if (mRefreshRateCallbacks.empty()) {
- toggleConfigEvents(ISurfaceComposer::ConfigChanged::eConfigChangedSuppress);
- // If callbacks are empty then clear out the most recently seen
- // vsync period so that when another callback is registered then the
- // up-to-date refresh rate can be communicated to the app again.
- mVsyncPeriod = 0;
- }
+ std::lock_guard<std::mutex> _l{mLock};
+ mRefreshRateCallbacks.erase(std::remove_if(mRefreshRateCallbacks.begin(),
+ mRefreshRateCallbacks.end(),
+ [&](const RefreshRateCallback& callback) {
+ return cb == callback.callback &&
+ data == callback.data;
+ }),
+ mRefreshRateCallbacks.end());
+}
+
+void Choreographer::scheduleLatestConfigRequest() {
+ if (mLooper != nullptr) {
+ Message m{MSG_HANDLE_REFRESH_RATE_UPDATES};
+ mLooper->sendMessage(this, m);
+ } else {
+ // If the looper thread is detached from Choreographer, then refresh rate
+ // changes will be handled in AChoreographer_handlePendingEvents, so we
+ // need to redispatch a config from SF
+ requestLatestConfig();
}
}
@@ -188,7 +303,7 @@
const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_t dueTime;
{
- AutoMutex _{mLock};
+ std::lock_guard<std::mutex> _l{mLock};
// If there are no pending callbacks then don't schedule a vsync
if (mFrameCallbacks.empty()) {
return;
@@ -203,13 +318,35 @@
}
}
+void Choreographer::handleRefreshRateUpdates() {
+ std::vector<RefreshRateCallback> callbacks{};
+ const nsecs_t pendingPeriod = gChoreographers.mLastKnownVsync.load();
+ const nsecs_t lastPeriod = mLatestVsyncPeriod;
+ if (pendingPeriod > 0) {
+ mLatestVsyncPeriod = pendingPeriod;
+ }
+ {
+ std::lock_guard<std::mutex> _l{mLock};
+ for (auto& cb : mRefreshRateCallbacks) {
+ callbacks.push_back(cb);
+ cb.firstCallbackFired = true;
+ }
+ }
+
+ for (auto& cb : callbacks) {
+ if (!cb.firstCallbackFired || (pendingPeriod > 0 && pendingPeriod != lastPeriod)) {
+ cb.callback(pendingPeriod, cb.data);
+ }
+ }
+}
+
// TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the
// internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for
// the internal display implicitly.
void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t) {
std::vector<FrameCallback> callbacks{};
{
- AutoMutex _l{mLock};
+ std::lock_guard<std::mutex> _l{mLock};
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) {
callbacks.push_back(mFrameCallbacks.top());
@@ -236,20 +373,29 @@
// display, so as such Choreographer does not support the notion of multiple
// displays. When multi-display choreographer is properly supported, then
// PhysicalDisplayId should no longer be ignored.
-void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId, int32_t,
+void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, int32_t configId,
nsecs_t vsyncPeriod) {
+ ALOGV("choreographer %p ~ received config change event "
+ "(displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%d).",
+ this, displayId, configId);
+
+ const nsecs_t lastPeriod = mLatestVsyncPeriod;
+ std::vector<RefreshRateCallback> callbacks{};
{
- AutoMutex _l{mLock};
- for (const auto& cb : mRefreshRateCallbacks) {
- // Only perform the callback when the old refresh rate is different
- // from the new refresh rate, so that we don't dispatch the callback
- // on every single configuration change.
- if (mVsyncPeriod != vsyncPeriod) {
- cb.callback(vsyncPeriod, cb.data);
- }
+ std::lock_guard<std::mutex> _l{mLock};
+ for (auto& cb : mRefreshRateCallbacks) {
+ callbacks.push_back(cb);
+ cb.firstCallbackFired = true;
}
- mVsyncPeriod = vsyncPeriod;
}
+
+ for (auto& cb : callbacks) {
+ if (!cb.firstCallbackFired || (vsyncPeriod > 0 && vsyncPeriod != lastPeriod)) {
+ cb.callback(vsyncPeriod, cb.data);
+ }
+ }
+
+ mLatestVsyncPeriod = vsyncPeriod;
}
void Choreographer::handleMessage(const Message& message) {
@@ -260,19 +406,80 @@
case MSG_SCHEDULE_VSYNC:
scheduleVsync();
break;
+ case MSG_HANDLE_REFRESH_RATE_UPDATES:
+ handleRefreshRateUpdates();
+ break;
}
}
-}
-
-/* Glue for the NDK interface */
-
+} // namespace android
using namespace android;
static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) {
return reinterpret_cast<Choreographer*>(choreographer);
}
+// Glue for private C api
+namespace android {
+void AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock) {
+ std::lock_guard<std::mutex> _l(gChoreographers.lock);
+ gChoreographers.mLastKnownVsync.store(vsyncPeriod);
+ for (auto c : gChoreographers.ptrs) {
+ c->scheduleLatestConfigRequest();
+ }
+}
+
+void AChoreographer_initJVM(JNIEnv* env) {
+ env->GetJavaVM(&gJni.jvm);
+ // Now we need to find the java classes.
+ jclass dmgClass = env->FindClass("android/hardware/display/DisplayManagerGlobal");
+ gJni.displayManagerGlobal.clazz = static_cast<jclass>(env->NewGlobalRef(dmgClass));
+ gJni.displayManagerGlobal.getInstance =
+ env->GetStaticMethodID(dmgClass, "getInstance",
+ "()Landroid/hardware/display/DisplayManagerGlobal;");
+ gJni.displayManagerGlobal.registerNativeChoreographerForRefreshRateCallbacks =
+ env->GetMethodID(dmgClass, "registerNativeChoreographerForRefreshRateCallbacks", "()V");
+ gJni.displayManagerGlobal.unregisterNativeChoreographerForRefreshRateCallbacks =
+ env->GetMethodID(dmgClass, "unregisterNativeChoreographerForRefreshRateCallbacks",
+ "()V");
+}
+
+AChoreographer* AChoreographer_routeGetInstance() {
+ return AChoreographer_getInstance();
+}
+void AChoreographer_routePostFrameCallback(AChoreographer* choreographer,
+ AChoreographer_frameCallback callback, void* data) {
+ return AChoreographer_postFrameCallback(choreographer, callback, data);
+}
+void AChoreographer_routePostFrameCallbackDelayed(AChoreographer* choreographer,
+ AChoreographer_frameCallback callback, void* data,
+ long delayMillis) {
+ return AChoreographer_postFrameCallbackDelayed(choreographer, callback, data, delayMillis);
+}
+void AChoreographer_routePostFrameCallback64(AChoreographer* choreographer,
+ AChoreographer_frameCallback64 callback, void* data) {
+ return AChoreographer_postFrameCallback64(choreographer, callback, data);
+}
+void AChoreographer_routePostFrameCallbackDelayed64(AChoreographer* choreographer,
+ AChoreographer_frameCallback64 callback,
+ void* data, uint32_t delayMillis) {
+ return AChoreographer_postFrameCallbackDelayed64(choreographer, callback, data, delayMillis);
+}
+void AChoreographer_routeRegisterRefreshRateCallback(AChoreographer* choreographer,
+ AChoreographer_refreshRateCallback callback,
+ void* data) {
+ return AChoreographer_registerRefreshRateCallback(choreographer, callback, data);
+}
+void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreographer,
+ AChoreographer_refreshRateCallback callback,
+ void* data) {
+ return AChoreographer_unregisterRefreshRateCallback(choreographer, callback, data);
+}
+
+} // namespace android
+
+/* Glue for the NDK interface */
+
static inline const Choreographer* AChoreographer_to_Choreographer(
const AChoreographer* choreographer) {
return reinterpret_cast<const Choreographer*>(choreographer);
@@ -343,5 +550,6 @@
// Pass dummy fd and events args to handleEvent, since the underlying
// DisplayEventDispatcher doesn't need them outside of validating that a
// Looper instance didn't break, but these args circumvent those checks.
- AChoreographer_to_Choreographer(choreographer)->handleEvent(-1, Looper::EVENT_INPUT, data);
+ Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
+ impl->handleEvent(-1, Looper::EVENT_INPUT, data);
}
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index c956578..f56b3a2 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -12,23 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-ndk_headers {
- name: "libnativedisplay_ndk_headers",
- from: "include/android",
- to: "android",
- srcs: ["include/android/*.h"],
- license: "NOTICE",
-}
-
cc_library_headers {
name: "libnativedisplay_headers",
- export_include_dirs: ["include"],
+ export_include_dirs: ["include",],
}
-cc_library {
+cc_library_shared {
name: "libnativedisplay",
export_include_dirs: [
"include",
+ "include-private",
],
clang: true,
@@ -63,6 +56,10 @@
"libnativehelper",
],
+ export_shared_lib_headers: [
+ "libnativehelper",
+ ],
+
header_libs: [
"libnativedisplay_headers",
],
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
new file mode 100644
index 0000000..2164930
--- /dev/null
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 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 <apex/choreographer.h>
+#include <inttypes.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+// Registers the global JVM for AChoreographer
+void AChoreographer_initJVM(JNIEnv* env);
+
+// Signals all AChoregorapher* instances that a new vsync period is available
+// for consumption by callbacks.
+void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod);
+
+// Trampoline functions allowing libandroid.so to define the NDK symbols without including
+// the entirety of libnativedisplay as a whole static lib. As libnativedisplay
+// maintains global state, libnativedisplay can never be directly statically
+// linked so that global state won't be duplicated. This way libandroid.so can
+// reroute the NDK methods into the implementations defined by libnativedisplay
+AChoreographer* AChoreographer_routeGetInstance();
+void AChoreographer_routePostFrameCallback(AChoreographer* choreographer,
+ AChoreographer_frameCallback callback, void* data);
+void AChoreographer_routePostFrameCallbackDelayed(AChoreographer* choreographer,
+ AChoreographer_frameCallback callback, void* data,
+ long delayMillis);
+void AChoreographer_routePostFrameCallback64(AChoreographer* choreographer,
+ AChoreographer_frameCallback64 callback, void* data);
+void AChoreographer_routePostFrameCallbackDelayed64(AChoreographer* choreographer,
+ AChoreographer_frameCallback64 callback,
+ void* data, uint32_t delayMillis);
+void AChoreographer_routeRegisterRefreshRateCallback(AChoreographer* choreographer,
+ AChoreographer_refreshRateCallback callback,
+ void* data);
+void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreographer,
+ AChoreographer_refreshRateCallback callback,
+ void* data);
+
+} // namespace android
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index 6a94a77..e2d036b 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-
+#include <nativehelper/JNIHelp.h>
#include <system/graphics.h>
// This file provides a facade API on top of SurfaceTexture, which avoids using
@@ -30,6 +30,20 @@
namespace android {
+// Trampoline functions allowing libandroid.so to define the NDK symbols without including
+// the entirety of libnativedisplay as a whole static lib. As libnativedisplay
+// maintains global state, libnativedisplay can never be directly statically
+// linked so that global state won't be duplicated. This way libandroid.so can
+// reroute the NDK methods into the implementations defined by libnativedisplay
+ANativeWindow* ASurfaceTexture_routeAcquireANativeWindow(ASurfaceTexture* st);
+int ASurfaceTexture_routeAttachToGLContext(ASurfaceTexture* st, uint32_t texName);
+int ASurfaceTexture_routeDetachFromGLContext(ASurfaceTexture* st);
+void ASurfaceTexture_routeRelease(ASurfaceTexture* st);
+int ASurfaceTexture_routeUpdateTexImage(ASurfaceTexture* st);
+void ASurfaceTexture_routeGetTransformMatrix(ASurfaceTexture* st, float mtx[16]);
+int64_t ASurfaceTexture_routeGetTimestamp(ASurfaceTexture* st);
+ASurfaceTexture* ASurfaceTexture_routeFromSurfaceTexture(JNIEnv* env, jobject surfacetexture);
+
/**
* ASurfaceTexture_getCurrentTextureTarget returns the texture target of the
* current texture.
diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt
index 483fb25..fc59431 100644
--- a/libs/nativedisplay/libnativedisplay.map.txt
+++ b/libs/nativedisplay/libnativedisplay.map.txt
@@ -20,6 +20,15 @@
LIBNATIVEDISPLAY_PLATFORM {
global:
extern "C++" {
+ android::AChoreographer_initJVM*;
+ android::AChoreographer_routeGetInstance*;
+ android::AChoreographer_routePostFrameCallback*;
+ android::AChoreographer_routePostFrameCallbackDelayed*;
+ android::AChoreographer_routePostFrameCallback64*;
+ android::AChoreographer_routePostFrameCallbackDelayed64*;
+ android::AChoreographer_routeRegisterRefreshRateCallback*;
+ android::AChoreographer_routeUnregisterRefreshRateCallback*;
+ android::AChoreographer_signalRefreshRateCallbacks*;
android::ADisplay_acquirePhysicalDisplays*;
android::ADisplay_release*;
android::ADisplay_getMaxSupportedFps*;
@@ -36,6 +45,14 @@
android::ASurfaceTexture_takeConsumerOwnership*;
android::ASurfaceTexture_releaseConsumerOwnership*;
android::ASurfaceTexture_dequeueBuffer*;
+ android::ASurfaceTexture_routeAcquireANativeWindow*;
+ android::ASurfaceTexture_routeAttachToGLContext*;
+ android::ASurfaceTexture_routeDetachFromGLContext*;
+ android::ASurfaceTexture_routeGetTimestamp*;
+ android::ASurfaceTexture_routeGetTransformMatrix*;
+ android::ASurfaceTexture_routeUpdateTexImage*;
+ android::ASurfaceTexture_routeFromSurfaceTexture*;
+ android::ASurfaceTexture_routeRelease*;
android::SurfaceTexture*;
};
ASurfaceTexture_acquireANativeWindow;
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index 1670fbb..d1bcd8d 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -149,6 +149,37 @@
// The following functions are private/unstable API.
namespace android {
+ANativeWindow* ASurfaceTexture_routeAcquireANativeWindow(ASurfaceTexture* st) {
+ return ASurfaceTexture_acquireANativeWindow(st);
+}
+
+int ASurfaceTexture_routeAttachToGLContext(ASurfaceTexture* st, uint32_t texName) {
+ return ASurfaceTexture_attachToGLContext(st, texName);
+}
+
+void ASurfaceTexture_routeRelease(ASurfaceTexture* st) {
+ return ASurfaceTexture_release(st);
+}
+
+int ASurfaceTexture_routeDetachFromGLContext(ASurfaceTexture* st) {
+ return ASurfaceTexture_detachFromGLContext(st);
+}
+
+int ASurfaceTexture_routeUpdateTexImage(ASurfaceTexture* st) {
+ return ASurfaceTexture_updateTexImage(st);
+}
+
+void ASurfaceTexture_routeGetTransformMatrix(ASurfaceTexture* st, float mtx[16]) {
+ return ASurfaceTexture_getTransformMatrix(st, mtx);
+}
+
+int64_t ASurfaceTexture_routeGetTimestamp(ASurfaceTexture* st) {
+ return ASurfaceTexture_getTimestamp(st);
+}
+
+ASurfaceTexture* ASurfaceTexture_routeFromSurfaceTexture(JNIEnv* env, jobject surfacetexture) {
+ return ASurfaceTexture_fromSurfaceTexture(env, surfacetexture);
+}
unsigned int ASurfaceTexture_getCurrentTextureTarget(ASurfaceTexture* st) {
return st->consumer->getCurrentTextureTarget();
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 55400c7..ee006aa 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -25,6 +25,7 @@
name: "libnativewindow_headers",
export_include_dirs: ["include"],
vendor_available: true,
+ min_sdk_version: "29",
}
ndk_library {
@@ -59,7 +60,6 @@
],
shared_libs: [
- "libhardware",
"libcutils",
"liblog",
"libutils",
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 869ca9e..b78fc5d 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -254,6 +254,7 @@
NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */
NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
+ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
// clang-format on
};
@@ -1062,4 +1063,38 @@
return value;
}
+/**
+ * Prototype of the function that an ANativeWindow implementation would call
+ * when ANativeWindow_query is called.
+ */
+typedef int (*ANativeWindow_queryFn)(const ANativeWindow* window, int what, int* value);
+
+/**
+ * Prototype of the function that intercepts an invocation of
+ * ANativeWindow_queryFn, along with a data pointer that's passed by the
+ * caller who set the interceptor, as well as arguments that would be
+ * passed to ANativeWindow_queryFn if it were to be called.
+ */
+typedef int (*ANativeWindow_queryInterceptor)(const ANativeWindow* window,
+ ANativeWindow_queryFn perform, void* data,
+ int what, int* value);
+
+/**
+ * Registers an interceptor for ANativeWindow_query. Instead of calling
+ * the underlying query function, instead the provided interceptor is
+ * called, which may optionally call the underlying query function. An
+ * optional data pointer is also provided to side-channel additional arguments.
+ *
+ * Note that usage of this should only be used for specialized use-cases by
+ * either the system partition or to Mainline modules. This should never be
+ * exposed to NDK or LL-NDK.
+ *
+ * Returns NO_ERROR on success, -errno if registration failed.
+ */
+static inline int ANativeWindow_setQueryInterceptor(ANativeWindow* window,
+ ANativeWindow_queryInterceptor interceptor,
+ void* data) {
+ return window->perform(window, NATIVE_WINDOW_SET_QUERY_INTERCEPTOR, interceptor, data);
+}
+
__END_DECLS
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index d56a82f..92e7e71 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -147,52 +147,6 @@
return NAME_NOT_FOUND;
}
-class EGLAttributeVector {
- struct Attribute;
- class Adder;
- friend class Adder;
- KeyedVector<Attribute, EGLint> mList;
- struct Attribute {
- Attribute() : v(0){};
- explicit Attribute(EGLint v) : v(v) {}
- EGLint v;
- bool operator<(const Attribute& other) const {
- // this places EGL_NONE at the end
- EGLint lhs(v);
- EGLint rhs(other.v);
- if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
- if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
- return lhs < rhs;
- }
- };
- class Adder {
- friend class EGLAttributeVector;
- EGLAttributeVector& v;
- EGLint attribute;
- Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
-
- public:
- void operator=(EGLint value) {
- if (attribute != EGL_NONE) {
- v.mList.add(Attribute(attribute), value);
- }
- }
- operator EGLint() const { return v.mList[attribute]; }
- };
-
-public:
- EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
- void remove(EGLint attribute) {
- if (attribute != EGL_NONE) {
- mList.removeItem(Attribute(attribute));
- }
- }
- Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
- EGLint operator[](EGLint attribute) const { return mList[attribute]; }
- // cast-operator to (EGLint const*)
- operator EGLint const*() const { return &mList.keyAt(0).v; }
-};
-
static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
EGLConfig* config) {
// select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
@@ -201,16 +155,33 @@
EGLint wantedAttribute;
EGLint wantedAttributeValue;
- EGLAttributeVector attribs;
+ std::vector<EGLint> attribs;
if (renderableType) {
- attribs[EGL_RENDERABLE_TYPE] = renderableType;
- attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
- attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
- attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
- attribs[EGL_RED_SIZE] = 8;
- attribs[EGL_GREEN_SIZE] = 8;
- attribs[EGL_BLUE_SIZE] = 8;
- attribs[EGL_ALPHA_SIZE] = 8;
+ const ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(format);
+ const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102;
+
+ // Default to 8 bits per channel.
+ const EGLint tmpAttribs[] = {
+ EGL_RENDERABLE_TYPE,
+ renderableType,
+ EGL_RECORDABLE_ANDROID,
+ EGL_TRUE,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_FRAMEBUFFER_TARGET_ANDROID,
+ EGL_TRUE,
+ EGL_RED_SIZE,
+ is1010102 ? 10 : 8,
+ EGL_GREEN_SIZE,
+ is1010102 ? 10 : 8,
+ EGL_BLUE_SIZE,
+ is1010102 ? 10 : 8,
+ EGL_ALPHA_SIZE,
+ is1010102 ? 2 : 8,
+ EGL_NONE,
+ };
+ std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)),
+ std::back_inserter(attribs));
wantedAttribute = EGL_NONE;
wantedAttributeValue = EGL_NONE;
} else {
@@ -219,7 +190,8 @@
wantedAttributeValue = format;
}
- err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
+ err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue,
+ config);
if (err == NO_ERROR) {
EGLint caveat;
if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
@@ -236,9 +208,20 @@
LOG_ALWAYS_FATAL("failed to initialize EGL");
}
+ const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
+ if (!eglVersion) {
+ checkGlError(__FUNCTION__, __LINE__);
+ LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
+ }
+
+ const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
+ if (!eglExtensions) {
+ checkGlError(__FUNCTION__, __LINE__);
+ LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
+ }
+
GLExtensions& extensions = GLExtensions::getInstance();
- extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION),
- eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS));
+ extensions.initWithEGLStrings(eglVersion, eglExtensions);
// The code assumes that ES2 or later is available if this extension is
// supported.
@@ -793,35 +776,66 @@
// top rectangle and the bottom rectangle, and turn off blending for the middle rectangle.
FloatRect bounds = layer.geometry.roundedCornersCrop;
- // Firstly, we need to convert the coordination from layer native coordination space to
- // device coordination space.
- // TODO(143929254): Verify that this transformation is correct
- const auto transformMatrix = display.globalTransform * layer.geometry.positionTransform;
- const vec4 leftTopCoordinate(bounds.left, bounds.top, 1.0, 1.0);
- const vec4 rightBottomCoordinate(bounds.right, bounds.bottom, 1.0, 1.0);
- const vec4 leftTopCoordinateInBuffer = transformMatrix * leftTopCoordinate;
- const vec4 rightBottomCoordinateInBuffer = transformMatrix * rightBottomCoordinate;
- bounds = FloatRect(leftTopCoordinateInBuffer[0], leftTopCoordinateInBuffer[1],
- rightBottomCoordinateInBuffer[0], rightBottomCoordinateInBuffer[1]);
-
- // Secondly, if the display is rotated, we need to undo the rotation on coordination and
- // align the (left, top) and (right, bottom) coordination with the device coordination
- // space.
+ // Explicitly compute the transform from the clip rectangle to the physical
+ // display. Normally, this is done in glViewport but we explicitly compute
+ // it here so that we can get the scissor bounds correct.
+ const Rect& source = display.clip;
+ const Rect& destination = display.physicalDisplay;
+ // Here we compute the following transform:
+ // 1. Translate the top left corner of the source clip to (0, 0)
+ // 2. Rotate the clip rectangle about the origin in accordance with the
+ // orientation flag
+ // 3. Translate the top left corner back to the origin.
+ // 4. Scale the clip rectangle to the destination rectangle dimensions
+ // 5. Translate the top left corner to the destination rectangle's top left
+ // corner.
+ const mat4 translateSource = mat4::translate(vec4(-source.left, -source.top, 0, 1));
+ mat4 rotation;
+ int displacementX = 0;
+ int displacementY = 0;
+ float destinationWidth = static_cast<float>(destination.getWidth());
+ float destinationHeight = static_cast<float>(destination.getHeight());
+ float sourceWidth = static_cast<float>(source.getWidth());
+ float sourceHeight = static_cast<float>(source.getHeight());
+ const float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
switch (display.orientation) {
case ui::Transform::ROT_90:
- std::swap(bounds.left, bounds.right);
+ rotation = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
+ displacementX = source.getHeight();
+ std::swap(sourceHeight, sourceWidth);
break;
case ui::Transform::ROT_180:
- std::swap(bounds.left, bounds.right);
- std::swap(bounds.top, bounds.bottom);
+ rotation = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
+ displacementY = source.getHeight();
+ displacementX = source.getWidth();
break;
case ui::Transform::ROT_270:
- std::swap(bounds.top, bounds.bottom);
+ rotation = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
+ displacementY = source.getWidth();
+ std::swap(sourceHeight, sourceWidth);
break;
default:
break;
}
+ const mat4 intermediateTranslation = mat4::translate(vec4(displacementX, displacementY, 0, 1));
+ const mat4 scale = mat4::scale(
+ vec4(destinationWidth / sourceWidth, destinationHeight / sourceHeight, 1, 1));
+ const mat4 translateDestination =
+ mat4::translate(vec4(destination.left, destination.top, 0, 1));
+ const mat4 globalTransform =
+ translateDestination * scale * intermediateTranslation * rotation * translateSource;
+
+ const mat4 transformMatrix = globalTransform * layer.geometry.positionTransform;
+ const vec4 leftTopCoordinate(bounds.left, bounds.top, 1.0, 1.0);
+ const vec4 rightBottomCoordinate(bounds.right, bounds.bottom, 1.0, 1.0);
+ const vec4 leftTopCoordinateInBuffer = transformMatrix * leftTopCoordinate;
+ const vec4 rightBottomCoordinateInBuffer = transformMatrix * rightBottomCoordinate;
+ bounds = FloatRect(std::min(leftTopCoordinateInBuffer[0], rightBottomCoordinateInBuffer[0]),
+ std::min(leftTopCoordinateInBuffer[1], rightBottomCoordinateInBuffer[1]),
+ std::max(leftTopCoordinateInBuffer[0], rightBottomCoordinateInBuffer[0]),
+ std::max(leftTopCoordinateInBuffer[1], rightBottomCoordinateInBuffer[1]));
+
// Finally, we cut the layer into 3 parts, with top and bottom parts having rounded corners
// and the middle part without rounded corners.
const int32_t radius = ceil(layer.geometry.roundedCornersRadius);
@@ -866,13 +880,32 @@
return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}
-void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /*framebuffer*/) {
ATRACE_CALL();
// back to main framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
+bool GLESRenderEngine::cleanupPostRender() {
+ ATRACE_CALL();
+
+ if (mPriorResourcesCleaned ||
+ (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled)) {
+ // If we don't have a prior frame needing cleanup, then don't do anything.
+ return false;
+ }
+
+ // Bind the texture to dummy data so that backing image data can be freed.
+ GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
+ glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
+ // Release the cached fence here, so that we don't churn reallocations when
+ // we could no-op repeated calls of this method instead.
+ mLastDrawFence = nullptr;
+ mPriorResourcesCleaned = true;
+ return true;
+}
+
void GLESRenderEngine::checkErrors() const {
checkErrors(nullptr);
}
@@ -1158,7 +1191,13 @@
// us bad parameters, or we messed up our shader generation).
return INVALID_OPERATION;
}
+ mLastDrawFence = nullptr;
+ } else {
+ // The caller takes ownership of drawFence, so we need to duplicate the
+ // fd here.
+ mLastDrawFence = new Fence(dup(drawFence->get()));
}
+ mPriorResourcesCleaned = false;
checkErrors();
return NO_ERROR;
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 32dbad1..42b8537 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -17,7 +17,6 @@
#ifndef SF_GLESRENDERENGINE_H_
#define SF_GLESRENDERENGINE_H_
-#include <stdint.h>
#include <condition_variable>
#include <deque>
#include <mutex>
@@ -76,6 +75,7 @@
const std::vector<const LayerSettings*>& layers,
ANativeWindowBuffer* buffer, const bool useFramebufferCache,
base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
+ bool cleanupPostRender() override;
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
// Creates an output image for rendering to
@@ -231,6 +231,17 @@
std::mutex mRenderingMutex;
std::unique_ptr<Framebuffer> mDrawingBuffer;
+ // this is a 1x1 RGB buffer, but over-allocate in case a driver wants more
+ // memory or if it needs to satisfy alignment requirements. In this case:
+ // assume that each channel requires 4 bytes, and add 3 additional bytes to
+ // ensure that we align on a word. Allocating 16 bytes will provide a
+ // guarantee that we don't clobber memory.
+ uint32_t mPlaceholderDrawBuffer[4];
+ sp<Fence> mLastDrawFence;
+ // Store a separate boolean checking if prior resources were cleaned up, as
+ // devices that don't support native sync fences can't rely on a last draw
+ // fence that doesn't exist.
+ bool mPriorResourcesCleaned = true;
// Blur effect processor, only instantiated when a layer requests it.
BlurFilter* mBlurFilter = nullptr;
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index cb0d5cf..383486b 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -68,11 +68,11 @@
return true;
}
-void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height) {
+void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height, void* data) {
ATRACE_CALL();
glBindTexture(GL_TEXTURE_2D, mTextureName);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
index b88da3b..6757695 100644
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ b/libs/renderengine/gl/GLFramebuffer.h
@@ -39,7 +39,7 @@
bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
const bool useFramebufferCache) override;
- void allocateBuffers(uint32_t width, uint32_t height);
+ void allocateBuffers(uint32_t width, uint32_t height, void* data = nullptr);
EGLImageKHR getEGLImage() const { return mEGLImage; }
uint32_t getTextureName() const { return mTextureName; }
uint32_t getFramebufferName() const { return mFramebufferName; }
diff --git a/libs/renderengine/gl/filters/BlurFilter.cpp b/libs/renderengine/gl/filters/BlurFilter.cpp
index 724877b..19f18c0 100644
--- a/libs/renderengine/gl/filters/BlurFilter.cpp
+++ b/libs/renderengine/gl/filters/BlurFilter.cpp
@@ -68,6 +68,8 @@
status_t BlurFilter::setAsDrawTarget(const DisplaySettings& display, uint32_t radius) {
ATRACE_NAME("BlurFilter::setAsDrawTarget");
mRadius = radius;
+ mDisplayX = display.physicalDisplay.left;
+ mDisplayY = display.physicalDisplay.top;
if (mDisplayWidth < display.physicalDisplay.width() ||
mDisplayHeight < display.physicalDisplay.height()) {
@@ -182,8 +184,8 @@
if (mix >= 1 || multiPass) {
mLastDrawTarget->bindAsReadBuffer();
glBlitFramebuffer(0, 0, mLastDrawTarget->getBufferWidth(),
- mLastDrawTarget->getBufferHeight(), 0, 0, mDisplayWidth, mDisplayHeight,
- GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ mLastDrawTarget->getBufferHeight(), mDisplayX, mDisplayY, mDisplayWidth,
+ mDisplayHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
return NO_ERROR;
}
@@ -261,15 +263,6 @@
return shader;
}
-void BlurFilter::blit(GLFramebuffer& read, GLFramebuffer& draw) const {
- ATRACE_NAME("BlurFilter::blit");
- read.bindAsReadBuffer();
- draw.bindAsDrawBuffer();
- glBlitFramebuffer(0, 0, read.getBufferWidth(), read.getBufferHeight(), 0, 0,
- draw.getBufferWidth(), draw.getBufferHeight(), GL_COLOR_BUFFER_BIT,
- GL_LINEAR);
-}
-
} // namespace gl
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/gl/filters/BlurFilter.h b/libs/renderengine/gl/filters/BlurFilter.h
index 36e5a77..593a8fd 100644
--- a/libs/renderengine/gl/filters/BlurFilter.h
+++ b/libs/renderengine/gl/filters/BlurFilter.h
@@ -38,7 +38,7 @@
// Downsample FBO to improve performance
static constexpr float kFboScale = 0.25f;
// Maximum number of render passes
- static constexpr uint32_t kMaxPasses = 6;
+ static constexpr uint32_t kMaxPasses = 4;
// To avoid downscaling artifacts, we interpolate the blurred fbo with the full composited
// image, up to this radius.
static constexpr float kMaxCrossFadeRadius = 30.0f;
@@ -56,7 +56,6 @@
private:
uint32_t mRadius;
void drawMesh(GLuint uv, GLuint position);
- void blit(GLFramebuffer& read, GLFramebuffer& draw) const;
string getVertexShader() const;
string getFragmentShader() const;
string getMixFragShader() const;
@@ -69,6 +68,8 @@
GLFramebuffer mPongFbo;
uint32_t mDisplayWidth = 0;
uint32_t mDisplayHeight = 0;
+ uint32_t mDisplayX = 0;
+ uint32_t mDisplayY = 0;
// Buffer holding the final blur pass.
GLFramebuffer* mLastDrawTarget;
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index c0766ab..ca16d2c 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -40,16 +40,6 @@
// z=1.
Rect clip = Rect::INVALID_RECT;
- // Global transform to apply to all layers.
- // The global transform is assumed to automatically apply when projecting
- // the clip rectangle onto the physical display; however, this should be
- // explicitly provided to perform CPU-side optimizations such as computing
- // scissor rectangles for rounded corners which require transformation to
- // the phsical display space.
- //
- // This transform is also assumed to include the orientation flag below.
- mat4 globalTransform = mat4();
-
// Maximum luminance pulled from the display's HDR capabilities.
float maxLuminance = 1.0f;
@@ -62,9 +52,7 @@
mat4 colorTransform = mat4();
// Region that will be cleared to (0, 0, 0, 1) prior to rendering.
- // RenderEngine will transform the clearRegion passed in here, by
- // globalTransform, so that it will be in the same coordinate space as the
- // rendered layers.
+ // This is specified in layer-stack space.
Region clearRegion = Region::INVALID_REGION;
// An additional orientation flag to be applied after clipping the output.
@@ -76,8 +64,7 @@
static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) {
return lhs.physicalDisplay == rhs.physicalDisplay && lhs.clip == rhs.clip &&
- lhs.globalTransform == rhs.globalTransform && lhs.maxLuminance == rhs.maxLuminance &&
- lhs.outputDataspace == rhs.outputDataspace &&
+ lhs.maxLuminance == rhs.maxLuminance && lhs.outputDataspace == rhs.outputDataspace &&
lhs.colorTransform == rhs.colorTransform &&
lhs.clearRegion.hasSameRects(rhs.clearRegion) && lhs.orientation == rhs.orientation;
}
@@ -89,7 +76,6 @@
PrintTo(settings.physicalDisplay, os);
*os << "\n .clip = ";
PrintTo(settings.clip, os);
- *os << "\n .globalTransform = " << settings.globalTransform;
*os << "\n .maxLuminance = " << settings.maxLuminance;
*os << "\n .outputDataspace = ";
PrintTo(settings.outputDataspace, os);
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 46f3fc6..e06e128 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -111,6 +111,14 @@
// Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
+ // Clean-up method that should be called on the main thread after the
+ // drawFence returned by drawLayers fires. This method will free up
+ // resources used by the most recently drawn frame. If the frame is still
+ // being drawn, then this call is silently ignored.
+ //
+ // Returns true if resources were cleaned up, and false if we didn't need to
+ // do any work.
+ virtual bool cleanupPostRender() = 0;
// queries
virtual size_t getMaxTextureSize() const = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index 3358c69..df0f17a 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -22,6 +22,7 @@
#include <renderengine/Mesh.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/Texture.h>
+#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
#include <ui/Region.h>
@@ -55,6 +56,7 @@
MOCK_CONST_METHOD0(isProtected, bool());
MOCK_CONST_METHOD0(supportsProtectedContent, bool());
MOCK_METHOD1(useProtectedContext, bool(bool));
+ MOCK_METHOD0(cleanupPostRender, bool());
MOCK_METHOD6(drawLayers,
status_t(const DisplaySettings&, const std::vector<const LayerSettings*>&,
ANativeWindowBuffer*, const bool, base::unique_fd&&, base::unique_fd*));
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index ce9131d..16a8a0d 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -924,7 +924,6 @@
settings.physicalDisplay = fullscreenRect();
// Here logical space is 4x4
settings.clip = Rect(4, 4);
- settings.globalTransform = mat4::scale(vec4(2, 4, 0, 1));
settings.clearRegion = Region(Rect(2, 4));
std::vector<const renderengine::LayerSettings*> layers;
// dummy layer, without bounds should not render anything
@@ -1242,12 +1241,12 @@
EXPECT_EQ(NO_ERROR, barrier->result);
}
-TEST_F(RenderEngineTest, drawLayers_bindExternalBufferWithNullBuffer) {
+TEST_F(RenderEngineTest, bindExternalBuffer_withNullBuffer) {
status_t result = sRE->bindExternalTextureBuffer(0, nullptr, nullptr);
ASSERT_EQ(BAD_VALUE, result);
}
-TEST_F(RenderEngineTest, drawLayers_bindExternalBufferCachesImages) {
+TEST_F(RenderEngineTest, bindExternalBuffer_cachesImages) {
sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
uint32_t texName;
sRE->genTextures(1, &texName);
@@ -1267,7 +1266,7 @@
EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
}
-TEST_F(RenderEngineTest, drawLayers_cacheExternalBufferWithNullBuffer) {
+TEST_F(RenderEngineTest, cacheExternalBuffer_withNullBuffer) {
std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
sRE->cacheExternalTextureBufferForTesting(nullptr);
std::lock_guard<std::mutex> lock(barrier->mutex);
@@ -1279,7 +1278,7 @@
EXPECT_EQ(BAD_VALUE, barrier->result);
}
-TEST_F(RenderEngineTest, drawLayers_cacheExternalBufferCachesImages) {
+TEST_F(RenderEngineTest, cacheExternalBuffer_cachesImages) {
sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
uint64_t bufferId = buf->getId();
std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
@@ -1402,6 +1401,35 @@
backgroundColor.a);
}
+TEST_F(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+
+ std::vector<const renderengine::LayerSettings*> layers;
+ renderengine::LayerSettings layer;
+ layer.geometry.boundaries = fullscreenRect().toFloatRect();
+ BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
+ layer.alpha = 1.0;
+ layers.push_back(&layer);
+
+ base::unique_fd fenceOne;
+ sRE->drawLayers(settings, layers, mBuffer->getNativeBuffer(), true, base::unique_fd(),
+ &fenceOne);
+ base::unique_fd fenceTwo;
+ sRE->drawLayers(settings, layers, mBuffer->getNativeBuffer(), true, std::move(fenceOne),
+ &fenceTwo);
+
+ const int fd = fenceTwo.get();
+ if (fd >= 0) {
+ sync_wait(fd, -1);
+ }
+
+ // Only cleanup the first time.
+ EXPECT_TRUE(sRE->cleanupPostRender());
+ EXPECT_FALSE(sRE->cleanupPostRender());
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index ba6255d..1ee8c71 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -36,9 +36,6 @@
srcs: [
"ColorSpace.cpp",
- "BufferHubBuffer.cpp",
- "BufferHubEventFd.cpp",
- "BufferHubMetadata.cpp",
"DebugUtils.cpp",
"Fence.cpp",
"FenceTime.cpp",
@@ -72,7 +69,6 @@
//defaults: ["libui-validate-regions-defaults"],
shared_libs: [
- "android.frameworks.bufferhub@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
@@ -109,30 +105,20 @@
vendor: {
cflags: ["-DLIBUI_IN_VNDK"],
exclude_srcs: [
- "BufferHubBuffer.cpp",
- "BufferHubEventFd.cpp",
- "BufferHubMetadata.cpp",
],
exclude_header_libs: [
- "libbufferhub_headers",
- "libdvr_headers",
],
exclude_shared_libs: [
- "android.frameworks.bufferhub@1.0",
- "libpdx_default_transport",
],
},
},
header_libs: [
"libbase_headers",
- "libbufferhub_headers",
- "libdvr_headers",
"libnativebase_headers",
"libnativewindow_headers",
"libhardware_headers",
"libui_headers",
- "libpdx_headers",
],
export_static_lib_headers: [
@@ -147,6 +133,7 @@
"libhardware_headers",
"libui_headers",
],
+ min_sdk_version: "29",
}
cc_library_headers {
@@ -165,6 +152,7 @@
export_header_lib_headers: [
"libnativewindow_headers",
],
+ min_sdk_version: "29",
}
// defaults to enable VALIDATE_REGIONS traces
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
deleted file mode 100644
index 1dfc1e9..0000000
--- a/libs/ui/BufferHubBuffer.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#define LOG_TAG "BufferHubBuffer"
-#include <poll.h>
-
-#include <android-base/unique_fd.h>
-#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
-#include <log/log.h>
-#include <ui/BufferHubBuffer.h>
-#include <ui/BufferHubDefs.h>
-#include <utils/Trace.h>
-
-using ::android::base::unique_fd;
-using ::android::BufferHubDefs::isAnyClientAcquired;
-using ::android::BufferHubDefs::isAnyClientGained;
-using ::android::BufferHubDefs::isClientAcquired;
-using ::android::BufferHubDefs::isClientGained;
-using ::android::BufferHubDefs::isClientPosted;
-using ::android::BufferHubDefs::isClientReleased;
-using ::android::frameworks::bufferhub::V1_0::BufferHubStatus;
-using ::android::frameworks::bufferhub::V1_0::BufferTraits;
-using ::android::frameworks::bufferhub::V1_0::IBufferClient;
-using ::android::frameworks::bufferhub::V1_0::IBufferHub;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription;
-
-namespace android {
-
-std::unique_ptr<BufferHubBuffer> BufferHubBuffer::create(uint32_t width, uint32_t height,
- uint32_t layerCount, uint32_t format,
- uint64_t usage, size_t userMetadataSize) {
- auto buffer = std::unique_ptr<BufferHubBuffer>(
- new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
- return buffer->isValid() ? std::move(buffer) : nullptr;
-}
-
-std::unique_ptr<BufferHubBuffer> BufferHubBuffer::import(const sp<NativeHandle>& token) {
- if (token == nullptr || token.get() == nullptr) {
- ALOGE("%s: token cannot be nullptr!", __FUNCTION__);
- return nullptr;
- }
-
- auto buffer = std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(token));
- return buffer->isValid() ? std::move(buffer) : nullptr;
-}
-
-BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
- uint32_t format, uint64_t usage, size_t userMetadataSize) {
- ATRACE_CALL();
- ALOGD("%s: width=%u height=%u layerCount=%u, format=%u "
- "usage=%" PRIx64 " mUserMetadataSize=%zu",
- __FUNCTION__, width, height, layerCount, format, usage, userMetadataSize);
-
- sp<IBufferHub> bufferhub = IBufferHub::getService();
- if (bufferhub.get() == nullptr) {
- ALOGE("%s: BufferHub service not found!", __FUNCTION__);
- return;
- }
-
- AHardwareBuffer_Desc aDesc = {width, height, layerCount, format,
- usage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
- HardwareBufferDescription desc;
- memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
-
- BufferHubStatus ret;
- sp<IBufferClient> client;
- BufferTraits bufferTraits;
- IBufferHub::allocateBuffer_cb allocCb = [&](const auto& status, const auto& outClient,
- const auto& outTraits) {
- ret = status;
- client = std::move(outClient);
- bufferTraits = std::move(outTraits);
- };
-
- if (!bufferhub->allocateBuffer(desc, static_cast<uint32_t>(userMetadataSize), allocCb).isOk()) {
- ALOGE("%s: allocateBuffer transaction failed!", __FUNCTION__);
- return;
- } else if (ret != BufferHubStatus::NO_ERROR) {
- ALOGE("%s: allocateBuffer failed with error %u.", __FUNCTION__, ret);
- return;
- } else if (client == nullptr) {
- ALOGE("%s: allocateBuffer got null BufferClient.", __FUNCTION__);
- return;
- }
-
- const int importRet = initWithBufferTraits(bufferTraits);
- if (importRet < 0) {
- ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
- client->close();
- }
- mBufferClient = std::move(client);
-}
-
-BufferHubBuffer::BufferHubBuffer(const sp<NativeHandle>& token) {
- sp<IBufferHub> bufferhub = IBufferHub::getService();
- if (bufferhub.get() == nullptr) {
- ALOGE("%s: BufferHub service not found!", __FUNCTION__);
- return;
- }
-
- BufferHubStatus ret;
- sp<IBufferClient> client;
- BufferTraits bufferTraits;
- IBufferHub::importBuffer_cb importCb = [&](const auto& status, const auto& outClient,
- const auto& outTraits) {
- ret = status;
- client = std::move(outClient);
- bufferTraits = std::move(outTraits);
- };
-
- // hidl_handle(native_handle_t*) simply creates a raw pointer reference withouth ownership
- // transfer.
- if (!bufferhub->importBuffer(hidl_handle(token.get()->handle()), importCb).isOk()) {
- ALOGE("%s: importBuffer transaction failed!", __FUNCTION__);
- return;
- } else if (ret != BufferHubStatus::NO_ERROR) {
- ALOGE("%s: importBuffer failed with error %u.", __FUNCTION__, ret);
- return;
- } else if (client == nullptr) {
- ALOGE("%s: importBuffer got null BufferClient.", __FUNCTION__);
- return;
- }
-
- const int importRet = initWithBufferTraits(bufferTraits);
- if (importRet < 0) {
- ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
- client->close();
- }
- mBufferClient = std::move(client);
-}
-
-BufferHubBuffer::~BufferHubBuffer() {
- // Close buffer client to avoid possible race condition: user could first duplicate and hold
- // token with the original buffer gone, and then try to import the token. The close function
- // will explicitly invalidate the token to avoid this.
- if (mBufferClient != nullptr) {
- if (!mBufferClient->close().isOk()) {
- ALOGE("%s: close BufferClient transaction failed!", __FUNCTION__);
- }
- }
-}
-
-int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) {
- ATRACE_CALL();
-
- if (bufferTraits.bufferInfo.getNativeHandle() == nullptr) {
- ALOGE("%s: missing buffer info handle.", __FUNCTION__);
- return -EINVAL;
- }
-
- if (bufferTraits.bufferHandle.getNativeHandle() == nullptr) {
- ALOGE("%s: missing gralloc handle.", __FUNCTION__);
- return -EINVAL;
- }
-
- // Import fds. Dup fds because hidl_handle owns the fds.
- unique_fd ashmemFd(fcntl(bufferTraits.bufferInfo->data[0], F_DUPFD_CLOEXEC, 0));
- mMetadata = BufferHubMetadata::import(std::move(ashmemFd));
- if (!mMetadata.isValid()) {
- ALOGE("%s: Received an invalid metadata.", __FUNCTION__);
- return -EINVAL;
- }
-
- mEventFd = BufferHubEventFd(fcntl(bufferTraits.bufferInfo->data[1], F_DUPFD_CLOEXEC, 0));
- if (!mEventFd.isValid()) {
- ALOGE("%s: Received ad invalid event fd.", __FUNCTION__);
- return -EINVAL;
- }
-
- int bufferId = bufferTraits.bufferInfo->data[2];
- if (bufferId < 0) {
- ALOGE("%s: Received an invalid (negative) id.", __FUNCTION__);
- return -EINVAL;
- }
-
- uint32_t clientBitMask;
- memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[3], sizeof(clientBitMask));
- if (clientBitMask == 0U) {
- ALOGE("%s: Received an invalid client state mask.", __FUNCTION__);
- return -EINVAL;
- }
-
- uint32_t userMetadataSize;
- memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[4], sizeof(userMetadataSize));
- if (mMetadata.userMetadataSize() != userMetadataSize) {
- ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__,
- userMetadataSize, mMetadata.userMetadataSize());
- return -EINVAL;
- }
-
- size_t metadataSize = static_cast<size_t>(mMetadata.metadataSize());
- if (metadataSize < BufferHubDefs::kMetadataHeaderSize) {
- ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize);
- return -EINVAL;
- }
-
- // Populate shortcuts to the atomics in metadata.
- auto metadataHeader = mMetadata.metadataHeader();
- mBufferState = &metadataHeader->bufferState;
- mFenceState = &metadataHeader->fenceState;
- mActiveClientsBitMask = &metadataHeader->activeClientsBitMask;
- // The C++ standard recommends (but does not require) that lock-free atomic operations are
- // also address-free, that is, suitable for communication between processes using shared
- // memory.
- LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(mBufferState) ||
- !std::atomic_is_lock_free(mFenceState) ||
- !std::atomic_is_lock_free(mActiveClientsBitMask),
- "Atomic variables in ashmen are not lock free.");
-
- // Import the buffer: We only need to hold on the native_handle_t here so that
- // GraphicBuffer instance can be created in future.
- mBufferHandle = std::move(bufferTraits.bufferHandle);
- memcpy(&mBufferDesc, &bufferTraits.bufferDesc, sizeof(AHardwareBuffer_Desc));
-
- mId = bufferId;
- mClientStateMask = clientBitMask;
-
- // TODO(b/112012161) Set up shared fences.
- ALOGD("%s: id=%d, mBufferState=%" PRIx32 ".", __FUNCTION__, mId,
- mBufferState->load(std::memory_order_acquire));
- return 0;
-}
-
-int BufferHubBuffer::gain() {
- uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
- if (isClientGained(currentBufferState, mClientStateMask)) {
- ALOGV("%s: Buffer is already gained by this client %" PRIx32 ".", __FUNCTION__,
- mClientStateMask);
- return 0;
- }
- do {
- if (isAnyClientGained(currentBufferState & (~mClientStateMask)) ||
- isAnyClientAcquired(currentBufferState)) {
- ALOGE("%s: Buffer is in use, id=%d mClientStateMask=%" PRIx32 " state=%" PRIx32 ".",
- __FUNCTION__, mId, mClientStateMask, currentBufferState);
- return -EBUSY;
- }
- // Change the buffer state to gained state, whose value happens to be the same as
- // mClientStateMask.
- } while (!mBufferState->compare_exchange_weak(currentBufferState, mClientStateMask,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
- // TODO(b/119837586): Update fence state and return GPU fence.
- return 0;
-}
-
-int BufferHubBuffer::post() {
- uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
- uint32_t updatedBufferState = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
- do {
- if (!isClientGained(currentBufferState, mClientStateMask)) {
- ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
- "mClientStateMask=%" PRIx32 " state=%" PRIx32 ".",
- __FUNCTION__, mId, mClientStateMask, currentBufferState);
- return -EBUSY;
- }
- // Set the producer client buffer state to released, other clients' buffer state to posted.
- // Post to all existing and non-existing clients.
- } while (!mBufferState->compare_exchange_weak(currentBufferState, updatedBufferState,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
- // TODO(b/119837586): Update fence state and return GPU fence if needed.
- return 0;
-}
-
-int BufferHubBuffer::acquire() {
- uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
- if (isClientAcquired(currentBufferState, mClientStateMask)) {
- ALOGV("%s: Buffer is already acquired by this client %" PRIx32 ".", __FUNCTION__,
- mClientStateMask);
- return 0;
- }
- uint32_t updatedBufferState = 0U;
- do {
- if (!isClientPosted(currentBufferState, mClientStateMask)) {
- ALOGE("%s: Cannot acquire a buffer that is not in posted state. buffer_id=%d "
- "mClientStateMask=%" PRIx32 " state=%" PRIx32 ".",
- __FUNCTION__, mId, mClientStateMask, currentBufferState);
- return -EBUSY;
- }
- // Change the buffer state for this consumer from posted to acquired.
- updatedBufferState = currentBufferState ^ mClientStateMask;
- } while (!mBufferState->compare_exchange_weak(currentBufferState, updatedBufferState,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
- // TODO(b/119837586): Update fence state and return GPU fence.
- return 0;
-}
-
-int BufferHubBuffer::release() {
- uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
- if (isClientReleased(currentBufferState, mClientStateMask)) {
- ALOGV("%s: Buffer is already released by this client %" PRIx32 ".", __FUNCTION__,
- mClientStateMask);
- return 0;
- }
- uint32_t updatedBufferState = 0U;
- do {
- updatedBufferState = currentBufferState & (~mClientStateMask);
- } while (!mBufferState->compare_exchange_weak(currentBufferState, updatedBufferState,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
- // TODO(b/119837586): Update fence state and return GPU fence if needed.
- return 0;
-}
-
-bool BufferHubBuffer::isReleased() const {
- return (mBufferState->load(std::memory_order_acquire) &
- mActiveClientsBitMask->load(std::memory_order_acquire)) == 0;
-}
-
-bool BufferHubBuffer::isValid() const {
- return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
- mEventFd.get() >= 0 && mMetadata.isValid() && mBufferClient != nullptr;
-}
-
-sp<NativeHandle> BufferHubBuffer::duplicate() {
- if (mBufferClient == nullptr) {
- ALOGE("%s: missing BufferClient!", __FUNCTION__);
- return nullptr;
- }
-
- hidl_handle token;
- BufferHubStatus ret;
- IBufferClient::duplicate_cb dupCb = [&](const auto& outToken, const auto& status) {
- token = std::move(outToken);
- ret = status;
- };
-
- if (!mBufferClient->duplicate(dupCb).isOk()) {
- ALOGE("%s: duplicate transaction failed!", __FUNCTION__);
- return nullptr;
- } else if (ret != BufferHubStatus::NO_ERROR) {
- ALOGE("%s: duplicate failed with error %u.", __FUNCTION__, ret);
- return nullptr;
- } else if (token.getNativeHandle() == nullptr) {
- ALOGE("%s: duplicate got null token.", __FUNCTION__);
- return nullptr;
- }
-
- return NativeHandle::create(native_handle_clone(token.getNativeHandle()), /*ownsHandle=*/true);
-}
-
-} // namespace android
diff --git a/libs/ui/BufferHubEventFd.cpp b/libs/ui/BufferHubEventFd.cpp
deleted file mode 100644
index bffc2ca..0000000
--- a/libs/ui/BufferHubEventFd.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2018 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 <sys/eventfd.h>
-
-#include <log/log.h>
-#include <ui/BufferHubEventFd.h>
-
-namespace android {
-
-BufferHubEventFd::BufferHubEventFd() : mFd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) {}
-
-BufferHubEventFd::BufferHubEventFd(int fd) : mFd(fd) {}
-
-status_t BufferHubEventFd::signal() const {
- if (!isValid()) {
- ALOGE("%s: cannot signal an invalid eventfd.", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- eventfd_write(mFd.get(), 1);
- return OK;
-}
-
-status_t BufferHubEventFd::clear() const {
- if (!isValid()) {
- ALOGE("%s: cannot clear an invalid eventfd.", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- eventfd_t value;
- eventfd_read(mFd.get(), &value);
- return OK;
-}
-
-} // namespace android
diff --git a/libs/ui/BufferHubMetadata.cpp b/libs/ui/BufferHubMetadata.cpp
deleted file mode 100644
index 05bc7dd..0000000
--- a/libs/ui/BufferHubMetadata.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2018 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 <errno.h>
-#include <sys/mman.h>
-#include <limits>
-
-#include <cutils/ashmem.h>
-#include <log/log.h>
-#include <ui/BufferHubMetadata.h>
-
-namespace android {
-
-namespace {
-
-static const int kAshmemProt = PROT_READ | PROT_WRITE;
-
-} // namespace
-
-using BufferHubDefs::kMetadataHeaderSize;
-using BufferHubDefs::MetadataHeader;
-
-/* static */
-BufferHubMetadata BufferHubMetadata::create(size_t userMetadataSize) {
- // The size the of metadata buffer is used as the "width" parameter during allocation. Thus it
- // cannot overflow uint32_t.
- if (userMetadataSize >= (std::numeric_limits<uint32_t>::max() - kMetadataHeaderSize)) {
- ALOGE("BufferHubMetadata::Create: metadata size too big: %zu.", userMetadataSize);
- return {};
- }
-
- const size_t metadataSize = userMetadataSize + kMetadataHeaderSize;
- int fd = ashmem_create_region(/*name=*/"BufferHubMetadata", metadataSize);
- if (fd < 0) {
- ALOGE("BufferHubMetadata::Create: failed to create ashmem region.");
- return {};
- }
-
- // Hand over the ownership of the fd to a unique_fd immediately after the successful
- // return of ashmem_create_region. The ashmemFd is going to own the fd and to prevent fd
- // leaks during error handling.
- unique_fd ashmemFd{fd};
-
- if (ashmem_set_prot_region(ashmemFd.get(), kAshmemProt) != 0) {
- ALOGE("BufferHubMetadata::Create: failed to set protect region.");
- return {};
- }
-
- return BufferHubMetadata::import(std::move(ashmemFd));
-}
-
-/* static */
-BufferHubMetadata BufferHubMetadata::import(unique_fd ashmemFd) {
- if (!ashmem_valid(ashmemFd.get())) {
- ALOGE("BufferHubMetadata::Import: invalid ashmem fd.");
- return {};
- }
-
- size_t metadataSize = static_cast<size_t>(ashmem_get_size_region(ashmemFd.get()));
- size_t userMetadataSize = metadataSize - kMetadataHeaderSize;
-
- // Note that here the buffer state is mapped from shared memory as an atomic object. The
- // std::atomic's constructor will not be called so that the original value stored in the memory
- // region can be preserved.
- auto metadataHeader = static_cast<MetadataHeader*>(mmap(nullptr, metadataSize, kAshmemProt,
- MAP_SHARED, ashmemFd.get(),
- /*offset=*/0));
- if (metadataHeader == nullptr) {
- ALOGE("BufferHubMetadata::Import: failed to map region.");
- return {};
- }
-
- return BufferHubMetadata(userMetadataSize, std::move(ashmemFd), metadataHeader);
-}
-
-BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd,
- MetadataHeader* metadataHeader)
- : mUserMetadataSize(userMetadataSize),
- mAshmemFd(std::move(ashmemFd)),
- mMetadataHeader(metadataHeader) {}
-
-BufferHubMetadata::~BufferHubMetadata() {
- if (mMetadataHeader != nullptr) {
- int ret = munmap(mMetadataHeader, metadataSize());
- ALOGE_IF(ret != 0,
- "BufferHubMetadata::~BufferHubMetadata: failed to unmap ashmem, error=%d.", errno);
- mMetadataHeader = nullptr;
- }
-}
-
-} // namespace android
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index d8e4059..f799ce4 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -203,7 +203,7 @@
std::vector<ui::PlaneLayout> planeLayouts;
status_t err = getPlaneLayouts(bufferHandle, &planeLayouts);
- if (err != NO_ERROR && !planeLayouts.empty()) {
+ if (err == NO_ERROR && !planeLayouts.empty()) {
if (outBytesPerPixel) {
int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
for (const auto& planeLayout : planeLayouts) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 05fc590..3732fee 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -23,10 +23,6 @@
#include <grallocusage/GrallocUsageConversion.h>
-#ifndef LIBUI_IN_VNDK
-#include <ui/BufferHubBuffer.h>
-#endif // LIBUI_IN_VNDK
-
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
#include <utils/Trace.h>
@@ -110,22 +106,6 @@
inUsage, inStride);
}
-#ifndef LIBUI_IN_VNDK
-GraphicBuffer::GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer) : GraphicBuffer() {
- if (buffer == nullptr) {
- mInitCheck = BAD_VALUE;
- return;
- }
-
- mInitCheck = initWithHandle(buffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
- buffer->desc().width, buffer->desc().height,
- static_cast<PixelFormat>(buffer->desc().format),
- buffer->desc().layers, buffer->desc().usage, buffer->desc().stride);
- mBufferId = buffer->id();
- mBufferHubBuffer = std::move(buffer);
-}
-#endif // LIBUI_IN_VNDK
-
GraphicBuffer::~GraphicBuffer()
{
ATRACE_CALL();
@@ -374,29 +354,14 @@
}
size_t GraphicBuffer::getFlattenedSize() const {
-#ifndef LIBUI_IN_VNDK
- if (mBufferHubBuffer != nullptr) {
- return 48;
- }
-#endif
return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
}
size_t GraphicBuffer::getFdCount() const {
-#ifndef LIBUI_IN_VNDK
- if (mBufferHubBuffer != nullptr) {
- return 0;
- }
-#endif
return static_cast<size_t>(handle ? mTransportNumFds : 0);
}
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
-#ifndef LIBUI_IN_VNDK
- if (mBufferHubBuffer != nullptr) {
- return flattenBufferHubBuffer(buffer, size);
- }
-#endif
size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
if (size < sizeNeeded) return NO_MEMORY;
@@ -453,12 +418,6 @@
} else if (buf[0] == 'GBFR') {
// old version, when usage bits were 32-bits
flattenWordCount = 12;
- } else if (buf[0] == 'BHBB') { // BufferHub backed buffer.
-#ifndef LIBUI_IN_VNDK
- return unflattenBufferHubBuffer(buffer, size);
-#else
- return BAD_TYPE;
-#endif
} else {
return BAD_TYPE;
}
@@ -565,76 +524,6 @@
mDeathCallbacks.emplace_back(deathCallback, context);
}
-#ifndef LIBUI_IN_VNDK
-status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size) const {
- sp<NativeHandle> tokenHandle = mBufferHubBuffer->duplicate();
- if (tokenHandle == nullptr || tokenHandle->handle() == nullptr ||
- tokenHandle->handle()->numFds != 0) {
- return BAD_VALUE;
- }
-
- // Size needed for one label, one number of ints inside the token, one generation number and
- // the token itself.
- int numIntsInToken = tokenHandle->handle()->numInts;
- const size_t sizeNeeded = static_cast<size_t>(3 + numIntsInToken) * sizeof(int);
- if (size < sizeNeeded) {
- ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__,
- static_cast<int>(sizeNeeded), static_cast<int>(size));
- return NO_MEMORY;
- }
- size -= sizeNeeded;
-
- int* buf = static_cast<int*>(buffer);
- buf[0] = 'BHBB';
- buf[1] = numIntsInToken;
- memcpy(buf + 2, tokenHandle->handle()->data, static_cast<size_t>(numIntsInToken) * sizeof(int));
- buf[2 + numIntsInToken] = static_cast<int32_t>(mGenerationNumber);
-
- return NO_ERROR;
-}
-
-status_t GraphicBuffer::unflattenBufferHubBuffer(void const*& buffer, size_t& size) {
- const int* buf = static_cast<const int*>(buffer);
- int numIntsInToken = buf[1];
- // Size needed for one label, one number of ints inside the token, one generation number and
- // the token itself.
- const size_t sizeNeeded = static_cast<size_t>(3 + numIntsInToken) * sizeof(int);
- if (size < sizeNeeded) {
- ALOGE("%s: needed size %d, given size %d. Not enough memory.", __FUNCTION__,
- static_cast<int>(sizeNeeded), static_cast<int>(size));
- return NO_MEMORY;
- }
- size -= sizeNeeded;
- native_handle_t* importToken = native_handle_create(/*numFds=*/0, /*numInts=*/numIntsInToken);
- memcpy(importToken->data, buf + 2, static_cast<size_t>(buf[1]) * sizeof(int));
- sp<NativeHandle> importTokenHandle = NativeHandle::create(importToken, /*ownHandle=*/true);
- std::unique_ptr<BufferHubBuffer> bufferHubBuffer = BufferHubBuffer::import(importTokenHandle);
- if (bufferHubBuffer == nullptr || bufferHubBuffer.get() == nullptr) {
- return BAD_VALUE;
- }
- // Reconstruct this GraphicBuffer object using the new BufferHubBuffer object.
- if (handle) {
- free_handle();
- }
- mId = 0;
- mGenerationNumber = static_cast<uint32_t>(buf[2 + numIntsInToken]);
- mInitCheck =
- initWithHandle(bufferHubBuffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
- bufferHubBuffer->desc().width, bufferHubBuffer->desc().height,
- static_cast<PixelFormat>(bufferHubBuffer->desc().format),
- bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage,
- bufferHubBuffer->desc().stride);
- mBufferId = bufferHubBuffer->id();
- mBufferHubBuffer = std::move(bufferHubBuffer);
-
- return NO_ERROR;
-}
-
-bool GraphicBuffer::isBufferHubBuffer() const {
- return mBufferHubBuffer != nullptr;
-}
-#endif // LIBUI_IN_VNDK
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index bf487c4..e01309b 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -67,19 +67,20 @@
// ----------------------------------------------------------------------------
Region::Region() {
- mStorage.add(Rect(0,0));
+ mStorage.push_back(Rect(0, 0));
}
Region::Region(const Region& rhs)
- : mStorage(rhs.mStorage)
{
+ mStorage.clear();
+ mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
#if defined(VALIDATE_REGIONS)
validate(rhs, "rhs copy-ctor");
#endif
}
Region::Region(const Rect& rhs) {
- mStorage.add(rhs);
+ mStorage.push_back(rhs);
}
Region::~Region()
@@ -100,8 +101,8 @@
* final, correctly ordered region buffer. Each rectangle will be compared with the span directly
* above it, and subdivided to resolve any remaining T-junctions.
*/
-static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end,
- Vector<Rect>& dst, int spanDirection) {
+static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst,
+ int spanDirection) {
dst.clear();
const Rect* current = end - 1;
@@ -109,7 +110,7 @@
// add first span immediately
do {
- dst.add(*current);
+ dst.push_back(*current);
current--;
} while (current->top == lastTop && current >= begin);
@@ -147,12 +148,12 @@
if (prev.right <= left) break;
if (prev.right > left && prev.right < right) {
- dst.add(Rect(prev.right, top, right, bottom));
+ dst.push_back(Rect(prev.right, top, right, bottom));
right = prev.right;
}
if (prev.left > left && prev.left < right) {
- dst.add(Rect(prev.left, top, right, bottom));
+ dst.push_back(Rect(prev.left, top, right, bottom));
right = prev.left;
}
@@ -166,12 +167,12 @@
if (prev.left >= right) break;
if (prev.left > left && prev.left < right) {
- dst.add(Rect(left, top, prev.left, bottom));
+ dst.push_back(Rect(left, top, prev.left, bottom));
left = prev.left;
}
if (prev.right > left && prev.right < right) {
- dst.add(Rect(left, top, prev.right, bottom));
+ dst.push_back(Rect(left, top, prev.right, bottom));
left = prev.right;
}
// if an entry in the previous span is too far left, nothing further right in the
@@ -183,7 +184,7 @@
}
if (left < right) {
- dst.add(Rect(left, top, right, bottom));
+ dst.push_back(Rect(left, top, right, bottom));
}
current--;
@@ -201,13 +202,14 @@
if (r.isEmpty()) return r;
if (r.isRect()) return r;
- Vector<Rect> reversed;
+ FatVector<Rect> reversed;
reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL);
Region outputRegion;
- reverseRectsResolvingJunctions(reversed.begin(), reversed.end(),
- outputRegion.mStorage, direction_LTR);
- outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds
+ reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(),
+ outputRegion.mStorage, direction_LTR);
+ outputRegion.mStorage.push_back(
+ r.getBounds()); // to make region valid, mStorage must end with bounds
#if defined(VALIDATE_REGIONS)
validate(outputRegion, "T-Junction free region");
@@ -222,7 +224,13 @@
validate(*this, "this->operator=");
validate(rhs, "rhs.operator=");
#endif
- mStorage = rhs.mStorage;
+ if (this == &rhs) {
+ // Already equal to itself
+ return *this;
+ }
+
+ mStorage.clear();
+ mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
return *this;
}
@@ -231,7 +239,7 @@
if (mStorage.size() >= 2) {
const Rect bounds(getBounds());
mStorage.clear();
- mStorage.add(bounds);
+ mStorage.push_back(bounds);
}
return *this;
}
@@ -255,25 +263,25 @@
void Region::clear()
{
mStorage.clear();
- mStorage.add(Rect(0,0));
+ mStorage.push_back(Rect(0, 0));
}
void Region::set(const Rect& r)
{
mStorage.clear();
- mStorage.add(r);
+ mStorage.push_back(r);
}
void Region::set(int32_t w, int32_t h)
{
mStorage.clear();
- mStorage.add(Rect(w, h));
+ mStorage.push_back(Rect(w, h));
}
void Region::set(uint32_t w, uint32_t h)
{
mStorage.clear();
- mStorage.add(Rect(w, h));
+ mStorage.push_back(Rect(w, h));
}
bool Region::isTriviallyEqual(const Region& region) const {
@@ -299,13 +307,16 @@
void Region::addRectUnchecked(int l, int t, int r, int b)
{
Rect rect(l,t,r,b);
- size_t where = mStorage.size() - 1;
- mStorage.insertAt(rect, where, 1);
+ mStorage.insert(mStorage.end() - 1, rect);
}
// ----------------------------------------------------------------------------
Region& Region::orSelf(const Rect& r) {
+ if (isEmpty()) {
+ set(r);
+ return *this;
+ }
return operationSelf(r, op_or);
}
Region& Region::xorSelf(const Rect& r) {
@@ -326,6 +337,10 @@
// ----------------------------------------------------------------------------
Region& Region::orSelf(const Region& rhs) {
+ if (isEmpty()) {
+ *this = rhs;
+ return *this;
+ }
return operationSelf(rhs, op_or);
}
Region& Region::xorSelf(const Region& rhs) {
@@ -350,7 +365,7 @@
Region& Region::scaleSelf(float sx, float sy) {
size_t count = mStorage.size();
- Rect* rects = mStorage.editArray();
+ Rect* rects = mStorage.data();
while (count) {
rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
@@ -455,10 +470,10 @@
class Region::rasterizer : public region_operator<Rect>::region_rasterizer
{
Rect bounds;
- Vector<Rect>& storage;
+ FatVector<Rect>& storage;
Rect* head;
Rect* tail;
- Vector<Rect> span;
+ FatVector<Rect> span;
Rect* cur;
public:
explicit rasterizer(Region& reg)
@@ -485,8 +500,8 @@
flushSpan();
}
if (storage.size()) {
- bounds.top = storage.itemAt(0).top;
- bounds.bottom = storage.top().bottom;
+ bounds.top = storage.front().top;
+ bounds.bottom = storage.back().bottom;
if (storage.size() == 1) {
storage.clear();
}
@@ -494,7 +509,7 @@
bounds.left = 0;
bounds.right = 0;
}
- storage.add(bounds);
+ storage.push_back(bounds);
}
void Region::rasterizer::operator()(const Rect& rect)
@@ -509,15 +524,15 @@
return;
}
}
- span.add(rect);
- cur = span.editArray() + (span.size() - 1);
+ span.push_back(rect);
+ cur = span.data() + (span.size() - 1);
}
void Region::rasterizer::flushSpan()
{
bool merge = false;
if (tail-head == ssize_t(span.size())) {
- Rect const* p = span.editArray();
+ Rect const* p = span.data();
Rect const* q = head;
if (p->top == q->bottom) {
merge = true;
@@ -532,17 +547,17 @@
}
}
if (merge) {
- const int bottom = span[0].bottom;
+ const int bottom = span.front().bottom;
Rect* r = head;
while (r != tail) {
r->bottom = bottom;
r++;
}
} else {
- bounds.left = min(span.itemAt(0).left, bounds.left);
- bounds.right = max(span.top().right, bounds.right);
- storage.appendVector(span);
- tail = storage.editArray() + storage.size();
+ bounds.left = min(span.front().left, bounds.left);
+ bounds.right = max(span.back().right, bounds.right);
+ storage.insert(storage.end(), span.begin(), span.end());
+ tail = storage.data() + storage.size();
head = tail - span.size();
}
span.clear();
@@ -550,7 +565,7 @@
bool Region::validate(const Region& reg, const char* name, bool silent)
{
- if (reg.mStorage.isEmpty()) {
+ if (reg.mStorage.empty()) {
ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name);
// return immediately as the code below assumes mStorage is non-empty
return false;
@@ -689,9 +704,8 @@
}
sk_dst.op(sk_lhs, sk_rhs, sk_op);
- if (sk_dst.isEmpty() && dst.isEmpty())
- return;
-
+ if (sk_dst.empty() && dst.empty()) return;
+
bool same = true;
Region::const_iterator head = dst.begin();
Region::const_iterator const tail = dst.end();
@@ -786,7 +800,7 @@
validate(reg, "translate (before)");
#endif
size_t count = reg.mStorage.size();
- Rect* rects = reg.mStorage.editArray();
+ Rect* rects = reg.mStorage.data();
while (count) {
rects->offsetBy(dx, dy);
rects++;
@@ -866,24 +880,25 @@
ALOGE("Region::unflatten() failed, invalid region");
return BAD_VALUE;
}
- mStorage = result.mStorage;
+ mStorage.clear();
+ mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end());
return NO_ERROR;
}
// ----------------------------------------------------------------------------
Region::const_iterator Region::begin() const {
- return mStorage.array();
+ return mStorage.data();
}
Region::const_iterator Region::end() const {
// Workaround for b/77643177
// mStorage should never be empty, but somehow it is and it's causing
// an abort in ubsan
- if (mStorage.isEmpty()) return mStorage.array();
+ if (mStorage.empty()) return mStorage.data();
size_t numRects = isRect() ? 1 : mStorage.size() - 1;
- return mStorage.array() + numRects;
+ return mStorage.data() + numRects;
}
Rect const* Region::getArray(size_t* count) const {
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
deleted file mode 100644
index 5ba189c..0000000
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_BUFFER_HUB_BUFFER_H_
-#define ANDROID_BUFFER_HUB_BUFFER_H_
-
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
-#include <android/hardware_buffer.h>
-#include <cutils/native_handle.h>
-#include <ui/BufferHubDefs.h>
-#include <ui/BufferHubEventFd.h>
-#include <ui/BufferHubMetadata.h>
-#include <utils/NativeHandle.h>
-
-namespace android {
-
-class BufferHubBuffer {
-public:
- // Allocates a standalone BufferHubBuffer.
- static std::unique_ptr<BufferHubBuffer> create(uint32_t width, uint32_t height,
- uint32_t layerCount, uint32_t format,
- uint64_t usage, size_t userMetadataSize);
-
- // Imports the given token to a BufferHubBuffer. Not taking ownership of the token.
- static std::unique_ptr<BufferHubBuffer> import(const sp<NativeHandle>& token);
-
- BufferHubBuffer(const BufferHubBuffer&) = delete;
- void operator=(const BufferHubBuffer&) = delete;
-
- virtual ~BufferHubBuffer();
-
- // Gets ID of the buffer client. All BufferHubBuffer clients derived from the same buffer in
- // BufferHub share the same buffer id.
- int id() const { return mId; }
-
- // Returns the buffer description, which is guaranteed to be faithful values from BufferHub.
- const AHardwareBuffer_Desc& desc() const { return mBufferDesc; }
-
- // Duplicate the underlying Gralloc buffer handle. Caller is responsible to free the handle
- // after use.
- native_handle_t* duplicateHandle() {
- return native_handle_clone(mBufferHandle.getNativeHandle());
- }
-
- const BufferHubEventFd& eventFd() const { return mEventFd; }
-
- // Returns the current value of MetadataHeader::bufferState.
- uint32_t bufferState() const { return mBufferState->load(std::memory_order_acquire); }
-
- // A state mask which is unique to a buffer hub client among all its siblings sharing the same
- // concrete graphic buffer.
- uint32_t clientStateMask() const { return mClientStateMask; }
-
- size_t userMetadataSize() const { return mMetadata.userMetadataSize(); }
-
- // Returns true if the BufferClient is still alive.
- bool isConnected() const { return mBufferClient->ping().isOk(); }
-
- // Returns true if the buffer is valid: non-null buffer handle, valid id, valid client bit mask,
- // valid metadata and valid buffer client
- bool isValid() const;
-
- // Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
- // gained.
- // The buffer can be gained as long as there is no other client in acquired or gained state.
- int gain();
-
- // Posts the gained buffer for other buffer clients to use the buffer.
- // The buffer can be posted iff the buffer state for this client is gained.
- // After posting the buffer, this client is put to released state and does not have access to
- // the buffer for this cycle of the usage of the buffer.
- int post();
-
- // Acquires the buffer for shared read permission.
- // The buffer can be acquired iff the buffer state for this client is posted.
- int acquire();
-
- // Releases the buffer.
- // The buffer can be released from any buffer state.
- // After releasing the buffer, this client no longer have any permissions to the buffer for the
- // current cycle of the usage of the buffer.
- int release();
-
- // Returns whether the buffer is released by all active clients or not.
- bool isReleased() const;
-
- // Creates a token that stands for this BufferHubBuffer client and could be used for Import to
- // create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
- // gralloc buffer and ashmem region for metadata. Not taking ownership of the token.
- // Returns a valid token on success, nullptr on failure.
- sp<NativeHandle> duplicate();
-
-private:
- BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
- uint64_t usage, size_t userMetadataSize);
-
- BufferHubBuffer(const sp<NativeHandle>& token);
-
- int initWithBufferTraits(const frameworks::bufferhub::V1_0::BufferTraits& bufferTraits);
-
- // Global id for the buffer that is consistent across processes.
- int mId = 0;
-
- // Client state mask of this BufferHubBuffer object. It is unique amoung all
- // clients/users of the buffer.
- uint32_t mClientStateMask = 0U;
-
- // Stores ground truth of the buffer.
- AHardwareBuffer_Desc mBufferDesc;
-
- // Wraps the gralloc buffer handle of this buffer.
- hardware::hidl_handle mBufferHandle;
-
- // Event fd used for signalling buffer state changes. Shared by all clients of the same buffer.
- BufferHubEventFd mEventFd;
-
- // An ashmem-based metadata object. The same shared memory are mapped to the
- // bufferhubd daemon and all buffer clients.
- BufferHubMetadata mMetadata;
- // Shortcuts to the atomics inside the header of mMetadata.
- std::atomic<uint32_t>* mBufferState = nullptr;
- std::atomic<uint32_t>* mFenceState = nullptr;
- std::atomic<uint32_t>* mActiveClientsBitMask = nullptr;
-
- // HwBinder backend
- sp<frameworks::bufferhub::V1_0::IBufferClient> mBufferClient;
-};
-
-} // namespace android
-
-#endif // ANDROID_BUFFER_HUB_BUFFER_H_
diff --git a/libs/ui/include/ui/BufferHubEventFd.h b/libs/ui/include/ui/BufferHubEventFd.h
deleted file mode 100644
index 8772304..0000000
--- a/libs/ui/include/ui/BufferHubEventFd.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_BUFFER_HUB_EVENT_FD_H_
-#define ANDROID_BUFFER_HUB_EVENT_FD_H_
-
-#include <android-base/unique_fd.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class BufferHubEventFd {
-public:
- /**
- * Constructs a valid event fd.
- */
- BufferHubEventFd();
-
- /**
- * Constructs from a valid event fd. Caller is responsible for the validity of the fd. Takes
- * ownership.
- */
- BufferHubEventFd(int fd);
-
- /**
- * Returns whether this BufferHubEventFd holds a valid event_fd.
- */
- bool isValid() const { return get() >= 0; }
-
- /**
- * Returns the fd number of the BufferHubEventFd object. Note that there is no ownership
- * transfer.
- */
- int get() const { return mFd.get(); }
-
- /**
- * Signals the eventfd.
- */
- status_t signal() const;
-
- /**
- * Clears the signal from this eventfd if it is signaled.
- */
- status_t clear() const;
-
-private:
- base::unique_fd mFd;
-};
-
-} // namespace android
-
-#endif // ANDROID_BUFFER_HUB_EVENT_FD_H_
diff --git a/libs/ui/include/ui/BufferHubMetadata.h b/libs/ui/include/ui/BufferHubMetadata.h
deleted file mode 100644
index 3482507..0000000
--- a/libs/ui/include/ui/BufferHubMetadata.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_BUFFER_HUB_METADATA_H_
-#define ANDROID_BUFFER_HUB_METADATA_H_
-
-#include <android-base/unique_fd.h>
-#include <ui/BufferHubDefs.h>
-
-namespace android {
-
-namespace {
-using base::unique_fd;
-} // namespace
-
-class BufferHubMetadata {
-public:
- // Creates a new BufferHubMetadata backed by an ashmem region.
- //
- // @param userMetadataSize Size in bytes of the user defined metadata. The entire metadata
- // shared memory region to be allocated is the size of canonical
- // BufferHubDefs::MetadataHeader plus userMetadataSize.
- static BufferHubMetadata create(size_t userMetadataSize);
-
- // Imports an existing BufferHubMetadata from an ashmem FD.
- //
- // @param ashmemFd Ashmem file descriptor representing an ashmem region.
- static BufferHubMetadata import(unique_fd ashmemFd);
-
- BufferHubMetadata() = default;
-
- BufferHubMetadata(BufferHubMetadata&& other) { *this = std::move(other); }
-
- ~BufferHubMetadata();
-
- BufferHubMetadata& operator=(BufferHubMetadata&& other) {
- if (this != &other) {
- mUserMetadataSize = other.mUserMetadataSize;
- other.mUserMetadataSize = 0;
-
- mAshmemFd = std::move(other.mAshmemFd);
-
- // The old raw mMetadataHeader pointer must be cleared, otherwise the destructor will
- // automatically mummap() the shared memory.
- mMetadataHeader = other.mMetadataHeader;
- other.mMetadataHeader = nullptr;
- }
- return *this;
- }
-
- // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem fd and the ashmem
- // has been mapped into virtual address space.
- bool isValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; }
-
- size_t userMetadataSize() const { return mUserMetadataSize; }
- size_t metadataSize() const { return mUserMetadataSize + BufferHubDefs::kMetadataHeaderSize; }
-
- const unique_fd& ashmemFd() const { return mAshmemFd; }
- BufferHubDefs::MetadataHeader* metadataHeader() { return mMetadataHeader; }
-
-private:
- BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd,
- BufferHubDefs::MetadataHeader* metadataHeader);
-
- BufferHubMetadata(const BufferHubMetadata&) = delete;
- void operator=(const BufferHubMetadata&) = delete;
-
- size_t mUserMetadataSize = 0;
- unique_fd mAshmemFd;
- BufferHubDefs::MetadataHeader* mMetadataHeader = nullptr;
-};
-
-} // namespace android
-
-#endif // ANDROID_BUFFER_HUB_METADATA_H_
diff --git a/libs/ui/include/ui/DeviceProductInfo.h b/libs/ui/include/ui/DeviceProductInfo.h
index c396e73..af00342 100644
--- a/libs/ui/include/ui/DeviceProductInfo.h
+++ b/libs/ui/include/ui/DeviceProductInfo.h
@@ -31,6 +31,10 @@
// product information about the intermediate device.
struct DeviceProductInfo {
static constexpr size_t TEXT_BUFFER_SIZE = 20;
+ static constexpr size_t RELATIVE_ADDRESS_SIZE = 4;
+
+ using RelativeAddress = std::array<uint8_t, RELATIVE_ADDRESS_SIZE>;
+ static constexpr RelativeAddress NO_RELATIVE_ADDRESS = {0xff, 0xff, 0xff, 0xff};
struct ModelYear {
uint32_t year;
@@ -54,6 +58,11 @@
using ManufactureOrModelDate = std::variant<ModelYear, ManufactureYear, ManufactureWeekAndYear>;
ManufactureOrModelDate manufactureOrModelDate;
+
+ // Relative address in the display network. Unavailable address is indicated
+ // by all elements equal to 255.
+ // For example, for HDMI connected device this will be the physical address.
+ RelativeAddress relativeAddress;
};
} // namespace android
diff --git a/libs/ui/include/ui/FatVector.h b/libs/ui/include/ui/FatVector.h
new file mode 100644
index 0000000..25fe3a0
--- /dev/null
+++ b/libs/ui/include/ui/FatVector.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019, 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.
+ */
+
+#ifndef ANDROID_REGION_FAT_VECTOR_H
+#define ANDROID_REGION_FAT_VECTOR_H
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <type_traits>
+
+#include <vector>
+
+namespace android {
+
+template <typename T, size_t SIZE = 4>
+class InlineStdAllocator {
+public:
+ struct Allocation {
+ private:
+ Allocation(const Allocation&) = delete;
+ void operator=(const Allocation&) = delete;
+
+ public:
+ Allocation() {}
+ // char array instead of T array, so memory is uninitialized, with no destructors run
+ char array[sizeof(T) * SIZE];
+ bool inUse = false;
+ };
+
+ typedef T value_type; // needed to implement std::allocator
+ typedef T* pointer; // needed to implement std::allocator
+
+ explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
+ InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
+ ~InlineStdAllocator() {}
+
+ T* allocate(size_t num, const void* = 0) {
+ if (!mAllocation.inUse && num <= SIZE) {
+ mAllocation.inUse = true;
+ return static_cast<T*>(static_cast<void*>(mAllocation.array));
+ } else {
+ return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T))));
+ }
+ }
+
+ void deallocate(pointer p, size_t) {
+ if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) {
+ mAllocation.inUse = false;
+ } else {
+ // 'free' instead of delete here - destruction handled separately
+ free(p);
+ }
+ }
+ Allocation& mAllocation;
+};
+
+/**
+ * std::vector with SIZE elements preallocated into an internal buffer.
+ *
+ * Useful for avoiding the cost of malloc in cases where only SIZE or
+ * fewer elements are needed in the common case.
+ */
+template <typename T, size_t SIZE = 4>
+class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
+public:
+ FatVector()
+ : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) {
+ this->reserve(SIZE);
+ }
+
+ explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
+
+private:
+ typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
+};
+
+} // namespace android
+
+#endif // ANDROID_REGION_FAT_VECTOR_H
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index c195342..013505a 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -38,10 +38,6 @@
namespace android {
-#ifndef LIBUI_IN_VNDK
-class BufferHubBuffer;
-#endif // LIBUI_IN_VNDK
-
class GraphicBufferMapper;
using GraphicBufferDeathCallback = std::function<void(void* /*context*/, uint64_t bufferId)>;
@@ -147,11 +143,6 @@
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inUsage, std::string requestorName = "<Unknown>");
-#ifndef LIBUI_IN_VNDK
- // Create a GraphicBuffer from an existing BufferHubBuffer.
- GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer);
-#endif // LIBUI_IN_VNDK
-
// return status
status_t initCheck() const;
@@ -163,7 +154,6 @@
uint32_t getLayerCount() const { return static_cast<uint32_t>(layerCount); }
Rect getBounds() const { return Rect(width, height); }
uint64_t getId() const { return mId; }
- int32_t getBufferId() const { return mBufferId; }
uint32_t getGenerationNumber() const { return mGenerationNumber; }
void setGenerationNumber(uint32_t generation) {
@@ -225,11 +215,6 @@
void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context);
-#ifndef LIBUI_IN_VNDK
- // Returns whether this GraphicBuffer is backed by BufferHubBuffer.
- bool isBufferHubBuffer() const;
-#endif // LIBUI_IN_VNDK
-
private:
~GraphicBuffer();
@@ -275,12 +260,6 @@
uint64_t mId;
- // System unique buffer ID. Note that this is different from mId, which is process unique. For
- // GraphicBuffer backed by BufferHub, the mBufferId is a system unique identifier that stays the
- // same cross process for the same chunck of underlying memory. Also note that this only applies
- // to GraphicBuffers that are backed by BufferHub.
- int32_t mBufferId = -1;
-
// Stores the generation number of this buffer. If this number does not
// match the BufferQueue's internal generation number (set through
// IGBP::setGenerationNumber), attempts to attach the buffer will fail.
@@ -299,22 +278,6 @@
// and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer.
std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>>
mDeathCallbacks;
-
-#ifndef LIBUI_IN_VNDK
- // Flatten this GraphicBuffer object if backed by BufferHubBuffer.
- status_t flattenBufferHubBuffer(void*& buffer, size_t& size) const;
-
- // Unflatten into BufferHubBuffer backed GraphicBuffer.
- // Unflatten will fail if the original GraphicBuffer object is destructed. For instance, a
- // GraphicBuffer backed by BufferHubBuffer_1 flatten in process/thread A, transport the token
- // to process/thread B through a socket, BufferHubBuffer_1 dies and bufferhub invalidated the
- // token. Race condition occurs between the invalidation of the token in bufferhub process and
- // process/thread B trying to unflatten and import the buffer with that token.
- status_t unflattenBufferHubBuffer(void const*& buffer, size_t& size);
-
- // Stores a BufferHubBuffer that handles buffer signaling, identification.
- std::unique_ptr<BufferHubBuffer> mBufferHubBuffer;
-#endif // LIBUI_IN_VNDK
};
}; // namespace android
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 2db3b10..6bb7b8d 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -21,13 +21,13 @@
#include <sys/types.h>
#include <ostream>
-#include <utils/Vector.h>
-
#include <ui/Rect.h>
#include <utils/Flattenable.h>
#include <android-base/macros.h>
+#include "FatVector.h"
+
#include <string>
namespace android {
@@ -180,7 +180,7 @@
// with an extra Rect as the last element which is set to the
// bounds of the region. However, if the region is
// a simple Rect then mStorage contains only that rect.
- Vector<Rect> mStorage;
+ FatVector<Rect> mStorage;
};
@@ -235,4 +235,3 @@
}; // namespace android
#endif // ANDROID_UI_REGION_H
-
diff --git a/libs/ui/include_vndk/ui/FatVector.h b/libs/ui/include_vndk/ui/FatVector.h
new file mode 120000
index 0000000..bf30166
--- /dev/null
+++ b/libs/ui/include_vndk/ui/FatVector.h
@@ -0,0 +1 @@
+../../include/ui/FatVector.h
\ No newline at end of file
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 605c5a9..b53342c 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -31,7 +31,6 @@
cc_test {
name: "GraphicBufferAllocator_test",
header_libs: [
- "libdvr_headers",
"libnativewindow_headers",
],
static_libs: [
@@ -52,11 +51,9 @@
cc_test {
name: "GraphicBuffer_test",
header_libs: [
- "libdvr_headers",
"libnativewindow_headers",
],
shared_libs: [
- "android.frameworks.bufferhub@1.0",
"libcutils",
"libhidlbase",
"libui",
@@ -71,11 +68,7 @@
name: "GraphicBufferOverBinder_test",
srcs: ["GraphicBufferOverBinder_test.cpp"],
cflags: ["-Wall", "-Werror"],
- header_libs: [
- "libdvr_headers",
- ],
shared_libs: [
- "android.frameworks.bufferhub@1.0",
"libbinder",
"libgui",
"liblog",
@@ -85,31 +78,6 @@
}
cc_test {
- name: "BufferHub_test",
- header_libs: [
- "libdvr_headers",
- "libnativewindow_headers",
- ],
- static_libs: [
- "libgmock",
- ],
- shared_libs: [
- "android.frameworks.bufferhub@1.0",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libui",
- "libutils"
- ],
- srcs: [
- "BufferHubBuffer_test.cpp",
- "BufferHubEventFd_test.cpp",
- "BufferHubMetadata_test.cpp",
- ],
- cflags: ["-Wall", "-Werror"],
-}
-
-cc_test {
name: "Size_test",
test_suites: ["device-tests"],
shared_libs: ["libui"],
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
deleted file mode 100644
index 0c73a72..0000000
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#define LOG_TAG "BufferHubBufferTest"
-
-#include <errno.h>
-#include <sys/epoll.h>
-
-#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
-#include <android/hardware_buffer.h>
-#include <cutils/native_handle.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <hidl/ServiceManagement.h>
-#include <hwbinder/IPCThreadState.h>
-#include <ui/BufferHubBuffer.h>
-#include <ui/BufferHubEventFd.h>
-
-namespace android {
-
-namespace {
-
-using ::android::BufferHubDefs::isAnyClientAcquired;
-using ::android::BufferHubDefs::isAnyClientGained;
-using ::android::BufferHubDefs::isAnyClientPosted;
-using ::android::BufferHubDefs::isClientAcquired;
-using ::android::BufferHubDefs::isClientGained;
-using ::android::BufferHubDefs::isClientPosted;
-using ::android::BufferHubDefs::isClientReleased;
-using ::android::BufferHubDefs::kMetadataHeaderSize;
-using ::android::frameworks::bufferhub::V1_0::IBufferHub;
-using ::testing::IsNull;
-using ::testing::NotNull;
-
-const int kWidth = 640;
-const int kHeight = 480;
-const int kLayerCount = 1;
-const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-const int kUsage = 0;
-const AHardwareBuffer_Desc kDesc = {kWidth, kHeight, kLayerCount, kFormat,
- kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
-const size_t kUserMetadataSize = 1;
-
-class BufferHubBufferTest : public ::testing::Test {
-protected:
- void SetUp() override {
- android::hardware::ProcessState::self()->startThreadPool();
-
- if (!BufferHubServiceRunning()) {
- // TODO(b/112940221): Enforce the test cross all devices once BufferHub lands in Android
- // R for all Android varieties.
- GTEST_SKIP() << "Skip test as the BufferHub service is not running.";
- }
- }
-
- bool BufferHubServiceRunning() {
- sp<IBufferHub> bufferhub = IBufferHub::getService();
- return bufferhub.get() != nullptr;
- }
-};
-
-bool cmpAHardwareBufferDesc(const AHardwareBuffer_Desc& desc, const AHardwareBuffer_Desc& other) {
- // Not comparing stride because it's unknown before allocation
- return desc.format == other.format && desc.height == other.height &&
- desc.layers == other.layers && desc.usage == other.usage && desc.width == other.width;
-}
-
-class BufferHubBufferStateTransitionTest : public BufferHubBufferTest {
-protected:
- void SetUp() override {
- BufferHubBufferTest::SetUp();
-
- if (IsSkipped()) {
- // If the base class' SetUp() stated the test should be skipped, we should short
- // circuit this sub-class' logic.
- return;
- }
-
- CreateTwoClientsOfABuffer();
- }
-
- std::unique_ptr<BufferHubBuffer> b1;
- uint32_t b1ClientMask = 0U;
- std::unique_ptr<BufferHubBuffer> b2;
- uint32_t b2ClientMask = 0U;
-
-private:
- // Creates b1 and b2 as the clients of the same buffer for testing.
- void CreateTwoClientsOfABuffer();
-};
-
-void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
- b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_THAT(b1, NotNull());
- b1ClientMask = b1->clientStateMask();
- ASSERT_NE(b1ClientMask, 0U);
-
- sp<NativeHandle> token = b1->duplicate();
- ASSERT_THAT(token, NotNull());
-
- b2 = BufferHubBuffer::import(token);
- ASSERT_THAT(b2, NotNull());
-
- b2ClientMask = b2->clientStateMask();
- ASSERT_NE(b2ClientMask, 0U);
- ASSERT_NE(b2ClientMask, b1ClientMask);
-}
-
-TEST_F(BufferHubBufferTest, CreateBufferFails) {
- // Buffer Creation will fail: BLOB format requires height to be 1.
- auto b1 = BufferHubBuffer::create(kWidth, /*height=*/2, kLayerCount,
- /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize);
-
- EXPECT_THAT(b1, IsNull());
-
- // Buffer Creation will fail: user metadata size too large.
- auto b2 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- /*userMetadataSize=*/std::numeric_limits<size_t>::max());
-
- EXPECT_THAT(b2, IsNull());
-
- // Buffer Creation will fail: user metadata size too large.
- const size_t userMetadataSize = std::numeric_limits<size_t>::max() - kMetadataHeaderSize;
- auto b3 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- userMetadataSize);
-
- EXPECT_THAT(b3, IsNull());
-}
-
-TEST_F(BufferHubBufferTest, CreateBuffer) {
- auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- kUserMetadataSize);
- ASSERT_THAT(b1, NotNull());
- EXPECT_TRUE(b1->isConnected());
- EXPECT_TRUE(b1->isValid());
- EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc));
- EXPECT_EQ(b1->userMetadataSize(), kUserMetadataSize);
-}
-
-TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) {
- auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- kUserMetadataSize);
- ASSERT_THAT(b1, NotNull());
- EXPECT_TRUE(b1->isValid());
-
- sp<NativeHandle> token = b1->duplicate();
- ASSERT_THAT(token, NotNull());
-
- // The detached buffer should still be valid.
- EXPECT_TRUE(b1->isConnected());
- EXPECT_TRUE(b1->isValid());
-
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
-
- ASSERT_THAT(b2, NotNull());
- EXPECT_TRUE(b2->isValid());
-
- EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc()));
- EXPECT_EQ(b1->userMetadataSize(), b2->userMetadataSize());
-
- // These two buffer instances are based on the same physical buffer under the
- // hood, so they should share the same id.
- EXPECT_EQ(b1->id(), b2->id());
- // We use clientStateMask() to tell those two instances apart.
- EXPECT_NE(b1->clientStateMask(), b2->clientStateMask());
-
- // Both buffer instances should be in released state currently.
- EXPECT_TRUE(b1->isReleased());
- EXPECT_TRUE(b2->isReleased());
-
- // The event fd should behave like duped event fds.
- const BufferHubEventFd& eventFd1 = b1->eventFd();
- ASSERT_GE(eventFd1.get(), 0);
- const BufferHubEventFd& eventFd2 = b2->eventFd();
- ASSERT_GE(eventFd2.get(), 0);
-
- base::unique_fd epollFd(epoll_create(64));
- ASSERT_GE(epollFd.get(), 0);
-
- // Add eventFd1 to epoll set, and signal eventFd2.
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e), 0) << strerror(errno);
-
- std::array<epoll_event, 1> events;
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- eventFd2.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- eventFd2.signal();
- eventFd2.clear();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
- auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- kUserMetadataSize);
- ASSERT_THAT(b1, NotNull());
- EXPECT_TRUE(b1->isValid());
-
- sp<NativeHandle> token = b1->duplicate();
- ASSERT_THAT(token, NotNull());
-
- // Explicitly destroy b1. Backend buffer should be freed and token becomes invalid
- b1.reset();
-
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
-
- // Import should fail with INVALID_TOKEN
- EXPECT_THAT(b2, IsNull());
-}
-
-// nullptr must not crash the service
-TEST_F(BufferHubBufferTest, ImportNullToken) {
- auto b1 = BufferHubBuffer::import(nullptr);
- EXPECT_THAT(b1, IsNull());
-}
-
-TEST_F(BufferHubBufferTest, ImportInvalidToken) {
- native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1);
- token->data[0] = 0;
-
- sp<NativeHandle> tokenHandle = NativeHandle::create(token, /*ownHandle=*/true);
- auto b1 = BufferHubBuffer::import(tokenHandle);
-
- EXPECT_THAT(b1, IsNull());
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
- ASSERT_TRUE(b1->isReleased());
-
- // Successful gaining the buffer should change the buffer state bit of b1 to
- // gained state, other client state bits to released state.
- EXPECT_EQ(b1->gain(), 0);
- EXPECT_TRUE(isClientGained(b1->bufferState(), b1ClientMask));
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromGainedState) {
- ASSERT_EQ(b1->gain(), 0);
- auto currentBufferState = b1->bufferState();
- ASSERT_TRUE(isClientGained(currentBufferState, b1ClientMask));
-
- // Gaining from gained state by the same client should not return error.
- EXPECT_EQ(b1->gain(), 0);
-
- // Gaining from gained state by another client should return error.
- EXPECT_EQ(b2->gain(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromAcquiredState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_EQ(b2->acquire(), 0);
- ASSERT_TRUE(isAnyClientAcquired(b1->bufferState()));
-
- // Gaining from acquired state should fail.
- EXPECT_EQ(b1->gain(), -EBUSY);
- EXPECT_EQ(b2->gain(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromOtherClientInPostedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
-
- // Gaining a buffer who has other posted client should succeed.
- EXPECT_EQ(b1->gain(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromSelfInPostedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
-
- // A posted client should be able to gain the buffer when there is no other clients in
- // acquired state.
- EXPECT_EQ(b2->gain(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromOtherInGainedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask));
-
- EXPECT_EQ(b2->post(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromSelfInGainedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask));
-
- EXPECT_EQ(b1->post(), 0);
- auto currentBufferState = b1->bufferState();
- EXPECT_TRUE(isClientReleased(currentBufferState, b1ClientMask));
- EXPECT_TRUE(isClientPosted(currentBufferState, b2ClientMask));
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromPostedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
-
- // Post from posted state should fail.
- EXPECT_EQ(b1->post(), -EBUSY);
- EXPECT_EQ(b2->post(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromAcquiredState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_EQ(b2->acquire(), 0);
- ASSERT_TRUE(isAnyClientAcquired(b1->bufferState()));
-
- // Posting from acquired state should fail.
- EXPECT_EQ(b1->post(), -EBUSY);
- EXPECT_EQ(b2->post(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromReleasedState) {
- ASSERT_TRUE(b1->isReleased());
-
- // Posting from released state should fail.
- EXPECT_EQ(b1->post(), -EBUSY);
- EXPECT_EQ(b2->post(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInPostedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask));
-
- // Acquire from posted state should pass.
- EXPECT_EQ(b2->acquire(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromOtherInPostedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask));
-
- // Acquire from released state should fail, although there are other clients
- // in posted state.
- EXPECT_EQ(b1->acquire(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInAcquiredState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_EQ(b2->acquire(), 0);
- auto currentBufferState = b1->bufferState();
- ASSERT_TRUE(isClientAcquired(currentBufferState, b2ClientMask));
-
- // Acquiring from acquired state by the same client should not error out.
- EXPECT_EQ(b2->acquire(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromReleasedState) {
- ASSERT_TRUE(b1->isReleased());
-
- // Acquiring form released state should fail.
- EXPECT_EQ(b1->acquire(), -EBUSY);
- EXPECT_EQ(b2->acquire(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromGainedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_TRUE(isAnyClientGained(b1->bufferState()));
-
- // Acquiring from gained state should fail.
- EXPECT_EQ(b1->acquire(), -EBUSY);
- EXPECT_EQ(b2->acquire(), -EBUSY);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInReleasedState) {
- ASSERT_TRUE(b1->isReleased());
-
- EXPECT_EQ(b1->release(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInGainedState) {
- ASSERT_TRUE(b1->isReleased());
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_TRUE(isAnyClientGained(b1->bufferState()));
-
- EXPECT_EQ(b1->release(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInPostedState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
-
- EXPECT_EQ(b2->release(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInAcquiredState) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_EQ(b2->acquire(), 0);
- ASSERT_TRUE(isAnyClientAcquired(b1->bufferState()));
-
- EXPECT_EQ(b2->release(), 0);
-}
-
-TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) {
- // 1 producer buffer and 1 consumer buffer initialised in testcase setup.
- // Test if this set of basic operation succeed:
- // Producer post three times to the consumer, and released by consumer.
- for (int i = 0; i < 3; ++i) {
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
- ASSERT_EQ(b2->acquire(), 0);
- ASSERT_EQ(b2->release(), 0);
- }
-}
-
-TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) {
- // Create a poducer buffer and gain.
- std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- kUserMetadataSize);
- ASSERT_THAT(b1, NotNull());
- ASSERT_EQ(b1->gain(), 0);
-
- // Create a consumer of the buffer and test if the consumer can acquire the
- // buffer if producer posts.
- sp<NativeHandle> token = b1->duplicate();
- ASSERT_THAT(token, NotNull());
-
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
-
- ASSERT_THAT(b2, NotNull());
- ASSERT_NE(b1->clientStateMask(), b2->clientStateMask());
-
- ASSERT_EQ(b1->post(), 0);
- EXPECT_EQ(b2->acquire(), 0);
-}
-
-TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) {
- // Create a poducer buffer and post.
- std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
- kUserMetadataSize);
- ASSERT_EQ(b1->gain(), 0);
- ASSERT_EQ(b1->post(), 0);
-
- // Create a consumer of the buffer and test if the consumer can acquire the
- // buffer if producer posts.
- sp<NativeHandle> token = b1->duplicate();
- ASSERT_THAT(token, NotNull());
-
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
-
- ASSERT_THAT(b2, NotNull());
- ASSERT_NE(b1->clientStateMask(), b2->clientStateMask());
-
- EXPECT_EQ(b2->acquire(), 0);
-}
-
-} // namespace
-
-} // namespace android
diff --git a/libs/ui/tests/BufferHubEventFd_test.cpp b/libs/ui/tests/BufferHubEventFd_test.cpp
deleted file mode 100644
index ef1781f..0000000
--- a/libs/ui/tests/BufferHubEventFd_test.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#define LOG_TAG "BufferHubEventFdTest"
-
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-
-#include <array>
-#include <condition_variable>
-#include <mutex>
-#include <thread>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <log/log.h>
-#include <ui/BufferHubEventFd.h>
-
-namespace android {
-
-namespace {
-
-const int kTimeout = 100;
-const std::chrono::milliseconds kTimeoutMs(kTimeout);
-const int kTestRuns = 5;
-
-using ::testing::Contains;
-using BufferHubEventFdTest = ::testing::Test;
-
-} // namespace
-
-TEST_F(BufferHubEventFdTest, EventFd_testSingleEpollFd) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
-
- base::unique_fd epollFd(epoll_create(64));
- ASSERT_GE(epollFd.get(), 0);
-
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- std::array<epoll_event, 1> events;
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- eventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- // Check that it can receive consecutive signal.
- eventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- // Check that it can receive consecutive signal from a duplicated eventfd.
- BufferHubEventFd dupEventFd(dup(eventFd.get()));
- ASSERT_TRUE(dupEventFd.isValid());
- dupEventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
- dupEventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testCreateEpollFdAndAddSignaledEventFd) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
- eventFd.signal();
-
- base::unique_fd epollFd(epoll_create(64));
- ASSERT_GE(epollFd.get(), 0);
-
- // Make sure that the epoll set has not been signal yet.
- std::array<epoll_event, 1> events;
- ASSERT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- // Check that adding an signaled fd into this epoll set will trigger the epoll set.
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testAddSignaledEventFdToEpollFd) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
-
- base::unique_fd epollFd(epoll_create(64));
- ASSERT_GE(epollFd.get(), 0);
-
- eventFd.signal();
-
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- std::array<epoll_event, 1> events;
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testConsecutiveSignalsFromAEventFd) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
- base::unique_fd epollFd(epoll_create(64));
- ASSERT_GE(epollFd.get(), 0);
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- std::array<epoll_event, 1> events;
- for (int i = 0; i < kTestRuns; ++i) {
- eventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
- }
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testConsecutiveSignalsFromADuplicatedEventFd) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
- base::unique_fd epollFd(epoll_create(64));
- ASSERT_GE(epollFd.get(), 0);
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- BufferHubEventFd dupEventFd(dup(eventFd.get()));
- ASSERT_TRUE(dupEventFd.isValid());
-
- std::array<epoll_event, 1> events;
- for (int i = 0; i < kTestRuns; ++i) {
- dupEventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
- }
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testClear) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
-
- base::unique_fd epollFd(epoll_create(64));
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
-
- ASSERT_GE(epollFd.get(), 0);
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- eventFd.signal();
- eventFd.clear();
-
- std::array<epoll_event, 1> events;
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testDupEventFd) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
-
- base::unique_fd epollFd(epoll_create(64));
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
-
- ASSERT_GE(epollFd.get(), 0);
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- // Technically, the dupliated eventFd and the original eventFd are pointing
- // to the same kernel object. This test signals the duplicated eventFd but epolls the origianl
- // eventFd.
- BufferHubEventFd dupedEventFd(dup(eventFd.get()));
- ASSERT_GE(dupedEventFd.get(), 0);
-
- std::array<epoll_event, 1> events;
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- dupedEventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- dupedEventFd.signal();
-
- dupedEventFd.clear();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testTwoEpollFds) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
-
- base::unique_fd epollFd1(epoll_create(64));
- base::unique_fd epollFd2(epoll_create(64));
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
-
- ASSERT_GE(epollFd1.get(), 0);
- ASSERT_GE(epollFd2.get(), 0);
-
- // Register the same eventFd to two EpollFds.
- ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
- ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- std::array<epoll_event, 1> events;
- EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
- EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
-
- eventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 1);
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
- EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
-
- eventFd.signal();
- EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
-
- eventFd.clear();
- EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
- EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testTwoEventFds) {
- BufferHubEventFd eventFd1;
- BufferHubEventFd eventFd2;
-
- ASSERT_TRUE(eventFd1.isValid());
- ASSERT_TRUE(eventFd2.isValid());
-
- base::unique_fd epollFd(epoll_create(64));
- epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
- epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
-
- ASSERT_GE(epollFd.get(), 0);
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
-
- std::array<epoll_event, 2> events;
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- // Signal one by one.
- eventFd1.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(events[0].data.u32, e1.data.u32);
-
- eventFd2.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
- EXPECT_EQ(events[0].data.u32, e2.data.u32);
-
- // Signal both.
- eventFd1.signal();
- eventFd2.signal();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 2);
-
- uint32_t u32s[] = {events[0].data.u32, events[1].data.u32};
- EXPECT_THAT(u32s, Contains(e1.data.u32));
- EXPECT_THAT(u32s, Contains(e2.data.u32));
-
- // The epoll fd is edge triggered, so it only responds to the eventFd once.
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
-
- eventFd1.signal();
- eventFd2.signal();
- eventFd2.clear();
- EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testPollingThreadWithTwoEventFds) {
- BufferHubEventFd eventFd1;
- BufferHubEventFd eventFd2;
-
- ASSERT_TRUE(eventFd1.isValid());
- ASSERT_TRUE(eventFd2.isValid());
-
- base::unique_fd epollFd(epoll_create(64));
- epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
- epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
-
- ASSERT_GE(epollFd.get(), 0);
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
- ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
-
- int countEvent1 = 0;
- int countEvent2 = 0;
- std::atomic<bool> stop{false};
- std::mutex mx;
- std::condition_variable cv;
-
- std::thread pollingThread([&] {
- std::array<epoll_event, 2> events;
- while (true) {
- if (stop.load()) {
- break;
- }
- int ret = epoll_wait(epollFd.get(), events.data(), events.size(), kTimeout);
- ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
-
- std::lock_guard<std::mutex> lock(mx);
- for (int i = 0; i < ret; i++) {
- if (events[i].data.u32 == e1.data.u32) {
- countEvent1++;
- cv.notify_one();
- } else if (events[i].data.u32 == e2.data.u32) {
- countEvent2++;
- cv.notify_one();
- }
- }
- }
- });
-
- {
- std::unique_lock<std::mutex> lock(mx);
-
- eventFd1.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 1; }));
-
- eventFd1.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 2; }));
-
- eventFd2.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 1; }));
-
- eventFd1.clear();
- eventFd2.clear();
- EXPECT_EQ(countEvent1, 2);
- EXPECT_EQ(countEvent2, 1);
-
- eventFd1.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 3; }));
-
- eventFd2.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 2; }));
- }
-
- stop.store(true);
- pollingThread.join();
-}
-
-TEST_F(BufferHubEventFdTest, EventFd_testTwoPollingThreads) {
- BufferHubEventFd eventFd;
- ASSERT_TRUE(eventFd.isValid());
-
- base::unique_fd epollFd1(epoll_create(64));
- base::unique_fd epollFd2(epoll_create(64));
- epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
-
- ASSERT_GE(epollFd1.get(), 0);
- ASSERT_GE(epollFd2.get(), 0);
-
- // Register the same eventFd to two EpollFds.
- ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
- ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
-
- int countEpoll1 = 0;
- int countEpoll2 = 0;
- std::atomic<bool> stop{false};
- std::mutex mx;
- std::condition_variable cv;
-
- std::thread pollingThread1([&] {
- std::array<epoll_event, 1> events;
- while (!stop.load()) {
- int ret = epoll_wait(epollFd1.get(), events.data(), events.size(), kTimeout);
- ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
-
- if (ret > 0) {
- std::lock_guard<std::mutex> lock(mx);
- countEpoll1++;
- cv.notify_one();
- }
- }
- });
-
- std::thread pollingThread2([&] {
- std::array<epoll_event, 1> events;
- while (!stop.load()) {
- int ret = epoll_wait(epollFd2.get(), events.data(), events.size(), kTimeout);
- ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
-
- if (ret > 0) {
- std::lock_guard<std::mutex> lock(mx);
- countEpoll2++;
- cv.notify_one();
- }
- }
- });
-
- {
- std::unique_lock<std::mutex> lock(mx);
-
- eventFd.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 1; }));
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 1; }));
-
- eventFd.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 2; }));
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 2; }));
-
- eventFd.clear();
- EXPECT_EQ(countEpoll1, 2);
- EXPECT_EQ(countEpoll2, 2);
-
- eventFd.signal();
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 3; }));
- EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 3; }));
- }
-
- stop.store(true);
- pollingThread1.join();
- pollingThread2.join();
-}
-
-} // namespace android
diff --git a/libs/ui/tests/BufferHubMetadata_test.cpp b/libs/ui/tests/BufferHubMetadata_test.cpp
deleted file mode 100644
index eb978ca..0000000
--- a/libs/ui/tests/BufferHubMetadata_test.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2018 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 <gtest/gtest.h>
-#include <ui/BufferHubMetadata.h>
-
-namespace android {
-namespace dvr {
-
-constexpr size_t kEmptyUserMetadataSize = 0;
-
-class BufferHubMetadataTest : public ::testing::Test {};
-
-TEST_F(BufferHubMetadataTest, Create_UserMetdataSizeTooBig) {
- BufferHubMetadata m1 = BufferHubMetadata::create(std::numeric_limits<uint32_t>::max());
- EXPECT_FALSE(m1.isValid());
-}
-
-TEST_F(BufferHubMetadataTest, Create_Success) {
- BufferHubMetadata m1 = BufferHubMetadata::create(kEmptyUserMetadataSize);
- EXPECT_TRUE(m1.isValid());
- EXPECT_NE(m1.metadataHeader(), nullptr);
-}
-
-TEST_F(BufferHubMetadataTest, Import_Success) {
- BufferHubMetadata m1 = BufferHubMetadata::create(kEmptyUserMetadataSize);
- EXPECT_TRUE(m1.isValid());
- EXPECT_NE(m1.metadataHeader(), nullptr);
-
- unique_fd h2 = unique_fd(dup(m1.ashmemFd().get()));
- EXPECT_NE(h2.get(), -1);
-
- BufferHubMetadata m2 = BufferHubMetadata::import(std::move(h2));
- EXPECT_EQ(h2.get(), -1);
- EXPECT_TRUE(m1.isValid());
- BufferHubDefs::MetadataHeader* mh1 = m1.metadataHeader();
- EXPECT_NE(mh1, nullptr);
-
- // Check if the newly allocated buffer is initialized in released state (i.e.
- // state equals to 0U).
- EXPECT_TRUE(mh1->bufferState.load() == 0U);
-
- EXPECT_TRUE(m2.isValid());
- BufferHubDefs::MetadataHeader* mh2 = m2.metadataHeader();
- EXPECT_NE(mh2, nullptr);
-
- // Check if the newly allocated buffer is initialized in released state (i.e.
- // state equals to 0U).
- EXPECT_TRUE(mh2->bufferState.load() == 0U);
-}
-
-TEST_F(BufferHubMetadataTest, MoveMetadataInvalidatesOldOne) {
- BufferHubMetadata m1 = BufferHubMetadata::create(sizeof(int));
- EXPECT_TRUE(m1.isValid());
- EXPECT_NE(m1.metadataHeader(), nullptr);
- EXPECT_NE(m1.ashmemFd().get(), -1);
- EXPECT_EQ(m1.userMetadataSize(), sizeof(int));
-
- BufferHubMetadata m2 = std::move(m1);
-
- // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
- EXPECT_EQ(m1.metadataHeader(), nullptr);
- EXPECT_NE(m2.metadataHeader(), nullptr);
-
- EXPECT_EQ(m1.ashmemFd().get(), -1);
- EXPECT_NE(m2.ashmemFd().get(), -1);
-
- EXPECT_EQ(m1.userMetadataSize(), 0U);
- EXPECT_EQ(m2.userMetadataSize(), sizeof(int));
-
- BufferHubMetadata m3{std::move(m2)};
-
- // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
- EXPECT_EQ(m2.metadataHeader(), nullptr);
- EXPECT_NE(m3.metadataHeader(), nullptr);
-
- EXPECT_EQ(m2.ashmemFd().get(), -1);
- EXPECT_NE(m3.ashmemFd().get(), -1);
-
- EXPECT_EQ(m2.userMetadataSize(), 0U);
- EXPECT_EQ(m3.userMetadataSize(), sizeof(int));
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/ui/tests/GraphicBufferOverBinder_test.cpp b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
index 7c0a44a..126a945 100644
--- a/libs/ui/tests/GraphicBufferOverBinder_test.cpp
+++ b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
@@ -23,7 +23,6 @@
#include <gui/BufferQueue.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
-#include <ui/BufferHubBuffer.h>
#include <ui/GraphicBuffer.h>
#include <utils/Log.h>
@@ -37,7 +36,6 @@
static const String16 kTestServiceName = String16("GraphicBufferOverBinderTestService");
enum GraphicBufferOverBinderTestServiceCode {
GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER,
};
class GraphicBufferOverBinderTestService : public BBinder {
@@ -46,21 +44,6 @@
// GraphicBuffer
mGraphicBuffer = new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount,
kTestUsage);
- ALOGI("mGraphicBuffer id %" PRIi32, mGraphicBuffer->getBufferId());
-
- // BufferHub-backed GraphicBuffer
- std::unique_ptr<BufferHubBuffer> bufferHubBuffer =
- BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
- kTestUsage, /*userMetadataSize=*/0);
- mBufferhubBackedGraphicBuffer = new GraphicBuffer(std::move(bufferHubBuffer));
- if (!mBufferhubBackedGraphicBuffer->isBufferHubBuffer()) {
- ALOGE("Failed to back GraphicBuffer with BufferHub.");
- }
- if (bufferHubBuffer != nullptr) {
- ALOGE("Failed to move BufferHubBuffer to GraphicBuffer");
- }
- ALOGI("mBufferhubBackedGraphicBuffer id %" PRIi32,
- mBufferhubBackedGraphicBuffer->getBufferId());
}
~GraphicBufferOverBinderTestService() = default;
@@ -71,9 +54,6 @@
case GRAPHIC_BUFFER: {
return reply->write(*mGraphicBuffer);
}
- case GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER: {
- return reply->write(*mBufferhubBackedGraphicBuffer);
- }
default:
return UNKNOWN_TRANSACTION;
};
@@ -81,7 +61,6 @@
protected:
sp<GraphicBuffer> mGraphicBuffer;
- sp<GraphicBuffer> mBufferhubBackedGraphicBuffer;
};
static int runBinderServer() {
@@ -138,17 +117,6 @@
sp<GraphicBuffer> gb;
EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER), OK);
EXPECT_NE(gb, nullptr);
- EXPECT_FALSE(gb->isBufferHubBuffer());
- void* vaddr;
- EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
- EXPECT_EQ(gb->unlock(), OK);
-}
-
-TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferFromBufferHubBufferOverBinder) {
- sp<GraphicBuffer> gb;
- EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER), NO_ERROR);
- EXPECT_NE(gb, nullptr);
- EXPECT_TRUE(gb->isBufferHubBuffer());
void* vaddr;
EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
EXPECT_EQ(gb->unlock(), OK);
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index 5e0b094..19551b3 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -16,7 +16,6 @@
#define LOG_TAG "GraphicBufferTest"
-#include <ui/BufferHubBuffer.h>
#include <ui/GraphicBuffer.h>
#include <gtest/gtest.h>
@@ -27,7 +26,6 @@
constexpr uint32_t kTestWidth = 1024;
constexpr uint32_t kTestHeight = 1;
-constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB;
constexpr uint32_t kTestLayerCount = 1;
constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
@@ -68,88 +66,4 @@
ASSERT_EQ(BAD_VALUE, gb2->initCheck());
}
-TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) {
- std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
- kTestUsage, /*userMetadataSize=*/0);
- ASSERT_NE(b1, nullptr);
- EXPECT_TRUE(b1->isValid());
-
- sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
- EXPECT_TRUE(gb->isBufferHubBuffer());
-
- EXPECT_EQ(gb->getWidth(), kTestWidth);
- EXPECT_EQ(gb->getHeight(), kTestHeight);
- EXPECT_EQ(static_cast<uint32_t>(gb->getPixelFormat()), kTestFormat);
- EXPECT_EQ(gb->getUsage(), kTestUsage);
- EXPECT_EQ(gb->getLayerCount(), kTestLayerCount);
-}
-
-TEST_F(GraphicBufferTest, InvalidBufferIdForNoneBufferHubBuffer) {
- sp<GraphicBuffer> gb(
- new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount, kTestUsage));
- EXPECT_FALSE(gb->isBufferHubBuffer());
- EXPECT_EQ(gb->getBufferId(), -1);
-}
-
-TEST_F(GraphicBufferTest, BufferIdMatchesBufferHubBufferId) {
- std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
- kTestUsage, /*userMetadataSize=*/0);
- EXPECT_NE(b1, nullptr);
- EXPECT_TRUE(b1->isValid());
-
- int b1_id = b1->id();
- EXPECT_GE(b1_id, 0);
-
- sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
- EXPECT_TRUE(gb->isBufferHubBuffer());
- EXPECT_EQ(gb->getBufferId(), b1_id);
-}
-
-TEST_F(GraphicBufferTest, flattenAndUnflatten) {
- std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
- kTestUsage, /*userMetadataSize=*/0);
- ASSERT_NE(b1, nullptr);
- sp<GraphicBuffer> gb1(new GraphicBuffer(std::move(b1)));
- gb1->setGenerationNumber(42);
-
- size_t flattenedSize = gb1->getFlattenedSize();
- EXPECT_EQ(flattenedSize, 48);
- size_t fdCount = gb1->getFdCount();
- EXPECT_EQ(fdCount, 0);
-
- int data[flattenedSize];
- int fds[0];
-
- // Make copies of needed items since flatten modifies them.
- size_t flattenedSizeCopy = flattenedSize;
- size_t fdCountCopy = fdCount;
- void* dataStart = data;
- int* fdsStart = fds;
- status_t err = gb1->flatten(dataStart, flattenedSizeCopy, fdsStart, fdCountCopy);
- ASSERT_EQ(err, NO_ERROR);
- EXPECT_EQ(flattenedSizeCopy, 0);
- EXPECT_EQ(fdCountCopy, 0);
-
- size_t unflattenSize = flattenedSize;
- size_t unflattenFdCount = fdCount;
- const void* unflattenData = static_cast<const void*>(dataStart);
- const int* unflattenFdData = static_cast<const int*>(fdsStart);
-
- GraphicBuffer* gb2 = new GraphicBuffer();
- err = gb2->unflatten(unflattenData, unflattenSize, unflattenFdData, unflattenFdCount);
- ASSERT_EQ(err, NO_ERROR);
- EXPECT_TRUE(gb2->isBufferHubBuffer());
-
- EXPECT_EQ(gb2->getWidth(), kTestWidth);
- EXPECT_EQ(gb2->getHeight(), kTestHeight);
- EXPECT_EQ(static_cast<uint32_t>(gb2->getPixelFormat()), kTestFormat);
- EXPECT_EQ(gb2->getUsage(), kTestUsage);
- EXPECT_EQ(gb2->getLayerCount(), kTestLayerCount);
- EXPECT_EQ(gb1->getBufferId(), gb2->getBufferId());
- EXPECT_EQ(gb2->getGenerationNumber(), 42);
-}
-
} // namespace android
diff --git a/libs/ui/tests/Region_test.cpp b/libs/ui/tests/Region_test.cpp
index b104a46..c6b826d 100644
--- a/libs/ui/tests/Region_test.cpp
+++ b/libs/ui/tests/Region_test.cpp
@@ -152,5 +152,20 @@
}
}
+TEST_F(RegionTest, EqualsToSelf) {
+ Region touchableRegion;
+ touchableRegion.orSelf(Rect(0, 0, 100, 100));
+
+ ASSERT_TRUE(touchableRegion.contains(50, 50));
+
+ // Compiler prevents us from directly calling 'touchableRegion = touchableRegion'
+ Region& referenceTouchableRegion = touchableRegion;
+ touchableRegion = referenceTouchableRegion;
+
+ ASSERT_FALSE(touchableRegion.isEmpty());
+
+ ASSERT_TRUE(touchableRegion.contains(50, 50));
+}
+
}; // namespace android
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 23a4224..24ba830 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -2,6 +2,7 @@
name: "libpdx_headers",
export_include_dirs: ["private"],
vendor_available: true,
+ min_sdk_version: "29",
}
cc_library_static {
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index ecbfdba..9bc70ea 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -535,13 +535,13 @@
*message = Message{info};
auto* state = static_cast<MessageState*>(message->GetState());
state->request = std::move(request);
- if (request.send_len > 0 && !request.is_impulse) {
- state->request_data.resize(request.send_len);
+ if (state->request.send_len > 0 && !state->request.is_impulse) {
+ state->request_data.resize(state->request.send_len);
status = ReceiveData(channel_fd, state->request_data.data(),
state->request_data.size());
}
- if (status && request.is_impulse)
+ if (status && state->request.is_impulse)
status = ReenableEpollEvent(channel_fd);
if (!status) {
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
index 410e234..7fafd3b 100644
--- a/libs/vr/libvrflinger/tests/Android.bp
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -11,6 +11,7 @@
"libutils",
"libnativewindow",
"libpdx_default_transport",
+ "libSurfaceFlingerProp",
]
static_libs = [
@@ -32,5 +33,6 @@
"-Wall",
"-Werror",
],
+ header_libs: ["libsurfaceflinger_headers"],
name: "vrflinger_test",
}
diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
index 7075e88..efd6d1d 100644
--- a/libs/vr/libvrflinger/tests/vrflinger_test.cpp
+++ b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
@@ -1,3 +1,4 @@
+#include <SurfaceFlingerProperties.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/types.h>
#include <android/hardware_buffer.h>
@@ -147,9 +148,7 @@
// Exit immediately if the device doesn't support vr flinger. This ConfigStore
// check is the same mechanism used by surface flinger to decide if it should
// initialize vr flinger.
- bool vr_flinger_enabled =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::useVrFlinger>(
- false);
+ bool vr_flinger_enabled = android::sysprop::use_vr_flinger(false);
if (!vr_flinger_enabled) {
return;
}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index e255b9d..e8d3684 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -75,7 +75,6 @@
"bionic_libc_platform_headers",
"gl_headers",
"libsystem_headers",
- "libhardware_headers",
"libnativebase_headers",
],
export_header_lib_headers: ["gl_headers"],
@@ -101,6 +100,7 @@
"libgraphicsenv",
"libnativewindow",
"libbacktrace",
+ "libbase",
],
target: {
vendor: {
@@ -154,6 +154,7 @@
"libnativebridge_lazy",
"libnativeloader_lazy",
"libutils",
+ "libSurfaceFlingerProp",
],
static_libs: [
"libEGL_getProcAddress",
@@ -165,6 +166,7 @@
symbol_file: "libEGL.map.txt",
versions: ["29"],
},
+ header_libs: ["libsurfaceflinger_headers"],
}
cc_test {
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 74c4d7d..74fb019 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -21,7 +21,7 @@
#include <errno.h>
#include <inttypes.h>
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#include <log/log.h>
#include <chrono>
@@ -165,7 +165,8 @@
}
size_t BlobCache::getFlattenedSize() const {
- size_t size = align4(sizeof(Header) + PROPERTY_VALUE_MAX);
+ auto buildId = base::GetProperty("ro.build.id", "");
+ size_t size = align4(sizeof(Header) + buildId.size());
for (const CacheEntry& e : mCacheEntries) {
std::shared_ptr<Blob> const& keyBlob = e.getKey();
std::shared_ptr<Blob> const& valueBlob = e.getValue();
@@ -185,9 +186,9 @@
header->mBlobCacheVersion = blobCacheVersion;
header->mDeviceVersion = blobCacheDeviceVersion;
header->mNumEntries = mCacheEntries.size();
- char buildId[PROPERTY_VALUE_MAX];
- header->mBuildIdLength = property_get("ro.build.id", buildId, "");
- memcpy(header->mBuildId, buildId, header->mBuildIdLength);
+ auto buildId = base::GetProperty("ro.build.id", "");
+ header->mBuildIdLength = buildId.size();
+ memcpy(header->mBuildId, buildId.c_str(), header->mBuildIdLength);
// Write cache entries
uint8_t* byteBuffer = reinterpret_cast<uint8_t*>(buffer);
@@ -238,12 +239,11 @@
ALOGE("unflatten: bad magic number: %" PRIu32, header->mMagicNumber);
return -EINVAL;
}
- char buildId[PROPERTY_VALUE_MAX];
- int len = property_get("ro.build.id", buildId, "");
+ auto buildId = base::GetProperty("ro.build.id", "");
if (header->mBlobCacheVersion != blobCacheVersion ||
- header->mDeviceVersion != blobCacheDeviceVersion ||
- len != header->mBuildIdLength ||
- strncmp(buildId, header->mBuildId, len)) {
+ header->mDeviceVersion != blobCacheDeviceVersion ||
+ buildId.size() != header->mBuildIdLength ||
+ strncmp(buildId.c_str(), header->mBuildId, buildId.size())) {
// We treat version mismatches as an empty cache.
return 0;
}
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e19802b..d66ef2b 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -24,8 +24,8 @@
#include <dirent.h>
#include <dlfcn.h>
+#include <android-base/properties.h>
#include <android/dlext.h>
-#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Timers.h>
@@ -222,13 +222,6 @@
return cnx->dso;
}
- // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries.
- if (android::GraphicsEnv::getInstance().shouldUseAngle()) {
- cnx->shouldUseAngle = true;
- } else {
- cnx->shouldUseAngle = false;
- }
-
// Firstly, try to load ANGLE driver.
driver_t* hnd = attempt_to_load_angle(cnx);
if (!hnd) {
@@ -248,12 +241,12 @@
// i.e.:
// libGLES_${prop}.so, or:
// libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
- char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) <= 0) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
continue;
}
- hnd = attempt_to_load_system_driver(cnx, prop, true);
+ hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
if (hnd) {
break;
} else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
@@ -278,6 +271,12 @@
if (!hnd) {
android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
false, systemTime() - openTime);
+ } else {
+ // init_angle_backend will check if loaded driver is ANGLE or not,
+ // will set cnx->useAngle appropriately.
+ // Do this here so that we use ANGLE path when driver is ANGLE (e.g. loaded as native),
+ // not just loading ANGLE as option.
+ init_angle_backend(hnd->dso[0], cnx);
}
LOG_ALWAYS_FATAL_IF(!hnd,
@@ -317,14 +316,7 @@
delete hnd;
cnx->dso = nullptr;
- cnx->shouldUseAngle = false;
- cnx->angleDecided = false;
cnx->useAngle = false;
-
- if (cnx->vendorEGL) {
- dlclose(cnx->vendorEGL);
- cnx->vendorEGL = nullptr;
- }
}
void Loader::init_api(void* dso,
@@ -491,7 +483,7 @@
return dso;
}
-static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns) {
+static void* load_angle(const char* kind, android_namespace_t* ns) {
const android_dlextinfo dlextinfo = {
.flags = ANDROID_DLEXT_USE_NAMESPACE,
.library_namespace = ns,
@@ -511,69 +503,6 @@
return nullptr;
}
-static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) {
- void* so = nullptr;
-
- if ((cnx->shouldUseAngle) || android::GraphicsEnv::getInstance().shouldUseAngle()) {
- so = load_angle_from_namespace(kind, ns);
- cnx->shouldUseAngle = true;
- } else {
- cnx->shouldUseAngle = false;
- }
-
- if (so) {
- ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind,
- android::GraphicsEnv::getInstance().getAngleAppName().c_str());
- cnx->useAngle = true;
-
- char prop[PROPERTY_VALUE_MAX];
-
- property_get("debug.hwui.renderer", prop, "UNSET");
- ALOGV("Skia's renderer set to %s", prop);
-
- EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
- property_get("debug.angle.backend", prop, "0");
- switch (atoi(prop)) {
- case 1:
- ALOGV("%s: Requesting OpenGLES back-end", __FUNCTION__);
- angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
- break;
- case 2:
- ALOGV("%s: Requesting Vulkan back-end", __FUNCTION__);
- angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
- break;
- default:
- break;
- }
-
- cnx->angleBackend = angleBackendDefault;
- if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) {
- // Find and load vendor libEGL for ANGLE's GL back-end to use.
- char prop[PROPERTY_VALUE_MAX + 1];
- for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) <= 0) {
- continue;
- }
- void* dso = load_system_driver("EGL", prop, true);
- if (dso) {
- cnx->vendorEGL = dso;
- break;
- }
- }
- if (!cnx->vendorEGL) {
- cnx->vendorEGL = load_system_driver("EGL", nullptr, true);
- }
- }
- } else {
- ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
- android::GraphicsEnv::getInstance().getAngleAppName().c_str());
- cnx->useAngle = false;
- }
- cnx->angleDecided = true;
-
- return so;
-}
-
static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
ATRACE_CALL();
const android_dlextinfo dlextinfo = {
@@ -581,9 +510,9 @@
.library_namespace = ns,
};
void* so = nullptr;
- char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) <= 0) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
continue;
}
std::string name = std::string("lib") + kind + "_" + prop + ".so";
@@ -597,6 +526,11 @@
Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
ATRACE_CALL();
+
+ if (!android::GraphicsEnv::getInstance().shouldUseAngle()) {
+ return nullptr;
+ }
+
android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
if (!ns) {
return nullptr;
@@ -606,22 +540,37 @@
driver_t* hnd = nullptr;
// ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
- void* dso = load_angle("EGL", ns, cnx);
+ void* dso = load_angle("EGL", ns);
if (dso) {
initialize_api(dso, cnx, EGL);
hnd = new driver_t(dso);
- dso = load_angle("GLESv1_CM", ns, cnx);
+ dso = load_angle("GLESv1_CM", ns);
initialize_api(dso, cnx, GLESv1_CM);
hnd->set(dso, GLESv1_CM);
- dso = load_angle("GLESv2", ns, cnx);
+ dso = load_angle("GLESv2", ns);
initialize_api(dso, cnx, GLESv2);
hnd->set(dso, GLESv2);
}
return hnd;
}
+void Loader::init_angle_backend(void* dso, egl_connection_t* cnx) {
+ void* eglCreateDeviceANGLE = nullptr;
+
+ ALOGV("dso: %p", dso);
+ eglCreateDeviceANGLE = dlsym(dso, "eglCreateDeviceANGLE");
+ ALOGV("eglCreateDeviceANGLE: %p", eglCreateDeviceANGLE);
+ if (eglCreateDeviceANGLE) {
+ ALOGV("ANGLE GLES library in use");
+ cnx->useAngle = true;
+ } else {
+ ALOGV("Native GLES library in use");
+ cnx->useAngle = false;
+ }
+}
+
Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
ATRACE_CALL();
#ifndef __ANDROID_VNDK__
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 6f31ab4..7b2d7c9 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -60,6 +60,7 @@
driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
void unload_system_driver(egl_connection_t* cnx);
void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
+ void init_angle_backend(void* dso, egl_connection_t* cnx);
static __attribute__((noinline))
void init_api(void* dso,
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 0581708..43f7a07 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -16,11 +16,9 @@
#include <stdlib.h>
-#include <hardware/gralloc.h>
-
#include <EGL/egl.h>
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#include <log/log.h>
@@ -60,9 +58,7 @@
} else {
LOG_ALWAYS_FATAL(error);
}
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.callstack", value, "0");
- if (atoi(value)) {
+ if (base::GetBoolProperty("debug.egl.callstack", false)) {
CallStack::log(LOG_TAG);
}
}
@@ -226,9 +222,7 @@
pthread_mutex_unlock(&sLogPrintMutex);
if (printLog) {
ALOGE("called unimplemented OpenGL ES API");
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.callstack", value, "0");
- if (atoi(value)) {
+ if (base::GetBoolProperty("debug.egl.callstack", false)) {
CallStack::log(LOG_TAG);
}
}
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 00caff2..97dc0f1 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -16,7 +16,6 @@
#if defined(__ANDROID__)
-#include <cutils/properties.h>
#include "Loader.h"
#include "egl_angle_platform.h"
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index a58e87c..3b1cf71 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -24,13 +24,14 @@
#include <EGL/eglext_angle.h>
#include <private/EGL/display.h>
-#include <cutils/properties.h>
#include "Loader.h"
#include "egl_angle_platform.h"
#include "egl_cache.h"
#include "egl_object.h"
#include "egl_tls.h"
+#include <SurfaceFlingerProperties.h>
+#include <android-base/properties.h>
#include <android/dlext.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
@@ -72,7 +73,7 @@
}
bool needsAndroidPEglMitigation() {
- static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
+ static const int32_t vndk_version = base::GetIntProperty("ro.vndk.version", -1);
return vndk_version <= 28;
}
@@ -133,45 +134,6 @@
return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list);
}
-static bool addAnglePlatformAttributes(egl_connection_t* const cnx,
- std::vector<EGLAttrib>& attrs) {
- intptr_t vendorEGL = (intptr_t)cnx->vendorEGL;
-
- attrs.reserve(4 * 2);
-
- attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
- attrs.push_back(cnx->angleBackend);
-
- switch (cnx->angleBackend) {
- case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
- ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__);
- char prop[PROPERTY_VALUE_MAX];
- property_get("debug.angle.validation", prop, "0");
- attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
- attrs.push_back(atoi(prop));
- break;
- case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
- ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__);
- break;
- case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
- ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__);
- // NOTE: This is only valid if the backend is OpenGL
- attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
- attrs.push_back(vendorEGL);
-
- // Context virtualization is only available on GL back-end.
- // Needed to support threading with GL back-end
- attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
- attrs.push_back(EGL_FALSE);
- break;
- default:
- ALOGE("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
- break;
- }
-
- return true;
-}
-
static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
const EGLAttrib* attrib_list, EGLint* error) {
EGLDisplay dpy = EGL_NO_DISPLAY;
@@ -186,11 +148,12 @@
}
}
- if (!addAnglePlatformAttributes(cnx, attrs)) {
- ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display);
- *error = EGL_BAD_PARAMETER;
- return EGL_NO_DISPLAY;
- }
+ attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
+
+ attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
+ attrs.push_back(base::GetBoolProperty("debug.angle.validation", false));
+
attrs.push_back(EGL_NONE);
dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
@@ -361,9 +324,7 @@
// Note: CDD requires that devices supporting wide color and/or HDR color also support
// the EGL_KHR_gl_colorspace extension.
- bool wideColorBoardConfig =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(
- false);
+ bool wideColorBoardConfig = android::sysprop::has_wide_color_display(false);
// Add wide-color extensions if device can support wide-color
if (wideColorBoardConfig && hasColorSpaceSupport) {
@@ -373,8 +334,7 @@
"EGL_EXT_gl_colorspace_display_p3_passthrough ");
}
- bool hasHdrBoardConfig =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+ bool hasHdrBoardConfig = android::sysprop::has_HDR_display(false);
if (hasHdrBoardConfig && hasColorSpaceSupport) {
// hasHDRBoardConfig indicates the system is capable of supporting HDR content.
@@ -410,16 +370,8 @@
egl_cache_t::get()->initialize(this);
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.finish", value, "0");
- if (atoi(value)) {
- finishOnSwap = true;
- }
-
- property_get("debug.egl.traceGpuCompletion", value, "0");
- if (atoi(value)) {
- traceGpuCompletion = true;
- }
+ finishOnSwap = base::GetBoolProperty("debug.egl.finish", false);
+ traceGpuCompletion = base::GetBoolProperty("debug.egl.traceGpuCompletion", false);
// TODO: If device doesn't provide 1.4 or 1.5 then we'll be
// changing the behavior from the past where we always advertise
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index 44a1c0b..ea86c9a 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -18,9 +18,9 @@
#include <EGL/egl.h>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android/dlext.h>
-#include <cutils/properties.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
#include <log/log.h>
@@ -157,9 +157,7 @@
if (debug_layers.empty()) {
// Only check system properties if Java settings are empty
- char prop[PROPERTY_VALUE_MAX];
- property_get("debug.gles.layers", prop, "");
- debug_layers = prop;
+ debug_layers = base::GetProperty("debug.gles.layers", "");
}
return debug_layers;
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index c8840f9..99283be 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -23,19 +23,17 @@
#include <stdlib.h>
#include <string.h>
-#include <hardware/gralloc1.h>
-
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglext_angle.h>
-#include <android/hardware_buffer.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <android/hardware_buffer.h>
#include <graphicsenv/GraphicsEnv.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <cutils/compiler.h>
-#include <cutils/properties.h>
#include <log/log.h>
#include <condition_variable>
@@ -383,10 +381,7 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso) {
if (attrib_list) {
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.force_msaa", value, "false");
-
- if (!strcmp(value, "true")) {
+ if (base::GetBoolProperty("debug.egl.force_msaa", false)) {
size_t attribCount = 0;
EGLint attrib = attrib_list[0];
@@ -721,7 +716,7 @@
// NOTE: When using Vulkan backend, the Vulkan runtime makes all the
// native_window_* calls, so don't do them here.
- if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!cnx->useAngle) {
int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
if (result < 0) {
ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
@@ -740,14 +735,14 @@
std::vector<AttrType> strippedAttribList;
if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) {
ALOGE("error invalid colorspace: %d", colorSpace);
- if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!cnx->useAngle) {
native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
}
return EGL_NO_SURFACE;
}
attrib_list = strippedAttribList.data();
- if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!cnx->useAngle) {
int err = native_window_set_buffers_format(window, format);
if (err != 0) {
ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
@@ -779,7 +774,7 @@
}
// EGLSurface creation failed
- if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!cnx->useAngle) {
native_window_set_buffers_format(window, 0);
native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
}
@@ -1419,7 +1414,7 @@
}
}
- if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!s->cnx->useAngle) {
if (!sendSurfaceMetadata(s)) {
native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
@@ -1444,7 +1439,7 @@
androidRect.bottom = y;
androidRects.push_back(androidRect);
}
- if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
+ if (!s->cnx->useAngle) {
native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(),
androidRects.size());
}
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index aaecb62..8d118e0 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -18,7 +18,7 @@
#include <stdlib.h>
-#include <cutils/properties.h>
+#include <android-base/properties.h>
#include <log/log.h>
#include "CallStack.h"
#include "egl_platform_entries.h"
@@ -96,9 +96,7 @@
if (!quiet) {
ALOGE("%s:%d error %x (%s)",
caller, line, error, egl_strerror(error));
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.callstack", value, "0");
- if (atoi(value)) {
+ if (base::GetBoolProperty("debug.egl.callstack", false)) {
CallStack::log(LOG_TAG);
}
}
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 7bb9b59..5fbffbd 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -81,11 +81,7 @@
void* libGles2;
bool systemDriverUnloaded;
- bool shouldUseAngle; // Should we attempt to load ANGLE
- bool angleDecided; // Have we tried to load ANGLE
bool useAngle; // Was ANGLE successfully loaded
- EGLint angleBackend;
- void* vendorEGL;
};
// clang-format on
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index 8bfe517..e3912a8 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -25,6 +25,7 @@
"liblog",
"libutils",
"libnativewindow",
+ "libSurfaceFlingerProp",
],
include_dirs: [
@@ -34,5 +35,6 @@
header_libs: [
"bionic_libc_platform_headers",
+ "libsurfaceflinger_headers",
],
}
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index cca91c3..510226d 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -16,6 +16,7 @@
#include <gtest/gtest.h>
+#include <SurfaceFlingerProperties.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
@@ -52,11 +53,9 @@
#define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
-static bool hasWideColorDisplay =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+static bool hasWideColorDisplay = android::sysprop::has_wide_color_display(false);
-static bool hasHdrDisplay =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+static bool hasHdrDisplay = android::sysprop::has_HDR_display(false);
class EGLTest : public ::testing::Test {
public:
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
deleted file mode 100644
index 2bb6aef..0000000
--- a/services/bufferhub/Android.bp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (C) 2018 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.
-//
-
-cc_library_shared {
- name: "libbufferhubservice",
- cflags: [
- "-DLOG_TAG=\"libbufferhubservice\"",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- srcs: [
- "BufferClient.cpp",
- "BufferHubIdGenerator.cpp",
- "BufferHubService.cpp",
- "BufferNode.cpp",
- ],
- header_libs: [
- "libdvr_headers",
- "libnativewindow_headers",
- ],
- shared_libs: [
- "android.frameworks.bufferhub@1.0",
- "libcrypto",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libui",
- "libutils",
- ],
- export_include_dirs: [
- "include"
- ],
-}
-
-cc_binary {
- name: "android.frameworks.bufferhub@1.0-service",
- relative_install_path: "hw",
- srcs: [
- "main_bufferhub.cpp"
- ],
- header_libs: [
- "libdvr_headers",
- "libnativewindow_headers",
- ],
- shared_libs: [
- "android.frameworks.bufferhub@1.0",
- "libbufferhubservice",
- "libcrypto",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libui",
- "libutils",
- ],
- cflags: [
- "-DLOG_TAG=\"bufferhub\"",
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- init_rc: ["android.frameworks.bufferhub@1.0-service.rc"],
- vintf_fragments: ["android.frameworks.bufferhub@1.0-service.xml"],
-}
diff --git a/services/bufferhub/BufferClient.cpp b/services/bufferhub/BufferClient.cpp
deleted file mode 100644
index ec7e535..0000000
--- a/services/bufferhub/BufferClient.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2018 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 <bufferhub/BufferClient.h>
-#include <bufferhub/BufferHubService.h>
-#include <hidl/HidlSupport.h>
-#include <log/log.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-using hardware::hidl_handle;
-using hardware::Void;
-
-BufferClient* BufferClient::create(BufferHubService* service,
- const std::shared_ptr<BufferNode>& node) {
- if (!service) {
- ALOGE("%s: service cannot be nullptr.", __FUNCTION__);
- return nullptr;
- } else if (!node) {
- ALOGE("%s: node cannot be nullptr.", __FUNCTION__);
- return nullptr;
- }
- return new BufferClient(service, node);
-}
-
-BufferClient::~BufferClient() {
- {
- std::lock_guard<std::mutex> lock(mClosedMutex);
- if (!mClosed) {
- ALOGW("%s: client of buffer #%d destroyed without close. Closing it now.", __FUNCTION__,
- mBufferNode->id());
- }
- }
-
- close();
-}
-
-Return<BufferHubStatus> BufferClient::close() {
- std::lock_guard<std::mutex> lock(mClosedMutex);
- if (mClosed) {
- return BufferHubStatus::CLIENT_CLOSED;
- }
-
- getService()->onClientClosed(this);
- mBufferNode.reset();
- mClosed = true;
- return BufferHubStatus::NO_ERROR;
-}
-
-Return<void> BufferClient::duplicate(duplicate_cb _hidl_cb) {
- std::lock_guard<std::mutex> lock(mClosedMutex);
- if (mClosed) {
- _hidl_cb(/*token=*/hidl_handle(), /*status=*/BufferHubStatus::CLIENT_CLOSED);
- return Void();
- }
-
- if (!mBufferNode) {
- // Should never happen
- ALOGE("%s: node is missing.", __FUNCTION__);
- _hidl_cb(/*token=*/hidl_handle(), /*status=*/BufferHubStatus::BUFFER_FREED);
- return Void();
- }
-
- const hidl_handle token = getService()->registerToken(this);
- _hidl_cb(/*token=*/token, /*status=*/BufferHubStatus::NO_ERROR);
- return Void();
-}
-
-sp<BufferHubService> BufferClient::getService() {
- sp<BufferHubService> service = mService.promote();
- if (service == nullptr) {
- // Should never happen. Kill the process.
- LOG_FATAL("%s: service died.", __FUNCTION__);
- }
-
- return service;
-}
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
\ No newline at end of file
diff --git a/services/bufferhub/BufferHubIdGenerator.cpp b/services/bufferhub/BufferHubIdGenerator.cpp
deleted file mode 100644
index 2c12f0e..0000000
--- a/services/bufferhub/BufferHubIdGenerator.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2018 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 <bufferhub/BufferHubIdGenerator.h>
-#include <log/log.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-BufferHubIdGenerator& BufferHubIdGenerator::getInstance() {
- static BufferHubIdGenerator generator;
-
- return generator;
-}
-
-int BufferHubIdGenerator::getId() {
- std::lock_guard<std::mutex> lock(mIdsInUseMutex);
-
- do {
- if (++mLastId >= std::numeric_limits<int>::max()) {
- mLastId = 0;
- }
- } while (mIdsInUse.find(mLastId) != mIdsInUse.end());
-
- mIdsInUse.insert(mLastId);
- return mLastId;
-}
-
-void BufferHubIdGenerator::freeId(int id) {
- std::lock_guard<std::mutex> lock(mIdsInUseMutex);
- auto iter = mIdsInUse.find(id);
- if (iter != mIdsInUse.end()) {
- mIdsInUse.erase(iter);
- } else {
- ALOGW("%s: Cannot free nonexistent id #%d", __FUNCTION__, id);
- }
-}
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
deleted file mode 100644
index 7a3472f..0000000
--- a/services/bufferhub/BufferHubService.cpp
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright (C) 2018 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 <array>
-#include <iomanip>
-#include <random>
-#include <sstream>
-
-#include <android/hardware_buffer.h>
-#include <bufferhub/BufferHubService.h>
-#include <cutils/native_handle.h>
-#include <log/log.h>
-#include <openssl/hmac.h>
-#include <system/graphics-base.h>
-#include <ui/BufferHubDefs.h>
-
-using ::android::BufferHubDefs::MetadataHeader;
-using ::android::hardware::Void;
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-BufferHubService::BufferHubService() {
- std::mt19937_64 randomEngine;
- randomEngine.seed(time(nullptr));
-
- mKey = randomEngine();
-}
-
-Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& description,
- const uint32_t userMetadataSize,
- allocateBuffer_cb _hidl_cb) {
- AHardwareBuffer_Desc desc;
- memcpy(&desc, &description, sizeof(AHardwareBuffer_Desc));
-
- std::shared_ptr<BufferNode> node =
- std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
- desc.usage, userMetadataSize,
- BufferHubIdGenerator::getInstance().getId());
- if (node == nullptr || !node->isValid()) {
- ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
- _hidl_cb(/*status=*/BufferHubStatus::ALLOCATION_FAILED, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- sp<BufferClient> client = BufferClient::create(this, node);
- // Add it to list for bookkeeping and dumpsys.
- std::lock_guard<std::mutex> lock(mClientSetMutex);
- mClientSet.emplace(client);
-
- // Allocate memory for bufferInfo of type hidl_handle on the stack. See
- // http://aosp/286282 for the usage of NATIVE_HANDLE_DECLARE_STORAGE.
- NATIVE_HANDLE_DECLARE_STORAGE(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds,
- BufferHubDefs::kBufferInfoNumInts);
- hidl_handle bufferInfo =
- buildBufferInfo(bufferInfoStorage, node->id(), node->addNewActiveClientsBitToMask(),
- node->userMetadataSize(), node->metadata().ashmemFd(),
- node->eventFd().get());
- // During the gralloc allocation carried out by BufferNode, gralloc allocator will populate the
- // fields of its HardwareBufferDescription (i.e. strides) according to the actual
- // gralloc implementation. We need to read those fields back and send them to the client via
- // BufferTraits.
- HardwareBufferDescription allocatedBufferDesc;
- memcpy(&allocatedBufferDesc, &node->bufferDesc(), sizeof(AHardwareBuffer_Desc));
- BufferTraits bufferTraits = {/*bufferDesc=*/allocatedBufferDesc,
- /*bufferHandle=*/hidl_handle(node->bufferHandle()),
- /*bufferInfo=*/std::move(bufferInfo)};
-
- _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
- /*bufferTraits=*/std::move(bufferTraits));
- return Void();
-}
-
-Return<void> BufferHubService::importBuffer(const hidl_handle& tokenHandle,
- importBuffer_cb _hidl_cb) {
- if (!tokenHandle.getNativeHandle() || tokenHandle->numFds != 0 || tokenHandle->numInts <= 1) {
- // nullptr handle or wrong format
- _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- int tokenId = tokenHandle->data[0];
-
- wp<BufferClient> originClientWp;
- {
- std::lock_guard<std::mutex> lock(mTokenMutex);
- auto iter = mTokenMap.find(tokenId);
- if (iter == mTokenMap.end()) {
- // Token Id not exist
- ALOGD("%s: token #%d not found.", __FUNCTION__, tokenId);
- _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- const std::vector<uint8_t>& tokenHMAC = iter->second.first;
-
- int numIntsForHMAC = (int)ceil(tokenHMAC.size() * sizeof(uint8_t) / (double)sizeof(int));
- if (tokenHandle->numInts - 1 != numIntsForHMAC) {
- // HMAC size not match
- ALOGD("%s: token #%d HMAC size not match. Expected: %d Actual: %d", __FUNCTION__,
- tokenId, numIntsForHMAC, tokenHandle->numInts - 1);
- _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- size_t hmacSize = tokenHMAC.size() * sizeof(uint8_t);
- if (memcmp(tokenHMAC.data(), &tokenHandle->data[1], hmacSize) != 0) {
- // HMAC not match
- ALOGD("%s: token #%d HMAC not match.", __FUNCTION__, tokenId);
- _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- originClientWp = iter->second.second;
- mTokenMap.erase(iter);
- }
-
- // Check if original client is dead
- sp<BufferClient> originClient = originClientWp.promote();
- if (!originClient) {
- // Should not happen since token should be removed if already gone
- ALOGE("%s: original client %p gone!", __FUNCTION__, originClientWp.unsafe_get());
- _hidl_cb(/*status=*/BufferHubStatus::BUFFER_FREED, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- sp<BufferClient> client = new BufferClient(*originClient);
- uint32_t clientStateMask = client->getBufferNode()->addNewActiveClientsBitToMask();
- if (clientStateMask == 0U) {
- // Reach max client count
- ALOGE("%s: import failed, BufferNode#%u reached maximum clients.", __FUNCTION__,
- client->getBufferNode()->id());
- _hidl_cb(/*status=*/BufferHubStatus::MAX_CLIENT, /*bufferClient=*/nullptr,
- /*bufferTraits=*/{});
- return Void();
- }
-
- std::lock_guard<std::mutex> lock(mClientSetMutex);
- mClientSet.emplace(client);
-
- std::shared_ptr<BufferNode> node = client->getBufferNode();
-
- HardwareBufferDescription bufferDesc;
- memcpy(&bufferDesc, &node->bufferDesc(), sizeof(HardwareBufferDescription));
-
- // Allocate memory for bufferInfo of type hidl_handle on the stack. See
- // http://aosp/286282 for the usage of NATIVE_HANDLE_DECLARE_STORAGE.
- NATIVE_HANDLE_DECLARE_STORAGE(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds,
- BufferHubDefs::kBufferInfoNumInts);
- hidl_handle bufferInfo = buildBufferInfo(bufferInfoStorage, node->id(), clientStateMask,
- node->userMetadataSize(), node->metadata().ashmemFd(),
- node->eventFd().get());
- BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc,
- /*bufferHandle=*/hidl_handle(node->bufferHandle()),
- /*bufferInfo=*/std::move(bufferInfo)};
-
- _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
- /*bufferTraits=*/std::move(bufferTraits));
- return Void();
-}
-
-Return<void> BufferHubService::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
- if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
- ALOGE("%s: missing fd for writing.", __FUNCTION__);
- return Void();
- }
-
- FILE* out = fdopen(dup(fd->data[0]), "w");
-
- if (args.size() != 0) {
- fprintf(out,
- "Note: lshal bufferhub currently does not support args. Input arguments are "
- "ignored.\n");
- }
-
- std::ostringstream stream;
-
- // Get the number of clients of each buffer.
- // Map from bufferId to bufferNode_clientCount pair.
- std::map<int, std::pair<const std::shared_ptr<BufferNode>, uint32_t>> clientCount;
- {
- std::lock_guard<std::mutex> lock(mClientSetMutex);
- for (auto iter = mClientSet.begin(); iter != mClientSet.end(); ++iter) {
- sp<BufferClient> client = iter->promote();
- if (client != nullptr) {
- const std::shared_ptr<BufferNode> node = client->getBufferNode();
- auto mapIter = clientCount.find(node->id());
- if (mapIter != clientCount.end()) {
- ++mapIter->second.second;
- } else {
- clientCount.emplace(node->id(),
- std::pair<std::shared_ptr<BufferNode>, uint32_t>(node, 1U));
- }
- }
- }
- }
-
- stream << "Active Buffers:\n";
- stream << std::right;
- stream << std::setw(6) << "Id";
- stream << " ";
- stream << std::setw(9) << "#Clients";
- stream << " ";
- stream << std::setw(14) << "Geometry";
- stream << " ";
- stream << std::setw(6) << "Format";
- stream << " ";
- stream << std::setw(10) << "Usage";
- stream << " ";
- stream << std::setw(10) << "State";
- stream << " ";
- stream << std::setw(8) << "Index";
- stream << std::endl;
-
- for (auto iter = clientCount.begin(); iter != clientCount.end(); ++iter) {
- const std::shared_ptr<BufferNode> node = std::move(iter->second.first);
- const uint32_t clientCount = iter->second.second;
- AHardwareBuffer_Desc desc = node->bufferDesc();
-
- MetadataHeader* metadataHeader =
- const_cast<BufferHubMetadata*>(&node->metadata())->metadataHeader();
- const uint32_t state = metadataHeader->bufferState.load(std::memory_order_acquire);
- const uint64_t index = metadataHeader->queueIndex;
-
- stream << std::right;
- stream << std::setw(6) << /*Id=*/node->id();
- stream << " ";
- stream << std::setw(9) << /*#Clients=*/clientCount;
- stream << " ";
- if (desc.format == HAL_PIXEL_FORMAT_BLOB) {
- std::string size = std::to_string(desc.width) + " B";
- stream << std::setw(14) << /*Geometry=*/size;
- } else {
- std::string dimensions = std::to_string(desc.width) + "x" +
- std::to_string(desc.height) + "x" + std::to_string(desc.layers);
- stream << std::setw(14) << /*Geometry=*/dimensions;
- }
- stream << " ";
- stream << std::setw(6) << /*Format=*/desc.format;
- stream << " ";
- stream << "0x" << std::hex << std::setfill('0');
- stream << std::setw(8) << /*Usage=*/desc.usage;
- stream << std::dec << std::setfill(' ');
- stream << " ";
- stream << "0x" << std::hex << std::setfill('0');
- stream << std::setw(8) << /*State=*/state;
- stream << std::dec << std::setfill(' ');
- stream << " ";
- stream << std::setw(8) << /*Index=*/index;
- stream << std::endl;
- }
-
- stream << std::endl;
-
- // Get the number of tokens of each buffer.
- // Map from bufferId to tokenCount
- std::map<int, uint32_t> tokenCount;
- {
- std::lock_guard<std::mutex> lock(mTokenMutex);
- for (auto iter = mTokenMap.begin(); iter != mTokenMap.end(); ++iter) {
- sp<BufferClient> client = iter->second.second.promote();
- if (client != nullptr) {
- const std::shared_ptr<BufferNode> node = client->getBufferNode();
- auto mapIter = tokenCount.find(node->id());
- if (mapIter != tokenCount.end()) {
- ++mapIter->second;
- } else {
- tokenCount.emplace(node->id(), 1U);
- }
- }
- }
- }
-
- stream << "Unused Tokens:\n";
- stream << std::right;
- stream << std::setw(8) << "Buffer Id";
- stream << " ";
- stream << std::setw(7) << "#Tokens";
- stream << std::endl;
-
- for (auto iter = tokenCount.begin(); iter != tokenCount.end(); ++iter) {
- stream << std::right;
- stream << std::setw(8) << /*Buffer Id=*/iter->first;
- stream << " ";
- stream << std::setw(7) << /*#Tokens=*/iter->second;
- stream << std::endl;
- }
-
- fprintf(out, "%s", stream.str().c_str());
-
- fclose(out);
- return Void();
-}
-
-hidl_handle BufferHubService::registerToken(const wp<BufferClient>& client) {
- // Find next available token id
- std::lock_guard<std::mutex> lock(mTokenMutex);
- do {
- ++mLastTokenId;
- } while (mTokenMap.find(mLastTokenId) != mTokenMap.end());
-
- std::array<uint8_t, EVP_MAX_MD_SIZE> hmac;
- uint32_t hmacSize = 0U;
-
- HMAC(/*evp_md=*/EVP_sha256(), /*key=*/&mKey, /*key_len=*/kKeyLen,
- /*data=*/(uint8_t*)&mLastTokenId, /*data_len=*/mTokenIdSize,
- /*out=*/hmac.data(), /*out_len=*/&hmacSize);
-
- int numIntsForHMAC = (int)ceil(hmacSize / (double)sizeof(int));
- native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1 + numIntsForHMAC);
- handle->data[0] = mLastTokenId;
- // Set all the the bits of last int to 0 since it might not be fully overwritten
- handle->data[numIntsForHMAC] = 0;
- memcpy(&handle->data[1], hmac.data(), hmacSize);
-
- // returnToken owns the native_handle_t* thus doing lifecycle management
- hidl_handle returnToken;
- returnToken.setTo(handle, /*shoudOwn=*/true);
-
- std::vector<uint8_t> hmacVec;
- hmacVec.resize(hmacSize);
- memcpy(hmacVec.data(), hmac.data(), hmacSize);
- mTokenMap.emplace(mLastTokenId, std::pair(hmacVec, client));
-
- return returnToken;
-}
-
-void BufferHubService::onClientClosed(const BufferClient* client) {
- removeTokenByClient(client);
-
- std::lock_guard<std::mutex> lock(mClientSetMutex);
- auto iter = std::find(mClientSet.begin(), mClientSet.end(), client);
- if (iter != mClientSet.end()) {
- mClientSet.erase(iter);
- }
-}
-
-// Implementation of this function should be consistent with the definition of bufferInfo handle in
-// ui/BufferHubDefs.h.
-hidl_handle BufferHubService::buildBufferInfo(char* bufferInfoStorage, int bufferId,
- uint32_t clientBitMask, uint32_t userMetadataSize,
- int metadataFd, int eventFd) {
- native_handle_t* infoHandle =
- native_handle_init(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds,
- BufferHubDefs::kBufferInfoNumInts);
-
- infoHandle->data[0] = metadataFd;
- infoHandle->data[1] = eventFd;
- infoHandle->data[2] = bufferId;
- // Use memcpy to convert to int without missing digit.
- // TOOD(b/121345852): use bit_cast to unpack bufferInfo when C++20 becomes available.
- memcpy(&infoHandle->data[3], &clientBitMask, sizeof(clientBitMask));
- memcpy(&infoHandle->data[4], &userMetadataSize, sizeof(userMetadataSize));
-
- hidl_handle bufferInfo;
- bufferInfo.setTo(infoHandle, /*shouldOwn=*/false);
-
- return bufferInfo;
-}
-
-void BufferHubService::removeTokenByClient(const BufferClient* client) {
- std::lock_guard<std::mutex> lock(mTokenMutex);
- auto iter = mTokenMap.begin();
- while (iter != mTokenMap.end()) {
- if (iter->second.second == client) {
- auto oldIter = iter;
- ++iter;
- mTokenMap.erase(oldIter);
- } else {
- ++iter;
- }
- }
-}
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
deleted file mode 100644
index 04ca649..0000000
--- a/services/bufferhub/BufferNode.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <errno.h>
-
-#include <bufferhub/BufferHubService.h>
-#include <bufferhub/BufferNode.h>
-#include <log/log.h>
-#include <ui/GraphicBufferAllocator.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-void BufferNode::initializeMetadata() {
- // Using placement new here to reuse shared memory instead of new allocation
- // Initialize the atomic variables to zero.
- BufferHubDefs::MetadataHeader* metadataHeader = mMetadata.metadataHeader();
- mBufferState = new (&metadataHeader->bufferState) std::atomic<uint32_t>(0);
- mFenceState = new (&metadataHeader->fenceState) std::atomic<uint32_t>(0);
- mActiveClientsBitMask = new (&metadataHeader->activeClientsBitMask) std::atomic<uint32_t>(0);
- // The C++ standard recommends (but does not require) that lock-free atomic operations are
- // also address-free, that is, suitable for communication between processes using shared
- // memory.
- LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(mBufferState) ||
- !std::atomic_is_lock_free(mFenceState) ||
- !std::atomic_is_lock_free(mActiveClientsBitMask),
- "Atomic variables in ashmen are not lock free.");
-}
-
-// Allocates a new BufferNode.
-BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
- uint64_t usage, size_t userMetadataSize, int id)
- : mId(id) {
- uint32_t outStride = 0;
- // graphicBufferId is not used in GraphicBufferAllocator::allocate
- // TODO(b/112338294) After move to the service folder, stop using the
- // hardcoded service name "bufferhub".
- int ret = GraphicBufferAllocator::get().allocate(width, height, format, layerCount, usage,
- const_cast<const native_handle_t**>(
- &mBufferHandle),
- &outStride,
- /*graphicBufferId=*/0,
- /*requestor=*/"bufferhub");
-
- if (ret != OK || mBufferHandle == nullptr) {
- ALOGE("%s: Failed to allocate buffer: %s", __FUNCTION__, strerror(-ret));
- return;
- }
-
- mBufferDesc.width = width;
- mBufferDesc.height = height;
- mBufferDesc.layers = layerCount;
- mBufferDesc.format = format;
- mBufferDesc.usage = usage;
- mBufferDesc.stride = outStride;
-
- mMetadata = BufferHubMetadata::create(userMetadataSize);
- if (!mMetadata.isValid()) {
- ALOGE("%s: Failed to allocate metadata.", __FUNCTION__);
- return;
- }
- initializeMetadata();
-}
-
-BufferNode::~BufferNode() {
- // Free the handle
- if (mBufferHandle != nullptr) {
- status_t ret = GraphicBufferAllocator::get().free(mBufferHandle);
- if (ret != OK) {
- ALOGE("%s: Failed to free handle; Got error: %d", __FUNCTION__, ret);
- }
- }
-
- // Free the id, if valid
- if (mId >= 0) {
- BufferHubIdGenerator::getInstance().freeId(mId);
- }
-}
-
-uint32_t BufferNode::getActiveClientsBitMask() const {
- return mActiveClientsBitMask->load(std::memory_order_acquire);
-}
-
-uint32_t BufferNode::addNewActiveClientsBitToMask() {
- uint32_t currentActiveClientsBitMask = getActiveClientsBitMask();
- uint32_t clientStateMask = 0U;
- uint32_t updatedActiveClientsBitMask = 0U;
- do {
- clientStateMask =
- BufferHubDefs::findNextAvailableClientStateMask(currentActiveClientsBitMask);
- if (clientStateMask == 0U) {
- ALOGE("%s: reached the maximum number of channels per buffer node: %d.", __FUNCTION__,
- BufferHubDefs::kMaxNumberOfClients);
- errno = E2BIG;
- return 0U;
- }
- updatedActiveClientsBitMask = currentActiveClientsBitMask | clientStateMask;
- } while (!(mActiveClientsBitMask->compare_exchange_weak(currentActiveClientsBitMask,
- updatedActiveClientsBitMask,
- std::memory_order_acq_rel,
- std::memory_order_acquire)));
- return clientStateMask;
-}
-
-void BufferNode::removeClientsBitFromMask(const uint32_t& value) {
- mActiveClientsBitMask->fetch_and(~value);
-}
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
diff --git a/services/bufferhub/android.frameworks.bufferhub@1.0-service.rc b/services/bufferhub/android.frameworks.bufferhub@1.0-service.rc
deleted file mode 100644
index 36fbede..0000000
--- a/services/bufferhub/android.frameworks.bufferhub@1.0-service.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service system_bufferhub /system/bin/hw/android.frameworks.bufferhub@1.0-service
- class hal animation
- user system
- group system graphics
- onrestart restart surfaceflinger
- writepid /dev/cpuset/system-background/tasks
diff --git a/services/bufferhub/android.frameworks.bufferhub@1.0-service.xml b/services/bufferhub/android.frameworks.bufferhub@1.0-service.xml
deleted file mode 100644
index bd958d3..0000000
--- a/services/bufferhub/android.frameworks.bufferhub@1.0-service.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="framework">
- <hal>
- <name>android.frameworks.bufferhub</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IBufferHub</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/services/bufferhub/include/bufferhub/BufferClient.h b/services/bufferhub/include/bufferhub/BufferClient.h
deleted file mode 100644
index 644b403..0000000
--- a/services/bufferhub/include/bufferhub/BufferClient.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_CLIENT_H
-#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_CLIENT_H
-
-#include <mutex>
-
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
-#include <bufferhub/BufferNode.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-using hardware::hidl_handle;
-using hardware::Return;
-
-// Forward declaration to avoid circular dependency
-class BufferHubService;
-
-class BufferClient : public IBufferClient {
-public:
- // Creates a server-side buffer client from an existing BufferNode. Note that
- // this function takes ownership of the shared_ptr.
- // Returns a raw pointer to the BufferClient on success, nullptr on failure.
- static BufferClient* create(BufferHubService* service, const std::shared_ptr<BufferNode>& node);
-
- // Creates a BufferClient from an existing BufferClient. Will share the same BufferNode.
- explicit BufferClient(const BufferClient& other)
- : mService(other.mService), mBufferNode(other.mBufferNode) {}
- ~BufferClient();
-
- Return<BufferHubStatus> close() override;
- Return<void> duplicate(duplicate_cb _hidl_cb) override;
-
- // Non-binder functions
- const std::shared_ptr<BufferNode>& getBufferNode() const { return mBufferNode; }
-
-private:
- BufferClient(wp<BufferHubService> service, const std::shared_ptr<BufferNode>& node)
- : mService(service), mBufferNode(node) {}
-
- sp<BufferHubService> getService();
-
- wp<BufferHubService> mService;
-
- std::mutex mClosedMutex;
- bool mClosed GUARDED_BY(mClosedMutex) = false;
-
- std::shared_ptr<BufferNode> mBufferNode;
-};
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
-
-#endif
diff --git a/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
deleted file mode 100644
index ef7c077..0000000
--- a/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
-#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
-
-#include <mutex>
-#include <set>
-
-#include <utils/Mutex.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-// A thread-safe, non-negative, incremental, int id generator.
-class BufferHubIdGenerator {
-public:
- // Get the singleton instance of this class
- static BufferHubIdGenerator& getInstance();
-
- // Gets next available id. If next id is greater than std::numeric_limits<int32_t>::max(), it
- // will try to get an id start from 0 again.
- int getId();
-
- // Free a specific id.
- void freeId(int id);
-
-private:
- BufferHubIdGenerator() = default;
- ~BufferHubIdGenerator() = default;
-
- // Start from -1 so all valid ids will be >= 0
- int mLastId = -1;
-
- std::mutex mIdsInUseMutex;
- std::set<int> mIdsInUse GUARDED_BY(mIdsInUseMutex);
-};
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
-
-#endif // ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_ID_GENERATOR_H
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
deleted file mode 100644
index edad20b..0000000
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
-#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
-
-#include <map>
-#include <mutex>
-#include <set>
-#include <vector>
-
-#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
-#include <bufferhub/BufferClient.h>
-#include <bufferhub/BufferHubIdGenerator.h>
-#include <utils/Mutex.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-using hardware::hidl_handle;
-using hardware::hidl_string;
-using hardware::hidl_vec;
-using hardware::Return;
-using hardware::graphics::common::V1_2::HardwareBufferDescription;
-
-class BufferHubService : public IBufferHub {
-public:
- BufferHubService();
-
- Return<void> allocateBuffer(const HardwareBufferDescription& description,
- const uint32_t userMetadataSize,
- allocateBuffer_cb _hidl_cb) override;
- Return<void> importBuffer(const hidl_handle& tokenHandle, importBuffer_cb _hidl_cb) override;
-
- Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
-
- // Non-binder functions
- // Internal help function for IBufferClient::duplicate.
- hidl_handle registerToken(const wp<BufferClient>& client);
-
- void onClientClosed(const BufferClient* client);
-
-private:
- // Helper function to build BufferTraits.bufferInfo handle
- hidl_handle buildBufferInfo(char* bufferInfoStorage, int bufferId, uint32_t clientBitMask,
- uint32_t userMetadataSize, int metadataFd, int eventFd);
-
- // Helper function to remove all the token belongs to a specific client.
- void removeTokenByClient(const BufferClient* client);
-
- // List of active BufferClient for bookkeeping.
- std::mutex mClientSetMutex;
- std::set<wp<BufferClient>> mClientSet GUARDED_BY(mClientSetMutex);
-
- // Token generation related
- // A random number used as private key for HMAC
- uint64_t mKey;
- static constexpr size_t kKeyLen = sizeof(uint64_t);
-
- std::mutex mTokenMutex;
- // The first TokenId will be 1. TokenId could be negative.
- int mLastTokenId GUARDED_BY(mTokenMutex) = 0;
- static constexpr size_t mTokenIdSize = sizeof(int);
- // A map from token id to the token-buffer_client pair. Using token id as the key to reduce
- // looking up time
- std::map<int, std::pair<std::vector<uint8_t>, const wp<BufferClient>>> mTokenMap
- GUARDED_BY(mTokenMutex);
-};
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
-
-#endif // ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
deleted file mode 100644
index 62a8d63..0000000
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ /dev/null
@@ -1,100 +0,0 @@
-#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
-#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
-
-#include <android/hardware_buffer.h>
-#include <bufferhub/BufferHubIdGenerator.h>
-#include <cutils/native_handle.h>
-#include <ui/BufferHubEventFd.h>
-#include <ui/BufferHubMetadata.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-class BufferNode {
-public:
- // Allocates a new BufferNode.
- BufferNode(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
- uint64_t usage, size_t userMetadataSize, int id = -1);
-
- ~BufferNode();
-
- // Returns whether the object holds a valid metadata.
- bool isValid() const { return mMetadata.isValid(); }
-
- int id() const { return mId; }
-
- size_t userMetadataSize() const { return mMetadata.userMetadataSize(); }
-
- // Accessors of the buffer description and handle
- const native_handle_t* bufferHandle() const { return mBufferHandle; }
- const AHardwareBuffer_Desc& bufferDesc() const { return mBufferDesc; }
-
- // Accessor of event fd.
- const BufferHubEventFd& eventFd() const { return mEventFd; }
-
- // Accessors of mMetadata.
- const BufferHubMetadata& metadata() const { return mMetadata; }
-
- // Gets the current value of mActiveClientsBitMask in mMetadata with
- // std::memory_order_acquire, so that all previous releases of
- // mActiveClientsBitMask from all threads will be returned here.
- uint32_t getActiveClientsBitMask() const;
-
- // Find and add a new client state mask to mActiveClientsBitMask in
- // mMetadata.
- // Return the new client state mask that is added to mActiveClientsBitMask.
- // Return 0U if there are already 16 clients of the buffer.
- uint32_t addNewActiveClientsBitToMask();
-
- // Removes the value from active_clients_bit_mask in mMetadata with
- // std::memory_order_release, so that the change will be visible to any
- // acquire of mActiveClientsBitMask in any threads after the succeed of
- // this operation.
- void removeClientsBitFromMask(const uint32_t& value);
-
-private:
- // Helper method for constructors to initialize atomic metadata header
- // variables in shared memory.
- void initializeMetadata();
-
- // Gralloc buffer handles.
- native_handle_t* mBufferHandle;
- AHardwareBuffer_Desc mBufferDesc;
-
- // Eventfd used for signalling buffer events among the clients of the buffer.
- BufferHubEventFd mEventFd;
-
- // Metadata in shared memory.
- BufferHubMetadata mMetadata;
-
- // A system-unique id generated by bufferhub from 0 to std::numeric_limits<int>::max().
- // BufferNodes not created by bufferhub will have id < 0, meaning "not specified".
- // TODO(b/118891412): remove default id = -1 and update comments after pdx is no longer in use
- const int mId = -1;
-
- // The following variables are atomic variables in mMetadata that are visible
- // to Bn object and Bp objects. Please find more info in
- // BufferHubDefs::MetadataHeader.
-
- // mBufferState tracks the state of the buffer. Buffer can be in one of these
- // four states: gained, posted, acquired, released.
- std::atomic<uint32_t>* mBufferState = nullptr;
-
- // TODO(b/112012161): add comments to mFenceState.
- std::atomic<uint32_t>* mFenceState = nullptr;
-
- // mActiveClientsBitMask tracks all the bp clients of the buffer. It is the
- // union of all client_state_mask of all bp clients.
- std::atomic<uint32_t>* mActiveClientsBitMask = nullptr;
-};
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
-
-#endif // ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
diff --git a/services/bufferhub/main_bufferhub.cpp b/services/bufferhub/main_bufferhub.cpp
deleted file mode 100644
index 084460d..0000000
--- a/services/bufferhub/main_bufferhub.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 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 <bufferhub/BufferHubService.h>
-#include <hidl/HidlTransportSupport.h>
-#include <hwbinder/IPCThreadState.h>
-#include <log/log.h>
-
-using android::sp;
-using android::frameworks::bufferhub::V1_0::IBufferHub;
-using android::frameworks::bufferhub::V1_0::implementation::BufferHubService;
-
-int main(int /*argc*/, char** /*argv*/) {
- ALOGI("Bootstrap bufferhub HIDL service.");
-
- android::hardware::configureRpcThreadpool(/*numThreads=*/1, /*willJoin=*/true);
-
- sp<IBufferHub> service = new BufferHubService();
- LOG_ALWAYS_FATAL_IF(service->registerAsService() != android::OK, "Failed to register service");
-
- android::hardware::joinRpcThreadpool();
-
- return 0;
-}
diff --git a/services/bufferhub/tests/Android.bp b/services/bufferhub/tests/Android.bp
deleted file mode 100644
index 3033e70..0000000
--- a/services/bufferhub/tests/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-cc_test {
- name: "BufferHubServer_test",
- srcs: [
- "BufferNode_test.cpp",
- "BufferHubIdGenerator_test.cpp",
- ],
- cflags: [
- "-DLOG_TAG=\"BufferHubServer_test\"",
- "-DTRACE=0",
- "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
- "-Wall",
- "-Werror",
- ],
- compile_multilib: "first",
- header_libs: [
- "libdvr_headers",
- "libnativewindow_headers",
- ],
- shared_libs: [
- "libbufferhubservice",
- "libui",
- ],
- static_libs: [
- "libgmock",
- ],
-}
diff --git a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
deleted file mode 100644
index fb6de0d..0000000
--- a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <bufferhub/BufferHubIdGenerator.h>
-#include <gtest/gtest.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-namespace {
-
-class BufferHubIdGeneratorTest : public testing::Test {
-protected:
- BufferHubIdGenerator* mIdGenerator = &BufferHubIdGenerator::getInstance();
-};
-
-TEST_F(BufferHubIdGeneratorTest, TestGenerateAndFreeID) {
- int id = mIdGenerator->getId();
- EXPECT_GE(id, 0);
-
- mIdGenerator->freeId(id);
-}
-
-TEST_F(BufferHubIdGeneratorTest, TestGenerateUniqueIncrementalID) {
- // 10 IDs should not overflow the UniqueIdGenerator to cause a roll back to start, so the
- // resulting IDs should still keep incresing.
- const int kTestSize = 10;
- int ids[kTestSize];
- for (int i = 0; i < kTestSize; ++i) {
- ids[i] = mIdGenerator->getId();
- EXPECT_GE(ids[i], 0);
- if (i >= 1) {
- EXPECT_GT(ids[i], ids[i - 1]);
- }
- }
-
- for (int i = 0; i < kTestSize; ++i) {
- mIdGenerator->freeId(ids[i]);
- }
-}
-
-} // namespace
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
\ No newline at end of file
diff --git a/services/bufferhub/tests/BufferNode_test.cpp b/services/bufferhub/tests/BufferNode_test.cpp
deleted file mode 100644
index 2dfd4fc..0000000
--- a/services/bufferhub/tests/BufferNode_test.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <errno.h>
-
-#include <bufferhub/BufferNode.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <ui/BufferHubDefs.h>
-#include <ui/GraphicBufferMapper.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-namespace {
-
-using testing::NotNull;
-
-const uint32_t kWidth = 640;
-const uint32_t kHeight = 480;
-const uint32_t kLayerCount = 1;
-const uint32_t kFormat = 1;
-const uint64_t kUsage = 0;
-const size_t kUserMetadataSize = 0;
-
-class BufferNodeTest : public ::testing::Test {
-protected:
- void SetUp() override {
- mBufferNode =
- new BufferNode(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_TRUE(mBufferNode->isValid());
- }
-
- void TearDown() override {
- if (mBufferNode != nullptr) {
- delete mBufferNode;
- }
- }
-
- BufferNode* mBufferNode = nullptr;
-};
-
-TEST_F(BufferNodeTest, TestCreateBufferNode) {
- EXPECT_EQ(mBufferNode->userMetadataSize(), kUserMetadataSize);
- // Test the handle just allocated is good (i.e. able to be imported)
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
- const native_handle_t* outHandle;
- status_t ret =
- mapper.importBuffer(mBufferNode->bufferHandle(), mBufferNode->bufferDesc().width,
- mBufferNode->bufferDesc().height, mBufferNode->bufferDesc().layers,
- mBufferNode->bufferDesc().format, mBufferNode->bufferDesc().usage,
- mBufferNode->bufferDesc().stride, &outHandle);
- EXPECT_EQ(ret, OK);
- EXPECT_THAT(outHandle, NotNull());
-}
-
-TEST_F(BufferNodeTest, TestaddNewActiveClientsBitToMask_twoNewClients) {
- uint32_t newClientStateMask1 = mBufferNode->addNewActiveClientsBitToMask();
- EXPECT_EQ(mBufferNode->getActiveClientsBitMask(), newClientStateMask1);
-
- // Request and add a new client_state_mask again.
- // Active clients bit mask should be the union of the two new
- // client_state_masks.
- uint32_t newClientStateMask2 = mBufferNode->addNewActiveClientsBitToMask();
- EXPECT_EQ(mBufferNode->getActiveClientsBitMask(), newClientStateMask1 | newClientStateMask2);
-}
-
-TEST_F(BufferNodeTest, TestaddNewActiveClientsBitToMask_32NewClients) {
- uint32_t newClientStateMask = 0U;
- uint32_t currentMask = 0U;
- uint32_t expectedMask = 0U;
-
- for (int i = 0; i < BufferHubDefs::kMaxNumberOfClients; ++i) {
- newClientStateMask = mBufferNode->addNewActiveClientsBitToMask();
- EXPECT_NE(newClientStateMask, 0U);
- EXPECT_FALSE(newClientStateMask & currentMask);
- expectedMask = currentMask | newClientStateMask;
- currentMask = mBufferNode->getActiveClientsBitMask();
- EXPECT_EQ(currentMask, expectedMask);
- }
-
- // Method should fail upon requesting for more than maximum allowable clients.
- newClientStateMask = mBufferNode->addNewActiveClientsBitToMask();
- EXPECT_EQ(newClientStateMask, 0U);
- EXPECT_EQ(errno, E2BIG);
-}
-
-TEST_F(BufferNodeTest, TestRemoveActiveClientsBitFromMask) {
- mBufferNode->addNewActiveClientsBitToMask();
- uint32_t currentMask = mBufferNode->getActiveClientsBitMask();
- uint32_t newClientStateMask = mBufferNode->addNewActiveClientsBitToMask();
- EXPECT_NE(mBufferNode->getActiveClientsBitMask(), currentMask);
-
- mBufferNode->removeClientsBitFromMask(newClientStateMask);
- EXPECT_EQ(mBufferNode->getActiveClientsBitMask(), currentMask);
-
- // Remove the test_mask again to the active client bit mask should not modify
- // the value of active clients bit mask.
- mBufferNode->removeClientsBitFromMask(newClientStateMask);
- EXPECT_EQ(mBufferNode->getActiveClientsBitMask(), currentMask);
-}
-
-} // namespace
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 7c5c9c5..5a14133 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -28,8 +28,8 @@
static const int32_t INJECTOR_PID = 999;
static const int32_t INJECTOR_UID = 1001;
-static const int32_t INJECT_EVENT_TIMEOUT = 5000;
-static const int32_t DISPATCHING_TIMEOUT = 100000;
+static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s;
+static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 100ms;
static nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -47,7 +47,7 @@
private:
virtual void notifyConfigurationChanged(nsecs_t) override {}
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&, const sp<IBinder>&,
+ virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&,
const std::string& name) override {
ALOGE("The window is not responding : %s", name.c_str());
return 0;
@@ -98,7 +98,7 @@
virtual ~FakeApplicationHandle() {}
virtual bool updateInfo() {
- mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
return true;
}
};
@@ -163,7 +163,7 @@
mInfo.name = "FakeWindowHandle";
mInfo.layoutParamsFlags = 0;
mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
- mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
mInfo.frameLeft = mFrame.left;
mInfo.frameTop = mFrame.top;
mInfo.frameRight = mFrame.right;
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 49630ad..a1eb007 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -37,6 +37,8 @@
return "MOVE";
case AMOTION_EVENT_ACTION_UP:
return "UP";
+ case AMOTION_EVENT_ACTION_CANCEL:
+ return "CANCEL";
case AMOTION_EVENT_ACTION_POINTER_DOWN:
return "POINTER_DOWN";
case AMOTION_EVENT_ACTION_POINTER_UP:
@@ -57,6 +59,7 @@
}
return StringPrintf("%" PRId32, action);
}
+
VerifiedKeyEvent verifiedKeyEventFromKeyEntry(const KeyEntry& entry) {
return {{VerifiedInputEvent::Type::KEY, entry.deviceId, entry.eventTime, entry.source,
entry.displayId},
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 4ec61b0..1dbcf98 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -352,18 +352,16 @@
break;
}
}
- std::vector<uint8_t> data;
const uint8_t* start = reinterpret_cast<const uint8_t*>(&event);
- data.assign(start, start + size);
- return sign(data);
+ return sign(start, size);
}
-std::array<uint8_t, 32> HmacKeyManager::sign(const std::vector<uint8_t>& data) const {
+std::array<uint8_t, 32> HmacKeyManager::sign(const uint8_t* data, size_t size) const {
// SHA256 always generates 32-bytes result
std::array<uint8_t, 32> hash;
unsigned int hashLen = 0;
- uint8_t* result = HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data.data(), data.size(),
- hash.data(), &hashLen);
+ uint8_t* result =
+ HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data, size, hash.data(), &hashLen);
if (result == nullptr) {
ALOGE("Could not sign the data using HMAC");
return INVALID_HMAC;
@@ -533,7 +531,7 @@
}
// Get ready to dispatch the event.
- resetANRTimeoutsLocked();
+ resetAnrTimeoutsLocked();
}
// Now we have an event to dispatch.
@@ -890,7 +888,7 @@
void InputDispatcher::releasePendingEventLocked() {
if (mPendingEvent) {
- resetANRTimeoutsLocked();
+ resetAnrTimeoutsLocked();
releaseInboundEventLocked(mPendingEvent);
mPendingEvent = nullptr;
}
@@ -1301,7 +1299,7 @@
}
if (currentTime >= mInputTargetWaitTimeoutTime) {
- onANRLocked(currentTime, applicationHandle, windowHandle, entry.eventTime,
+ onAnrLocked(currentTime, applicationHandle, windowHandle, entry.eventTime,
mInputTargetWaitStartTime, reason);
// Force poll loop to wake up immediately on next iteration once we get the
@@ -1354,7 +1352,7 @@
return 0;
}
-void InputDispatcher::resetANRTimeoutsLocked() {
+void InputDispatcher::resetAnrTimeoutsLocked() {
if (DEBUG_FOCUS) {
ALOGD("Resetting ANR timeouts.");
}
@@ -1988,18 +1986,49 @@
return true;
}
+/**
+ * Indicate whether one window handle should be considered as obscuring
+ * another window handle. We only check a few preconditions. Actually
+ * checking the bounds is left to the caller.
+ */
+static bool canBeObscuredBy(const sp<InputWindowHandle>& windowHandle,
+ const sp<InputWindowHandle>& otherHandle) {
+ // Compare by token so cloned layers aren't counted
+ if (haveSameToken(windowHandle, otherHandle)) {
+ return false;
+ }
+ auto info = windowHandle->getInfo();
+ auto otherInfo = otherHandle->getInfo();
+ if (!otherInfo->visible) {
+ return false;
+ } else if (info->ownerPid == otherInfo->ownerPid && otherHandle->getToken() == nullptr) {
+ // In general, if ownerPid is the same we don't want to generate occlusion
+ // events. This line is now necessary since we are including all Surfaces
+ // in occlusion calculation, so if we didn't check PID like this SurfaceView
+ // would occlude their parents. On the other hand before we started including
+ // all surfaces in occlusion calculation and had this line, we would count
+ // windows with an input channel from the same PID as occluding, and so we
+ // preserve this behavior with the getToken() == null check.
+ return false;
+ } else if (otherInfo->isTrustedOverlay()) {
+ return false;
+ } else if (otherInfo->displayId != info->displayId) {
+ return false;
+ }
+ return true;
+}
+
bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
int32_t x, int32_t y) const {
int32_t displayId = windowHandle->getInfo()->displayId;
const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
- if (otherHandle == windowHandle) {
- break;
+ if (windowHandle == otherHandle) {
+ break; // All future windows are below us. Exit early.
}
-
const InputWindowInfo* otherInfo = otherHandle->getInfo();
- if (otherInfo->displayId == displayId && otherInfo->visible &&
- !otherInfo->isTrustedOverlay() && otherInfo->frameContainsPoint(x, y)) {
+ if (canBeObscuredBy(windowHandle, otherHandle) &&
+ otherInfo->frameContainsPoint(x, y)) {
return true;
}
}
@@ -2011,13 +2040,13 @@
const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
for (const sp<InputWindowHandle>& otherHandle : windowHandles) {
- if (otherHandle == windowHandle) {
- break;
+ if (windowHandle == otherHandle) {
+ break; // All future windows are below us. Exit early.
}
const InputWindowInfo* otherInfo = otherHandle->getInfo();
- if (otherInfo->displayId == displayId && otherInfo->visible &&
- !otherInfo->isTrustedOverlay() && otherInfo->overlaps(windowInfo)) {
+ if (canBeObscuredBy(windowHandle, otherHandle) &&
+ otherInfo->overlaps(windowInfo)) {
return true;
}
}
@@ -2451,11 +2480,8 @@
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::Type::KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
- VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(*keyEntry);
- verifiedEvent.flags = dispatchEntry->resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
- verifiedEvent.action = dispatchEntry->resolvedAction;
- std::array<uint8_t, 32> hmac = mHmacKeyManager.sign(verifiedEvent);
+ const KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+ std::array<uint8_t, 32> hmac = getSignature(*keyEntry, *dispatchEntry);
// Publish the key event.
status =
@@ -2507,12 +2533,8 @@
usingCoords = scaledCoords;
}
}
- VerifiedMotionEvent verifiedEvent =
- verifiedMotionEventFromMotionEntry(*motionEntry);
- verifiedEvent.actionMasked =
- dispatchEntry->resolvedAction & AMOTION_EVENT_ACTION_MASK;
- verifiedEvent.flags = dispatchEntry->resolvedFlags & VERIFIED_MOTION_EVENT_FLAGS;
- std::array<uint8_t, 32> hmac = mHmacKeyManager.sign(verifiedEvent);
+
+ std::array<uint8_t, 32> hmac = getSignature(*motionEntry, *dispatchEntry);
// Publish the motion event.
status = connection->inputPublisher
@@ -2592,6 +2614,28 @@
}
}
+const std::array<uint8_t, 32> InputDispatcher::getSignature(
+ const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const {
+ int32_t actionMasked = dispatchEntry.resolvedAction & AMOTION_EVENT_ACTION_MASK;
+ if ((actionMasked == AMOTION_EVENT_ACTION_UP) || (actionMasked == AMOTION_EVENT_ACTION_DOWN)) {
+ // Only sign events up and down events as the purely move events
+ // are tied to their up/down counterparts so signing would be redundant.
+ VerifiedMotionEvent verifiedEvent = verifiedMotionEventFromMotionEntry(motionEntry);
+ verifiedEvent.actionMasked = actionMasked;
+ verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_MOTION_EVENT_FLAGS;
+ return mHmacKeyManager.sign(verifiedEvent);
+ }
+ return INVALID_HMAC;
+}
+
+const std::array<uint8_t, 32> InputDispatcher::getSignature(
+ const KeyEntry& keyEntry, const DispatchEntry& dispatchEntry) const {
+ VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(keyEntry);
+ verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
+ verifiedEvent.action = dispatchEntry.resolvedAction;
+ return mHmacKeyManager.sign(verifiedEvent);
+}
+
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, uint32_t seq,
bool handled) {
@@ -2704,7 +2748,10 @@
// Monitor channels are never explicitly unregistered.
// We do it automatically when the remote endpoint is closed so don't warn
// about them.
- notify = !connection->monitor;
+ const bool stillHaveWindowHandle =
+ d->getWindowHandleLocked(connection->inputChannel->getConnectionToken()) !=
+ nullptr;
+ notify = !connection->monitor && stillHaveWindowHandle;
if (notify) {
ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. "
"events=0x%x",
@@ -3229,14 +3276,14 @@
int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid,
int32_t injectorUid, int32_t syncMode,
- int32_t timeoutMillis, uint32_t policyFlags) {
+ std::chrono::milliseconds timeout, uint32_t policyFlags) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
- event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
+ "syncMode=%d, timeout=%lld, policyFlags=0x%08x",
+ event->getType(), injectorPid, injectorUid, syncMode, timeout.count(), policyFlags);
#endif
- nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
+ nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
policyFlags |= POLICY_FLAG_INJECTED;
if (hasInjectionPermission(injectorPid, injectorUid)) {
@@ -3280,9 +3327,8 @@
KeyEntry* injectedEntry =
new KeyEntry(incomingKey.getId(), incomingKey.getEventTime(),
VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
- incomingKey.getDisplayId(), policyFlags, action, flags,
- incomingKey.getKeyCode(), incomingKey.getScanCode(),
- incomingKey.getMetaState(), incomingKey.getRepeatCount(),
+ incomingKey.getDisplayId(), policyFlags, action, flags, keyCode,
+ incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
incomingKey.getDownTime());
injectedEntries.push(injectedEntry);
break;
@@ -3424,8 +3470,7 @@
} // release lock
#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Finished with result %d. "
- "injectorPid=%d, injectorUid=%d",
+ ALOGD("injectInputEvent - Finished with result %d. injectorPid=%d, injectorUid=%d",
injectionResult, injectorPid, injectorUid);
#endif
@@ -3598,8 +3643,8 @@
if (canReceiveInput && !noInputChannel) {
ALOGV("Window handle %s has no registered input channel",
handle->getName().c_str());
+ continue;
}
- continue;
}
if (info->displayId != displayId) {
@@ -3757,12 +3802,12 @@
if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
if (oldFocusedApplicationHandle != inputApplicationHandle) {
if (oldFocusedApplicationHandle != nullptr) {
- resetANRTimeoutsLocked();
+ resetAnrTimeoutsLocked();
}
mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
}
} else if (oldFocusedApplicationHandle != nullptr) {
- resetANRTimeoutsLocked();
+ resetAnrTimeoutsLocked();
oldFocusedApplicationHandle.clear();
mFocusedApplicationHandlesByDisplay.erase(displayId);
}
@@ -3843,7 +3888,7 @@
if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
if (mDispatchFrozen && !frozen) {
- resetANRTimeoutsLocked();
+ resetAnrTimeoutsLocked();
}
if (mDispatchEnabled && !enabled) {
@@ -3983,7 +4028,7 @@
resetKeyRepeatLocked();
releasePendingEventLocked();
drainInboundQueueLocked();
- resetANRTimeoutsLocked();
+ resetAnrTimeoutsLocked();
mTouchStatesByDisplay.clear();
mLastHoverWindowHandle.clear();
@@ -4483,7 +4528,7 @@
postCommandLocked(std::move(commandEntry));
}
-void InputDispatcher::onANRLocked(nsecs_t currentTime,
+void InputDispatcher::onAnrLocked(nsecs_t currentTime,
const sp<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
nsecs_t waitStartTime, const char* reason) {
@@ -4500,19 +4545,19 @@
localtime_r(&t, &tm);
char timestr[64];
strftime(timestr, sizeof(timestr), "%F %T", &tm);
- mLastANRState.clear();
- mLastANRState += INDENT "ANR:\n";
- mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr);
- mLastANRState +=
+ mLastAnrState.clear();
+ mLastAnrState += INDENT "ANR:\n";
+ mLastAnrState += StringPrintf(INDENT2 "Time: %s\n", timestr);
+ mLastAnrState +=
StringPrintf(INDENT2 "Window: %s\n",
getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
- mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
- mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
- mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
- dumpDispatchStateLocked(mLastANRState);
+ mLastAnrState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
+ mLastAnrState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
+ mLastAnrState += StringPrintf(INDENT2 "Reason: %s\n", reason);
+ dumpDispatchStateLocked(mLastAnrState);
std::unique_ptr<CommandEntry> commandEntry =
- std::make_unique<CommandEntry>(&InputDispatcher::doNotifyANRLockedInterruptible);
+ std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
commandEntry->inputApplicationHandle = applicationHandle;
commandEntry->inputChannel =
windowHandle != nullptr ? getInputChannelLocked(windowHandle->getToken()) : nullptr;
@@ -4548,13 +4593,13 @@
mLock.lock();
}
-void InputDispatcher::doNotifyANRLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) {
sp<IBinder> token =
commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr;
mLock.unlock();
nsecs_t newTimeout =
- mPolicy->notifyANR(commandEntry->inputApplicationHandle, token, commandEntry->reason);
+ mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason);
mLock.lock();
@@ -4915,9 +4960,9 @@
dump += "Input Dispatcher State:\n";
dumpDispatchStateLocked(dump);
- if (!mLastANRState.empty()) {
+ if (!mLastAnrState.empty()) {
dump += "\nInput Dispatcher State at time of last ANR:\n";
- dump += mLastANRState;
+ dump += mLastAnrState;
}
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index cbba7e1..670d0e1 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -62,7 +62,7 @@
std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
private:
- std::array<uint8_t, 32> sign(const std::vector<uint8_t>& data) const;
+ std::array<uint8_t, 32> sign(const uint8_t* data, size_t size) const;
const std::array<uint8_t, 128> mHmacKey;
};
@@ -103,7 +103,8 @@
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
- int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ int32_t injectorUid, int32_t syncMode,
+ std::chrono::milliseconds timeout,
uint32_t policyFlags) override;
virtual std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override;
@@ -219,7 +220,11 @@
// the pointer stream in order to claim it for a system gesture.
std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay GUARDED_BY(mLock);
- HmacKeyManager mHmacKeyManager;
+ const HmacKeyManager mHmacKeyManager;
+ const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry,
+ const DispatchEntry& dispatchEntry) const;
+ const std::array<uint8_t, 32> getSignature(const KeyEntry& keyEntry,
+ const DispatchEntry& dispatchEntry) const;
// Event injection and synchronization.
std::condition_variable mInjectionResultAvailable;
@@ -310,7 +315,7 @@
int32_t mFocusedDisplayId GUARDED_BY(mLock);
// Dispatcher state at time of last ANR.
- std::string mLastANRState GUARDED_BY(mLock);
+ std::string mLastAnrState GUARDED_BY(mLock);
// Dispatch inbound events.
bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry)
@@ -356,7 +361,7 @@
const sp<IBinder>& inputConnectionToken)
REQUIRES(mLock);
nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock);
- void resetANRTimeoutsLocked() REQUIRES(mLock);
+ void resetAnrTimeoutsLocked() REQUIRES(mLock);
int32_t getTargetDisplayId(const EventEntry& entry);
int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry& entry,
@@ -464,7 +469,7 @@
REQUIRES(mLock);
void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
const sp<InputWindowHandle>& newFocus) REQUIRES(mLock);
- void onANRLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
+ void onAnrLocked(nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
const sp<InputWindowHandle>& windowHandle, nsecs_t eventTime,
nsecs_t waitStartTime, const char* reason) REQUIRES(mLock);
@@ -473,7 +478,7 @@
REQUIRES(mLock);
void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
- void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+ void doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
REQUIRES(mLock);
void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 09dc92c..9b002f4 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -90,8 +90,8 @@
* This method may be called on any thread (usually by the input manager).
*/
virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid,
- int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags) = 0;
+ int32_t injectorUid, int32_t syncMode,
+ std::chrono::milliseconds timeout, uint32_t policyFlags) = 0;
/*
* Check whether InputEvent actually happened by checking the signature of the event.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 4214488..667af9b 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -47,7 +47,7 @@
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+ virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& inputApplicationHandle,
const sp<IBinder>& token, const std::string& reason) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index f8d0150..8317b05 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -22,7 +22,6 @@
#include <input/Input.h>
#include <input/TouchVideoFrame.h>
#include <utils/RefBase.h>
-#include <utils/Vector.h>
namespace android {
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index d77c8c8..43bd9f1 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -255,6 +255,7 @@
getDeviceName().c_str());
cancelTouch(when);
}
+ continue;
}
if (outCount >= MAX_POINTERS) {
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 29f3dac..f33cc65 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -83,9 +83,13 @@
args.displayId);
}
- void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
+ void assertFilterInputEventWasNotCalled() {
+ std::scoped_lock lock(mLock);
+ ASSERT_EQ(nullptr, mFilteredEvent);
+ }
void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
+ std::scoped_lock lock(mLock);
ASSERT_TRUE(mConfigurationChangedTime)
<< "Timed out waiting for configuration changed call";
ASSERT_EQ(*mConfigurationChangedTime, when);
@@ -93,6 +97,7 @@
}
void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
+ std::scoped_lock lock(mLock);
ASSERT_TRUE(mLastNotifySwitch);
// We do not check id because it is not exposed to the policy
EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
@@ -103,11 +108,13 @@
}
void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
+ std::scoped_lock lock(mLock);
ASSERT_EQ(touchedToken, mOnPointerDownToken);
mOnPointerDownToken.clear();
}
void assertOnPointerDownWasNotCalled() {
+ std::scoped_lock lock(mLock);
ASSERT_TRUE(mOnPointerDownToken == nullptr)
<< "Expected onPointerDownOutsideFocus to not have been called";
}
@@ -118,32 +125,32 @@
}
private:
- std::unique_ptr<InputEvent> mFilteredEvent;
- std::optional<nsecs_t> mConfigurationChangedTime;
- sp<IBinder> mOnPointerDownToken;
- std::optional<NotifySwitchArgs> mLastNotifySwitch;
+ std::mutex mLock;
+ std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
+ std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
+ sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
+ std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
virtual void notifyConfigurationChanged(nsecs_t when) override {
+ std::scoped_lock lock(mLock);
mConfigurationChangedTime = when;
}
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
- const sp<IBinder>&,
- const std::string&) {
+ virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&,
+ const std::string&) override {
return 0;
}
- virtual void notifyInputChannelBroken(const sp<IBinder>&) {
- }
+ virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
- virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
- }
+ virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
- virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
+ virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
*outConfig = mConfig;
}
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
+ std::scoped_lock lock(mLock);
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY: {
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
@@ -160,43 +167,43 @@
return true;
}
- virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
- }
+ virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
- virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
- }
+ virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
- const KeyEvent*, uint32_t) {
+ virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
+ uint32_t) override {
return 0;
}
- virtual bool dispatchUnhandledKey(const sp<IBinder>&,
- const KeyEvent*, uint32_t, KeyEvent*) {
+ virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
+ KeyEvent*) override {
return false;
}
virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
uint32_t policyFlags) override {
+ std::scoped_lock lock(mLock);
/** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
* essentially a passthrough for notifySwitch.
*/
mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
}
- virtual void pokeUserActivity(nsecs_t, int32_t) {
- }
+ virtual void pokeUserActivity(nsecs_t, int32_t) override {}
- virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
+ virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
return false;
}
- virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
+ virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
+ std::scoped_lock lock(mLock);
mOnPointerDownToken = newToken;
}
void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
int32_t displayId) {
+ std::scoped_lock lock(mLock);
ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
ASSERT_EQ(mFilteredEvent->getType(), type);
@@ -313,18 +320,18 @@
INVALID_HMAC,
/*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
ARBITRARY_TIME);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject key events with undefined action.";
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
ARBITRARY_TIME, ARBITRARY_TIME);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject key events with ACTION_MULTIPLE.";
}
@@ -350,9 +357,9 @@
1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
@@ -363,9 +370,9 @@
0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with pointer down index too large.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -375,9 +382,9 @@
0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
@@ -388,9 +395,9 @@
0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with pointer up index too large.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -400,9 +407,9 @@
0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
@@ -412,9 +419,9 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with 0 pointers.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -423,9 +430,9 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
@@ -436,9 +443,9 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerProperties[0].id = MAX_POINTER_ID + 1;
@@ -448,9 +455,9 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
@@ -462,9 +469,9 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
<< "Should reject motion events with duplicate pointer ids.";
}
@@ -490,16 +497,16 @@
}
// --- InputDispatcherTest SetInputWindowTest ---
-static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
-static constexpr int32_t DISPATCHING_TIMEOUT = 100;
+static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
+static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
class FakeApplicationHandle : public InputApplicationHandle {
public:
FakeApplicationHandle() {}
virtual ~FakeApplicationHandle() {}
- virtual bool updateInfo() {
- mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ virtual bool updateInfo() override {
+ mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
return true;
}
};
@@ -634,11 +641,11 @@
mInfo.applicationInfo = *inputApplicationHandle->getInfo();
mInfo.token = token;
- mInfo.id = 0;
+ mInfo.id = sId++;
mInfo.name = name;
mInfo.layoutParamsFlags = 0;
mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
- mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
mInfo.frameLeft = 0;
mInfo.frameTop = 0;
mInfo.frameRight = WIDTH;
@@ -672,8 +679,6 @@
void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
- void setId(int32_t id) { mInfo.id = id; }
-
void setWindowScale(float xScale, float yScale) {
mInfo.windowXScale = xScale;
mInfo.windowYScale = yScale;
@@ -755,8 +760,11 @@
private:
const std::string mName;
std::unique_ptr<FakeInputReceiver> mInputReceiver;
+ static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
};
+std::atomic<int32_t> FakeWindowHandle::sId{1};
+
static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
int32_t displayId = ADISPLAY_ID_NONE) {
KeyEvent event;
@@ -810,13 +818,15 @@
}
static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
- int32_t displayId, int32_t x = 100, int32_t y = 200) {
- return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
+ int32_t displayId, const PointF& location = {100, 200}) {
+ return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x,
+ location.y);
}
static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
- int32_t displayId, int32_t x = 100, int32_t y = 200) {
- return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
+ int32_t displayId, const PointF& location = {100, 200}) {
+ return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location.x,
+ location.y);
}
static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
@@ -880,6 +890,55 @@
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
}
+/**
+ * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
+ * To ensure that window receives only events that were directly inside of it, add
+ * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
+ * when finding touched windows.
+ * This test serves as a sanity check for the next test, where setInputWindows is
+ * called twice.
+ */
+TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 100, 100));
+ window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {50, 50}))
+ << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+ // Window should receive motion event.
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+}
+
+/**
+ * Calling setInputWindows twice, with the same info, should not cause any issues.
+ * To ensure that window receives only events that were directly inside of it, add
+ * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
+ * when finding touched windows.
+ */
+TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 100, 100));
+ window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {50, 50}))
+ << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+ // Window should receive motion event.
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+}
+
// The foreground window should receive the first touch down event.
TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
@@ -1821,7 +1880,6 @@
new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
- mFocusedWindowTouchPoint = 60;
// Set focused application.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1842,16 +1900,18 @@
protected:
sp<FakeWindowHandle> mUnfocusedWindow;
sp<FakeWindowHandle> mFocusedWindow;
- int32_t mFocusedWindowTouchPoint;
+ static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
};
// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
// the onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
- ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
- AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {20, 20}))
<< "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ mUnfocusedWindow->consumeMotionDown();
ASSERT_TRUE(mDispatcher->waitForIdle());
mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
@@ -1861,9 +1921,10 @@
// DOWN on the window that doesn't have focus. Ensure no window received the
// onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
- ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
- AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
+ ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
<< "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ mFocusedWindow->consumeMotionDown();
ASSERT_TRUE(mDispatcher->waitForIdle());
mFakePolicy->assertOnPointerDownWasNotCalled();
@@ -1874,6 +1935,7 @@
TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
<< "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
ASSERT_TRUE(mDispatcher->waitForIdle());
mFakePolicy->assertOnPointerDownWasNotCalled();
@@ -1886,8 +1948,9 @@
OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
+ FOCUSED_WINDOW_TOUCH_POINT))
<< "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ mFocusedWindow->consumeMotionDown();
ASSERT_TRUE(mDispatcher->waitForIdle());
mFakePolicy->assertOnPointerDownWasNotCalled();
@@ -1906,14 +1969,12 @@
// We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
InputWindowInfo::FLAG_SPLIT_TOUCH);
- mWindow1->setId(0);
mWindow1->setFrame(Rect(0, 0, 100, 100));
mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
ADISPLAY_ID_DEFAULT, mWindow1->getToken());
mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
InputWindowInfo::FLAG_SPLIT_TOUCH);
- mWindow2->setId(1);
mWindow2->setFrame(Rect(100, 100, 200, 200));
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 96d86b6..109edfe 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1748,7 +1748,8 @@
virtual void SetUp() override {
mFakePolicy = new FakeInputReaderPolicy();
- mTestListener = new TestInputListener(50ms);
+ mTestListener = new TestInputListener(2000ms /*eventHappenedTimeout*/,
+ 30ms /*eventDidNotHappenTimeout*/);
mReader = new InputReader(std::make_shared<EventHub>(), mFakePolicy, mTestListener);
ASSERT_EQ(mReader->start(), OK);
@@ -7081,6 +7082,76 @@
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
}
+/**
+ * Test multi-touch should be canceled when received the MT_TOOL_PALM event from some finger,
+ * and could be allowed again after all non-MT_TOOL_PALM is release and the new point is
+ * MT_TOOL_FINGER.
+ */
+TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType2) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ NotifyMotionArgs motionArgs;
+
+ // default tool type is finger
+ constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
+ processId(mapper, 1);
+ processPosition(mapper, x1, y1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+
+ // Second finger down.
+ processSlot(mapper, 1);
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+
+ // If the tool type of the first pointer changes to MT_TOOL_PALM,
+ // the entire gesture should be aborted, so we expect to receive ACTION_CANCEL.
+ processSlot(mapper, 0);
+ processId(mapper, 1);
+ processToolType(mapper, MT_TOOL_PALM);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
+
+ // Ignore the following MOVE and UP events if had detect a palm event.
+ processSlot(mapper, 1);
+ processId(mapper, 2);
+ processPosition(mapper, x3, y3);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // second finger up.
+ processId(mapper, -1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // first finger move, but still in palm
+ processSlot(mapper, 0);
+ processId(mapper, 1);
+ processPosition(mapper, x1 - 1, y1 - 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // second finger down, expect as new finger down.
+ processSlot(mapper, 1);
+ processId(mapper, 2);
+ processPosition(mapper, x2, y2);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+}
+
// --- MultiTouchInputMapperTest_ExternalDevice ---
class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp
index 86ff3b1..9bff166 100644
--- a/services/inputflinger/tests/TestInputListener.cpp
+++ b/services/inputflinger/tests/TestInputListener.cpp
@@ -23,7 +23,10 @@
// --- TestInputListener ---
-TestInputListener::TestInputListener(const std::chrono::milliseconds timeout) : mTimeout(timeout) {}
+TestInputListener::TestInputListener(std::chrono::milliseconds eventHappenedTimeout,
+ std::chrono::milliseconds eventDidNotHappenTimeout)
+ : mEventHappenedTimeout(eventHappenedTimeout),
+ mEventDidNotHappenTimeout(eventDidNotHappenTimeout) {}
TestInputListener::~TestInputListener() { }
@@ -86,9 +89,9 @@
std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
if (queue.empty()) {
- const bool eventReceived = mCondition.wait_for(lock, mTimeout, [&queue]() REQUIRES(mLock) {
- return !queue.empty();
- });
+ const bool eventReceived =
+ mCondition.wait_for(lock, mEventHappenedTimeout,
+ [&queue]() REQUIRES(mLock) { return !queue.empty(); });
if (!eventReceived) {
FAIL() << "Timed out waiting for event: " << message.c_str();
}
@@ -105,9 +108,9 @@
base::ScopedLockAssertion assumeLocked(mLock);
std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- const bool eventReceived = mCondition.wait_for(lock, mTimeout, [&queue]() REQUIRES(mLock) {
- return !queue.empty();
- });
+ const bool eventReceived =
+ mCondition.wait_for(lock, mEventDidNotHappenTimeout,
+ [&queue]() REQUIRES(mLock) { return !queue.empty(); });
if (eventReceived) {
FAIL() << "Unexpected event: " << message.c_str();
}
diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h
index 4262f5a..d50c6bc 100644
--- a/services/inputflinger/tests/TestInputListener.h
+++ b/services/inputflinger/tests/TestInputListener.h
@@ -32,7 +32,8 @@
virtual ~TestInputListener();
public:
- TestInputListener(const std::chrono::milliseconds timeout = 5ms);
+ TestInputListener(std::chrono::milliseconds eventHappenedTimeout = 0ms,
+ std::chrono::milliseconds eventDidNotHappenTimeout = 0ms);
void assertNotifyConfigurationChangedWasCalled(
NotifyConfigurationChangedArgs* outEventArgs = nullptr);
@@ -75,7 +76,8 @@
std::mutex mLock;
std::condition_variable mCondition;
- const std::chrono::milliseconds mTimeout;
+ const std::chrono::milliseconds mEventHappenedTimeout;
+ const std::chrono::milliseconds mEventDidNotHappenTimeout;
std::tuple<std::vector<NotifyConfigurationChangedArgs>, //
std::vector<NotifyDeviceResetArgs>, //
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 3b68e0e..45e67f7 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -20,7 +20,6 @@
#include "android/hardware/sensors/2.1/ISensorsCallback.h"
#include "android/hardware/sensors/2.1/types.h"
#include "convertV2_1.h"
-#include "SensorService.h"
#include <android-base/logging.h>
#include <android/util/ProtoOutputStream.h>
@@ -30,6 +29,7 @@
#include <utils/Errors.h>
#include <utils/Singleton.h>
+#include <cstddef>
#include <chrono>
#include <cinttypes>
#include <thread>
@@ -143,6 +143,25 @@
for (size_t i=0 ; i < count; i++) {
sensor_t sensor;
convertToSensor(convertToOldSensorInfo(list[i]), &sensor);
+
+ if (sensor.type < static_cast<int>(SensorType::DEVICE_PRIVATE_BASE)) {
+ if(sensor.resolution == 0) {
+ // Don't crash here or the device will go into a crashloop.
+ ALOGW("%s must have a non-zero resolution", sensor.name);
+ // For simple algos, map their resolution to 1 if it's not specified
+ sensor.resolution =
+ SensorDeviceUtils::defaultResolutionForType(sensor.type);
+ }
+
+ double promotedResolution = sensor.resolution;
+ double promotedMaxRange = sensor.maxRange;
+ if (fmod(promotedMaxRange, promotedResolution) != 0) {
+ ALOGW("%s's max range %f is not a multiple of the resolution %f",
+ sensor.name, sensor.maxRange, sensor.resolution);
+ SensorDeviceUtils::quantizeValue(&sensor.maxRange, promotedResolution);
+ }
+ }
+
// Sanity check and clamp power if it is 0 (or close)
if (sensor.power < minPowerMa) {
ALOGI("Reported power %f not deemed sane, clamping to %f",
@@ -403,8 +422,8 @@
if (mSensors == nullptr) return "HAL not initialized\n";
String8 result;
- result.appendFormat("Total %zu h/w sensors, %zu running:\n",
- mSensorList.size(), mActivationCount.size());
+ result.appendFormat("Total %zu h/w sensors, %zu running %zu disabled clients:\n",
+ mSensorList.size(), mActivationCount.size(), mDisabledClients.size());
Mutex::Autolock _l(mLock);
for (const auto & s : mSensorList) {
@@ -417,16 +436,18 @@
result.append("sampling_period(ms) = {");
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& params = info.batchParams[j];
- result.appendFormat("%.1f%s", params.mTSample / 1e6f,
- j < info.batchParams.size() - 1 ? ", " : "");
+ result.appendFormat("%.1f%s%s", params.mTSample / 1e6f,
+ isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)" : "",
+ (j < info.batchParams.size() - 1) ? ", " : "");
}
result.appendFormat("}, selected = %.2f ms; ", info.bestBatchParams.mTSample / 1e6f);
result.append("batching_period(ms) = {");
for (size_t j = 0; j < info.batchParams.size(); j++) {
const BatchParams& params = info.batchParams[j];
- result.appendFormat("%.1f%s", params.mTBatch / 1e6f,
- j < info.batchParams.size() - 1 ? ", " : "");
+ result.appendFormat("%.1f%s%s", params.mTBatch / 1e6f,
+ isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)" : "",
+ (j < info.batchParams.size() - 1) ? ", " : "");
}
result.appendFormat("}, selected = %.2f ms\n", info.bestBatchParams.mTBatch / 1e6f);
}
@@ -508,7 +529,7 @@
const auto &events,
const auto &dynamicSensorsAdded) {
if (result == Result::OK) {
- convertToSensorEvents(convertToNewEvents(events),
+ convertToSensorEventsAndQuantize(convertToNewEvents(events),
convertToNewSensorInfos(dynamicSensorsAdded), buffer);
err = (ssize_t)events.size();
} else {
@@ -571,6 +592,8 @@
for (size_t i = 0; i < eventsToRead; i++) {
convertToSensorEvent(mEventBuffer[i], &buffer[i]);
+ android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
+ getResolutionForSensor(buffer[i].sensor));
}
eventsRead = eventsToRead;
} else {
@@ -641,7 +664,7 @@
}
status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
- bool actuateHardware = false;
+ bool activateHardware = false;
status_t err(NO_ERROR);
@@ -667,7 +690,7 @@
if (info.batchParams.indexOfKey(ident) >= 0) {
if (info.numActiveClients() > 0 && !info.isActive) {
- actuateHardware = true;
+ activateHardware = true;
}
} else {
// Log error. Every activate call should be preceded by a batch() call.
@@ -687,7 +710,7 @@
if (info.removeBatchParamsForIdent(ident) >= 0) {
if (info.numActiveClients() == 0) {
// This is the last connection, we need to de-activate the underlying h/w sensor.
- actuateHardware = true;
+ activateHardware = true;
} else {
// Call batch for this sensor with the previously calculated best effort
// batch_rate and timeout. One of the apps has unregistered for sensor
@@ -707,12 +730,8 @@
}
}
- if (actuateHardware) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
- enabled);
- err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
- ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
- strerror(-err));
+ if (activateHardware) {
+ err = doActivateHardwareLocked(handle, enabled);
if (err != NO_ERROR && enabled) {
// Failure when enabling the sensor. Clean up on failure.
@@ -728,6 +747,15 @@
return err;
}
+status_t SensorDevice::doActivateHardwareLocked(int handle, bool enabled) {
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
+ enabled);
+ status_t err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
+ ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
+ strerror(-err));
+ return err;
+}
+
status_t SensorDevice::batch(
void* ident,
int handle,
@@ -768,6 +796,18 @@
info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
}
+ status_t err = updateBatchParamsLocked(handle, info);
+ if (err != NO_ERROR) {
+ ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
+ mSensors.get(), handle, info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch, strerror(-err));
+ info.removeBatchParamsForIdent(ident);
+ }
+
+ return err;
+}
+
+status_t SensorDevice::updateBatchParamsLocked(int handle, Info &info) {
BatchParams prevBestBatchParams = info.bestBatchParams;
// Find the minimum of all timeouts and batch_rates for this sensor.
info.selectBatchParams();
@@ -785,13 +825,8 @@
info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
err = checkReturnAndGetStatus(mSensors->batch(
handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
- if (err != NO_ERROR) {
- ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
- mSensors.get(), handle, info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch, strerror(-err));
- info.removeBatchParamsForIdent(ident);
- }
}
+
return err;
}
@@ -811,13 +846,61 @@
return checkReturnAndGetStatus(mSensors->flush(handle));
}
-bool SensorDevice::isClientDisabled(void* ident) {
+bool SensorDevice::isClientDisabled(void* ident) const {
Mutex::Autolock _l(mLock);
return isClientDisabledLocked(ident);
}
-bool SensorDevice::isClientDisabledLocked(void* ident) {
- return mDisabledClients.indexOf(ident) >= 0;
+bool SensorDevice::isClientDisabledLocked(void* ident) const {
+ return mDisabledClients.count(ident) > 0;
+}
+
+std::vector<void *> SensorDevice::getDisabledClientsLocked() const {
+ std::vector<void *> vec;
+ for (const auto& it : mDisabledClients) {
+ vec.push_back(it.first);
+ }
+
+ return vec;
+}
+
+void SensorDevice::addDisabledReasonForIdentLocked(void* ident, DisabledReason reason) {
+ mDisabledClients[ident] |= 1 << reason;
+}
+
+void SensorDevice::removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason) {
+ if (isClientDisabledLocked(ident)) {
+ mDisabledClients[ident] &= ~(1 << reason);
+ if (mDisabledClients[ident] == 0) {
+ mDisabledClients.erase(ident);
+ }
+ }
+}
+
+void SensorDevice::setUidStateForConnection(void* ident, SensorService::UidState state) {
+ Mutex::Autolock _l(mLock);
+ if (state == SensorService::UID_STATE_ACTIVE) {
+ removeDisabledReasonForIdentLocked(ident, DisabledReason::DISABLED_REASON_UID_IDLE);
+ } else {
+ addDisabledReasonForIdentLocked(ident, DisabledReason::DISABLED_REASON_UID_IDLE);
+ }
+
+ for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ int handle = mActivationCount.keyAt(i);
+ Info& info = mActivationCount.editValueAt(i);
+
+ if (info.hasBatchParamsForIdent(ident)) {
+ if (updateBatchParamsLocked(handle, info) != NO_ERROR) {
+ bool enable = info.numActiveClients() == 0 && info.isActive;
+ bool disable = info.numActiveClients() > 0 && !info.isActive;
+
+ if ((enable || disable) &&
+ doActivateHardwareLocked(handle, enable) == NO_ERROR) {
+ info.isActive = enable;
+ }
+ }
+ }
+ }
}
bool SensorDevice::isSensorActive(int handle) const {
@@ -832,8 +915,12 @@
void SensorDevice::enableAllSensors() {
if (mSensors == nullptr) return;
Mutex::Autolock _l(mLock);
- mDisabledClients.clear();
- ALOGI("cleared mDisabledClients");
+
+ for (void *client : getDisabledClientsLocked()) {
+ removeDisabledReasonForIdentLocked(
+ client, DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
+ }
+
for (size_t i = 0; i< mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(i);
if (info.batchParams.isEmpty()) continue;
@@ -873,7 +960,8 @@
// Add all the connections that were registered for this sensor to the disabled
// clients list.
for (size_t j = 0; j < info.batchParams.size(); ++j) {
- mDisabledClients.add(info.batchParams.keyAt(j));
+ addDisabledReasonForIdentLocked(
+ info.batchParams.keyAt(j), DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
}
@@ -1048,7 +1136,7 @@
void SensorDevice::notifyConnectionDestroyed(void* ident) {
Mutex::Autolock _l(mLock);
- mDisabledClients.remove(ident);
+ mDisabledClients.erase(ident);
}
bool SensorDevice::isDirectReportSupported() const {
@@ -1077,7 +1165,7 @@
}
}
-void SensorDevice::convertToSensorEvents(
+void SensorDevice::convertToSensorEventsAndQuantize(
const hidl_vec<Event> &src,
const hidl_vec<SensorInfo> &dynamicSensorsAdded,
sensors_event_t *dst) {
@@ -1088,9 +1176,26 @@
for (size_t i = 0; i < src.size(); ++i) {
V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
+ android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
+ getResolutionForSensor(dst[i].sensor));
}
}
+float SensorDevice::getResolutionForSensor(int sensorHandle) {
+ for (size_t i = 0; i < mSensorList.size(); i++) {
+ if (sensorHandle == mSensorList[i].handle) {
+ return mSensorList[i].resolution;
+ }
+ }
+
+ auto it = mConnectedDynamicSensors.find(sensorHandle);
+ if (it != mConnectedDynamicSensors.end()) {
+ return it->second->resolution;
+ }
+
+ return 0;
+}
+
void SensorDevice::handleHidlDeath(const std::string & detail) {
if (!mSensors->supportsMessageQueues()) {
// restart is the only option at present.
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 24d03c6..5e7d3da 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -18,6 +18,7 @@
#define ANDROID_SENSOR_DEVICE_H
#include "SensorDeviceUtils.h"
+#include "SensorService.h"
#include "SensorServiceUtils.h"
#include "ISensorsWrapper.h"
@@ -116,6 +117,8 @@
hardware::Return<void> onDynamicSensorsDisconnected(
const hardware::hidl_vec<int32_t> &dynamicSensorHandlesRemoved);
+ void setUidStateForConnection(void* ident, SensorService::UidState state);
+
bool isReconnecting() const {
return mReconnecting;
}
@@ -179,6 +182,13 @@
// the removed ident. If index >=0, ident is present and successfully removed.
ssize_t removeBatchParamsForIdent(void* ident);
+ bool hasBatchParamsForIdent(void* ident) const {
+ return batchParams.indexOfKey(ident) >= 0;
+ }
+
+ /**
+ * @return The number of active clients of this sensor.
+ */
int numActiveClients() const;
};
DefaultKeyedVector<int, Info> mActivationCount;
@@ -187,8 +197,26 @@
SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
int mTotalHidlTransportErrors;
- // Use this vector to determine which client is activated or deactivated.
- SortedVector<void *> mDisabledClients;
+ /**
+ * Enums describing the reason why a client was disabled.
+ */
+ enum DisabledReason : uint8_t {
+ // UID becomes idle (e.g. app goes to background).
+ DISABLED_REASON_UID_IDLE = 0,
+
+ // Sensors are restricted for all clients.
+ DISABLED_REASON_SERVICE_RESTRICTED,
+ DISABLED_REASON_MAX,
+ };
+
+ static_assert(DisabledReason::DISABLED_REASON_MAX < sizeof(uint8_t) * CHAR_BIT);
+
+ // Use this map to determine which client is activated or deactivated.
+ std::unordered_map<void *, uint8_t> mDisabledClients;
+
+ void addDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
+ void removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
+
SensorDevice();
bool connectHidlService();
void initializeSensorList();
@@ -214,6 +242,9 @@
status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs);
+ status_t updateBatchParamsLocked(int handle, Info& info);
+ status_t doActivateHardwareLocked(int handle, bool enable);
+
void handleHidlDeath(const std::string &detail);
template<typename T>
void checkReturn(const Return<T>& ret) {
@@ -225,19 +256,24 @@
//TODO(b/67425500): remove waiter after bug is resolved.
sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
- bool isClientDisabled(void* ident);
- bool isClientDisabledLocked(void* ident);
+ bool isClientDisabled(void* ident) const;
+ bool isClientDisabledLocked(void* ident) const;
+ std::vector<void *> getDisabledClientsLocked() const;
+
+ bool clientHasNoAccessLocked(void* ident) const;
using Event = hardware::sensors::V2_1::Event;
using SensorInfo = hardware::sensors::V2_1::SensorInfo;
void convertToSensorEvent(const Event &src, sensors_event_t *dst);
- void convertToSensorEvents(
+ void convertToSensorEventsAndQuantize(
const hardware::hidl_vec<Event> &src,
const hardware::hidl_vec<SensorInfo> &dynamicSensorsAdded,
sensors_event_t *dst);
+ float getResolutionForSensor(int sensorHandle);
+
bool mIsDirectReportSupported;
typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue;
diff --git a/services/sensorservice/SensorDeviceUtils.cpp b/services/sensorservice/SensorDeviceUtils.cpp
index dbafffe..0dcf8c0 100644
--- a/services/sensorservice/SensorDeviceUtils.cpp
+++ b/services/sensorservice/SensorDeviceUtils.cpp
@@ -17,17 +17,101 @@
#include "SensorDeviceUtils.h"
#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/2.1/ISensors.h>
#include <utils/Log.h>
#include <chrono>
#include <thread>
using ::android::hardware::Void;
+using SensorTypeV2_1 = android::hardware::sensors::V2_1::SensorType;
using namespace android::hardware::sensors::V1_0;
namespace android {
namespace SensorDeviceUtils {
+void quantizeSensorEventValues(sensors_event_t *event, float resolution) {
+ LOG_FATAL_IF(resolution == 0, "Resolution must be specified for all sensors!");
+ if (resolution == 0) {
+ return;
+ }
+
+ size_t axes = 0;
+ switch ((SensorTypeV2_1)event->type) {
+ case SensorTypeV2_1::ACCELEROMETER:
+ case SensorTypeV2_1::MAGNETIC_FIELD:
+ case SensorTypeV2_1::ORIENTATION:
+ case SensorTypeV2_1::GYROSCOPE:
+ case SensorTypeV2_1::GRAVITY:
+ case SensorTypeV2_1::LINEAR_ACCELERATION:
+ case SensorTypeV2_1::MAGNETIC_FIELD_UNCALIBRATED:
+ case SensorTypeV2_1::GYROSCOPE_UNCALIBRATED:
+ case SensorTypeV2_1::ACCELEROMETER_UNCALIBRATED:
+ axes = 3;
+ break;
+ case SensorTypeV2_1::GAME_ROTATION_VECTOR:
+ axes = 4;
+ break;
+ case SensorTypeV2_1::ROTATION_VECTOR:
+ case SensorTypeV2_1::GEOMAGNETIC_ROTATION_VECTOR:
+ axes = 5;
+ break;
+ case SensorTypeV2_1::DEVICE_ORIENTATION:
+ case SensorTypeV2_1::LIGHT:
+ case SensorTypeV2_1::PRESSURE:
+ case SensorTypeV2_1::TEMPERATURE:
+ case SensorTypeV2_1::PROXIMITY:
+ case SensorTypeV2_1::RELATIVE_HUMIDITY:
+ case SensorTypeV2_1::AMBIENT_TEMPERATURE:
+ case SensorTypeV2_1::SIGNIFICANT_MOTION:
+ case SensorTypeV2_1::STEP_DETECTOR:
+ case SensorTypeV2_1::TILT_DETECTOR:
+ case SensorTypeV2_1::WAKE_GESTURE:
+ case SensorTypeV2_1::GLANCE_GESTURE:
+ case SensorTypeV2_1::PICK_UP_GESTURE:
+ case SensorTypeV2_1::WRIST_TILT_GESTURE:
+ case SensorTypeV2_1::STATIONARY_DETECT:
+ case SensorTypeV2_1::MOTION_DETECT:
+ case SensorTypeV2_1::HEART_BEAT:
+ case SensorTypeV2_1::LOW_LATENCY_OFFBODY_DETECT:
+ case SensorTypeV2_1::HINGE_ANGLE:
+ axes = 1;
+ break;
+ case SensorTypeV2_1::POSE_6DOF:
+ axes = 15;
+ break;
+ default:
+ // No other sensors have data that needs to be rounded.
+ break;
+ }
+
+ // sensor_event_t is a union so we're able to perform the same quanitization action for most
+ // sensors by only knowing the number of axes their output data has.
+ for (size_t i = 0; i < axes; i++) {
+ quantizeValue(&event->data[i], resolution);
+ }
+}
+
+float defaultResolutionForType(int type) {
+ switch ((SensorTypeV2_1)type) {
+ case SensorTypeV2_1::SIGNIFICANT_MOTION:
+ case SensorTypeV2_1::STEP_DETECTOR:
+ case SensorTypeV2_1::STEP_COUNTER:
+ case SensorTypeV2_1::TILT_DETECTOR:
+ case SensorTypeV2_1::WAKE_GESTURE:
+ case SensorTypeV2_1::GLANCE_GESTURE:
+ case SensorTypeV2_1::PICK_UP_GESTURE:
+ case SensorTypeV2_1::WRIST_TILT_GESTURE:
+ case SensorTypeV2_1::STATIONARY_DETECT:
+ case SensorTypeV2_1::MOTION_DETECT:
+ return 1.0f;
+ default:
+ // fall through and return 0 for all other types
+ break;
+ }
+ return 0.0f;
+}
+
HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter() {
}
diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h
index e2eb606..d7e621c 100644
--- a/services/sensorservice/SensorDeviceUtils.h
+++ b/services/sensorservice/SensorDeviceUtils.h
@@ -18,7 +18,9 @@
#define ANDROID_SENSOR_DEVICE_UTIL
#include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <hardware/sensors.h>
+#include <cmath>
#include <condition_variable>
#include <thread>
@@ -29,6 +31,21 @@
namespace android {
namespace SensorDeviceUtils {
+// Quantizes a single value using a sensor's resolution.
+inline void quantizeValue(float *value, double resolution) {
+ // Increase the value of the sensor's nominal resolution to ensure that
+ // sensor accuracy improvements, like runtime calibration, are not masked
+ // during requantization.
+ double incRes = 0.25 * resolution;
+ *value = round(static_cast<double>(*value) / incRes) * incRes;
+}
+
+// Ensures a sensor event doesn't provide values finer grained than its sensor resolution allows.
+void quantizeSensorEventValues(sensors_event_t *event, float resolution);
+
+// Provides a default resolution for simple sensor types if one wasn't provided by the HAL.
+float defaultResolutionForType(int type);
+
class HidlServiceRegistrationWaiter : public IServiceNotification {
public:
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index 1622e77..e4c33da 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -93,21 +93,16 @@
return nullptr;
}
-void SensorService::SensorDirectConnection::updateSensorSubscriptions() {
- if (!hasSensorAccess()) {
+void SensorService::SensorDirectConnection::onSensorAccessChanged(bool hasAccess) {
+ if (!hasAccess) {
stopAll(true /* backupRecord */);
} else {
recoverAll();
}
}
-void SensorService::SensorDirectConnection::setSensorAccess(bool hasAccess) {
- mHasSensorAccess = hasAccess;
- updateSensorSubscriptions();
-}
-
bool SensorService::SensorDirectConnection::hasSensorAccess() const {
- return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
+ return mService->hasSensorAccess(mUid, mOpPackageName);
}
status_t SensorService::SensorDirectConnection::enableDisable(
@@ -142,7 +137,7 @@
return NO_ERROR;
}
- if (!mService->isOperationPermitted(mOpPackageName)) {
+ if (!hasSensorAccess()) {
return PERMISSION_DENIED;
}
@@ -186,12 +181,15 @@
}
void SensorService::SensorDirectConnection::stopAll(bool backupRecord) {
+ Mutex::Autolock _l(mConnectionLock);
+ stopAllLocked(backupRecord);
+}
+void SensorService::SensorDirectConnection::stopAllLocked(bool backupRecord) {
struct sensors_direct_cfg_t config = {
.rate_level = SENSOR_DIRECT_RATE_STOP
};
- Mutex::Autolock _l(mConnectionLock);
SensorDevice& dev(SensorDevice::getInstance());
for (auto &i : mActivated) {
dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
@@ -204,21 +202,25 @@
}
void SensorService::SensorDirectConnection::recoverAll() {
- stopAll(false);
-
Mutex::Autolock _l(mConnectionLock);
- SensorDevice& dev(SensorDevice::getInstance());
+ if (!mActivatedBackup.empty()) {
+ stopAllLocked(false);
- // recover list of report from backup
- mActivated = mActivatedBackup;
- mActivatedBackup.clear();
+ SensorDevice& dev(SensorDevice::getInstance());
- // re-enable them
- for (auto &i : mActivated) {
- struct sensors_direct_cfg_t config = {
- .rate_level = i.second
- };
- dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
+ // recover list of report from backup
+ ALOG_ASSERT(mActivated.empty(),
+ "mActivated must be empty if mActivatedBackup was non-empty");
+ mActivated = mActivatedBackup;
+ mActivatedBackup.clear();
+
+ // re-enable them
+ for (auto &i : mActivated) {
+ struct sensors_direct_cfg_t config = {
+ .rate_level = i.second
+ };
+ dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
+ }
}
}
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index fa88fbc..4181b65 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -42,21 +42,15 @@
void dump(String8& result) const;
void dump(util::ProtoOutputStream* proto) const;
uid_t getUid() const { return mUid; }
+ const String16& getOpPackageName() const { return mOpPackageName; }
int32_t getHalChannelHandle() const;
bool isEquivalent(const sensors_direct_mem_t *mem) const;
- // stop all active sensor report. if backupRecord is set to false,
- // those report can be recovered by recoverAll
- // called by SensorService when enter restricted mode
- void stopAll(bool backupRecord = false);
+ // Invoked when access to sensors for this connection has changed, e.g. lost or
+ // regained due to changes in the sensor restricted/privacy mode or the
+ // app changed to idle/active status.
+ void onSensorAccessChanged(bool hasAccess);
- // recover sensor reports previously stopped by stopAll(true)
- // called by SensorService when return to NORMAL mode.
- void recoverAll();
-
- void updateSensorSubscriptions();
-
- void setSensorAccess(bool hasAccess);
protected:
virtual ~SensorDirectConnection();
// ISensorEventConnection functions
@@ -70,6 +64,24 @@
virtual void destroy();
private:
bool hasSensorAccess() const;
+
+ // Stops all active sensor direct report requests.
+ //
+ // If backupRecord is true, stopped requests can be recovered
+ // by a subsequent recoverAll() call (e.g. when temporarily stopping
+ // sensors for sensor privacy/restrict mode or when an app becomes
+ // idle).
+ void stopAll(bool backupRecord = false);
+ // Same as stopAll() but with mConnectionLock held.
+ void stopAllLocked(bool backupRecord);
+
+ // Recover sensor requests previously stopped by stopAll(true).
+ // This method can be called when a sensor access resumes (e.g.
+ // sensor privacy/restrict mode lifted or app becomes active).
+ //
+ // If no requests are backed up by stopAll(), this method is no-op.
+ void recoverAll();
+
const sp<SensorService> mService;
const uid_t mUid;
const sensors_direct_mem_t mMem;
@@ -80,8 +92,6 @@
std::unordered_map<int, int> mActivated;
std::unordered_map<int, int> mActivatedBackup;
- std::atomic_bool mHasSensorAccess = true;
-
mutable Mutex mDestroyLock;
bool mDestroyed;
};
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 5be4ccd..ccf05d9 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <cinttypes>
#include <sys/socket.h>
#include <utils/threads.h>
@@ -32,12 +31,11 @@
SensorService::SensorEventConnection::SensorEventConnection(
const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
- const String16& opPackageName, bool hasSensorAccess)
+ const String16& opPackageName)
: mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),
mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
- mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false),
- mHasSensorAccess(hasSensorAccess) {
+ mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false) {
mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -70,16 +68,17 @@
}
bool SensorService::SensorEventConnection::needsWakeLock() {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
return !mDead && mWakeLockRefCount > 0;
}
void SensorService::SensorEventConnection::resetWakeLockRefCount() {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
mWakeLockRefCount = 0;
}
void SensorService::SensorEventConnection::dump(String8& result) {
+ Mutex::Autolock _l(mConnectionLock);
result.appendFormat("\tOperating Mode: ");
if (!mService->isWhiteListedPackage(getPackageName())) {
result.append("RESTRICTED\n");
@@ -91,10 +90,8 @@
result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
"max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
mMaxCacheSize);
-
- std::lock_guard<std::mutex> _l(mConnectionLock);
for (auto& it : mSensorInfo) {
- const FlushInfo& flushInfo = it.second.flushInfo;
+ const FlushInfo& flushInfo = it.second;
result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
mService->getSensorName(it.first).string(),
it.first,
@@ -123,7 +120,7 @@
*/
void SensorService::SensorEventConnection::dump(util::ProtoOutputStream* proto) const {
using namespace service::SensorEventConnectionProto;
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
if (!mService->isWhiteListedPackage(getPackageName())) {
proto->write(OPERATING_MODE, OP_MODE_RESTRICTED);
@@ -138,7 +135,7 @@
proto->write(CACHE_SIZE, int32_t(mCacheSize));
proto->write(MAX_CACHE_SIZE, int32_t(mMaxCacheSize));
for (auto& it : mSensorInfo) {
- const FlushInfo& flushInfo = it.second.flushInfo;
+ const FlushInfo& flushInfo = it.second;
const uint64_t token = proto->start(FLUSH_INFOS);
proto->write(FlushInfoProto::SENSOR_NAME,
std::string(mService->getSensorName(it.first)));
@@ -159,33 +156,28 @@
#endif
}
-bool SensorService::SensorEventConnection::addSensor(
- int32_t handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
+ Mutex::Autolock _l(mConnectionLock);
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
if (si == nullptr ||
!canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
mSensorInfo.count(handle) > 0) {
return false;
}
-
- SensorRequest request = {
- .samplingPeriodNs = samplingPeriodNs,
- .maxBatchReportLatencyNs = maxBatchReportLatencyNs,
- .reservedFlags = reservedFlags
- };
-
- mSensorInfo[handle] = request;
+ mSensorInfo[handle] = FlushInfo();
return true;
}
bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
- std::lock_guard<std::mutex> _l(mConnectionLock);
- return mSensorInfo.erase(handle) > 0;
+ Mutex::Autolock _l(mConnectionLock);
+ if (mSensorInfo.erase(handle) >= 0) {
+ return true;
+ }
+ return false;
}
std::vector<int32_t> SensorService::SensorEventConnection::getActiveSensorHandles() const {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
std::vector<int32_t> list;
for (auto& it : mSensorInfo) {
list.push_back(it.first);
@@ -194,19 +186,17 @@
}
bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
- std::lock_guard<std::recursive_mutex> _backlock(mBackupLock);
- std::lock_guard<std::mutex> _lock(mConnectionLock);
- return mSensorInfo.count(handle) + mSensorInfoBackup.count(handle) > 0;
+ Mutex::Autolock _l(mConnectionLock);
+ return mSensorInfo.count(handle) > 0;
}
bool SensorService::SensorEventConnection::hasAnySensor() const {
- std::lock_guard<std::recursive_mutex> _backlock(mBackupLock);
- std::lock_guard<std::mutex> _lock(mConnectionLock);
- return mSensorInfo.size() + mSensorInfoBackup.size() ? true : false;
+ Mutex::Autolock _l(mConnectionLock);
+ return mSensorInfo.size() ? true : false;
}
bool SensorService::SensorEventConnection::hasOneShotSensors() const {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
for (auto &it : mSensorInfo) {
const int handle = it.first;
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
@@ -223,15 +213,15 @@
void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
bool value) {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
if (mSensorInfo.count(handle) > 0) {
- FlushInfo& flushInfo = mSensorInfo[handle].flushInfo;
+ FlushInfo& flushInfo = mSensorInfo[handle];
flushInfo.mFirstFlushPending = value;
}
}
void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
updateLooperRegistrationLocked(looper);
}
@@ -282,9 +272,9 @@
}
void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
if (mSensorInfo.count(handle) > 0) {
- FlushInfo& flushInfo = mSensorInfo[handle].flushInfo;
+ FlushInfo& flushInfo = mSensorInfo[handle];
flushInfo.mPendingFlushEventsToSend++;
}
}
@@ -298,7 +288,7 @@
std::unique_ptr<sensors_event_t[]> sanitizedBuffer;
int count = 0;
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
if (scratch) {
size_t i=0;
while (i<numEvents) {
@@ -319,7 +309,7 @@
continue;
}
- FlushInfo& flushInfo = mSensorInfo[sensor_handle].flushInfo;
+ FlushInfo& flushInfo = mSensorInfo[sensor_handle];
// Check if there is a pending flush_complete event for this sensor on this connection.
if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
mapFlushEventsToConnections[i] == this) {
@@ -440,66 +430,9 @@
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
-void SensorService::SensorEventConnection::updateSensorSubscriptions() {
- if (!hasSensorAccess()) {
- stopAll();
- } else {
- recoverAll();
- }
-}
-
-void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) {
- if (mHasSensorAccess != hasAccess) {
- mHasSensorAccess = hasAccess;
- updateSensorSubscriptions();
- }
-}
-
-void SensorService::SensorEventConnection::stopAll() {
- bool backupPerformed = false;
- std::lock_guard<std::recursive_mutex> _backlock(mBackupLock);
- {
- std::lock_guard<std::mutex> _lock(mConnectionLock);
- if (!mSensorInfo.empty()) {
- mSensorInfoBackup = mSensorInfo;
- mSensorInfo.clear();
- backupPerformed = true;
- }
- }
-
- if (backupPerformed) {
- for (auto& it : mSensorInfoBackup) {
- int32_t handle = it.first;
-
- status_t err = mService->disable(this, handle);
-
- if (err != NO_ERROR) {
- ALOGE("Error disabling sensor %d", handle);
- }
- }
- }
-}
-
-void SensorService::SensorEventConnection::recoverAll() {
- std::lock_guard<std::recursive_mutex> _l(mBackupLock);
- for (auto& it : mSensorInfoBackup) {
- int32_t handle = it.first;
- SensorRequest &request = it.second;
-
- status_t err = mService->enable(
- this, handle, request.samplingPeriodNs, request.maxBatchReportLatencyNs,
- request.reservedFlags, mOpPackageName);
-
- if (err != NO_ERROR) {
- ALOGE("Error recovering sensor %d", handle);
- }
- }
-
- mSensorInfoBackup.clear();
-}
-
bool SensorService::SensorEventConnection::hasSensorAccess() {
- return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
+ return mService->isUidActive(mUid)
+ && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
}
bool SensorService::SensorEventConnection::noteOpIfRequired(const sensors_event_t& event) {
@@ -597,7 +530,7 @@
continue;
}
- FlushInfo& flushInfo = it.second.flushInfo;
+ FlushInfo& flushInfo = it.second;
while (flushInfo.mPendingFlushEventsToSend > 0) {
flushCompleteEvent.meta_data.sensor = handle;
bool wakeUpSensor = si->getSensor().isWakeUpSensor();
@@ -622,7 +555,7 @@
// half the size of the socket buffer allocated in BitTube whichever is smaller.
const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
// Send pending flush complete events (if any)
sendPendingFlushEventsLocked();
for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
@@ -689,7 +622,7 @@
continue;
}
- FlushInfo& flushInfo = mSensorInfo[scratch[j].meta_data.sensor].flushInfo;
+ FlushInfo& flushInfo = mSensorInfo[scratch[j].meta_data.sensor];
flushInfo.mPendingFlushEventsToSend++;
ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
flushInfo.mPendingFlushEventsToSend);
@@ -725,21 +658,13 @@
} else {
err = mService->disable(this, handle);
}
-
return err;
}
status_t SensorService::SensorEventConnection::setEventRate(
int handle, nsecs_t samplingPeriodNs)
{
- status_t err = mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
-
- std::lock_guard<std::mutex> _l(mConnectionLock);
- if (err == NO_ERROR && mSensorInfo.count(handle) > 0) {
- mSensorInfo[handle].samplingPeriodNs = samplingPeriodNs;
- }
-
- return err;
+ return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
}
status_t SensorService::SensorEventConnection::flush() {
@@ -760,7 +685,7 @@
// and remove the fd from Looper. Call checkWakeLockState to know if SensorService
// can release the wake-lock.
ALOGD_IF(DEBUG_CONNECTIONS, "%p Looper error %d", this, fd);
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
mDead = true;
mWakeLockRefCount = 0;
updateLooperRegistrationLocked(mService->getLooper());
@@ -779,7 +704,7 @@
unsigned char buf[sizeof(sensors_event_t)];
ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
{
- std::lock_guard<std::mutex> _l(mConnectionLock);
+ Mutex::Autolock _l(mConnectionLock);
if (numBytesRead == sizeof(sensors_event_t)) {
if (!mDataInjectionMode) {
ALOGE("Data injected in normal mode, dropping event"
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 80e7431..13cee6f 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -49,16 +49,14 @@
public:
SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
- bool isDataInjectionMode, const String16& opPackageName,
- bool hasSensorAccess);
+ bool isDataInjectionMode, const String16& opPackageName);
status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
wp<const SensorEventConnection> const * mapFlushEventsToConnections = nullptr);
bool hasSensor(int32_t handle) const;
bool hasAnySensor() const;
bool hasOneShotSensors() const;
- bool addSensor(
- int32_t handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags);
+ bool addSensor(int32_t handle);
bool removeSensor(int32_t handle);
std::vector<int32_t> getActiveSensorHandles() const;
void setFirstFlushPending(int32_t handle, bool value);
@@ -70,8 +68,6 @@
uid_t getUid() const { return mUid; }
- void setSensorAccess(const bool hasAccess);
- void updateSensorSubscriptions();
private:
virtual ~SensorEventConnection();
virtual void onFirstRef();
@@ -137,22 +133,13 @@
// privacy not being enabled.
bool hasSensorAccess();
- void stopAll();
- void recoverAll();
-
// Call noteOp for the sensor if the sensor requires a permission
bool noteOpIfRequired(const sensors_event_t& event);
sp<SensorService> const mService;
sp<BitTube> mChannel;
uid_t mUid;
-
- // A lock that should be used when modifying mSensorInfo
- mutable std::mutex mConnectionLock;
-
- // A lock that should be used when modifying mSensorInfoBackup
- mutable std::recursive_mutex mBackupLock;
-
+ mutable Mutex mConnectionLock;
// Number of events from wake up sensors which are still pending and haven't been delivered to
// the corresponding application. It is incremented by one unit for each write to the socket.
uint32_t mWakeLockRefCount;
@@ -179,17 +166,8 @@
FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
};
-
- struct SensorRequest {
- nsecs_t samplingPeriodNs;
- nsecs_t maxBatchReportLatencyNs;
- int reservedFlags;
- FlushInfo flushInfo;
- };
-
// protected by SensorService::mLock. Key for this map is the sensor handle.
- std::unordered_map<int32_t, SensorRequest> mSensorInfo;
- std::unordered_map<int32_t, SensorRequest> mSensorInfoBackup;
+ std::unordered_map<int32_t, FlushInfo> mSensorInfo;
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
@@ -204,7 +182,6 @@
mutable Mutex mDestroyLock;
bool mDestroyed;
- std::atomic_bool mHasSensorAccess;
// Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
// valid mapping for sensors that require a permission in order to reduce the lookup time.
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 29df825..ffcd0a0 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -299,26 +299,33 @@
}
}
-void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
+void SensorService::onUidStateChanged(uid_t uid, UidState state) {
+ SensorDevice& dev(SensorDevice::getInstance());
+
ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
- const auto& connections = connLock.getActiveConnections();
- const auto& directConnections = connLock.getDirectConnections();
-
- mLock.unlock();
- for (const sp<SensorEventConnection>& conn : connections) {
+ for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
if (conn->getUid() == uid) {
- conn->setSensorAccess(hasAccess);
+ dev.setUidStateForConnection(conn.get(), state);
}
}
- for (const sp<SensorDirectConnection>& conn : directConnections) {
+ for (const sp<SensorDirectConnection>& conn : connLock.getDirectConnections()) {
if (conn->getUid() == uid) {
- conn->setSensorAccess(hasAccess);
+ // Update sensor subscriptions if needed
+ bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
+ conn->onSensorAccessChanged(hasAccess);
}
}
+}
- // Lock the mutex again for clean shutdown
- mLock.lock();
+bool SensorService::hasSensorAccess(uid_t uid, const String16& opPackageName) {
+ Mutex::Autolock _l(mLock);
+ return hasSensorAccessLocked(uid, opPackageName);
+}
+
+bool SensorService::hasSensorAccessLocked(uid_t uid, const String16& opPackageName) {
+ return !mSensorPrivacyPolicy->isSensorPrivacyEnabled()
+ && isUidActive(uid) && !isOperationRestrictedLocked(opPackageName);
}
const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
@@ -651,11 +658,9 @@
void SensorService::disableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
SensorDevice& dev(SensorDevice::getInstance());
- for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
- connection->updateSensorSubscriptions();
- }
- for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
- connection->updateSensorSubscriptions();
+ for (const sp<SensorDirectConnection>& conn : connLock->getDirectConnections()) {
+ bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
+ conn->onSensorAccessChanged(hasAccess);
}
dev.disableAllSensors();
// Clear all pending flush connections for all active sensors. If one of the active
@@ -682,11 +687,9 @@
}
SensorDevice& dev(SensorDevice::getInstance());
dev.enableAllSensors();
- for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
- connection->updateSensorSubscriptions();
- }
- for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
- connection->updateSensorSubscriptions();
+ for (const sp<SensorDirectConnection>& conn : connLock->getDirectConnections()) {
+ bool hasAccess = hasSensorAccessLocked(conn->getUid(), conn->getOpPackageName());
+ conn->onSensorAccessChanged(hasAccess);
}
}
@@ -1253,9 +1256,8 @@
(packageName == "") ? String8::format("unknown_package_pid_%d", pid) : packageName;
String16 connOpPackageName =
(opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
- bool hasSensorAccess = mUidPolicy->isUidActive(uid);
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
- requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess));
+ requestedMode == DATA_INJECTION, connOpPackageName));
if (requestedMode == DATA_INJECTION) {
mConnectionHolder.addEventConnectionIfNotPresent(result);
// Add the associated file descriptor to the Looper for polling whenever there is data to
@@ -1608,7 +1610,7 @@
}
}
- if (connection->addSensor(handle, samplingPeriodNs, maxBatchReportLatencyNs, reservedFlags)) {
+ if (connection->addSensor(handle)) {
BatteryService::enableSensor(connection->getUid(), handle);
// the sensor was added (which means it wasn't already there)
// so, see if this connection becomes active
@@ -1758,22 +1760,17 @@
const int halVersion = dev.getHalDeviceVersion();
status_t err(NO_ERROR);
Mutex::Autolock _l(mLock);
-
- size_t numSensors = 0;
// Loop through all sensors for this connection and call flush on each of them.
for (int handle : connection->getActiveSensorHandles()) {
sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
if (sensor == nullptr) {
continue;
}
- numSensors++;
-
if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
ALOGE("flush called on a one-shot sensor");
err = INVALID_OPERATION;
continue;
}
-
if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0 || isVirtualSensor(handle)) {
// For older devices just increment pending flush count which will send a trivial
// flush complete event.
@@ -1791,8 +1788,7 @@
err = (err_flush != NO_ERROR) ? err_flush : err;
}
}
-
- return (numSensors == 0) ? INVALID_OPERATION : err;
+ return err;
}
bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
@@ -1912,13 +1908,12 @@
return (packageName.contains(mWhiteListedPackage.string()));
}
-bool SensorService::isOperationPermitted(const String16& opPackageName) {
- Mutex::Autolock _l(mLock);
+bool SensorService::isOperationRestrictedLocked(const String16& opPackageName) {
if (mCurrentOperatingMode == RESTRICTED) {
String8 package(opPackageName);
- return isWhiteListedPackage(package);
+ return !isWhiteListedPackage(package);
}
- return true;
+ return false;
}
void SensorService::UidPolicy::registerSelf() {
@@ -1946,7 +1941,7 @@
}
sp<SensorService> service = mService.promote();
if (service != nullptr) {
- service->setSensorAccess(uid, true);
+ service->onUidStateChanged(uid, UID_STATE_ACTIVE);
}
}
@@ -1961,7 +1956,7 @@
if (deleted) {
sp<SensorService> service = mService.promote();
if (service != nullptr) {
- service->setSensorAccess(uid, false);
+ service->onUidStateChanged(uid, UID_STATE_IDLE);
}
}
}
@@ -1989,7 +1984,7 @@
if (wasActive != isActive) {
sp<SensorService> service = mService.promote();
if (service != nullptr) {
- service->setSensorAccess(uid, isActive);
+ service->onUidStateChanged(uid, isActive ? UID_STATE_ACTIVE : UID_STATE_IDLE);
}
}
}
@@ -2015,6 +2010,10 @@
return mActiveUids.find(uid) != mActiveUids.end();
}
+bool SensorService::isUidActive(uid_t uid) {
+ return mUidPolicy->isUidActive(uid);
+}
+
void SensorService::SensorPrivacyPolicy::registerSelf() {
SensorPrivacyManager spm;
mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 7d17dda..3bb8421 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -75,6 +75,11 @@
class SensorDirectConnection;
public:
+ enum UidState {
+ UID_STATE_ACTIVE = 0,
+ UID_STATE_IDLE,
+ };
+
void cleanupConnection(SensorEventConnection* connection);
void cleanupConnection(SensorDirectConnection* c);
@@ -194,6 +199,8 @@
std::unordered_map<uid_t, bool> mOverrideUids;
};
+ bool isUidActive(uid_t uid);
+
// Sensor privacy allows a user to disable access to all sensors on the device. When
// enabled sensor privacy will prevent all apps, including active apps, from accessing
// sensors, they will not receive trigger nor on-change events, flush event behavior
@@ -332,7 +339,11 @@
// allowed to register for or call flush on sensors. Typically only cts test packages are
// allowed.
bool isWhiteListedPackage(const String8& packageName);
- bool isOperationPermitted(const String16& opPackageName);
+
+ // Returns true if a connection with the specified opPackageName has no access to sensors
+ // in the RESTRICTED mode (i.e. the service is in RESTRICTED mode, and the package is not
+ // whitelisted). mLock must be held to invoke this method.
+ bool isOperationRestrictedLocked(const String16& opPackageName);
// Reset the state of SensorService to NORMAL mode.
status_t resetToNormalMode();
@@ -349,7 +360,13 @@
void enableSchedFifoMode();
// Sets whether the given UID can get sensor data
- void setSensorAccess(uid_t uid, bool hasAccess);
+ void onUidStateChanged(uid_t uid, UidState state);
+
+ // Returns true if a connection with the given uid and opPackageName
+ // currently has access to sensors.
+ bool hasSensorAccess(uid_t uid, const String16& opPackageName);
+ // Same as hasSensorAccess but with mLock held.
+ bool hasSensorAccessLocked(uid_t uid, const String16& opPackageName);
// Overrides the UID state as if it is idle
status_t handleSetUidState(Vector<String16>& args, int err);
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index c6f1f7e..0182937 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -44,7 +44,6 @@
"libGLESv1_CM",
"libGLESv2",
"libgui",
- "libhardware",
"libhidlbase",
"liblayers_proto",
"liblog",
@@ -287,6 +286,7 @@
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
"libhidlbase",
+ "libui",
],
export_static_lib_headers: [
"SurfaceFlingerProperties",
diff --git a/services/surfaceflinger/Barrier.h b/services/surfaceflinger/Barrier.h
deleted file mode 100644
index 97028a8..0000000
--- a/services/surfaceflinger/Barrier.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef ANDROID_BARRIER_H
-#define ANDROID_BARRIER_H
-
-#include <stdint.h>
-#include <condition_variable>
-#include <mutex>
-
-namespace android {
-
-class Barrier
-{
-public:
- // Release any threads waiting at the Barrier.
- // Provides release semantics: preceding loads and stores will be visible
- // to other threads before they wake up.
- void open() {
- std::lock_guard<std::mutex> lock(mMutex);
- mIsOpen = true;
- mCondition.notify_all();
- }
-
- // Reset the Barrier, so wait() will block until open() has been called.
- void close() {
- std::lock_guard<std::mutex> lock(mMutex);
- mIsOpen = false;
- }
-
- // Wait until the Barrier is OPEN.
- // Provides acquire semantics: no subsequent loads or stores will occur
- // until wait() returns.
- void wait() const {
- std::unique_lock<std::mutex> lock(mMutex);
- mCondition.wait(lock, [this]() NO_THREAD_SAFETY_ANALYSIS { return mIsOpen; });
- }
-private:
- mutable std::mutex mMutex;
- mutable std::condition_variable mCondition;
- int mIsOpen GUARDED_BY(mMutex){false};
-};
-
-}; // namespace android
-
-#endif // ANDROID_BARRIER_H
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 5f90566..f0b0200 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -294,6 +294,7 @@
auto* compositionState = editCompositionState();
if (compositionState->sidebandStream.get()) {
compositionState->compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+ return;
} else {
// Normal buffer layers
compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
@@ -301,6 +302,12 @@
? Hwc2::IComposerClient::Composition::CURSOR
: Hwc2::IComposerClient::Composition::DEVICE;
}
+
+ compositionState->buffer = mBufferInfo.mBuffer;
+ compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
+ ? 0
+ : mBufferInfo.mBufferSlot;
+ compositionState->acquireFence = mBufferInfo.mFence;
}
bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
@@ -312,7 +319,7 @@
return hasReadyFrame();
}
-bool BufferLayer::onPostComposition(sp<const DisplayDevice> displayDevice,
+bool BufferLayer::onPostComposition(const DisplayDevice* display,
const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
const CompositorTiming& compositorTiming) {
@@ -335,7 +342,7 @@
const int32_t layerId = getSequence();
mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);
- const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ const auto outputLayer = findOutputLayerForDisplay(display);
if (outputLayer && outputLayer->requiresClientComposition()) {
nsecs_t clientCompositionTimestamp = outputLayer->getState().clientCompositionTimestamp;
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
@@ -352,13 +359,15 @@
mFrameTracker.setFrameReadyTime(desiredPresentTime);
}
- const auto displayId = displayDevice->getId();
if (presentFence->isValid()) {
mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence);
mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
- } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
+ } else if (!display) {
+ // Do nothing.
+ } else if (const auto displayId = display->getId();
+ displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
@@ -490,10 +499,6 @@
}
}
- if (recomputeVisibleRegions == true) {
- maybeDirtyInput();
- }
-
return true;
}
@@ -597,14 +602,8 @@
return true;
}
-bool BufferLayer::needsFiltering(const sp<const DisplayDevice>& displayDevice) const {
- // If we are not capturing based on the state of a known display device,
- // just return false.
- if (displayDevice == nullptr) {
- return false;
- }
-
- const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+bool BufferLayer::needsFiltering(const DisplayDevice* display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
if (outputLayer == nullptr) {
return false;
}
@@ -618,15 +617,9 @@
sourceCrop.getWidth() != displayFrame.getWidth();
}
-bool BufferLayer::needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+bool BufferLayer::needsFilteringForScreenshots(const DisplayDevice* display,
const ui::Transform& inverseParentTransform) const {
- // If we are not capturing based on the state of a known display device,
- // just return false.
- if (displayDevice == nullptr) {
- return false;
- }
-
- const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+ const auto outputLayer = findOutputLayerForDisplay(display);
if (outputLayer == nullptr) {
return false;
}
@@ -634,7 +627,7 @@
// We need filtering if the sourceCrop rectangle size does not match the
// viewport rectangle size (not a 1:1 render)
const auto& compositionState = outputLayer->getState();
- const ui::Transform& displayTransform = displayDevice->getTransform();
+ const ui::Transform& displayTransform = display->getTransform();
const ui::Transform inverseTransform = inverseParentTransform * displayTransform.inverse();
// Undo the transformation of the displayFrame so that we're back into
// layer-stack space.
@@ -840,6 +833,13 @@
mDrawingState.inputInfo = tmpInputInfo;
}
+void BufferLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
+ mTransformHint = getFixedTransformHint();
+ if (mTransformHint == ui::Transform::ROT_INVALID) {
+ mTransformHint = displayTransformHint;
+ }
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 56bab1b..97ffe6f 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -79,10 +79,9 @@
bool isHdrY410() const override;
- bool onPostComposition(sp<const DisplayDevice> displayDevice,
- const std::shared_ptr<FenceTime>& glDoneFence,
+ bool onPostComposition(const DisplayDevice*, const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) override;
+ const CompositorTiming&) override;
// latchBuffer - called each time the screen is redrawn and returns whether
// the visible regions need to be recomputed (this is a fairly heavy
@@ -117,7 +116,7 @@
sp<GraphicBuffer> getBuffer() const override;
- // -----------------------------------------------------------------------
+ ui::Transform::RotationFlags getTransformHint() const override { return mTransformHint; }
// -----------------------------------------------------------------------
// Functions that must be implemented by derived classes
@@ -205,10 +204,16 @@
virtual uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
+ void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
+
+ // Transform hint provided to the producer. This must be accessed holding
+ /// the mStateLock.
+ ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
+
private:
// Returns true if this layer requires filtering
- bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const override;
- bool needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+ bool needsFiltering(const DisplayDevice*) const override;
+ bool needsFilteringForScreenshots(const DisplayDevice*,
const ui::Transform& inverseParentTransform) const override;
// BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index e50a909..648d129 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -407,8 +407,17 @@
}
Rect BufferLayerConsumer::getCurrentCropLocked() const {
+ uint32_t width = mDefaultWidth;
+ uint32_t height = mDefaultHeight;
+ // If the buffer comes with a rotated bit for 90 (or 270) degrees, switch width/height in order
+ // to scale and crop correctly.
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ width = mDefaultHeight;
+ height = mDefaultWidth;
+ }
+
return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
- ? GLConsumer::scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
+ ? GLConsumer::scaleDownCrop(mCurrentCrop, width, height)
: mCurrentCrop;
}
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index c84b15d..e5b94e4 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -58,8 +58,9 @@
}
}
-void BufferQueueLayer::setTransformHint(uint32_t orientation) const {
- mConsumer->setTransformHint(orientation);
+void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
+ BufferLayer::setTransformHint(displayTransformHint);
+ mConsumer->setTransformHint(mTransformHint);
}
std::vector<OccupancyTracker::Segment> BufferQueueLayer::getOccupancyHistory(bool forceFlush) {
@@ -365,21 +366,6 @@
return NO_ERROR;
}
-void BufferQueueLayer::preparePerFrameCompositionState() {
- BufferLayer::preparePerFrameCompositionState();
-
- auto* compositionState = editCompositionState();
- if (compositionState->compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
- return;
- }
-
- compositionState->buffer = mBufferInfo.mBuffer;
- compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
- ? 0
- : mBufferInfo.mBufferSlot;
- compositionState->acquireFence = mBufferInfo.mFence;
-}
-
// -----------------------------------------------------------------------
// Interface implementation for BufferLayerConsumer::ContentsChangedListener
// -----------------------------------------------------------------------
@@ -508,10 +494,6 @@
if (!mFlinger->isLayerTripleBufferingDisabled()) {
mProducer->setMaxDequeuedBufferCount(2);
}
-
- if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
- updateTransformHint(display);
- }
}
status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) {
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index ea7f203..5ebc22d 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -43,8 +43,6 @@
void onLayerDisplayed(const sp<Fence>& releaseFence) override;
- void setTransformHint(uint32_t orientation) const override;
-
std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
// If a buffer was replaced this frame, release the former buffer
@@ -72,6 +70,7 @@
bool getSidebandStreamChanged() const override;
bool latchSidebandStream(bool& recomputeVisibleRegions) override;
+ void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
bool hasFrameUpdate() const override;
@@ -82,7 +81,6 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void preparePerFrameCompositionState() override;
sp<Layer> createClone() override;
void onFrameAvailable(const BufferItem& item);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 3e65171..a1ed6d7 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -51,9 +51,6 @@
: BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
- if (const auto display = args.displayDevice) {
- updateTransformHint(display);
- }
}
BufferStateLayer::~BufferStateLayer() {
@@ -108,10 +105,6 @@
}
}
-void BufferStateLayer::setTransformHint(uint32_t orientation) const {
- mTransformHint = orientation;
-}
-
void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
for (const auto& handle : mDrawingState.callbackHandles) {
handle->transformHint = mTransformHint;
@@ -631,19 +624,6 @@
return NO_ERROR;
}
-void BufferStateLayer::preparePerFrameCompositionState() {
- BufferLayer::preparePerFrameCompositionState();
-
- auto* compositionState = editCompositionState();
- if (compositionState->compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) {
- return;
- }
-
- compositionState->buffer = mBufferInfo.mBuffer;
- compositionState->bufferSlot = mBufferInfo.mBufferSlot;
- compositionState->acquireFence = mBufferInfo.mFence;
-}
-
void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
std::lock_guard lock(mMutex);
if (!clientCacheId.isValid()) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 753a742..00fa7f7 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -42,7 +42,6 @@
const char* getType() const override { return "BufferStateLayer"; }
void onLayerDisplayed(const sp<Fence>& releaseFence) override;
- void setTransformHint(uint32_t orientation) const override;
void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
@@ -68,7 +67,6 @@
}
Rect getCrop(const Layer::State& s) const;
- uint32_t getTransformHint() const { return mTransformHint; }
bool setTransform(uint32_t transform) override;
bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
bool setCrop(const Rect& crop) override;
@@ -138,7 +136,6 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void preparePerFrameCompositionState() override;
sp<Layer> createClone() override;
// Crop that applies to the buffer
@@ -165,8 +162,6 @@
bool mReleasePreviousBuffer = false;
nsecs_t mCallbackHandleAcquireTime = -1;
- mutable uint32_t mTransformHint = 0;
-
// TODO(marissaw): support sticky transform for LEGACY camera mode
class HwcSlotGenerator : public ClientCache::ErasedRecipient {
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index fb72ab8..78bbcba 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -93,11 +93,6 @@
uint32_t* outTransformHint) {
if (mFlinger->authenticateSurfaceTexture(parent) == false) {
ALOGE("failed to authenticate surface texture");
- // The extra parent layer check below before returning is to help with debugging
- // b/134888387. Once the bug is fixed the check can be deleted.
- if ((static_cast<MonitoredProducer*>(parent.get()))->getLayer() == nullptr) {
- ALOGE("failed to find parent layer");
- }
return BAD_VALUE;
}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index d3712d9..a0606b4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -24,6 +24,7 @@
#include <compositionengine/LayerFE.h>
#include <compositionengine/OutputColorSetting.h>
#include <math/mat4.h>
+#include <ui/Transform.h>
namespace android::compositionengine {
@@ -57,6 +58,9 @@
// Forces a color mode on the outputs being refreshed
ui::ColorMode forceOutputColorMode{ui::ColorMode::NATIVE};
+ // Used to correctly apply an inverse-display buffer transform if applicable
+ ui::Transform::RotationFlags internalDisplayRotationFlags{ui::Transform::ROT_0};
+
// If true, GPU clocks will be increased when rendering blurs
bool blursAreExpensive{false};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index d8ce629..8a9763b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -33,13 +33,15 @@
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
-#include "DisplayHardware/ComposerHal.h"
+#include "DisplayHardware/Hal.h"
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
namespace android::compositionengine {
+namespace hal = android::hardware::graphics::composer::hal;
+
// More complex metadata for this layer
struct GenericLayerMetadataEntry {
// True if the metadata may affect the composed result.
@@ -108,7 +110,7 @@
Region transparentRegionHint;
// The blend mode for this layer
- Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID};
+ hal::BlendMode blendMode{hal::BlendMode::INVALID};
// The bounds of the layer in layer local coordinates
FloatRect geomLayerBounds;
@@ -145,7 +147,7 @@
*/
// The type of composition for this layer
- Hwc2::IComposerClient::Composition compositionType{Hwc2::IComposerClient::Composition::INVALID};
+ hal::Composition compositionType{hal::Composition::INVALID};
// The buffer and related state
sp<GraphicBuffer> buffer;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index a5711a3..baf5258 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -34,11 +34,13 @@
#include "DisplayHardware/DisplayIdentification.h"
+namespace android {
+
namespace HWC2 {
class Layer;
} // namespace HWC2
-namespace android::compositionengine {
+namespace compositionengine {
class DisplayColorProfile;
class LayerFE;
@@ -280,4 +282,5 @@
virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0;
};
-} // namespace android::compositionengine
+} // namespace compositionengine
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index 007b0e8..aa70ef8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -19,6 +19,7 @@
#include <optional>
#include <string>
+#include <ui/Transform.h>
#include <utils/StrongPointer.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
@@ -31,12 +32,12 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
+namespace android {
+
namespace HWC2 {
class Layer;
} // namespace HWC2
-namespace android {
-
namespace compositionengine {
class CompositionEngine;
@@ -77,7 +78,12 @@
// Recalculates the state of the output layer from the output-independent
// layer. If includeGeometry is false, the geometry state can be skipped.
- virtual void updateCompositionState(bool includeGeometry, bool forceClientComposition) = 0;
+ // internalDisplayRotationFlags must be set to the rotation flags for the
+ // internal display, and is used to properly compute the inverse-display
+ // transform, if needed.
+ virtual void updateCompositionState(
+ bool includeGeometry, bool forceClientComposition,
+ ui::Transform::RotationFlags internalDisplayRotationFlags) = 0;
// Writes the geometry state to the HWC, or does nothing if this layer does
// not use the HWC. If includeGeometry is false, the geometry state can be
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 79df9b2..8cb5ae8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -39,7 +39,8 @@
void setHwcLayer(std::shared_ptr<HWC2::Layer>) override;
- void updateCompositionState(bool includeGeometry, bool forceClientComposition) override;
+ void updateCompositionState(bool includeGeometry, bool forceClientComposition,
+ ui::Transform::RotationFlags) override;
void writeStateToHWC(bool) override;
void writeCursorPositionToHWC() const override;
@@ -55,7 +56,8 @@
virtual FloatRect calculateOutputSourceCrop() const;
virtual Rect calculateOutputDisplayFrame() const;
- virtual uint32_t calculateOutputRelativeBufferTransform() const;
+ virtual uint32_t calculateOutputRelativeBufferTransform(
+ uint32_t internalDisplayRotationFlags) const;
protected:
// Implemented by the final implementation for the final state it uses.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index b0a9bc9..75394fa 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -36,12 +36,12 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
+namespace android {
+
namespace HWC2 {
class Layer;
} // namespace HWC2
-namespace android {
-
class HWComposer;
namespace compositionengine::impl {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 2ecbad8..81e1fc7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -38,7 +38,7 @@
MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&());
MOCK_METHOD0(editState, impl::OutputLayerCompositionState&());
- MOCK_METHOD2(updateCompositionState, void(bool, bool));
+ MOCK_METHOD3(updateCompositionState, void(bool, bool, ui::Transform::RotationFlags));
MOCK_METHOD1(writeStateToHWC, void(bool));
MOCK_CONST_METHOD0(writeCursorPositionToHWC, void());
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index c345405..ab26939 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -268,12 +268,9 @@
}
bool Display::getSkipColorTransform() const {
- if (!mId) {
- return false;
- }
-
- auto& hwc = getCompositionEngine().getHwComposer();
- return hwc.hasDisplayCapability(*mId, HWC2::DisplayCapability::SkipClientColorTransform);
+ const auto& hwc = getCompositionEngine().getHwComposer();
+ return mId ? hwc.hasDisplayCapability(*mId, hal::DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM)
+ : hwc.hasCapability(hal::Capability::SKIP_CLIENT_COLOR_TRANSFORM);
}
bool Display::anyLayersRequireClientComposition() const {
@@ -309,7 +306,7 @@
void Display::applyDisplayRequests(const DisplayRequests& displayRequests) {
auto& state = editState();
state.flipClientTarget = (static_cast<uint32_t>(displayRequests) &
- static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0;
+ static_cast<uint32_t>(hal::DisplayRequest::FLIP_CLIENT_TARGET)) != 0;
// Note: HWC2::DisplayRequest::WriteClientTargetToOutput is currently ignored.
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 248933e..e8f54f5 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -588,7 +588,8 @@
for (auto* layer : getOutputLayersOrderedByZ()) {
layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
refreshArgs.devOptForceClientComposition ||
- forceClientComposition);
+ forceClientComposition,
+ refreshArgs.internalDisplayRotationFlags);
if (mLayerRequestingBackgroundBlur == layer) {
forceClientComposition = false;
@@ -815,6 +816,43 @@
OutputCompositionState& outputCompositionState = editState();
const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
outputState.usesClientComposition};
+
+ auto& renderEngine = getCompositionEngine().getRenderEngine();
+ const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
+
+ // If we the display is secure, protected content support is enabled, and at
+ // least one layer has protected content, we need to use a secure back
+ // buffer.
+ if (outputState.isSecure && supportsProtectedContent) {
+ auto layers = getOutputLayersOrderedByZ();
+ bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
+ return layer->getLayerFE().getCompositionState()->hasProtectedContent;
+ });
+ if (needsProtected != renderEngine.isProtected()) {
+ renderEngine.useProtectedContext(needsProtected);
+ }
+ if (needsProtected != mRenderSurface->isProtected() &&
+ needsProtected == renderEngine.isProtected()) {
+ mRenderSurface->setProtected(needsProtected);
+ }
+ }
+
+ base::unique_fd fd;
+ sp<GraphicBuffer> buf;
+
+ // 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 (hasClientComposition || outputState.flipClientTarget) {
+ buf = mRenderSurface->dequeueBuffer(&fd);
+ if (buf == nullptr) {
+ ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
+ "client composition for this frame",
+ mName.c_str());
+ return {};
+ }
+ }
+
base::unique_fd readyFence;
if (!hasClientComposition) {
setExpensiveRenderingExpected(false);
@@ -823,13 +861,9 @@
ALOGV("hasClientComposition");
- auto& renderEngine = getCompositionEngine().getRenderEngine();
- const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
-
renderengine::DisplaySettings clientCompositionDisplay;
clientCompositionDisplay.physicalDisplay = outputState.destinationClip;
clientCompositionDisplay.clip = outputState.sourceClip;
- clientCompositionDisplay.globalTransform = outputState.transform.asMatrix4();
clientCompositionDisplay.orientation = outputState.orientation;
clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
? outputState.dataspace
@@ -852,32 +886,6 @@
clientCompositionDisplay.outputDataspace);
appendRegionFlashRequests(debugRegion, clientCompositionLayers);
- // If we the display is secure, protected content support is enabled, and at
- // least one layer has protected content, we need to use a secure back
- // buffer.
- if (outputState.isSecure && supportsProtectedContent) {
- auto layers = getOutputLayersOrderedByZ();
- bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
- return layer->getLayerFE().getCompositionState()->hasProtectedContent;
- });
- if (needsProtected != renderEngine.isProtected()) {
- renderEngine.useProtectedContext(needsProtected);
- }
- if (needsProtected != mRenderSurface->isProtected() &&
- needsProtected == renderEngine.isProtected()) {
- mRenderSurface->setProtected(needsProtected);
- }
- }
-
- base::unique_fd fd;
- sp<GraphicBuffer> buf = mRenderSurface->dequeueBuffer(&fd);
- if (buf == nullptr) {
- ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
- "client composition for this frame",
- mName.c_str());
- return std::nullopt;
- }
-
// 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) {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index c4171d7..1faf775 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -223,7 +223,8 @@
return displayTransform.transform(frame);
}
-uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
+uint32_t OutputLayer::calculateOutputRelativeBufferTransform(
+ uint32_t internalDisplayRotationFlags) const {
const auto& layerState = *getLayerFE().getCompositionState();
const auto& outputState = getOutput().getState();
@@ -241,10 +242,11 @@
if (layerState.geomBufferUsesDisplayInverseTransform) {
/*
- * the code below applies the primary display's inverse transform to the
- * buffer
+ * We must apply the internal display's inverse transform to the buffer
+ * transform, and not the one for the output this layer is on.
*/
- uint32_t invTransform = outputState.orientation;
+ uint32_t invTransform = internalDisplayRotationFlags;
+
// calculate the inverse transform
if (invTransform & HAL_TRANSFORM_ROT_90) {
invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
@@ -261,9 +263,11 @@
// this gives us only the "orientation" component of the transform
return transform.getOrientation();
-} // namespace impl
+}
-void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition) {
+void OutputLayer::updateCompositionState(
+ bool includeGeometry, bool forceClientComposition,
+ ui::Transform::RotationFlags internalDisplayRotationFlags) {
const auto* layerFEState = getLayerFE().getCompositionState();
if (!layerFEState) {
return;
@@ -283,8 +287,8 @@
state.displayFrame = calculateOutputDisplayFrame();
state.sourceCrop = calculateOutputSourceCrop();
- state.bufferTransform =
- static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
+ state.bufferTransform = static_cast<Hwc2::Transform>(
+ calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));
if ((layerFEState->isSecure && !outputState.isSecure) ||
(state.bufferTransform & ui::Transform::ROT_INVALID)) {
@@ -344,11 +348,11 @@
}
void OutputLayer::writeOutputDependentGeometryStateToHWC(
- HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
+ HWC2::Layer* hwcLayer, hal::Composition requestedCompositionType) {
const auto& outputDependentState = getState();
if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
getLayerFE().getDebugName(), outputDependentState.displayFrame.left,
outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
@@ -357,7 +361,7 @@
}
if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
"%s (%d)",
getLayerFE().getDebugName(), outputDependentState.sourceCrop.left,
@@ -366,18 +370,17 @@
static_cast<int32_t>(error));
}
- if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
+ if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != hal::Error::NONE) {
ALOGE("[%s] Failed to set Z %u: %s (%d)", getLayerFE().getDebugName(),
outputDependentState.z, to_string(error).c_str(), static_cast<int32_t>(error));
}
// Solid-color layers should always use an identity transform.
- const auto bufferTransform =
- requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR
+ const auto bufferTransform = requestedCompositionType != hal::Composition::SOLID_COLOR
? outputDependentState.bufferTransform
- : static_cast<Hwc2::Transform>(0);
- if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
- error != HWC2::Error::None) {
+ : static_cast<hal::Transform>(0);
+ if (auto error = hwcLayer->setTransform(static_cast<hal::Transform>(bufferTransform));
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set transform %s: %s (%d)", getLayerFE().getDebugName(),
toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
static_cast<int32_t>(error));
@@ -386,30 +389,29 @@
void OutputLayer::writeOutputIndependentGeometryStateToHWC(
HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
- if (auto error = hwcLayer->setBlendMode(
- static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
- error != HWC2::Error::None) {
+ if (auto error = hwcLayer->setBlendMode(outputIndependentState.blendMode);
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set blend mode %s: %s (%d)", getLayerFE().getDebugName(),
toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
static_cast<int32_t>(error));
}
if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", getLayerFE().getDebugName(),
outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
}
if (auto error = hwcLayer->setInfo(static_cast<uint32_t>(outputIndependentState.type),
static_cast<uint32_t>(outputIndependentState.appId));
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set info %s (%d)", getLayerFE().getDebugName(),
to_string(error).c_str(), static_cast<int32_t>(error));
}
for (const auto& [name, entry] : outputIndependentState.metadata) {
if (auto error = hwcLayer->setLayerGenericMetadata(name, entry.mandatory, entry.value);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set generic metadata %s %s (%d)", getLayerFE().getDebugName(),
name.c_str(), to_string(error).c_str(), static_cast<int32_t>(error));
}
@@ -422,14 +424,14 @@
// TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
// state and should not change every frame.
if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set visible region: %s (%d)", getLayerFE().getDebugName(),
to_string(error).c_str(), static_cast<int32_t>(error));
outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG);
}
if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set dataspace %d: %s (%d)", getLayerFE().getDebugName(),
outputDependentState.dataspace, to_string(error).c_str(),
static_cast<int32_t>(error));
@@ -439,9 +441,9 @@
void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) {
switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
- case HWC2::Error::None:
+ case hal::Error::NONE:
break;
- case HWC2::Error::Unsupported:
+ case hal::Error::UNSUPPORTED:
editState().forceClientComposition = true;
break;
default:
@@ -450,7 +452,7 @@
}
if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set surface damage: %s (%d)", getLayerFE().getDebugName(),
to_string(error).c_str(), static_cast<int32_t>(error));
outputIndependentState.surfaceDamage.dump(LOG_TAG);
@@ -458,18 +460,18 @@
// Content-specific per-frame state
switch (outputIndependentState.compositionType) {
- case Hwc2::IComposerClient::Composition::SOLID_COLOR:
+ case hal::Composition::SOLID_COLOR:
// For compatibility, should be written AFTER the composition type.
break;
- case Hwc2::IComposerClient::Composition::SIDEBAND:
+ case hal::Composition::SIDEBAND:
writeSidebandStateToHWC(hwcLayer, outputIndependentState);
break;
- case Hwc2::IComposerClient::Composition::CURSOR:
- case Hwc2::IComposerClient::Composition::DEVICE:
+ case hal::Composition::CURSOR:
+ case hal::Composition::DEVICE:
writeBufferStateToHWC(hwcLayer, outputIndependentState);
break;
- case Hwc2::IComposerClient::Composition::INVALID:
- case Hwc2::IComposerClient::Composition::CLIENT:
+ case hal::Composition::INVALID:
+ case hal::Composition::CLIENT:
// Ignored
break;
}
@@ -477,16 +479,16 @@
void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
const LayerFECompositionState& outputIndependentState) {
- if (outputIndependentState.compositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR) {
+ if (outputIndependentState.compositionType != hal::Composition::SOLID_COLOR) {
return;
}
- hwc_color_t color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
- static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
- static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
- 255};
+ hal::Color color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
+ static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
+ static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
+ 255};
- if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
+ if (auto error = hwcLayer->setColor(color); error != hal::Error::NONE) {
ALOGE("[%s] Failed to set color: %s (%d)", getLayerFE().getDebugName(),
to_string(error).c_str(), static_cast<int32_t>(error));
}
@@ -495,7 +497,7 @@
void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
const LayerFECompositionState& outputIndependentState) {
if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", getLayerFE().getDebugName(),
outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
static_cast<int32_t>(error));
@@ -508,7 +510,7 @@
getOutput().getDisplayColorProfile()->getSupportedPerFrameMetadata();
if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
outputIndependentState.hdrMetadata);
- error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
+ error != hal::Error::NONE && error != hal::Error::UNSUPPORTED) {
ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", getLayerFE().getDebugName(),
to_string(error).c_str(), static_cast<int32_t>(error));
}
@@ -522,29 +524,28 @@
&hwcBuffer);
if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set buffer %p: %s (%d)", getLayerFE().getDebugName(),
outputIndependentState.buffer->handle, to_string(error).c_str(),
static_cast<int32_t>(error));
}
}
-void OutputLayer::writeCompositionTypeToHWC(
- HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) {
+void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
+ hal::Composition requestedCompositionType) {
auto& outputDependentState = editState();
// If we are forcing client composition, we need to tell the HWC
if (outputDependentState.forceClientComposition) {
- requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+ requestedCompositionType = hal::Composition::CLIENT;
}
// Set the requested composition type with the HWC whenever it changes
if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
- if (auto error = hwcLayer->setCompositionType(
- static_cast<HWC2::Composition>(requestedCompositionType));
- error != HWC2::Error::None) {
+ if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set composition type %s: %s (%d)", getLayerFE().getDebugName(),
toString(requestedCompositionType).c_str(), to_string(error).c_str(),
static_cast<int32_t>(error));
@@ -571,7 +572,7 @@
Rect position = outputState.transform.transform(frame);
if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
- error != HWC2::Error::None) {
+ error != hal::Error::NONE) {
ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)",
getLayerFE().getDebugName(), position.left, position.top, to_string(error).c_str(),
static_cast<int32_t>(error));
@@ -585,33 +586,31 @@
bool OutputLayer::requiresClientComposition() const {
const auto& state = getState();
- return !state.hwc ||
- state.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
+ return !state.hwc || state.hwc->hwcCompositionType == hal::Composition::CLIENT;
}
bool OutputLayer::isHardwareCursor() const {
const auto& state = getState();
- return state.hwc && state.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
+ return state.hwc && state.hwc->hwcCompositionType == hal::Composition::CURSOR;
}
-void OutputLayer::detectDisallowedCompositionTypeChange(
- Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
+void OutputLayer::detectDisallowedCompositionTypeChange(hal::Composition from,
+ hal::Composition to) const {
bool result = false;
switch (from) {
- case Hwc2::IComposerClient::Composition::INVALID:
- case Hwc2::IComposerClient::Composition::CLIENT:
+ case hal::Composition::INVALID:
+ case hal::Composition::CLIENT:
result = false;
break;
- case Hwc2::IComposerClient::Composition::DEVICE:
- case Hwc2::IComposerClient::Composition::SOLID_COLOR:
- result = (to == Hwc2::IComposerClient::Composition::CLIENT);
+ case hal::Composition::DEVICE:
+ case hal::Composition::SOLID_COLOR:
+ result = (to == hal::Composition::CLIENT);
break;
- case Hwc2::IComposerClient::Composition::CURSOR:
- case Hwc2::IComposerClient::Composition::SIDEBAND:
- result = (to == Hwc2::IComposerClient::Composition::CLIENT ||
- to == Hwc2::IComposerClient::Composition::DEVICE);
+ case hal::Composition::CURSOR:
+ case hal::Composition::SIDEBAND:
+ result = (to == hal::Composition::CLIENT || to == hal::Composition::DEVICE);
break;
}
@@ -622,8 +621,7 @@
}
}
-void OutputLayer::applyDeviceCompositionTypeChange(
- Hwc2::IComposerClient::Composition compositionType) {
+void OutputLayer::applyDeviceCompositionTypeChange(hal::Composition compositionType) {
auto& state = editState();
LOG_FATAL_IF(!state.hwc);
auto& hwcState = *state.hwc;
@@ -638,10 +636,10 @@
state.clearClientTarget = false;
}
-void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
+void OutputLayer::applyDeviceLayerRequest(hal::LayerRequest request) {
auto& state = editState();
switch (request) {
- case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
+ case hal::LayerRequest::CLEAR_CLIENT_TARGET:
state.clearClientTarget = true;
break;
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 88f2686..62977a4 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -30,6 +30,7 @@
#include <compositionengine/mock/OutputLayer.h>
#include <compositionengine/mock/RenderSurface.h>
#include <gtest/gtest.h>
+#include <renderengine/mock/RenderEngine.h>
#include <ui/DisplayInfo.h>
#include <ui/Rect.h>
@@ -40,6 +41,8 @@
namespace android::compositionengine {
namespace {
+namespace hal = android::hardware::graphics::composer::hal;
+
using testing::_;
using testing::DoAll;
using testing::Eq;
@@ -154,6 +157,8 @@
DisplayTestCommon() {
EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
+ EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
}
DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() {
@@ -180,6 +185,7 @@
StrictMock<android::mock::HWComposer> mHwComposer;
StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor;
+ StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
StrictMock<mock::CompositionEngine> mCompositionEngine;
sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
};
@@ -645,9 +651,9 @@
TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) {
android::HWComposer::DeviceRequestedChanges changes{
- {{nullptr, HWC2::Composition::Client}},
- HWC2::DisplayRequest::FlipClientTarget,
- {{nullptr, HWC2::LayerRequest::ClearClientTarget}},
+ {{nullptr, hal::Composition::CLIENT}},
+ hal::DisplayRequest::FLIP_CLIENT_TARGET,
+ {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
};
// Since two calls are made to anyLayersRequireClientComposition with different return
@@ -681,16 +687,18 @@
using DisplayGetSkipColorTransformTest = DisplayWithLayersTestCommon;
-TEST_F(DisplayGetSkipColorTransformTest, doesNothingIfNonHwcDisplay) {
+TEST_F(DisplayGetSkipColorTransformTest, checksCapabilityIfNonHwcDisplay) {
+ EXPECT_CALL(mHwComposer, hasCapability(hal::Capability::SKIP_CLIENT_COLOR_TRANSFORM))
+ .WillOnce(Return(true));
auto args = getDisplayCreationArgsForNonHWCVirtualDisplay();
auto nonHwcDisplay{impl::createDisplay(mCompositionEngine, args)};
- EXPECT_FALSE(nonHwcDisplay->getSkipColorTransform());
+ EXPECT_TRUE(nonHwcDisplay->getSkipColorTransform());
}
-TEST_F(DisplayGetSkipColorTransformTest, checksHwcCapability) {
+TEST_F(DisplayGetSkipColorTransformTest, checksDisplayCapability) {
EXPECT_CALL(mHwComposer,
- hasDisplayCapability(std::make_optional(DEFAULT_DISPLAY_ID),
- HWC2::DisplayCapability::SkipClientColorTransform))
+ hasDisplayCapability(DEFAULT_DISPLAY_ID,
+ hal::DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM))
.WillOnce(Return(true));
EXPECT_TRUE(mDisplay->getSkipColorTransform());
}
@@ -756,9 +764,9 @@
.Times(1);
mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes{
- {&mLayer1.hwc2Layer, HWC2::Composition::Client},
- {&mLayer2.hwc2Layer, HWC2::Composition::Device},
- {&hwc2LayerUnknown, HWC2::Composition::SolidColor},
+ {&mLayer1.hwc2Layer, hal::Composition::CLIENT},
+ {&mLayer2.hwc2Layer, hal::Composition::DEVICE},
+ {&hwc2LayerUnknown, hal::Composition::SOLID_COLOR},
});
}
@@ -769,28 +777,28 @@
using DisplayApplyDisplayRequestsTest = DisplayWithLayersTestCommon;
TEST_F(DisplayApplyDisplayRequestsTest, handlesNoRequests) {
- mDisplay->applyDisplayRequests(static_cast<HWC2::DisplayRequest>(0));
+ mDisplay->applyDisplayRequests(static_cast<hal::DisplayRequest>(0));
auto& state = mDisplay->getState();
EXPECT_FALSE(state.flipClientTarget);
}
TEST_F(DisplayApplyDisplayRequestsTest, handlesFlipClientTarget) {
- mDisplay->applyDisplayRequests(HWC2::DisplayRequest::FlipClientTarget);
+ mDisplay->applyDisplayRequests(hal::DisplayRequest::FLIP_CLIENT_TARGET);
auto& state = mDisplay->getState();
EXPECT_TRUE(state.flipClientTarget);
}
TEST_F(DisplayApplyDisplayRequestsTest, handlesWriteClientTargetToOutput) {
- mDisplay->applyDisplayRequests(HWC2::DisplayRequest::WriteClientTargetToOutput);
+ mDisplay->applyDisplayRequests(hal::DisplayRequest::WRITE_CLIENT_TARGET_TO_OUTPUT);
auto& state = mDisplay->getState();
EXPECT_FALSE(state.flipClientTarget);
}
TEST_F(DisplayApplyDisplayRequestsTest, handlesAllRequestFlagsSet) {
- mDisplay->applyDisplayRequests(static_cast<HWC2::DisplayRequest>(~0));
+ mDisplay->applyDisplayRequests(static_cast<hal::DisplayRequest>(~0));
auto& state = mDisplay->getState();
EXPECT_TRUE(state.flipClientTarget);
@@ -820,8 +828,8 @@
.Times(1);
mDisplay->applyLayerRequestsToLayers(impl::Display::LayerRequests{
- {&mLayer1.hwc2Layer, HWC2::LayerRequest::ClearClientTarget},
- {&hwc2LayerUnknown, HWC2::LayerRequest::ClearClientTarget},
+ {&mLayer1.hwc2Layer, hal::LayerRequest::CLEAR_CLIENT_TARGET},
+ {&hwc2LayerUnknown, hal::LayerRequest::CLEAR_CLIENT_TARGET},
});
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
index 8c10341..0baa79d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
@@ -16,7 +16,7 @@
#include "MockHWC2.h"
-namespace HWC2 {
+namespace android::HWC2 {
// This will go away once HWC2::Layer is moved into the "backend" library
Layer::~Layer() = default;
@@ -29,4 +29,4 @@
Layer::~Layer() = default;
} // namespace mock
-} // namespace HWC2
+} // namespace android::HWC2
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index be89c1a..d21b97e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -20,7 +20,6 @@
#include <ui/Fence.h>
#include <ui/FloatRect.h>
#include <ui/GraphicBuffer.h>
-
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Transform.h>
@@ -35,31 +34,36 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
+namespace android {
namespace HWC2 {
namespace mock {
+namespace hal = android::hardware::graphics::composer::hal;
+
+using Error = hal::Error;
+
class Layer : public HWC2::Layer {
public:
Layer();
~Layer() override;
- MOCK_CONST_METHOD0(getId, hwc2_layer_t());
+ MOCK_CONST_METHOD0(getId, hal::HWLayerId());
MOCK_METHOD2(setCursorPosition, Error(int32_t, int32_t));
MOCK_METHOD3(setBuffer,
Error(uint32_t, const android::sp<android::GraphicBuffer>&,
const android::sp<android::Fence>&));
MOCK_METHOD1(setSurfaceDamage, Error(const android::Region&));
- MOCK_METHOD1(setBlendMode, Error(BlendMode));
- MOCK_METHOD1(setColor, Error(hwc_color_t));
- MOCK_METHOD1(setCompositionType, Error(Composition));
+ MOCK_METHOD1(setBlendMode, Error(hal::BlendMode));
+ MOCK_METHOD1(setColor, Error(hal::Color));
+ MOCK_METHOD1(setCompositionType, Error(hal::Composition));
MOCK_METHOD1(setDataspace, Error(android::ui::Dataspace));
MOCK_METHOD2(setPerFrameMetadata, Error(const int32_t, const android::HdrMetadata&));
MOCK_METHOD1(setDisplayFrame, Error(const android::Rect&));
MOCK_METHOD1(setPlaneAlpha, Error(float));
MOCK_METHOD1(setSidebandStream, Error(const native_handle_t*));
MOCK_METHOD1(setSourceCrop, Error(const android::FloatRect&));
- MOCK_METHOD1(setTransform, Error(Transform));
+ MOCK_METHOD1(setTransform, Error(hal::Transform));
MOCK_METHOD1(setVisibleRegion, Error(const android::Region&));
MOCK_METHOD1(setZOrder, Error(uint32_t));
MOCK_METHOD2(setInfo, Error(uint32_t, uint32_t));
@@ -71,3 +75,4 @@
} // namespace mock
} // namespace HWC2
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 88f6649..75a4fec 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -31,6 +31,8 @@
namespace android {
namespace mock {
+namespace hal = android::hardware::graphics::composer::hal;
+
class HWComposer : public android::HWComposer {
public:
HWComposer();
@@ -38,14 +40,13 @@
MOCK_METHOD2(setConfiguration, void(HWC2::ComposerCallback*, int32_t));
MOCK_CONST_METHOD3(getDisplayIdentificationData,
- bool(hwc2_display_t, uint8_t*, DisplayIdentificationData*));
- MOCK_CONST_METHOD1(hasCapability, bool(HWC2::Capability));
- MOCK_CONST_METHOD2(hasDisplayCapability,
- bool(const std::optional<DisplayId>&, HWC2::DisplayCapability));
+ bool(hal::HWDisplayId, uint8_t*, DisplayIdentificationData*));
+ MOCK_CONST_METHOD1(hasCapability, bool(hal::Capability));
+ MOCK_CONST_METHOD2(hasDisplayCapability, bool(DisplayId, hal::DisplayCapability));
MOCK_METHOD3(allocateVirtualDisplay,
std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
- MOCK_METHOD2(allocatePhysicalDisplay, void(hwc2_display_t, DisplayId));
+ MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, DisplayId));
MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
MOCK_METHOD3(getDeviceCompositionChanges,
@@ -55,7 +56,7 @@
status_t(DisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
ui::Dataspace));
MOCK_METHOD1(presentAndGetReleaseFences, status_t(DisplayId));
- MOCK_METHOD2(setPowerMode, status_t(DisplayId, int));
+ MOCK_METHOD2(setPowerMode, status_t(DisplayId, hal::PowerMode));
MOCK_METHOD2(setActiveConfig, status_t(DisplayId, size_t));
MOCK_METHOD2(setColorTransform, status_t(DisplayId, const mat4&));
MOCK_METHOD1(disconnectDisplay, void(DisplayId));
@@ -73,13 +74,13 @@
MOCK_METHOD4(setDisplayContentSamplingEnabled, status_t(DisplayId, bool, uint8_t, uint64_t));
MOCK_METHOD4(getDisplayedContentSample,
status_t(DisplayId, uint64_t, uint64_t, DisplayedFrameStats*));
- MOCK_METHOD2(setDisplayBrightness, status_t(DisplayId, float));
+ MOCK_METHOD2(setDisplayBrightness, std::future<status_t>(DisplayId, float));
MOCK_METHOD2(getDisplayBrightnessSupport, status_t(DisplayId, bool*));
MOCK_METHOD2(onHotplug,
- std::optional<DisplayIdentificationInfo>(hwc2_display_t, HWC2::Connection));
- MOCK_METHOD2(onVsync, bool(hwc2_display_t, int64_t));
- MOCK_METHOD2(setVsyncEnabled, void(DisplayId, HWC2::Vsync));
+ std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection));
+ MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
+ MOCK_METHOD2(setVsyncEnabled, void(DisplayId, hal::Vsync));
MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(DisplayId));
MOCK_CONST_METHOD1(isConnected, bool(DisplayId));
MOCK_CONST_METHOD1(getConfigs,
@@ -93,21 +94,21 @@
MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(DisplayId));
MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(DisplayId));
MOCK_METHOD4(setActiveConfigWithConstraints,
- status_t(DisplayId, size_t, const HWC2::VsyncPeriodChangeConstraints&,
- HWC2::VsyncPeriodChangeTimeline*));
+ status_t(DisplayId, size_t, const hal::VsyncPeriodChangeConstraints&,
+ hal::VsyncPeriodChangeTimeline*));
MOCK_METHOD2(setAutoLowLatencyMode, status_t(DisplayId, bool));
- MOCK_METHOD2(getSupportedContentTypes, status_t(DisplayId, std::vector<HWC2::ContentType>*));
- MOCK_METHOD2(setContentType, status_t(DisplayId, HWC2::ContentType));
+ MOCK_METHOD2(getSupportedContentTypes, status_t(DisplayId, std::vector<hal::ContentType>*));
+ MOCK_METHOD2(setContentType, status_t(DisplayId, hal::ContentType));
MOCK_CONST_METHOD0(getSupportedLayerGenericMetadata,
const std::unordered_map<std::string, bool>&());
MOCK_CONST_METHOD1(dump, void(std::string&));
MOCK_CONST_METHOD0(getComposer, android::Hwc2::Composer*());
- MOCK_CONST_METHOD1(getHwcDisplayId, std::optional<hwc2_display_t>(int32_t));
- MOCK_CONST_METHOD0(getInternalHwcDisplayId, std::optional<hwc2_display_t>());
- MOCK_CONST_METHOD0(getExternalHwcDisplayId, std::optional<hwc2_display_t>());
- MOCK_CONST_METHOD1(toPhysicalDisplayId, std::optional<DisplayId>(hwc2_display_t));
- MOCK_CONST_METHOD1(fromPhysicalDisplayId, std::optional<hwc2_display_t>(DisplayId));
+ MOCK_CONST_METHOD1(getHwcDisplayId, std::optional<hal::HWDisplayId>(int32_t));
+ MOCK_CONST_METHOD0(getInternalHwcDisplayId, std::optional<hal::HWDisplayId>());
+ MOCK_CONST_METHOD0(getExternalHwcDisplayId, std::optional<hal::HWDisplayId>());
+ MOCK_CONST_METHOD1(toPhysicalDisplayId, std::optional<DisplayId>(hal::HWDisplayId));
+ MOCK_CONST_METHOD1(fromPhysicalDisplayId, std::optional<hal::HWDisplayId>(DisplayId));
};
} // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 1b5617c..020f93a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -29,6 +29,8 @@
namespace android::compositionengine {
namespace {
+namespace hal = android::hardware::graphics::composer::hal;
+
using testing::_;
using testing::InSequence;
using testing::Return;
@@ -359,7 +361,7 @@
mOutputState.orientation = entry.display;
mOutputState.transform = ui::Transform{entry.display};
- auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+ const auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(entry.display);
EXPECT_EQ(entry.expected, actual) << "entry " << i;
}
}
@@ -369,56 +371,109 @@
mLayerFEState.geomBufferUsesDisplayInverseTransform = true;
struct Entry {
- uint32_t layer;
+ uint32_t layer; /* shouldn't affect the result, so we just use arbitrary values */
uint32_t buffer;
uint32_t display;
+ uint32_t internal;
uint32_t expected;
};
- // Not an exhaustive list of cases, but hopefully enough.
- const std::array<Entry, 24> testData = {
+ const std::array<Entry, 64> testData = {
// clang-format off
- // layer buffer display expected
- /* 0 */ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT},
- /* 1 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_IDENT},
- /* 2 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_180, TR_IDENT},
- /* 3 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_IDENT},
+ // layer buffer display internal expected
+ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT},
+ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_ROT_90, TR_ROT_270},
+ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_ROT_180, TR_ROT_180},
+ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_ROT_270, TR_ROT_90},
- /* 4 */ Entry{TR_IDENT, TR_FLP_H, TR_IDENT, TR_FLP_H},
- /* 5 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_90, TR_FLP_H},
- /* 6 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_180, TR_FLP_H},
- /* 7 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_270, TR_FLP_H},
+ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_IDENT, TR_ROT_90},
+ Entry{TR_ROT_90, TR_IDENT, TR_ROT_90, TR_ROT_90, TR_IDENT},
+ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_ROT_180, TR_ROT_270},
+ Entry{TR_ROT_90, TR_IDENT, TR_ROT_90, TR_ROT_270, TR_ROT_180},
- /* 8 */ Entry{TR_IDENT, TR_FLP_V, TR_IDENT, TR_FLP_V},
- /* 9 */ Entry{TR_IDENT, TR_ROT_90, TR_ROT_90, TR_ROT_90},
- /* 10 */ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_ROT_180},
- /* 11 */ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_ROT_270},
+ Entry{TR_ROT_180, TR_IDENT, TR_ROT_180, TR_IDENT, TR_ROT_180},
+ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_ROT_90, TR_ROT_90},
+ Entry{TR_ROT_180, TR_IDENT, TR_ROT_180, TR_ROT_180, TR_IDENT},
+ Entry{TR_ROT_270, TR_IDENT, TR_ROT_180, TR_ROT_270, TR_ROT_270},
- /* 12 */ Entry{TR_ROT_90, TR_IDENT, TR_IDENT, TR_IDENT},
- /* 13 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_90, TR_FLP_H},
- /* 14 */ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_IDENT},
- /* 15 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_270, TR_FLP_H},
+ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT, TR_ROT_270},
+ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_ROT_90, TR_ROT_180},
+ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_ROT_180, TR_ROT_90},
+ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_ROT_270, TR_IDENT},
- /* 16 */ Entry{TR_ROT_180, TR_FLP_H, TR_IDENT, TR_FLP_H},
- /* 17 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_IDENT},
- /* 18 */ Entry{TR_ROT_180, TR_FLP_H, TR_ROT_180, TR_FLP_H},
- /* 19 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_IDENT},
+ // layer buffer display internal expected
+ Entry{TR_IDENT, TR_ROT_90, TR_IDENT, TR_IDENT, TR_ROT_90},
+ Entry{TR_ROT_90, TR_ROT_90, TR_IDENT, TR_ROT_90, TR_IDENT},
+ Entry{TR_ROT_180, TR_ROT_90, TR_IDENT, TR_ROT_180, TR_ROT_270},
+ Entry{TR_ROT_270, TR_ROT_90, TR_IDENT, TR_ROT_270, TR_ROT_180},
- /* 20 */ Entry{TR_ROT_270, TR_IDENT, TR_IDENT, TR_IDENT},
- /* 21 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_90, TR_FLP_H},
- /* 22 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_180, TR_FLP_H},
- /* 23 */ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT},
+ Entry{TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_IDENT, TR_ROT_180},
+ Entry{TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_ROT_90},
+ Entry{TR_ROT_90, TR_ROT_90, TR_ROT_90, TR_ROT_180, TR_IDENT},
+ Entry{TR_ROT_270, TR_ROT_90, TR_ROT_90, TR_ROT_270, TR_ROT_270},
+
+ Entry{TR_IDENT, TR_ROT_90, TR_ROT_180, TR_IDENT, TR_ROT_270},
+ Entry{TR_ROT_90, TR_ROT_90, TR_ROT_180, TR_ROT_90, TR_ROT_180},
+ Entry{TR_ROT_180, TR_ROT_90, TR_ROT_180, TR_ROT_180, TR_ROT_90},
+ Entry{TR_ROT_90, TR_ROT_90, TR_ROT_180, TR_ROT_270, TR_IDENT},
+
+ Entry{TR_IDENT, TR_ROT_90, TR_ROT_270, TR_IDENT, TR_IDENT},
+ Entry{TR_ROT_270, TR_ROT_90, TR_ROT_270, TR_ROT_90, TR_ROT_270},
+ Entry{TR_ROT_180, TR_ROT_90, TR_ROT_270, TR_ROT_180, TR_ROT_180},
+ Entry{TR_ROT_270, TR_ROT_90, TR_ROT_270, TR_ROT_270, TR_ROT_90},
+
+ // layer buffer display internal expected
+ Entry{TR_IDENT, TR_ROT_180, TR_IDENT, TR_IDENT, TR_ROT_180},
+ Entry{TR_IDENT, TR_ROT_180, TR_IDENT, TR_ROT_90, TR_ROT_90},
+ Entry{TR_ROT_180, TR_ROT_180, TR_IDENT, TR_ROT_180, TR_IDENT},
+ Entry{TR_ROT_270, TR_ROT_180, TR_IDENT, TR_ROT_270, TR_ROT_270},
+
+ Entry{TR_IDENT, TR_ROT_180, TR_ROT_90, TR_IDENT, TR_ROT_270},
+ Entry{TR_ROT_90, TR_ROT_180, TR_ROT_90, TR_ROT_90, TR_ROT_180},
+ Entry{TR_ROT_180, TR_ROT_180, TR_ROT_90, TR_ROT_180, TR_ROT_90},
+ Entry{TR_ROT_180, TR_ROT_180, TR_ROT_90, TR_ROT_270, TR_IDENT},
+
+ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_IDENT, TR_IDENT},
+ Entry{TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_90, TR_ROT_270},
+ Entry{TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_180, TR_ROT_180},
+ Entry{TR_ROT_270, TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_90},
+
+ Entry{TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_IDENT, TR_ROT_90},
+ Entry{TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_90, TR_IDENT},
+ Entry{TR_ROT_180, TR_ROT_180, TR_ROT_270, TR_ROT_180, TR_ROT_270},
+ Entry{TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_ROT_270, TR_ROT_180},
+
+ // layer buffer display internal expected
+ Entry{TR_IDENT, TR_ROT_270, TR_IDENT, TR_IDENT, TR_ROT_270},
+ Entry{TR_ROT_90, TR_ROT_270, TR_IDENT, TR_ROT_90, TR_ROT_180},
+ Entry{TR_ROT_270, TR_ROT_270, TR_IDENT, TR_ROT_180, TR_ROT_90},
+ Entry{TR_IDENT, TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT},
+
+ Entry{TR_ROT_270, TR_ROT_270, TR_ROT_90, TR_IDENT, TR_IDENT},
+ Entry{TR_ROT_90, TR_ROT_270, TR_ROT_90, TR_ROT_90, TR_ROT_270},
+ Entry{TR_ROT_180, TR_ROT_270, TR_ROT_90, TR_ROT_180, TR_ROT_180},
+ Entry{TR_ROT_90, TR_ROT_270, TR_ROT_90, TR_ROT_270, TR_ROT_90},
+
+ Entry{TR_IDENT, TR_ROT_270, TR_ROT_180, TR_IDENT, TR_ROT_90},
+ Entry{TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_ROT_90, TR_IDENT},
+ Entry{TR_ROT_180, TR_ROT_270, TR_ROT_180, TR_ROT_180, TR_ROT_270},
+ Entry{TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_ROT_270, TR_ROT_180},
+
+ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_IDENT, TR_ROT_180},
+ Entry{TR_ROT_90, TR_ROT_270, TR_ROT_270, TR_ROT_90, TR_ROT_90},
+ Entry{TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_180, TR_IDENT},
+ Entry{TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_270, TR_ROT_270},
// clang-format on
};
for (size_t i = 0; i < testData.size(); i++) {
const auto& entry = testData[i];
- mLayerFEState.geomLayerTransform = ui::Transform{entry.layer};
+ mLayerFEState.geomLayerTransform.set(entry.layer, 1920, 1080);
mLayerFEState.geomBufferTransform = entry.buffer;
mOutputState.orientation = entry.display;
mOutputState.transform = ui::Transform{entry.display};
- auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
+ const auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(entry.internal);
EXPECT_EQ(entry.expected, actual) << "entry " << i;
}
}
@@ -434,7 +489,7 @@
// Mock everything called by updateCompositionState to simplify testing it.
MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
- MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
+ MOCK_CONST_METHOD1(calculateOutputRelativeBufferTransform, uint32_t(uint32_t));
// compositionengine::OutputLayer overrides
const compositionengine::Output& getOutput() const override { return mOutput; }
@@ -461,10 +516,11 @@
~OutputLayerUpdateCompositionStateTest() = default;
- void setupGeometryChildCallValues() {
+ void setupGeometryChildCallValues(ui::Transform::RotationFlags internalDisplayRotationFlags) {
EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
- EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform())
+ EXPECT_CALL(mOutputLayer,
+ calculateOutputRelativeBufferTransform(internalDisplayRotationFlags))
.WillOnce(Return(mBufferTransform));
}
@@ -487,7 +543,7 @@
TEST_F(OutputLayerUpdateCompositionStateTest, doesNothingIfNoFECompositionState) {
EXPECT_CALL(*mLayerFE, getCompositionState()).WillOnce(Return(nullptr));
- mOutputLayer.updateCompositionState(true, false);
+ mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_90);
}
TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
@@ -495,9 +551,9 @@
mOutputState.isSecure = true;
mOutputLayer.editState().forceClientComposition = true;
- setupGeometryChildCallValues();
+ setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_90);
- mOutputLayer.updateCompositionState(true, false);
+ mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_90);
validateComputedGeometryState();
@@ -509,9 +565,9 @@
mLayerFEState.isSecure = true;
mOutputState.isSecure = false;
- setupGeometryChildCallValues();
+ setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0);
- mOutputLayer.updateCompositionState(true, false);
+ mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_0);
validateComputedGeometryState();
@@ -525,9 +581,9 @@
mBufferTransform = ui::Transform::ROT_INVALID;
- setupGeometryChildCallValues();
+ setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0);
- mOutputLayer.updateCompositionState(true, false);
+ mOutputLayer.updateCompositionState(true, false, ui::Transform::RotationFlags::ROT_0);
validateComputedGeometryState();
@@ -542,7 +598,7 @@
// should use the layers requested colorspace.
mLayerFEState.isColorspaceAgnostic = false;
- mOutputLayer.updateCompositionState(false, false);
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace);
@@ -550,7 +606,7 @@
// should use the colorspace chosen for the whole output.
mLayerFEState.isColorspaceAgnostic = true;
- mOutputLayer.updateCompositionState(false, false);
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace);
}
@@ -558,7 +614,7 @@
TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
mOutputLayer.editState().forceClientComposition = false;
- mOutputLayer.updateCompositionState(false, false);
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
}
@@ -567,7 +623,7 @@
doesNotClearForceClientCompositionIfNotDoingGeometry) {
mOutputLayer.editState().forceClientComposition = true;
- mOutputLayer.updateCompositionState(false, false);
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
}
@@ -576,7 +632,7 @@
mLayerFEState.forceClientComposition = true;
mOutputLayer.editState().forceClientComposition = false;
- mOutputLayer.updateCompositionState(false, false);
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
}
@@ -586,7 +642,7 @@
mOutputLayer.editState().forceClientComposition = false;
EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false));
- mOutputLayer.updateCompositionState(false, false);
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
}
@@ -595,15 +651,15 @@
mLayerFEState.forceClientComposition = false;
mOutputLayer.editState().forceClientComposition = false;
- mOutputLayer.updateCompositionState(false, true);
+ mOutputLayer.updateCompositionState(false, true, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
mOutputLayer.editState().forceClientComposition = false;
- setupGeometryChildCallValues();
+ setupGeometryChildCallValues(ui::Transform::RotationFlags::ROT_0);
- mOutputLayer.updateCompositionState(true, true);
+ mOutputLayer.updateCompositionState(true, true, ui::Transform::RotationFlags::ROT_0);
EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
}
@@ -613,7 +669,7 @@
*/
struct OutputLayerWriteStateToHWCTest : public OutputLayerTest {
- static constexpr HWC2::Error kError = HWC2::Error::Unsupported;
+ static constexpr hal::Error kError = hal::Error::UNSUPPORTED;
static constexpr FloatRect kSourceCrop{11.f, 12.f, 13.f, 14.f};
static constexpr uint32_t kZOrder = 21u;
static constexpr Hwc2::Transform kBufferTransform = static_cast<Hwc2::Transform>(31);
@@ -686,11 +742,9 @@
EXPECT_CALL(*mHwcLayer, setDisplayFrame(kDisplayFrame)).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setSourceCrop(kSourceCrop)).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setZOrder(kZOrder)).WillOnce(Return(kError));
- EXPECT_CALL(*mHwcLayer, setTransform(static_cast<HWC2::Transform>(kBufferTransform)))
- .WillOnce(Return(kError));
+ EXPECT_CALL(*mHwcLayer, setTransform(kBufferTransform)).WillOnce(Return(kError));
- EXPECT_CALL(*mHwcLayer, setBlendMode(static_cast<HWC2::BlendMode>(kBlendMode)))
- .WillOnce(Return(kError));
+ EXPECT_CALL(*mHwcLayer, setBlendMode(kBlendMode)).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setPlaneAlpha(kAlpha)).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError));
}
@@ -701,15 +755,14 @@
EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError));
EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform))
.WillOnce(Return(unsupported == SimulateUnsupported::ColorTransform
- ? HWC2::Error::Unsupported
- : HWC2::Error::None));
+ ? hal::Error::UNSUPPORTED
+ : hal::Error::NONE));
EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(kSurfaceDamage)))
.WillOnce(Return(kError));
}
void expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition compositionType) {
- EXPECT_CALL(*mHwcLayer, setCompositionType(static_cast<HWC2::Composition>(compositionType)))
- .WillOnce(Return(kError));
+ EXPECT_CALL(*mHwcLayer, setCompositionType(compositionType)).WillOnce(Return(kError));
}
void expectNoSetCompositionTypeCall() {
@@ -717,9 +770,9 @@
}
void expectSetColorCall() {
- hwc_color_t color = {static_cast<uint8_t>(std::round(kColor.r * 255)),
- static_cast<uint8_t>(std::round(kColor.g * 255)),
- static_cast<uint8_t>(std::round(kColor.b * 255)), 255};
+ const hal::Color color = {static_cast<uint8_t>(std::round(kColor.r * 255)),
+ static_cast<uint8_t>(std::round(kColor.g * 255)),
+ static_cast<uint8_t>(std::round(kColor.b * 255)), 255};
EXPECT_CALL(*mHwcLayer, setColor(ColorEq(color))).WillOnce(Return(kError));
}
@@ -811,7 +864,7 @@
// geomBufferTransform is set to the inverse transform.
mLayerFEState.geomBufferTransform = TR_ROT_270;
- EXPECT_EQ(TR_IDENT, mOutputLayer.calculateOutputRelativeBufferTransform());
+ EXPECT_EQ(TR_IDENT, mOutputLayer.calculateOutputRelativeBufferTransform(ui::Transform::ROT_90));
}
TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) {
@@ -924,7 +977,7 @@
struct OutputLayerWriteCursorPositionToHWCTest : public OutputLayerTest {
static constexpr int kDefaultTransform = TR_IDENT;
- static constexpr HWC2::Error kDefaultError = HWC2::Error::Unsupported;
+ static constexpr hal::Error kDefaultError = hal::Error::UNSUPPORTED;
static const Rect kDefaultDisplayViewport;
static const Rect kDefaultCursorFrame;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 63bb459..59ed72e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -696,11 +696,11 @@
InjectedLayer layer2;
InjectedLayer layer3;
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
injectOutputLayer(layer1);
@@ -712,6 +712,7 @@
CompositionRefreshArgs args;
args.updatingGeometryThisFrame = false;
args.devOptForceClientComposition = false;
+ args.internalDisplayRotationFlags = ui::Transform::ROT_180;
mOutput->updateAndWriteCompositionState(args);
}
@@ -720,11 +721,11 @@
InjectedLayer layer2;
InjectedLayer layer3;
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(true));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(true));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(true));
injectOutputLayer(layer1);
@@ -744,11 +745,11 @@
InjectedLayer layer2;
InjectedLayer layer3;
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
injectOutputLayer(layer1);
@@ -2797,6 +2798,7 @@
mOutput.mState.usesClientComposition = true;
mOutput.mState.usesDeviceComposition = false;
mOutput.mState.reusedClientComposition = false;
+ mOutput.mState.flipClientTarget = false;
EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
@@ -2868,19 +2870,40 @@
TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) {
mOutput.mState.usesClientComposition = false;
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
verify().execute().expectAFenceWasReturned();
}
-TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) {
- EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
- EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
+TEST_F(OutputComposeSurfacesTest,
+ dequeuesABufferIfNoClientCompositionButFlipClientTargetRequested) {
+ mOutput.mState.usesClientComposition = false;
+ mOutput.mState.flipClientTarget = true;
+
EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
- EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
- .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
- EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
- .WillRepeatedly(Return());
+
+ EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
+ EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
+
+ verify().execute().expectAFenceWasReturned();
+}
+
+TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) {
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
+
+ verify().execute().expectNoFenceWasReturned();
+}
+
+TEST_F(OutputComposeSurfacesTest,
+ doesMinimalWorkIfDequeueBufferFailsForNoClientCompositionButFlipClientTargetRequested) {
+ mOutput.mState.usesClientComposition = false;
+ mOutput.mState.flipClientTarget = true;
+
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
@@ -3100,9 +3123,8 @@
.andIfUsesHdr(true)
.andIfSkipColorTransform(false)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
- mat4(), Region::INVALID_REGION,
- kDefaultOutputOrientation})
+ kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
+ Region::INVALID_REGION, kDefaultOutputOrientation})
.execute()
.expectAFenceWasReturned();
}
@@ -3112,9 +3134,8 @@
.andIfUsesHdr(false)
.andIfSkipColorTransform(false)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
- mat4(), Region::INVALID_REGION,
- kDefaultOutputOrientation})
+ kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
+ Region::INVALID_REGION, kDefaultOutputOrientation})
.execute()
.expectAFenceWasReturned();
}
@@ -3124,7 +3145,7 @@
.andIfUsesHdr(true)
.andIfSkipColorTransform(false)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
+ kDefaultMaxLuminance, kDefaultOutputDataspace,
kDefaultColorTransformMat, Region::INVALID_REGION,
kDefaultOutputOrientation})
.execute()
@@ -3136,7 +3157,7 @@
.andIfUsesHdr(false)
.andIfSkipColorTransform(false)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
+ kDefaultMaxLuminance, kDefaultOutputDataspace,
kDefaultColorTransformMat, Region::INVALID_REGION,
kDefaultOutputOrientation})
.execute()
@@ -3149,9 +3170,8 @@
.andIfUsesHdr(true)
.andIfSkipColorTransform(true)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
- mat4(), Region::INVALID_REGION,
- kDefaultOutputOrientation})
+ kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
+ Region::INVALID_REGION, kDefaultOutputOrientation})
.execute()
.expectAFenceWasReturned();
}
@@ -3318,7 +3338,7 @@
mLayer.layerFEState.backgroundBlurRadius = 10;
mOutput.editState().isEnabled = true;
- EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
EXPECT_CALL(mLayer.outputLayer, writeStateToHWC(false));
EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
.WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
@@ -3897,11 +3917,11 @@
InjectedLayer layer3;
// Layer requesting blur, or below, should request client composition.
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0));
EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false));
layer2.layerFEState.backgroundBlurRadius = 10;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f0bbdf6..0c8aafc 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -43,6 +43,8 @@
namespace android {
+namespace hal = hardware::graphics::composer::hal;
+
using android::base::StringAppendF;
ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0;
@@ -119,17 +121,17 @@
}
// ----------------------------------------------------------------------------
-void DisplayDevice::setPowerMode(int mode) {
+void DisplayDevice::setPowerMode(hal::PowerMode mode) {
mPowerMode = mode;
- getCompositionDisplay()->setCompositionEnabled(mPowerMode != HWC_POWER_MODE_OFF);
+ getCompositionDisplay()->setCompositionEnabled(mPowerMode != hal::PowerMode::OFF);
}
-int DisplayDevice::getPowerMode() const {
+hal::PowerMode DisplayDevice::getPowerMode() const {
return mPowerMode;
}
bool DisplayDevice::isPoweredOn() const {
- return mPowerMode != HWC_POWER_MODE_OFF;
+ return mPowerMode != hal::PowerMode::OFF;
}
void DisplayDevice::setActiveConfig(HwcConfigIndexType mode) {
@@ -262,7 +264,8 @@
StringAppendF(&result, "+ %s\n", getDebugName().c_str());
result.append(" ");
- StringAppendF(&result, "powerMode=%d, ", mPowerMode);
+ StringAppendF(&result, "powerMode=%s (%d), ", to_string(mPowerMode).c_str(),
+ static_cast<int32_t>(mPowerMode));
StringAppendF(&result, "activeConfig=%d, ", mActiveConfig.value());
getCompositionDisplay()->dump(result);
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e670d78..cb467ea 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -24,7 +24,6 @@
#include <android/native_window.h>
#include <binder/IBinder.h>
#include <gui/LayerState.h>
-#include <hardware/hwcomposer_defs.h>
#include <math/mat4.h>
#include <renderengine/RenderEngine.h>
#include <system/window.h>
@@ -39,6 +38,7 @@
#include <utils/Timers.h>
#include "DisplayHardware/DisplayIdentification.h"
+#include "DisplayHardware/Hal.h"
#include "DisplayHardware/PowerAdvisor.h"
#include "RenderArea.h"
#include "Scheduler/HwcStrongTypes.h"
@@ -93,6 +93,10 @@
static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags();
+ ui::Transform::RotationFlags getTransformHint() const {
+ return static_cast<ui::Transform::RotationFlags>(getTransform().getOrientation());
+ }
+
const ui::Transform& getTransform() const;
const Rect& getViewport() const;
const Rect& getFrame() const;
@@ -135,8 +139,8 @@
/* ------------------------------------------------------------------------
* Display power mode management.
*/
- int getPowerMode() const;
- void setPowerMode(int mode);
+ hardware::graphics::composer::hal::PowerMode getPowerMode() const;
+ void setPowerMode(hardware::graphics::composer::hal::PowerMode mode);
bool isPoweredOn() const;
ui::Dataspace getCompositionDataSpace() const;
@@ -172,7 +176,8 @@
static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags;
- int mPowerMode = HWC_POWER_MODE_OFF;
+ hardware::graphics::composer::hal::PowerMode mPowerMode =
+ hardware::graphics::composer::hal::PowerMode::OFF;
HwcConfigIndexType mActiveConfig;
// TODO(b/74619554): Remove special cases for primary display.
@@ -183,7 +188,7 @@
struct Physical {
DisplayId id;
DisplayConnectionType type;
- hwc2_display_t hwcDisplayId;
+ hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
bool operator==(const Physical& other) const {
return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId;
@@ -227,7 +232,8 @@
HdrCapabilities hdrCapabilities;
int32_t supportedPerFrameMetadata{0};
std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes;
- int initialPowerMode{HWC_POWER_MODE_NORMAL};
+ hardware::graphics::composer::hal::PowerMode initialPowerMode{
+ hardware::graphics::composer::hal::PowerMode::ON};
bool isPrimary{false};
};
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index b6d904f..4dfc743 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -96,6 +96,12 @@
info.manufactureOrModelDate = date;
}
+ if (edid.cea861Block && edid.cea861Block->hdmiVendorDataBlock) {
+ const auto& address = edid.cea861Block->hdmiVendorDataBlock->physicalAddress;
+ info.relativeAddress = {address.a, address.b, address.c, address.d};
+ } else {
+ info.relativeAddress = DeviceProductInfo::NO_RELATIVE_ADDRESS;
+ }
return info;
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index fc2f72e..4819d1d 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -26,6 +26,9 @@
#include <ui/DeviceProductInfo.h>
#include <ui/PhysicalDisplayId.h>
+#define LEGACY_DISPLAY_TYPE_PRIMARY 0
+#define LEGACY_DISPLAY_TYPE_EXTERNAL 1
+
namespace android {
struct DisplayId {
@@ -70,7 +73,7 @@
};
struct HdmiVendorDataBlock {
- std::optional<HdmiPhysicalAddress> physicalAddress;
+ HdmiPhysicalAddress physicalAddress;
};
struct Cea861ExtensionBlock : ExtensionBlock {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index fc5d441..fb82033 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -25,7 +25,6 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "HWC2.h"
-#include "ComposerHal.h"
#include <ui/Fence.h>
#include <ui/FloatRect.h>
@@ -38,6 +37,11 @@
#include <iterator>
#include <set>
+#include "../Promise.h"
+#include "ComposerHal.h"
+
+namespace android {
+
using android::Fence;
using android::FloatRect;
using android::GraphicBuffer;
@@ -49,11 +53,9 @@
namespace HWC2 {
+using namespace android::hardware::graphics::composer::hal;
+
namespace Hwc2 = android::Hwc2;
-using android::ui::ColorMode;
-using android::ui::Dataspace;
-using android::ui::PixelFormat;
-using android::ui::RenderIntent;
namespace {
@@ -67,7 +69,7 @@
// Display methods
Display::~Display() = default;
-Display::Config::Config(Display& display, hwc2_config_t id)
+Display::Config::Config(Display& display, HWConfigId id)
: mDisplay(display),
mId(id),
mWidth(-1),
@@ -76,7 +78,7 @@
mDpiX(-1),
mDpiY(-1) {}
-Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
+Display::Config::Builder::Builder(Display& display, HWConfigId id)
: mConfig(new Config(display, id)) {}
float Display::Config::Builder::getDefaultDensity() {
@@ -97,37 +99,34 @@
namespace impl {
Display::Display(android::Hwc2::Composer& composer,
- const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
+ const std::unordered_set<Capability>& capabilities, HWDisplayId id,
DisplayType type)
- : mComposer(composer),
- mCapabilities(capabilities),
- mId(id),
- mType(type) {
+ : mComposer(composer), mCapabilities(capabilities), mId(id), mType(type) {
ALOGV("Created display %" PRIu64, id);
}
Display::~Display() {
mLayers.clear();
- Error error = Error::None;
+ Error error = Error::NONE;
const char* msg;
switch (mType) {
- case DisplayType::Physical:
- error = setVsyncEnabled(HWC2::Vsync::Disable);
+ case DisplayType::PHYSICAL:
+ error = setVsyncEnabled(HWC2::Vsync::DISABLE);
msg = "disable VSYNC for";
break;
- case DisplayType::Virtual:
+ case DisplayType::VIRTUAL:
error = static_cast<Error>(mComposer.destroyVirtualDisplay(mId));
msg = "destroy virtual";
break;
- case DisplayType::Invalid: // Used in unit tests.
+ case DisplayType::INVALID: // Used in unit tests.
break;
}
- ALOGE_IF(error != Error::None, "%s: Failed to %s display %" PRIu64 ": %s (%d)", __FUNCTION__,
- msg, mId, to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE_IF(error != Error::NONE, "%s: Failed to %s display %" PRIu64 ": %d", __FUNCTION__, msg,
+ mId, static_cast<int32_t>(error));
ALOGV("Destroyed display %" PRIu64, mId);
}
@@ -141,38 +140,38 @@
Error Display::createLayer(HWC2::Layer** outLayer) {
if (!outLayer) {
- return Error::BadParameter;
+ return Error::BAD_PARAMETER;
}
- hwc2_layer_t layerId = 0;
+ HWLayerId layerId = 0;
auto intError = mComposer.createLayer(mId, &layerId);
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
auto layer = std::make_unique<impl::Layer>(mComposer, mCapabilities, mId, layerId);
*outLayer = layer.get();
mLayers.emplace(layerId, std::move(layer));
- return Error::None;
+ return Error::NONE;
}
Error Display::destroyLayer(HWC2::Layer* layer) {
if (!layer) {
- return Error::BadParameter;
+ return Error::BAD_PARAMETER;
}
mLayers.erase(layer->getId());
- return Error::None;
+ return Error::NONE;
}
Error Display::getActiveConfig(
std::shared_ptr<const Display::Config>* outConfig) const
{
ALOGV("[%" PRIu64 "] getActiveConfig", mId);
- hwc2_config_t configId = 0;
+ HWConfigId configId = 0;
auto intError = mComposer.getActiveConfig(mId, &configId);
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
ALOGE("Unable to get active config for mId:[%" PRIu64 "]", mId);
*outConfig = nullptr;
return error;
@@ -188,7 +187,7 @@
*outConfig = nullptr;
}
- return Error::None;
+ return Error::NONE;
}
bool Display::isVsyncPeriodSwitchSupported() const {
@@ -209,10 +208,10 @@
*outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
} else {
// Get the default vsync period
- hwc2_config_t configId = 0;
+ HWConfigId configId = 0;
auto intError_2_1 = mComposer.getActiveConfig(mId, &configId);
error = static_cast<Error>(intError_2_1);
- if (error == Error::None) {
+ if (error == Error::NONE) {
auto config = mConfigs.at(configId);
*outVsyncPeriod = config->getVsyncPeriod();
}
@@ -223,11 +222,11 @@
Error Display::getActiveConfigIndex(int* outIndex) const {
ALOGV("[%" PRIu64 "] getActiveConfigIndex", mId);
- hwc2_config_t configId = 0;
+ HWConfigId configId = 0;
auto intError = mComposer.getActiveConfig(mId, &configId);
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
ALOGE("Unable to get active config for mId:[%" PRIu64 "]", mId);
*outIndex = -1;
return error;
@@ -244,7 +243,7 @@
*outIndex = -1;
}
- return Error::None;
+ return Error::NONE;
}
Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
@@ -255,7 +254,7 @@
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
@@ -264,7 +263,7 @@
for (uint32_t element = 0; element < numElements; ++element) {
auto layer = getLayerById(layerIds[element]);
if (layer) {
- auto type = static_cast<Composition>(types[element]);
+ auto type = types[element];
ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s",
layer->getId(), to_string(type).c_str());
outTypes->emplace(layer, type);
@@ -274,7 +273,7 @@
}
}
- return Error::None;
+ return Error::NONE;
}
Error Display::getColorModes(std::vector<ColorMode>* outModes) const
@@ -350,14 +349,14 @@
Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
std::unordered_map<HWC2::Layer*, LayerRequest>* outLayerRequests) {
- uint32_t intDisplayRequests;
+ uint32_t intDisplayRequests = 0;
std::vector<Hwc2::Layer> layerIds;
std::vector<uint32_t> layerRequests;
auto intError = mComposer.getDisplayRequests(
mId, &intDisplayRequests, &layerIds, &layerRequests);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
@@ -376,28 +375,28 @@
}
}
- return Error::None;
+ return Error::NONE;
}
Error Display::getConnectionType(android::DisplayConnectionType* outType) const {
- if (mType != DisplayType::Physical) return Error::BadDisplay;
+ if (mType != DisplayType::PHYSICAL) return Error::BAD_DISPLAY;
using ConnectionType = Hwc2::IComposerClient::DisplayConnectionType;
ConnectionType connectionType;
const auto error = static_cast<Error>(mComposer.getDisplayConnectionType(mId, &connectionType));
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
*outType = connectionType == ConnectionType::INTERNAL
? android::DisplayConnectionType::Internal
: android::DisplayConnectionType::External;
- return Error::None;
+ return Error::NONE;
}
Error Display::supportsDoze(bool* outSupport) const {
- *outSupport = mDisplayCapabilities.count(DisplayCapability::Doze) > 0;
- return Error::None;
+ *outSupport = mDisplayCapabilities.count(DisplayCapability::DOZE) > 0;
+ return Error::NONE;
}
Error Display::getHdrCapabilities(HdrCapabilities* outCapabilities) const
@@ -410,16 +409,16 @@
&maxLuminance, &maxAverageLuminance, &minLuminance);
auto error = static_cast<HWC2::Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
*outCapabilities = HdrCapabilities(std::move(types),
maxLuminance, maxAverageLuminance, minLuminance);
- return Error::None;
+ return Error::NONE;
}
-Error Display::getDisplayedContentSamplingAttributes(PixelFormat* outFormat,
+Error Display::getDisplayedContentSamplingAttributes(hal::PixelFormat* outFormat,
Dataspace* outDataspace,
uint8_t* outComponentMask) const {
auto intError = mComposer.getDisplayedContentSamplingAttributes(mId, outFormat, outDataspace,
@@ -446,7 +445,7 @@
auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds);
auto error = static_cast<Error>(intError);
uint32_t numElements = layerIds.size();
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
@@ -463,12 +462,12 @@
for (; element < numElements; ++element) {
close(fenceFds[element]);
}
- return Error::BadLayer;
+ return Error::BAD_LAYER;
}
}
*outFences = std::move(releaseFences);
- return Error::None;
+ return Error::NONE;
}
Error Display::present(sp<Fence>* outPresentFence)
@@ -476,12 +475,12 @@
int32_t presentFenceFd = -1;
auto intError = mComposer.presentDisplay(mId, &presentFenceFd);
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
*outPresentFence = new Fence(presentFenceFd);
- return Error::None;
+ return Error::NONE;
}
Error Display::setActiveConfigWithConstraints(
@@ -492,7 +491,7 @@
ALOGE("setActiveConfigWithConstraints received config %u for the wrong display %" PRIu64
" (expected %" PRIu64 ")",
config->getId(), config->getDisplayId(), mId);
- return Error::BadConfig;
+ return Error::BAD_CONFIG;
}
if (isVsyncPeriodSwitchSupported()) {
@@ -530,7 +529,7 @@
ALOGE("setActiveConfig received config %u for the wrong display %"
PRIu64 " (expected %" PRIu64 ")", config->getId(),
config->getDisplayId(), mId);
- return Error::BadConfig;
+ return Error::BAD_CONFIG;
}
auto intError = mComposer.setActiveConfig(mId, config->getId());
return static_cast<Error>(intError);
@@ -552,11 +551,8 @@
return static_cast<Error>(intError);
}
-Error Display::setColorTransform(const android::mat4& matrix,
- android_color_transform_t hint)
-{
- auto intError = mComposer.setColorTransform(mId,
- matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
+Error Display::setColorTransform(const android::mat4& matrix, ColorTransform hint) {
+ auto intError = mComposer.setColorTransform(mId, matrix.asArray(), hint);
return static_cast<Error>(intError);
}
@@ -575,23 +571,23 @@
auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
auto intError = mComposer.setPowerMode(mId, intMode);
- if (mode == PowerMode::On) {
+ if (mode == PowerMode::ON) {
std::call_once(mDisplayCapabilityQueryFlag, [this]() {
std::vector<Hwc2::DisplayCapability> tmpCapabilities;
auto error =
static_cast<Error>(mComposer.getDisplayCapabilities(mId, &tmpCapabilities));
- if (error == Error::None) {
+ if (error == Error::NONE) {
for (auto capability : tmpCapabilities) {
mDisplayCapabilities.emplace(static_cast<DisplayCapability>(capability));
}
- } else if (error == Error::Unsupported) {
- if (mCapabilities.count(Capability::SkipClientColorTransform)) {
- mDisplayCapabilities.emplace(DisplayCapability::SkipClientColorTransform);
+ } else if (error == Error::UNSUPPORTED) {
+ if (mCapabilities.count(Capability::SKIP_CLIENT_COLOR_TRANSFORM)) {
+ mDisplayCapabilities.emplace(DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
}
bool dozeSupport = false;
error = static_cast<Error>(mComposer.getDozeSupport(mId, &dozeSupport));
- if (error == Error::None && dozeSupport) {
- mDisplayCapabilities.emplace(DisplayCapability::Doze);
+ if (error == Error::NONE && dozeSupport) {
+ mDisplayCapabilities.emplace(DisplayCapability::DOZE);
}
}
});
@@ -613,7 +609,7 @@
uint32_t numRequests = 0;
auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests);
auto error = static_cast<Error>(intError);
- if (error != Error::None && error != Error::HasChanges) {
+ if (error != Error::NONE && !hasChangesError(error)) {
return error;
}
@@ -631,7 +627,7 @@
auto intError = mComposer.presentOrValidateDisplay(
mId, &numTypes, &numRequests, &presentFenceFd, state);
auto error = static_cast<Error>(intError);
- if (error != Error::None && error != Error::HasChanges) {
+ if (error != Error::NONE && !hasChangesError(error)) {
return error;
}
@@ -646,12 +642,14 @@
return error;
}
-Error Display::setDisplayBrightness(float brightness) const {
- auto intError = mComposer.setDisplayBrightness(mId, brightness);
- return static_cast<Error>(intError);
+std::future<Error> Display::setDisplayBrightness(float brightness) {
+ return promise::defer([composer = &mComposer, id = mId, brightness] {
+ const auto intError = composer->setDisplayBrightness(id, brightness);
+ return static_cast<Error>(intError);
+ });
}
-Error Display::setAutoLowLatencyMode(bool on) const {
+Error Display::setAutoLowLatencyMode(bool on) {
auto intError = mComposer.setAutoLowLatencyMode(mId, on);
return static_cast<Error>(intError);
}
@@ -665,9 +663,8 @@
return static_cast<Error>(intError);
}
-Error Display::setContentType(ContentType contentType) const {
- using Hwc2_ContentType = Hwc2::IComposerClient::ContentType;
- auto intError = mComposer.setContentType(mId, static_cast<Hwc2_ContentType>(contentType));
+Error Display::setContentType(ContentType contentType) {
+ auto intError = mComposer.setContentType(mId, contentType);
return static_cast<Error>(intError);
}
@@ -676,21 +673,18 @@
void Display::setConnected(bool connected) {
if (!mIsConnected && connected) {
mComposer.setClientTargetSlotCount(mId);
- if (mType == DisplayType::Physical) {
+ if (mType == DisplayType::PHYSICAL) {
loadConfigs();
}
}
mIsConnected = connected;
}
-int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
-{
+int32_t Display::getAttribute(HWConfigId configId, Attribute attribute) {
int32_t value = 0;
- auto intError = mComposer.getDisplayAttribute(mId, configId,
- static_cast<Hwc2::IComposerClient::Attribute>(attribute),
- &value);
+ auto intError = mComposer.getDisplayAttribute(mId, configId, attribute, &value);
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
configId, to_string(attribute).c_str(),
to_string(error).c_str(), intError);
@@ -699,17 +693,16 @@
return value;
}
-void Display::loadConfig(hwc2_config_t configId)
-{
+void Display::loadConfig(HWConfigId configId) {
ALOGV("[%" PRIu64 "] loadConfig(%u)", mId, configId);
auto config = Config::Builder(*this, configId)
- .setWidth(getAttribute(configId, Attribute::Width))
- .setHeight(getAttribute(configId, Attribute::Height))
- .setVsyncPeriod(getAttribute(configId, Attribute::VsyncPeriod))
- .setDpiX(getAttribute(configId, Attribute::DpiX))
- .setDpiY(getAttribute(configId, Attribute::DpiY))
- .setConfigGroup(getAttribute(configId, Attribute::ConfigGroup))
+ .setWidth(getAttribute(configId, hal::Attribute::WIDTH))
+ .setHeight(getAttribute(configId, hal::Attribute::HEIGHT))
+ .setVsyncPeriod(getAttribute(configId, hal::Attribute::VSYNC_PERIOD))
+ .setDpiX(getAttribute(configId, hal::Attribute::DPI_X))
+ .setDpiY(getAttribute(configId, hal::Attribute::DPI_Y))
+ .setConfigGroup(getAttribute(configId, hal::Attribute::CONFIG_GROUP))
.build();
mConfigs.emplace(configId, std::move(config));
}
@@ -718,10 +711,10 @@
{
ALOGV("[%" PRIu64 "] loadConfigs", mId);
- std::vector<Hwc2::Config> configIds;
+ std::vector<HWConfigId> configIds;
auto intError = mComposer.getDisplayConfigs(mId, &configIds);
auto error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
to_string(error).c_str(), intError);
return;
@@ -734,7 +727,7 @@
// Other Display methods
-HWC2::Layer* Display::getLayerById(hwc2_layer_t id) const {
+HWC2::Layer* Display::getLayerById(HWLayerId id) const {
if (mLayers.count(id) == 0) {
return nullptr;
}
@@ -750,7 +743,7 @@
namespace impl {
Layer::Layer(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
- hwc2_display_t displayId, hwc2_layer_t layerId)
+ HWDisplayId displayId, HWLayerId layerId)
: mComposer(composer),
mCapabilities(capabilities),
mDisplayId(displayId),
@@ -763,9 +756,10 @@
{
auto intError = mComposer.destroyLayer(mDisplayId, mId);
auto error = static_cast<Error>(intError);
- ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
- " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(),
- intError);
+ ALOGE_IF(error != Error::NONE,
+ "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
+ " failed: %s (%d)",
+ mDisplayId, mId, to_string(error).c_str(), intError);
}
Error Layer::setCursorPosition(int32_t x, int32_t y)
@@ -778,7 +772,7 @@
const sp<Fence>& acquireFence)
{
if (buffer == nullptr && mBufferSlot == slot) {
- return Error::None;
+ return Error::NONE;
}
mBufferSlot = slot;
@@ -792,7 +786,7 @@
{
if (damage.isRect() && mDamageRegion.isRect() &&
(damage.getBounds() == mDamageRegion.getBounds())) {
- return Error::None;
+ return Error::NONE;
}
mDamageRegion = damage;
@@ -820,30 +814,25 @@
Error Layer::setBlendMode(BlendMode mode)
{
- auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
- auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode);
+ auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, mode);
return static_cast<Error>(intError);
}
-Error Layer::setColor(hwc_color_t color)
-{
- Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
- auto intError = mComposer.setLayerColor(mDisplayId, mId, hwcColor);
+Error Layer::setColor(Color color) {
+ auto intError = mComposer.setLayerColor(mDisplayId, mId, color);
return static_cast<Error>(intError);
}
Error Layer::setCompositionType(Composition type)
{
- auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
- auto intError = mComposer.setLayerCompositionType(
- mDisplayId, mId, intType);
+ auto intError = mComposer.setLayerCompositionType(mDisplayId, mId, type);
return static_cast<Error>(intError);
}
Error Layer::setDataspace(Dataspace dataspace)
{
if (dataspace == mDataSpace) {
- return Error::None;
+ return Error::NONE;
}
mDataSpace = dataspace;
auto intError = mComposer.setLayerDataspace(mDisplayId, mId, mDataSpace);
@@ -854,7 +843,7 @@
const android::HdrMetadata& metadata)
{
if (metadata == mHdrMetadata) {
- return Error::None;
+ return Error::NONE;
}
mHdrMetadata = metadata;
@@ -901,7 +890,7 @@
{Hwc2::PerFrameMetadataKey::HDR10_PLUS_SEI, mHdrMetadata.hdr10plus});
Error setMetadataBlobsError = static_cast<Error>(
mComposer.setLayerPerFrameMetadataBlobs(mDisplayId, mId, perFrameMetadataBlobs));
- if (error == Error::None) {
+ if (error == Error::NONE) {
return setMetadataBlobsError;
}
}
@@ -924,10 +913,10 @@
Error Layer::setSidebandStream(const native_handle_t* stream)
{
- if (mCapabilities.count(Capability::SidebandStream) == 0) {
+ if (mCapabilities.count(Capability::SIDEBAND_STREAM) == 0) {
ALOGE("Attempted to call setSidebandStream without checking that the "
"device supports sideband streams");
- return Error::Unsupported;
+ return Error::UNSUPPORTED;
}
auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream);
return static_cast<Error>(intError);
@@ -952,7 +941,7 @@
{
if (region.isRect() && mVisibleRegion.isRect() &&
(region.getBounds() == mVisibleRegion.getBounds())) {
- return Error::None;
+ return Error::NONE;
}
mVisibleRegion = region;
@@ -984,11 +973,11 @@
// Composer HAL 2.3
Error Layer::setColorTransform(const android::mat4& matrix) {
if (matrix == mColorMatrix) {
- return Error::None;
+ return Error::NONE;
}
auto intError = mComposer.setLayerColorTransform(mDisplayId, mId, matrix.asArray());
Error error = static_cast<Error>(intError);
- if (error != Error::None) {
+ if (error != Error::NONE) {
return error;
}
mColorMatrix = matrix;
@@ -1004,6 +993,7 @@
} // namespace impl
} // namespace HWC2
+} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 6549525..f4c7fdd 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -17,16 +17,9 @@
#ifndef ANDROID_SF_HWC2_H
#define ANDROID_SF_HWC2_H
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
#include <ui/DisplayInfo.h>
-#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
#include <utils/Log.h>
@@ -34,11 +27,14 @@
#include <utils/Timers.h>
#include <functional>
+#include <future>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include "Hal.h"
+
namespace android {
struct DisplayedFrameStats;
class Fence;
@@ -49,13 +45,12 @@
}
class TestableSurfaceFlinger;
-}
namespace HWC2 {
class Layer;
-using VsyncPeriodChangeConstraints = hwc_vsync_period_change_constraints_t;
-using VsyncPeriodChangeTimeline = hwc_vsync_period_change_timeline_t;
+
+namespace hal = android::hardware::graphics::composer::hal;
// Implement this interface to receive hardware composer events.
//
@@ -68,21 +63,20 @@
// from different hardware composer instances.
class ComposerCallback {
public:
- virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
- Connection connection) = 0;
- virtual void onRefreshReceived(int32_t sequenceId,
- hwc2_display_t display) = 0;
- virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, int64_t timestamp,
- std::optional<hwc2_vsync_period_t> vsyncPeriod) = 0;
- virtual void onVsyncPeriodTimingChangedReceived(
- int32_t sequenceId, hwc2_display_t display,
- const hwc_vsync_period_change_timeline_t& updatedTimeline) = 0;
- virtual void onSeamlessPossible(int32_t sequenceId, hwc2_display_t display) = 0;
+ virtual void onHotplugReceived(int32_t sequenceId, hal::HWDisplayId display,
+ hal::Connection connection) = 0;
+ virtual void onRefreshReceived(int32_t sequenceId, hal::HWDisplayId display) = 0;
+ virtual void onVsyncReceived(int32_t sequenceId, hal::HWDisplayId display, int64_t timestamp,
+ std::optional<hal::VsyncPeriodNanos> vsyncPeriod) = 0;
+ virtual void onVsyncPeriodTimingChangedReceived(
+ int32_t sequenceId, hal::HWDisplayId display,
+ const hal::VsyncPeriodChangeTimeline& updatedTimeline) = 0;
+ virtual void onSeamlessPossible(int32_t sequenceId, hal::HWDisplayId display) = 0;
- virtual ~ComposerCallback() = default;
+ virtual ~ComposerCallback() = default;
};
-// Convenience C++ class to access hwc2_device_t Display functions directly.
+// Convenience C++ class to access per display functions directly.
class Display {
public:
virtual ~Display();
@@ -92,7 +86,7 @@
class Builder
{
public:
- Builder(Display& display, hwc2_config_t id);
+ Builder(Display& display, hal::HWConfigId id);
std::shared_ptr<const Config> build() {
return std::const_pointer_cast<const Config>(
@@ -137,8 +131,8 @@
std::shared_ptr<Config> mConfig;
};
- hwc2_display_t getDisplayId() const { return mDisplay.getId(); }
- hwc2_config_t getId() const { return mId; }
+ hal::HWDisplayId getDisplayId() const { return mDisplay.getId(); }
+ hal::HWConfigId getId() const { return mId; }
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
@@ -148,10 +142,10 @@
int32_t getConfigGroup() const { return mConfigGroup; }
private:
- Config(Display& display, hwc2_config_t id);
+ Config(Display& display, hal::HWConfigId id);
Display& mDisplay;
- hwc2_config_t mId;
+ hal::HWConfigId mId;
int32_t mWidth;
int32_t mHeight;
@@ -161,168 +155,173 @@
int32_t mConfigGroup;
};
- virtual hwc2_display_t getId() const = 0;
+ virtual hal::HWDisplayId getId() const = 0;
virtual bool isConnected() const = 0;
virtual void setConnected(bool connected) = 0; // For use by Device only
- virtual const std::unordered_set<DisplayCapability>& getCapabilities() const = 0;
+ virtual const std::unordered_set<hal::DisplayCapability>& getCapabilities() const = 0;
virtual bool isVsyncPeriodSwitchSupported() const = 0;
- [[clang::warn_unused_result]] virtual Error acceptChanges() = 0;
- [[clang::warn_unused_result]] virtual Error createLayer(Layer** outLayer) = 0;
- [[clang::warn_unused_result]] virtual Error destroyLayer(Layer* layer) = 0;
- [[clang::warn_unused_result]] virtual Error getActiveConfig(
+ [[clang::warn_unused_result]] virtual hal::Error acceptChanges() = 0;
+ [[clang::warn_unused_result]] virtual hal::Error createLayer(Layer** outLayer) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error destroyLayer(Layer* layer) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getActiveConfig(
std::shared_ptr<const Config>* outConfig) const = 0;
- [[clang::warn_unused_result]] virtual Error getActiveConfigIndex(int* outIndex) const = 0;
- [[clang::warn_unused_result]] virtual Error getChangedCompositionTypes(
- std::unordered_map<Layer*, Composition>* outTypes) = 0;
- [[clang::warn_unused_result]] virtual Error getColorModes(
- std::vector<android::ui::ColorMode>* outModes) const = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getActiveConfigIndex(int* outIndex) const = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getChangedCompositionTypes(
+ std::unordered_map<Layer*, hal::Composition>* outTypes) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getColorModes(
+ std::vector<hal::ColorMode>* outModes) const = 0;
// Returns a bitmask which contains HdrMetadata::Type::*.
[[clang::warn_unused_result]] virtual int32_t getSupportedPerFrameMetadata() const = 0;
- [[clang::warn_unused_result]] virtual Error getRenderIntents(
- android::ui::ColorMode colorMode,
- std::vector<android::ui::RenderIntent>* outRenderIntents) const = 0;
- [[clang::warn_unused_result]] virtual Error getDataspaceSaturationMatrix(
- android::ui::Dataspace dataspace, android::mat4* outMatrix) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getRenderIntents(
+ hal::ColorMode colorMode, std::vector<hal::RenderIntent>* outRenderIntents) const = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getDataspaceSaturationMatrix(
+ hal::Dataspace dataspace, android::mat4* outMatrix) = 0;
- // Doesn't call into the HWC2 device, so no Errors are possible
- virtual std::vector<std::shared_ptr<const Config>> getConfigs() const = 0;
+ // Doesn't call into the HWC2 device, so no errors are possible
+ [[clang::warn_unused_result]] virtual std::vector<std::shared_ptr<const Config>> getConfigs()
+ const = 0;
- [[clang::warn_unused_result]] virtual Error getName(std::string* outName) const = 0;
- [[clang::warn_unused_result]] virtual Error getRequests(
- DisplayRequest* outDisplayRequests,
- std::unordered_map<Layer*, LayerRequest>* outLayerRequests) = 0;
- [[clang::warn_unused_result]] virtual Error getConnectionType(
+ [[clang::warn_unused_result]] virtual hal::Error getName(std::string* outName) const = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getRequests(
+ hal::DisplayRequest* outDisplayRequests,
+ std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getConnectionType(
android::DisplayConnectionType*) const = 0;
- [[clang::warn_unused_result]] virtual Error supportsDoze(bool* outSupport) const = 0;
- [[clang::warn_unused_result]] virtual Error getHdrCapabilities(
+ [[clang::warn_unused_result]] virtual hal::Error supportsDoze(bool* outSupport) const = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getHdrCapabilities(
android::HdrCapabilities* outCapabilities) const = 0;
- [[clang::warn_unused_result]] virtual Error getDisplayedContentSamplingAttributes(
- android::ui::PixelFormat* outFormat, android::ui::Dataspace* outDataspace,
+ [[clang::warn_unused_result]] virtual hal::Error getDisplayedContentSamplingAttributes(
+ hal::PixelFormat* outFormat, hal::Dataspace* outDataspace,
uint8_t* outComponentMask) const = 0;
- [[clang::warn_unused_result]] virtual Error setDisplayContentSamplingEnabled(
+ [[clang::warn_unused_result]] virtual hal::Error setDisplayContentSamplingEnabled(
bool enabled, uint8_t componentMask, uint64_t maxFrames) const = 0;
- [[clang::warn_unused_result]] virtual Error getDisplayedContentSample(
+ [[clang::warn_unused_result]] virtual hal::Error getDisplayedContentSample(
uint64_t maxFrames, uint64_t timestamp,
android::DisplayedFrameStats* outStats) const = 0;
- [[clang::warn_unused_result]] virtual Error getReleaseFences(
+ [[clang::warn_unused_result]] virtual hal::Error getReleaseFences(
std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const = 0;
- [[clang::warn_unused_result]] virtual Error present(
+ [[clang::warn_unused_result]] virtual hal::Error present(
android::sp<android::Fence>* outPresentFence) = 0;
- [[clang::warn_unused_result]] virtual Error setActiveConfig(
+ [[clang::warn_unused_result]] virtual hal::Error setActiveConfig(
const std::shared_ptr<const Config>& config) = 0;
- [[clang::warn_unused_result]] virtual Error setClientTarget(
+ [[clang::warn_unused_result]] virtual hal::Error setClientTarget(
uint32_t slot, const android::sp<android::GraphicBuffer>& target,
- const android::sp<android::Fence>& acquireFence, android::ui::Dataspace dataspace) = 0;
- [[clang::warn_unused_result]] virtual Error setColorMode(
- android::ui::ColorMode mode, android::ui::RenderIntent renderIntent) = 0;
- [[clang::warn_unused_result]] virtual Error setColorTransform(
- const android::mat4& matrix, android_color_transform_t hint) = 0;
- [[clang::warn_unused_result]] virtual Error setOutputBuffer(
+ const android::sp<android::Fence>& acquireFence, hal::Dataspace dataspace) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setColorMode(
+ hal::ColorMode mode, hal::RenderIntent renderIntent) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setColorTransform(
+ const android::mat4& matrix, hal::ColorTransform hint) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setOutputBuffer(
const android::sp<android::GraphicBuffer>& buffer,
const android::sp<android::Fence>& releaseFence) = 0;
- [[clang::warn_unused_result]] virtual Error setPowerMode(PowerMode mode) = 0;
- [[clang::warn_unused_result]] virtual Error setVsyncEnabled(Vsync enabled) = 0;
- [[clang::warn_unused_result]] virtual Error validate(uint32_t* outNumTypes,
- uint32_t* outNumRequests) = 0;
- [[clang::warn_unused_result]] virtual Error presentOrValidate(
+ [[clang::warn_unused_result]] virtual hal::Error setPowerMode(hal::PowerMode mode) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setVsyncEnabled(hal::Vsync enabled) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error validate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error presentOrValidate(
uint32_t* outNumTypes, uint32_t* outNumRequests,
android::sp<android::Fence>* outPresentFence, uint32_t* state) = 0;
- [[clang::warn_unused_result]] virtual Error setDisplayBrightness(float brightness) const = 0;
- [[clang::warn_unused_result]] virtual Error getDisplayVsyncPeriod(
+ [[clang::warn_unused_result]] virtual std::future<hal::Error> setDisplayBrightness(
+ float brightness) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getDisplayVsyncPeriod(
nsecs_t* outVsyncPeriod) const = 0;
- [[clang::warn_unused_result]] virtual Error setActiveConfigWithConstraints(
+ [[clang::warn_unused_result]] virtual hal::Error setActiveConfigWithConstraints(
const std::shared_ptr<const HWC2::Display::Config>& config,
- const VsyncPeriodChangeConstraints& constraints,
- VsyncPeriodChangeTimeline* outTimeline) = 0;
- [[clang::warn_unused_result]] virtual Error setAutoLowLatencyMode(bool on) const = 0;
- [[clang::warn_unused_result]] virtual Error getSupportedContentTypes(
- std::vector<HWC2::ContentType>*) const = 0;
- [[clang::warn_unused_result]] virtual Error setContentType(HWC2::ContentType) const = 0;
+ const hal::VsyncPeriodChangeConstraints& constraints,
+ hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setAutoLowLatencyMode(bool on) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getSupportedContentTypes(
+ std::vector<hal::ContentType>*) const = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0;
};
namespace impl {
class Display : public HWC2::Display {
public:
- Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
- hwc2_display_t id, DisplayType type);
+ Display(android::Hwc2::Composer& composer,
+ const std::unordered_set<hal::Capability>& capabilities, hal::HWDisplayId id,
+ hal::DisplayType type);
~Display() override;
// Required by HWC2
- Error acceptChanges() override;
- Error createLayer(Layer** outLayer) override;
- Error destroyLayer(Layer* layer) override;
- Error getActiveConfig(std::shared_ptr<const Config>* outConfig) const override;
- Error getActiveConfigIndex(int* outIndex) const override;
- Error getChangedCompositionTypes(std::unordered_map<Layer*, Composition>* outTypes) override;
- Error getColorModes(std::vector<android::ui::ColorMode>* outModes) const override;
+ hal::Error acceptChanges() override;
+ hal::Error createLayer(Layer** outLayer) override;
+ hal::Error destroyLayer(Layer* layer) override;
+ hal::Error getActiveConfig(std::shared_ptr<const Config>* outConfig) const override;
+ hal::Error getActiveConfigIndex(int* outIndex) const override;
+ hal::Error getChangedCompositionTypes(
+ std::unordered_map<Layer*, hal::Composition>* outTypes) override;
+ hal::Error getColorModes(std::vector<hal::ColorMode>* outModes) const override;
// Returns a bitmask which contains HdrMetadata::Type::*.
int32_t getSupportedPerFrameMetadata() const override;
- Error getRenderIntents(android::ui::ColorMode colorMode,
- std::vector<android::ui::RenderIntent>* outRenderIntents) const override;
- Error getDataspaceSaturationMatrix(android::ui::Dataspace dataspace,
- android::mat4* outMatrix) override;
+ hal::Error getRenderIntents(hal::ColorMode colorMode,
+ std::vector<hal::RenderIntent>* outRenderIntents) const override;
+ hal::Error getDataspaceSaturationMatrix(hal::Dataspace dataspace,
+ android::mat4* outMatrix) override;
// Doesn't call into the HWC2 device, so no errors are possible
std::vector<std::shared_ptr<const Config>> getConfigs() const override;
- Error getName(std::string* outName) const override;
- Error getRequests(DisplayRequest* outDisplayRequests,
- std::unordered_map<Layer*, LayerRequest>* outLayerRequests) override;
- Error getConnectionType(android::DisplayConnectionType*) const override;
- Error supportsDoze(bool* outSupport) const override;
- Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override;
- Error getDisplayedContentSamplingAttributes(android::ui::PixelFormat* outFormat,
- android::ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override;
- Error setDisplayContentSamplingEnabled(bool enabled, uint8_t componentMask,
- uint64_t maxFrames) const override;
- Error getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp,
- android::DisplayedFrameStats* outStats) const override;
- Error getReleaseFences(
+ hal::Error getName(std::string* outName) const override;
+ hal::Error getRequests(
+ hal::DisplayRequest* outDisplayRequests,
+ std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) override;
+ hal::Error getConnectionType(android::DisplayConnectionType*) const override;
+ hal::Error supportsDoze(bool* outSupport) const override;
+ hal::Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override;
+ hal::Error getDisplayedContentSamplingAttributes(hal::PixelFormat* outFormat,
+ hal::Dataspace* outDataspace,
+ uint8_t* outComponentMask) const override;
+ hal::Error setDisplayContentSamplingEnabled(bool enabled, uint8_t componentMask,
+ uint64_t maxFrames) const override;
+ hal::Error getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp,
+ android::DisplayedFrameStats* outStats) const override;
+ hal::Error getReleaseFences(
std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const override;
- Error present(android::sp<android::Fence>* outPresentFence) override;
- Error setActiveConfig(const std::shared_ptr<const HWC2::Display::Config>& config) override;
- Error setClientTarget(uint32_t slot, const android::sp<android::GraphicBuffer>& target,
- const android::sp<android::Fence>& acquireFence,
- android::ui::Dataspace dataspace) override;
- Error setColorMode(android::ui::ColorMode mode,
- android::ui::RenderIntent renderIntent) override;
- Error setColorTransform(const android::mat4& matrix, android_color_transform_t hint) override;
- Error setOutputBuffer(const android::sp<android::GraphicBuffer>& buffer,
- const android::sp<android::Fence>& releaseFence) override;
- Error setPowerMode(PowerMode mode) override;
- Error setVsyncEnabled(Vsync enabled) override;
- Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests) override;
- Error presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
- android::sp<android::Fence>* outPresentFence, uint32_t* state) override;
- Error setDisplayBrightness(float brightness) const override;
- Error getDisplayVsyncPeriod(nsecs_t* outVsyncPeriod) const override;
- Error setActiveConfigWithConstraints(const std::shared_ptr<const HWC2::Display::Config>& config,
- const VsyncPeriodChangeConstraints& constraints,
- VsyncPeriodChangeTimeline* outTimeline) override;
- Error setAutoLowLatencyMode(bool on) const override;
- Error getSupportedContentTypes(
- std::vector<HWC2::ContentType>* outSupportedContentTypes) const override;
- Error setContentType(HWC2::ContentType contentType) const override;
+ hal::Error present(android::sp<android::Fence>* outPresentFence) override;
+ hal::Error setActiveConfig(const std::shared_ptr<const HWC2::Display::Config>& config) override;
+ hal::Error setClientTarget(uint32_t slot, const android::sp<android::GraphicBuffer>& target,
+ const android::sp<android::Fence>& acquireFence,
+ hal::Dataspace dataspace) override;
+ hal::Error setColorMode(hal::ColorMode mode, hal::RenderIntent renderIntent) override;
+ hal::Error setColorTransform(const android::mat4& matrix, hal::ColorTransform hint) override;
+ hal::Error setOutputBuffer(const android::sp<android::GraphicBuffer>& buffer,
+ const android::sp<android::Fence>& releaseFence) override;
+ hal::Error setPowerMode(hal::PowerMode mode) override;
+ hal::Error setVsyncEnabled(hal::Vsync enabled) override;
+ hal::Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests) override;
+ hal::Error presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
+ android::sp<android::Fence>* outPresentFence,
+ uint32_t* state) override;
+ std::future<hal::Error> setDisplayBrightness(float brightness) override;
+ hal::Error getDisplayVsyncPeriod(nsecs_t* outVsyncPeriod) const override;
+ hal::Error setActiveConfigWithConstraints(
+ const std::shared_ptr<const HWC2::Display::Config>& config,
+ const hal::VsyncPeriodChangeConstraints& constraints,
+ hal::VsyncPeriodChangeTimeline* outTimeline) override;
+ hal::Error setAutoLowLatencyMode(bool on) override;
+ hal::Error getSupportedContentTypes(
+ std::vector<hal::ContentType>* outSupportedContentTypes) const override;
+ hal::Error setContentType(hal::ContentType) override;
// Other Display methods
- hwc2_display_t getId() const override { return mId; }
+ hal::HWDisplayId getId() const override { return mId; }
bool isConnected() const override { return mIsConnected; }
void setConnected(bool connected) override; // For use by Device only
- const std::unordered_set<DisplayCapability>& getCapabilities() const override {
+ const std::unordered_set<hal::DisplayCapability>& getCapabilities() const override {
return mDisplayCapabilities;
};
virtual bool isVsyncPeriodSwitchSupported() const override;
private:
- int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
- void loadConfig(hwc2_config_t configId);
+ int32_t getAttribute(hal::HWConfigId configId, hal::Attribute attribute);
+ void loadConfig(hal::HWConfigId configId);
void loadConfigs();
// This may fail (and return a null pointer) if no layer with this ID exists
// on this display
- Layer* getLayerById(hwc2_layer_t id) const;
+ Layer* getLayerById(hal::HWLayerId id) const;
friend android::TestableSurfaceFlinger;
@@ -332,17 +331,17 @@
// this HWC2::Display, so these references are guaranteed to be valid for
// the lifetime of this object.
android::Hwc2::Composer& mComposer;
- const std::unordered_set<Capability>& mCapabilities;
+ const std::unordered_set<hal::Capability>& mCapabilities;
- const hwc2_display_t mId;
- DisplayType mType;
+ const hal::HWDisplayId mId;
+ hal::DisplayType mType;
bool mIsConnected = false;
- std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
- std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
+ std::unordered_map<hal::HWLayerId, std::unique_ptr<Layer>> mLayers;
+ std::unordered_map<hal::HWConfigId, std::shared_ptr<const Config>> mConfigs;
std::once_flag mDisplayCapabilityQueryFlag;
- std::unordered_set<DisplayCapability> mDisplayCapabilities;
+ std::unordered_set<hal::DisplayCapability> mDisplayCapabilities;
};
} // namespace impl
@@ -351,99 +350,105 @@
public:
virtual ~Layer();
- virtual hwc2_layer_t getId() const = 0;
+ virtual hal::HWLayerId getId() const = 0;
- [[clang::warn_unused_result]] virtual Error setCursorPosition(int32_t x, int32_t y) = 0;
- [[clang::warn_unused_result]] virtual Error setBuffer(
+ [[clang::warn_unused_result]] virtual hal::Error setCursorPosition(int32_t x, int32_t y) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setBuffer(
uint32_t slot, const android::sp<android::GraphicBuffer>& buffer,
const android::sp<android::Fence>& acquireFence) = 0;
- [[clang::warn_unused_result]] virtual Error setSurfaceDamage(const android::Region& damage) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setSurfaceDamage(
+ const android::Region& damage) = 0;
- [[clang::warn_unused_result]] virtual Error setBlendMode(BlendMode mode) = 0;
- [[clang::warn_unused_result]] virtual Error setColor(hwc_color_t color) = 0;
- [[clang::warn_unused_result]] virtual Error setCompositionType(Composition type) = 0;
- [[clang::warn_unused_result]] virtual Error setDataspace(android::ui::Dataspace dataspace) = 0;
- [[clang::warn_unused_result]] virtual Error setPerFrameMetadata(
+ [[clang::warn_unused_result]] virtual hal::Error setBlendMode(hal::BlendMode mode) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setColor(hal::Color color) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setCompositionType(hal::Composition type) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setDataspace(hal::Dataspace dataspace) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setPerFrameMetadata(
const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) = 0;
- [[clang::warn_unused_result]] virtual Error setDisplayFrame(const android::Rect& frame) = 0;
- [[clang::warn_unused_result]] virtual Error setPlaneAlpha(float alpha) = 0;
- [[clang::warn_unused_result]] virtual Error setSidebandStream(
+ [[clang::warn_unused_result]] virtual hal::Error setDisplayFrame(
+ const android::Rect& frame) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setPlaneAlpha(float alpha) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setSidebandStream(
const native_handle_t* stream) = 0;
- [[clang::warn_unused_result]] virtual Error setSourceCrop(const android::FloatRect& crop) = 0;
- [[clang::warn_unused_result]] virtual Error setTransform(Transform transform) = 0;
- [[clang::warn_unused_result]] virtual Error setVisibleRegion(const android::Region& region) = 0;
- [[clang::warn_unused_result]] virtual Error setZOrder(uint32_t z) = 0;
- [[clang::warn_unused_result]] virtual Error setInfo(uint32_t type, uint32_t appId) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setSourceCrop(
+ const android::FloatRect& crop) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setTransform(hal::Transform transform) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setVisibleRegion(
+ const android::Region& region) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setZOrder(uint32_t z) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setInfo(uint32_t type, uint32_t appId) = 0;
// Composer HAL 2.3
- [[clang::warn_unused_result]] virtual Error setColorTransform(const android::mat4& matrix) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setColorTransform(
+ const android::mat4& matrix) = 0;
// Composer HAL 2.4
- [[clang::warn_unused_result]] virtual Error setLayerGenericMetadata(
+ [[clang::warn_unused_result]] virtual hal::Error setLayerGenericMetadata(
const std::string& name, bool mandatory, const std::vector<uint8_t>& value) = 0;
};
namespace impl {
-// Convenience C++ class to access hwc2_device_t Layer functions directly.
+// Convenience C++ class to access per layer functions directly.
class Layer : public HWC2::Layer {
public:
- Layer(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
- hwc2_display_t displayId, hwc2_layer_t layerId);
+ Layer(android::Hwc2::Composer& composer,
+ const std::unordered_set<hal::Capability>& capabilities, hal::HWDisplayId displayId,
+ hal::HWLayerId layerId);
~Layer() override;
- hwc2_layer_t getId() const override { return mId; }
+ hal::HWLayerId getId() const override { return mId; }
- Error setCursorPosition(int32_t x, int32_t y) override;
- Error setBuffer(uint32_t slot, const android::sp<android::GraphicBuffer>& buffer,
- const android::sp<android::Fence>& acquireFence) override;
- Error setSurfaceDamage(const android::Region& damage) override;
+ hal::Error setCursorPosition(int32_t x, int32_t y) override;
+ hal::Error setBuffer(uint32_t slot, const android::sp<android::GraphicBuffer>& buffer,
+ const android::sp<android::Fence>& acquireFence) override;
+ hal::Error setSurfaceDamage(const android::Region& damage) override;
- Error setBlendMode(BlendMode mode) override;
- Error setColor(hwc_color_t color) override;
- Error setCompositionType(Composition type) override;
- Error setDataspace(android::ui::Dataspace dataspace) override;
- Error setPerFrameMetadata(const int32_t supportedPerFrameMetadata,
- const android::HdrMetadata& metadata) override;
- Error setDisplayFrame(const android::Rect& frame) override;
- Error setPlaneAlpha(float alpha) override;
- Error setSidebandStream(const native_handle_t* stream) override;
- Error setSourceCrop(const android::FloatRect& crop) override;
- Error setTransform(Transform transform) override;
- Error setVisibleRegion(const android::Region& region) override;
- Error setZOrder(uint32_t z) override;
- Error setInfo(uint32_t type, uint32_t appId) override;
+ hal::Error setBlendMode(hal::BlendMode mode) override;
+ hal::Error setColor(hal::Color color) override;
+ hal::Error setCompositionType(hal::Composition type) override;
+ hal::Error setDataspace(hal::Dataspace dataspace) override;
+ hal::Error setPerFrameMetadata(const int32_t supportedPerFrameMetadata,
+ const android::HdrMetadata& metadata) override;
+ hal::Error setDisplayFrame(const android::Rect& frame) override;
+ hal::Error setPlaneAlpha(float alpha) override;
+ hal::Error setSidebandStream(const native_handle_t* stream) override;
+ hal::Error setSourceCrop(const android::FloatRect& crop) override;
+ hal::Error setTransform(hal::Transform transform) override;
+ hal::Error setVisibleRegion(const android::Region& region) override;
+ hal::Error setZOrder(uint32_t z) override;
+ hal::Error setInfo(uint32_t type, uint32_t appId) override;
// Composer HAL 2.3
- Error setColorTransform(const android::mat4& matrix) override;
+ hal::Error setColorTransform(const android::mat4& matrix) override;
// Composer HAL 2.4
- Error setLayerGenericMetadata(const std::string& name, bool mandatory,
- const std::vector<uint8_t>& value) override;
+ hal::Error setLayerGenericMetadata(const std::string& name, bool mandatory,
+ const std::vector<uint8_t>& value) override;
private:
// These are references to data owned by HWC2::Device, which will outlive
// this HWC2::Layer, so these references are guaranteed to be valid for
// the lifetime of this object.
android::Hwc2::Composer& mComposer;
- const std::unordered_set<Capability>& mCapabilities;
+ const std::unordered_set<hal::Capability>& mCapabilities;
- hwc2_display_t mDisplayId;
- hwc2_layer_t mId;
+ hal::HWDisplayId mDisplayId;
+ hal::HWLayerId mId;
// Cached HWC2 data, to ensure the same commands aren't sent to the HWC
// multiple times.
android::Region mVisibleRegion = android::Region::INVALID_REGION;
android::Region mDamageRegion = android::Region::INVALID_REGION;
- android::ui::Dataspace mDataSpace = android::ui::Dataspace::UNKNOWN;
+ hal::Dataspace mDataSpace = hal::Dataspace::UNKNOWN;
android::HdrMetadata mHdrMetadata;
android::mat4 mColorMatrix;
uint32_t mBufferSlot;
};
} // namespace impl
-
} // namespace HWC2
+} // namespace android
#endif // ANDROID_SF_HWC2_H
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 560299a..038cec4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -36,6 +36,7 @@
#include <utils/Trace.h>
#include "../Layer.h" // needed only for debugging
+#include "../Promise.h"
#include "../SurfaceFlinger.h"
#include "ComposerHal.h"
#include "HWC2.h"
@@ -60,7 +61,7 @@
#define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
do { \
- if (error != HWC2::Error::None) { \
+ if (error != hal::Error::NONE) { \
LOG_HWC_ERROR(what, error, displayId); \
return __VA_ARGS__; \
} \
@@ -69,34 +70,34 @@
#define RETURN_IF_HWC_ERROR(error, displayId, ...) \
RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
+namespace hal = android::hardware::graphics::composer::hal;
+
namespace {
using android::hardware::Return;
using android::hardware::Void;
+using android::HWC2::ComposerCallback;
-class ComposerCallbackBridge : public android::Hwc2::IComposerCallback {
+class ComposerCallbackBridge : public hal::IComposerCallback {
public:
- ComposerCallbackBridge(HWC2::ComposerCallback* callback, int32_t sequenceId,
+ ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
bool vsyncSwitchingSupported)
: mCallback(callback),
mSequenceId(sequenceId),
mVsyncSwitchingSupported(vsyncSwitchingSupported) {}
- android::hardware::Return<void> onHotplug(
- android::Hwc2::Display display,
- android::Hwc2::IComposerCallback::Connection conn) override {
- HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
- mCallback->onHotplugReceived(mSequenceId, display, connection);
+ android::hardware::Return<void> onHotplug(hal::HWDisplayId display,
+ hal::Connection conn) override {
+ mCallback->onHotplugReceived(mSequenceId, display, conn);
return android::hardware::Void();
}
- android::hardware::Return<void> onRefresh(android::Hwc2::Display display) override {
+ android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override {
mCallback->onRefreshReceived(mSequenceId, display);
return android::hardware::Void();
}
- android::hardware::Return<void> onVsync(android::Hwc2::Display display,
- int64_t timestamp) override {
+ android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override {
if (!mVsyncSwitchingSupported) {
mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
} else {
@@ -105,9 +106,8 @@
return android::hardware::Void();
}
- android::hardware::Return<void> onVsync_2_4(
- android::Hwc2::Display display, int64_t timestamp,
- android::Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
+ android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp,
+ hal::VsyncPeriodNanos vsyncPeriodNanos) override {
if (mVsyncSwitchingSupported) {
mCallback->onVsyncReceived(mSequenceId, display, timestamp,
std::make_optional(vsyncPeriodNanos));
@@ -118,23 +118,19 @@
}
android::hardware::Return<void> onVsyncPeriodTimingChanged(
- android::Hwc2::Display display,
- const android::Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override {
- hwc_vsync_period_change_timeline_t timeline;
- timeline.newVsyncAppliedTimeNanos = updatedTimeline.newVsyncAppliedTimeNanos;
- timeline.refreshRequired = updatedTimeline.refreshRequired;
- timeline.refreshTimeNanos = updatedTimeline.refreshTimeNanos;
- mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, timeline);
+ hal::HWDisplayId display,
+ const hal::VsyncPeriodChangeTimeline& updatedTimeline) override {
+ mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline);
return android::hardware::Void();
}
- android::hardware::Return<void> onSeamlessPossible(android::Hwc2::Display display) override {
+ android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override {
mCallback->onSeamlessPossible(mSequenceId, display);
return android::hardware::Void();
}
private:
- HWC2::ComposerCallback* mCallback;
+ ComposerCallback* mCallback;
const int32_t mSequenceId;
const bool mVsyncSwitchingSupported;
};
@@ -173,12 +169,12 @@
mComposer->registerCallback(callbackBridge);
}
-bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
DisplayIdentificationData* outData) const {
- const auto error = static_cast<HWC2::Error>(
+ const auto error = static_cast<hal::Error>(
mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
- if (error != HWC2::Error::None) {
- if (error != HWC2::Error::Unsupported) {
+ if (error != hal::Error::NONE) {
+ if (error != hal::Error::UNSUPPORTED) {
LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
}
return false;
@@ -186,36 +182,29 @@
return true;
}
-bool HWComposer::hasCapability(HWC2::Capability capability) const {
+bool HWComposer::hasCapability(hal::Capability capability) const {
return mCapabilities.count(capability) > 0;
}
-bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
- HWC2::DisplayCapability capability) const {
- if (!displayId) {
- // Checkout global capabilities for displays without a corresponding HWC display.
- if (capability == HWC2::DisplayCapability::SkipClientColorTransform) {
- return hasCapability(HWC2::Capability::SkipClientColorTransform);
- }
- return false;
- }
- RETURN_IF_INVALID_DISPLAY(*displayId, false);
- return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0;
+bool HWComposer::hasDisplayCapability(DisplayId displayId,
+ hal::DisplayCapability capability) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, false);
+ return mDisplayData.at(displayId).hwcDisplay->getCapabilities().count(capability) > 0;
}
-std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
- HWC2::Connection connection) {
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
+ hal::Connection connection) {
switch (connection) {
- case HWC2::Connection::Connected:
+ case hal::Connection::CONNECTED:
return onHotplugConnect(hwcDisplayId);
- case HWC2::Connection::Disconnected:
+ case hal::Connection::DISCONNECTED:
return onHotplugDisconnect(hwcDisplayId);
- case HWC2::Connection::Invalid:
+ case hal::Connection::INVALID:
return {};
}
}
-bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
+bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
const auto displayId = toPhysicalDisplayId(hwcDisplayId);
if (!displayId) {
LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
@@ -267,16 +256,16 @@
height, SurfaceFlinger::maxVirtualDisplaySize);
return {};
}
- hwc2_display_t hwcDisplayId = 0;
- const auto error = static_cast<HWC2::Error>(
+ hal::HWDisplayId hwcDisplayId = 0;
+ const auto error = static_cast<hal::Error>(
mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
- if (error != HWC2::Error::None) {
+ if (error != hal::Error::NONE) {
ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
return {};
}
auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
- hwcDisplayId, HWC2::DisplayType::Virtual);
+ hwcDisplayId, hal::DisplayType::VIRTUAL);
display->setConnected(true);
DisplayId displayId;
@@ -295,7 +284,7 @@
return displayId;
}
-void HWComposer::allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) {
+void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) {
if (!mInternalHwcDisplayId) {
mInternalHwcDisplayId = hwcDisplayId;
} else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
@@ -305,7 +294,7 @@
auto& displayData = mDisplayData[displayId];
auto newDisplay =
std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
- HWC2::DisplayType::Physical);
+ hal::DisplayType::PHYSICAL);
newDisplay->setConnected(true);
displayData.hwcDisplay = std::move(newDisplay);
mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
@@ -364,7 +353,7 @@
std::shared_ptr<const HWC2::Display::Config> config;
auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
- if (error == HWC2::Error::BadConfig) {
+ if (error == hal::Error::BAD_CONFIG) {
LOG_DISPLAY_ERROR(displayId, "No active config");
return nullptr;
}
@@ -415,7 +404,7 @@
int index;
auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
- if (error == HWC2::Error::BadConfig) {
+ if (error == hal::Error::BAD_CONFIG) {
LOG_DISPLAY_ERROR(displayId, "No active config");
return -1;
}
@@ -453,7 +442,7 @@
return NO_ERROR;
}
-void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) {
+void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
@@ -478,7 +467,7 @@
displayData.vsyncEnabled = enabled;
const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
- ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
+ ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0);
}
status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
@@ -509,7 +498,7 @@
uint32_t numTypes = 0;
uint32_t numRequests = 0;
- HWC2::Error error = HWC2::Error::None;
+ hal::Error error = hal::Error::NONE;
// First try to skip validate altogether when there is no client
// composition. When there is client composition, since we haven't
@@ -520,7 +509,7 @@
sp<Fence> outPresentFence;
uint32_t state = UINT32_MAX;
error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
- if (error != HWC2::Error::HasChanges) {
+ if (!hasChangesError(error)) {
RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
}
if (state == 1) { //Present Succeeded.
@@ -537,7 +526,7 @@
error = hwcDisplay->validate(&numTypes, &numRequests);
}
ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
- if (error != HWC2::Error::HasChanges) {
+ if (!hasChangesError(error)) {
RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
}
@@ -546,7 +535,7 @@
error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
- auto displayRequests = static_cast<HWC2::DisplayRequest>(0);
+ auto displayRequests = static_cast<hal::DisplayRequest>(0);
android::HWComposer::DeviceRequestedChanges::LayerRequests layerRequests;
layerRequests.reserve(numRequests);
error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
@@ -587,7 +576,7 @@
if (displayData.validateWasSkipped) {
// explicitly flush all pending commands
- auto error = static_cast<HWC2::Error>(mComposer->executeCommands());
+ auto error = static_cast<hal::Error>(mComposer->executeCommands());
RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
return NO_ERROR;
@@ -605,7 +594,7 @@
return NO_ERROR;
}
-status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) {
+status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto& displayData = mDisplayData[displayId];
@@ -614,42 +603,41 @@
return INVALID_OPERATION;
}
- auto mode = static_cast<HWC2::PowerMode>(intMode);
- if (mode == HWC2::PowerMode::Off) {
- setVsyncEnabled(displayId, HWC2::Vsync::Disable);
+ if (mode == hal::PowerMode::OFF) {
+ setVsyncEnabled(displayId, hal::Vsync::DISABLE);
}
auto& hwcDisplay = displayData.hwcDisplay;
switch (mode) {
- case HWC2::PowerMode::Off:
- case HWC2::PowerMode::On:
+ case hal::PowerMode::OFF:
+ case hal::PowerMode::ON:
ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
{
auto error = hwcDisplay->setPowerMode(mode);
- if (error != HWC2::Error::None) {
- LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(),
- error, displayId);
+ if (error != hal::Error::NONE) {
+ LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
+ displayId);
}
}
break;
- case HWC2::PowerMode::Doze:
- case HWC2::PowerMode::DozeSuspend:
+ case hal::PowerMode::DOZE:
+ case hal::PowerMode::DOZE_SUSPEND:
ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
{
bool supportsDoze = false;
auto error = hwcDisplay->supportsDoze(&supportsDoze);
- if (error != HWC2::Error::None) {
+ if (error != hal::Error::NONE) {
LOG_HWC_ERROR("supportsDoze", error, displayId);
}
if (!supportsDoze) {
- mode = HWC2::PowerMode::On;
+ mode = hal::PowerMode::ON;
}
error = hwcDisplay->setPowerMode(mode);
- if (error != HWC2::Error::None) {
- LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(),
- error, displayId);
+ if (error != hal::Error::NONE) {
+ LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), error,
+ displayId);
}
}
break;
@@ -662,8 +650,8 @@
}
status_t HWComposer::setActiveConfigWithConstraints(
- DisplayId displayId, size_t configId, const HWC2::VsyncPeriodChangeConstraints& constraints,
- HWC2::VsyncPeriodChangeTimeline* outTimeline) {
+ DisplayId displayId, size_t configId, const hal::VsyncPeriodChangeConstraints& constraints,
+ hal::VsyncPeriodChangeTimeline* outTimeline) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
@@ -684,9 +672,10 @@
auto& displayData = mDisplayData[displayId];
bool isIdentity = transform == mat4();
- auto error = displayData.hwcDisplay->setColorTransform(transform,
- isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY :
- HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX);
+ auto error = displayData.hwcDisplay
+ ->setColorTransform(transform,
+ isIdentity ? hal::ColorTransform::IDENTITY
+ : hal::ColorTransform::ARBITRARY_MATRIX);
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
@@ -777,7 +766,7 @@
mDisplayData[displayId]
.hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
outComponentMask);
- if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ if (error == hal::Error::UNSUPPORTED) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
@@ -790,8 +779,8 @@
componentMask,
maxFrames);
- if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
- if (error == HWC2::Error::BadParameter) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ 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;
}
@@ -806,17 +795,21 @@
return NO_ERROR;
}
-status_t HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
- RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
- const auto error = mDisplayData[displayId].hwcDisplay->setDisplayBrightness(brightness);
- if (error == HWC2::Error::Unsupported) {
- RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
- }
- if (error == HWC2::Error::BadParameter) {
- RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
- }
- RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
- return NO_ERROR;
+std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
+ RETURN_IF_INVALID_DISPLAY(displayId, promise::yield<status_t>(BAD_INDEX));
+ auto& display = mDisplayData[displayId].hwcDisplay;
+
+ return promise::chain(display->setDisplayBrightness(brightness))
+ .then([displayId](hal::Error error) -> status_t {
+ 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::isUsingVrComposer() const {
@@ -826,10 +819,10 @@
status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
- if (error == HWC2::Error::Unsupported) {
+ if (error == hal::Error::UNSUPPORTED) {
RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
}
- if (error == HWC2::Error::BadParameter) {
+ if (error == hal::Error::BAD_PARAMETER) {
RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
}
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
@@ -837,7 +830,7 @@
}
status_t HWComposer::getSupportedContentTypes(
- DisplayId displayId, std::vector<HWC2::ContentType>* outSupportedContentTypes) {
+ DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error =
mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes);
@@ -847,13 +840,13 @@
return NO_ERROR;
}
-status_t HWComposer::setContentType(DisplayId displayId, HWC2::ContentType contentType) {
+status_t HWComposer::setContentType(DisplayId displayId, hal::ContentType contentType) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType);
- if (error == HWC2::Error::Unsupported) {
+ if (error == hal::Error::UNSUPPORTED) {
RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
}
- if (error == HWC2::Error::BadParameter) {
+ if (error == hal::Error::BAD_PARAMETER) {
RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
}
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
@@ -869,7 +862,7 @@
result.append(mComposer->dumpDebugInfo());
}
-std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
+std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const {
if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
it != mPhysicalDisplayIdMap.end()) {
return it->second;
@@ -877,7 +870,7 @@
return {};
}
-std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
+std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
if (const auto it = mDisplayData.find(displayId);
it != mDisplayData.end() && !it->second.isVirtual) {
return it->second.hwcDisplay->getId();
@@ -885,7 +878,7 @@
return {};
}
-bool HWComposer::shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
+bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
bool hasDisplayIdentificationData) const {
if (isUsingVrComposer() && mInternalHwcDisplayId) {
ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
@@ -906,7 +899,8 @@
return false;
}
-std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
+ hal::HWDisplayId hwcDisplayId) {
std::optional<DisplayIdentificationInfo> info;
if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
info = DisplayIdentificationInfo{.id = *displayId,
@@ -937,7 +931,7 @@
} else {
ALOGW_IF(hasDisplayIdentificationData,
"Ignoring identification data for display %" PRIu64, hwcDisplayId);
- port = isPrimary ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL;
+ port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL;
}
return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
@@ -954,7 +948,7 @@
}
std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
- hwc2_display_t hwcDisplayId) {
+ hal::HWDisplayId hwcDisplayId) {
const auto displayId = toPhysicalDisplayId(hwcDisplayId);
if (!displayId) {
ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
@@ -976,10 +970,10 @@
}
void HWComposer::loadCapabilities() {
- static_assert(sizeof(HWC2::Capability) == sizeof(int32_t), "Capability size has changed");
+ static_assert(sizeof(hal::Capability) == sizeof(int32_t), "Capability size has changed");
auto capabilities = mComposer->getCapabilities();
for (auto capability : capabilities) {
- mCapabilities.emplace(static_cast<HWC2::Capability>(capability));
+ mCapabilities.emplace(static_cast<hal::Capability>(capability));
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3cb40b1..b7e9f3a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -18,6 +18,7 @@
#define ANDROID_SF_HWCOMPOSER_H
#include <cstdint>
+#include <future>
#include <memory>
#include <mutex>
#include <optional>
@@ -39,9 +40,12 @@
#include "DisplayIdentification.h"
#include "HWC2.h"
+#include "Hal.h"
namespace android {
+namespace hal = hardware::graphics::composer::hal;
+
struct DisplayedFrameStats;
class GraphicBuffer;
class TestableSurfaceFlinger;
@@ -66,18 +70,18 @@
virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
- virtual bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ virtual bool getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
DisplayIdentificationData* outData) const = 0;
- virtual bool hasCapability(HWC2::Capability capability) const = 0;
- virtual bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
- HWC2::DisplayCapability capability) const = 0;
+ virtual bool hasCapability(hal::Capability capability) const = 0;
+ virtual bool hasDisplayCapability(DisplayId displayId,
+ hal::DisplayCapability capability) const = 0;
// Attempts to allocate a virtual display and returns its ID if created on the HWC device.
virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
ui::PixelFormat* format) = 0;
- virtual void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) = 0;
+ virtual void allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) = 0;
// Attempts to create a new layer on this display
virtual HWC2::Layer* createLayer(DisplayId displayId) = 0;
@@ -85,9 +89,9 @@
virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
struct DeviceRequestedChanges {
- using ChangedTypes = std::unordered_map<HWC2::Layer*, HWC2::Composition>;
- using DisplayRequests = HWC2::DisplayRequest;
- using LayerRequests = std::unordered_map<HWC2::Layer*, HWC2::LayerRequest>;
+ using ChangedTypes = std::unordered_map<HWC2::Layer*, hal::Composition>;
+ using DisplayRequests = hal::DisplayRequest;
+ using LayerRequests = std::unordered_map<HWC2::Layer*, hal::LayerRequest>;
ChangedTypes changedTypes;
DisplayRequests displayRequests;
@@ -113,7 +117,7 @@
virtual status_t presentAndGetReleaseFences(DisplayId displayId) = 0;
// set power mode
- virtual status_t setPowerMode(DisplayId displayId, int mode) = 0;
+ virtual status_t setPowerMode(DisplayId displayId, hal::PowerMode mode) = 0;
// Sets a color transform to be applied to the result of composition
virtual status_t setColorTransform(DisplayId displayId, const mat4& transform) = 0;
@@ -160,18 +164,18 @@
DisplayedFrameStats* outStats) = 0;
// Sets the brightness of a display.
- virtual status_t setDisplayBrightness(DisplayId displayId, float brightness) = 0;
+ virtual std::future<status_t> setDisplayBrightness(DisplayId displayId, float brightness) = 0;
// Events handling ---------------------------------------------------------
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
// This function is called from SurfaceFlinger.
- virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
- HWC2::Connection connection) = 0;
+ virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId hwcDisplayId,
+ hal::Connection connection) = 0;
- virtual bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) = 0;
- virtual void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) = 0;
+ virtual bool onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) = 0;
+ virtual void setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) = 0;
virtual nsecs_t getRefreshTimestamp(DisplayId displayId) const = 0;
virtual bool isConnected(DisplayId displayId) const = 0;
@@ -197,12 +201,12 @@
virtual nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const = 0;
virtual status_t setActiveConfigWithConstraints(
DisplayId displayId, size_t configId,
- const HWC2::VsyncPeriodChangeConstraints& constraints,
- HWC2::VsyncPeriodChangeTimeline* outTimeline) = 0;
+ const hal::VsyncPeriodChangeConstraints& constraints,
+ hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
virtual status_t setAutoLowLatencyMode(DisplayId displayId, bool on) = 0;
virtual status_t getSupportedContentTypes(
- DisplayId displayId, std::vector<HWC2::ContentType>* outSupportedContentTypes) = 0;
- virtual status_t setContentType(DisplayId displayId, HWC2::ContentType contentType) = 0;
+ DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) = 0;
+ virtual status_t setContentType(DisplayId displayId, hal::ContentType contentType) = 0;
virtual const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata()
const = 0;
@@ -212,11 +216,11 @@
virtual Hwc2::Composer* getComposer() const = 0;
// TODO(b/74619554): Remove special cases for internal/external display.
- virtual std::optional<hwc2_display_t> getInternalHwcDisplayId() const = 0;
- virtual std::optional<hwc2_display_t> getExternalHwcDisplayId() const = 0;
+ virtual std::optional<hal::HWDisplayId> getInternalHwcDisplayId() const = 0;
+ virtual std::optional<hal::HWDisplayId> getExternalHwcDisplayId() const = 0;
- virtual std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const = 0;
- virtual std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const = 0;
+ virtual std::optional<DisplayId> toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const = 0;
+ virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(DisplayId displayId) const = 0;
};
namespace impl {
@@ -230,19 +234,19 @@
void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) override;
- bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ bool getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
DisplayIdentificationData* outData) const override;
- bool hasCapability(HWC2::Capability capability) const override;
- bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
- HWC2::DisplayCapability capability) const override;
+ bool hasCapability(hal::Capability capability) const override;
+ bool hasDisplayCapability(DisplayId displayId,
+ hal::DisplayCapability capability) const override;
// Attempts to allocate a virtual display and returns its ID if created on the HWC device.
std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
ui::PixelFormat* format) override;
// Called from SurfaceFlinger, when the state for a new physical display needs to be recreated.
- void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) override;
+ void allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) override;
// Attempts to create a new layer on this display
HWC2::Layer* createLayer(DisplayId displayId) override;
@@ -260,7 +264,7 @@
status_t presentAndGetReleaseFences(DisplayId displayId) override;
// set power mode
- status_t setPowerMode(DisplayId displayId, int mode) override;
+ status_t setPowerMode(DisplayId displayId, hal::PowerMode mode) override;
// Sets a color transform to be applied to the result of composition
status_t setColorTransform(DisplayId displayId, const mat4& transform) override;
@@ -302,17 +306,17 @@
uint8_t componentMask, uint64_t maxFrames) override;
status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp,
DisplayedFrameStats* outStats) override;
- status_t setDisplayBrightness(DisplayId displayId, float brightness) override;
+ std::future<status_t> setDisplayBrightness(DisplayId displayId, float brightness) override;
// Events handling ---------------------------------------------------------
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
- std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
- HWC2::Connection connection) override;
+ std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId hwcDisplayId,
+ hal::Connection connection) override;
- bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) override;
- void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) override;
+ bool onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) override;
+ void setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) override;
nsecs_t getRefreshTimestamp(DisplayId displayId) const override;
bool isConnected(DisplayId displayId) const override;
@@ -337,12 +341,11 @@
bool isVsyncPeriodSwitchSupported(DisplayId displayId) const override;
nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const override;
status_t setActiveConfigWithConstraints(DisplayId displayId, size_t configId,
- const HWC2::VsyncPeriodChangeConstraints& constraints,
- HWC2::VsyncPeriodChangeTimeline* outTimeline) override;
+ const hal::VsyncPeriodChangeConstraints& constraints,
+ hal::VsyncPeriodChangeTimeline* outTimeline) override;
status_t setAutoLowLatencyMode(DisplayId displayId, bool) override;
- status_t getSupportedContentTypes(DisplayId displayId,
- std::vector<HWC2::ContentType>*) override;
- status_t setContentType(DisplayId displayId, HWC2::ContentType) override;
+ status_t getSupportedContentTypes(DisplayId displayId, std::vector<hal::ContentType>*) override;
+ status_t setContentType(DisplayId displayId, hal::ContentType) override;
const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata() const override;
@@ -352,23 +355,23 @@
Hwc2::Composer* getComposer() const override { return mComposer.get(); }
// TODO(b/74619554): Remove special cases for internal/external display.
- std::optional<hwc2_display_t> getInternalHwcDisplayId() const override {
+ std::optional<hal::HWDisplayId> getInternalHwcDisplayId() const override {
return mInternalHwcDisplayId;
}
- std::optional<hwc2_display_t> getExternalHwcDisplayId() const override {
+ std::optional<hal::HWDisplayId> getExternalHwcDisplayId() const override {
return mExternalHwcDisplayId;
}
- std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const override;
- std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const override;
+ std::optional<DisplayId> toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const override;
+ std::optional<hal::HWDisplayId> fromPhysicalDisplayId(DisplayId displayId) const override;
private:
// For unit tests
friend TestableSurfaceFlinger;
- std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
- std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hwc2_display_t hwcDisplayId);
- bool shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
+ std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId hwcDisplayId);
+ std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hal::HWDisplayId hwcDisplayId);
+ bool shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
bool hasDisplayIdentificationData) const;
void loadCapabilities();
@@ -386,12 +389,12 @@
std::shared_ptr<const HWC2::Display::Config>> configMap;
bool validateWasSkipped;
- HWC2::Error presentError;
+ hal::Error presentError;
bool vsyncTraceToggle = false;
std::mutex vsyncEnabledLock;
- HWC2::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = HWC2::Vsync::Disable;
+ hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
mutable std::mutex lastHwVsyncLock;
nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
@@ -400,13 +403,13 @@
std::unordered_map<DisplayId, DisplayData> mDisplayData;
std::unique_ptr<android::Hwc2::Composer> mComposer;
- std::unordered_set<HWC2::Capability> mCapabilities;
+ std::unordered_set<hal::Capability> mCapabilities;
std::unordered_map<std::string, bool> mSupportedLayerGenericMetadata;
bool mRegisteredCallback = false;
- std::unordered_map<hwc2_display_t, DisplayId> mPhysicalDisplayIdMap;
- std::optional<hwc2_display_t> mInternalHwcDisplayId;
- std::optional<hwc2_display_t> mExternalHwcDisplayId;
+ std::unordered_map<hal::HWDisplayId, DisplayId> mPhysicalDisplayIdMap;
+ std::optional<hal::HWDisplayId> mInternalHwcDisplayId;
+ std::optional<hal::HWDisplayId> mExternalHwcDisplayId;
bool mHasMultiDisplaySupport = false;
std::unordered_set<DisplayId> mFreeVirtualDisplayIds;
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
new file mode 100644
index 0000000..66ee425
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2020 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/hardware/graphics/common/1.1/types.h>
+#include <android/hardware/graphics/composer/2.4/IComposer.h>
+#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
+
+#define ERROR_HAS_CHANGES 5
+
+namespace android {
+namespace hardware::graphics::composer::hal {
+
+namespace types = android::hardware::graphics::common;
+namespace V2_1 = android::hardware::graphics::composer::V2_1;
+namespace V2_2 = android::hardware::graphics::composer::V2_2;
+namespace V2_3 = android::hardware::graphics::composer::V2_3;
+namespace V2_4 = android::hardware::graphics::composer::V2_4;
+
+using types::V1_0::ColorTransform;
+using types::V1_0::Transform;
+using types::V1_1::RenderIntent;
+using types::V1_2::ColorMode;
+using types::V1_2::Dataspace;
+using types::V1_2::Hdr;
+using types::V1_2::PixelFormat;
+
+using V2_1::Error;
+using V2_4::IComposer;
+using V2_4::IComposerCallback;
+using V2_4::IComposerClient;
+using V2_4::VsyncPeriodChangeTimeline;
+using V2_4::VsyncPeriodNanos;
+
+using Attribute = IComposerClient::Attribute;
+using BlendMode = IComposerClient::BlendMode;
+using Color = IComposerClient::Color;
+using Composition = IComposerClient::Composition;
+using Connection = IComposerCallback::Connection;
+using ContentType = IComposerClient::ContentType;
+using Capability = IComposer::Capability;
+using DisplayCapability = IComposerClient::DisplayCapability;
+using DisplayRequest = IComposerClient::DisplayRequest;
+using DisplayType = IComposerClient::DisplayType;
+using HWConfigId = V2_1::Config;
+using HWDisplayId = V2_1::Display;
+using HWError = V2_1::Error;
+using HWLayerId = V2_1::Layer;
+using LayerGenericMetadataKey = IComposerClient::LayerGenericMetadataKey;
+using LayerRequest = IComposerClient::LayerRequest;
+using PerFrameMetadata = IComposerClient::PerFrameMetadata;
+using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey;
+using PerFrameMetadataBlob = IComposerClient::PerFrameMetadataBlob;
+using PowerMode = IComposerClient::PowerMode;
+using Vsync = IComposerClient::Vsync;
+using VsyncPeriodChangeConstraints = IComposerClient::VsyncPeriodChangeConstraints;
+
+} // namespace hardware::graphics::composer::hal
+
+inline bool hasChangesError(hardware::graphics::composer::hal::Error error) {
+ return ERROR_HAS_CHANGES == static_cast<int32_t>(error);
+}
+
+inline std::string to_string(hardware::graphics::composer::hal::Attribute attribute) {
+ switch (attribute) {
+ case hardware::graphics::composer::hal::Attribute::INVALID:
+ return "Invalid";
+ case hardware::graphics::composer::hal::Attribute::WIDTH:
+ return "Width";
+ case hardware::graphics::composer::hal::Attribute::HEIGHT:
+ return "Height";
+ case hardware::graphics::composer::hal::Attribute::VSYNC_PERIOD:
+ return "VsyncPeriod";
+ case hardware::graphics::composer::hal::Attribute::DPI_X:
+ return "DpiX";
+ case hardware::graphics::composer::hal::Attribute::DPI_Y:
+ return "DpiY";
+ default:
+ return "Unknown";
+ }
+}
+
+inline std::string to_string(hardware::graphics::composer::hal::Composition composition) {
+ switch (composition) {
+ case hardware::graphics::composer::hal::Composition::INVALID:
+ return "Invalid";
+ case hardware::graphics::composer::hal::Composition::CLIENT:
+ return "Client";
+ case hardware::graphics::composer::hal::Composition::DEVICE:
+ return "Device";
+ case hardware::graphics::composer::hal::Composition::SOLID_COLOR:
+ return "SolidColor";
+ case hardware::graphics::composer::hal::Composition::CURSOR:
+ return "Cursor";
+ case hardware::graphics::composer::hal::Composition::SIDEBAND:
+ return "Sideband";
+ default:
+ return "Unknown";
+ }
+}
+
+inline std::string to_string(hardware::graphics::composer::hal::V2_4::Error error) {
+ // 5 is reserved for historical reason, during validation 5 means has changes.
+ if (ERROR_HAS_CHANGES == static_cast<int32_t>(error)) {
+ return "HasChanges";
+ }
+ switch (error) {
+ case hardware::graphics::composer::hal::V2_4::Error::NONE:
+ return "None";
+ case hardware::graphics::composer::hal::V2_4::Error::BAD_CONFIG:
+ return "BadConfig";
+ case hardware::graphics::composer::hal::V2_4::Error::BAD_DISPLAY:
+ return "BadDisplay";
+ case hardware::graphics::composer::hal::V2_4::Error::BAD_LAYER:
+ return "BadLayer";
+ case hardware::graphics::composer::hal::V2_4::Error::BAD_PARAMETER:
+ return "BadParameter";
+ case hardware::graphics::composer::hal::V2_4::Error::NO_RESOURCES:
+ return "NoResources";
+ case hardware::graphics::composer::hal::V2_4::Error::NOT_VALIDATED:
+ return "NotValidated";
+ case hardware::graphics::composer::hal::V2_4::Error::UNSUPPORTED:
+ return "Unsupported";
+ case hardware::graphics::composer::hal::V2_4::Error::SEAMLESS_NOT_ALLOWED:
+ return "SeamlessNotAllowed";
+ case hardware::graphics::composer::hal::V2_4::Error::SEAMLESS_NOT_POSSIBLE:
+ return "SeamlessNotPossible";
+ default:
+ return "Unknown";
+ }
+}
+
+inline std::string to_string(hardware::graphics::composer::hal::Error error) {
+ return to_string(static_cast<hardware::graphics::composer::hal::V2_4::Error>(error));
+}
+
+inline std::string to_string(hardware::graphics::composer::hal::PowerMode mode) {
+ switch (mode) {
+ case hardware::graphics::composer::hal::PowerMode::OFF:
+ return "Off";
+ case hardware::graphics::composer::hal::PowerMode::DOZE:
+ return "Doze";
+ case hardware::graphics::composer::hal::PowerMode::ON:
+ return "On";
+ case hardware::graphics::composer::hal::PowerMode::DOZE_SUSPEND:
+ return "DozeSuspend";
+ case hardware::graphics::composer::hal::PowerMode::ON_SUSPEND:
+ return "OnSuspend";
+ default:
+ return "Unknown";
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 4a90acb..34e63e7 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -16,12 +16,6 @@
#pragma once
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
#include <atomic>
#include <unordered_set>
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5039761..17458e3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -117,6 +117,7 @@
mCurrentState.metadata = args.metadata;
mCurrentState.shadowRadius = 0.f;
mCurrentState.treeHasFrameRateVote = false;
+ mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
// drawing state & current state are identical
mDrawingState = mCurrentState;
@@ -144,11 +145,10 @@
mFlinger->onLayerDestroyed(this);
}
-LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client> client,
- std::string name, uint32_t w, uint32_t h, uint32_t flags,
- LayerMetadata metadata)
+LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
+ uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata)
: flinger(flinger),
- client(client),
+ client(std::move(client)),
name(std::move(name)),
w(w),
h(h),
@@ -220,9 +220,6 @@
}
mFlinger->markLayerPendingRemovalLocked(this);
- if (hasInput()) {
- mFlinger->dirtyInput();
- }
}
void Layer::onRemovedFromCurrentState() {
@@ -720,9 +717,8 @@
return {*shadowSettings};
}
-Hwc2::IComposerClient::Composition Layer::getCompositionType(
- const sp<const DisplayDevice>& display) const {
- const auto outputLayer = findOutputLayerForDisplay(display);
+Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(&display);
if (outputLayer == nullptr) {
return Hwc2::IComposerClient::Composition::INVALID;
}
@@ -733,12 +729,6 @@
}
}
-bool Layer::getClearClientTarget(const sp<const DisplayDevice>& display) const {
- const auto outputLayer = findOutputLayerForDisplay(display);
- LOG_FATAL_IF(!outputLayer);
- return outputLayer->getState().clearClientTarget;
-}
-
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
if (point->getFrameNumber() <= mCurrentFrameNumber) {
// Don't bother with a SyncPoint, since we've already latched the
@@ -998,8 +988,6 @@
mPendingStatesSnapshot = mPendingStates;
mCurrentState.callbackHandles = {};
- maybeDirtyInput();
-
return flags;
}
@@ -1338,6 +1326,18 @@
return true;
}
+bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint) {
+ if (mCurrentState.fixedTransformHint == fixedTransformHint) {
+ return false;
+ }
+
+ mCurrentState.sequence++;
+ mCurrentState.fixedTransformHint = fixedTransformHint;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
void Layer::updateTreeHasFrameRateVote() {
const auto traverseTree = [&](const LayerVector::Visitor& visitor) {
auto parent = getParent();
@@ -1384,6 +1384,9 @@
return false;
}
+ // Activate the layer in Scheduler's LayerHistory
+ mFlinger->mScheduler->recordLayerHistory(this, systemTime());
+
mCurrentState.sequence++;
mCurrentState.frameRate = frameRate;
mCurrentState.modified = true;
@@ -1461,20 +1464,12 @@
return usage;
}
-void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
- uint32_t orientation = 0;
- // Disable setting transform hint if the debug flag is set.
- if (!mFlinger->mDebugDisableTransformHint) {
- // The transform hint is used to improve performance, but we can
- // only have a single transform hint, it cannot
- // apply to all displays.
- const ui::Transform& planeTransform = display->getTransform();
- orientation = planeTransform.getOrientation();
- if (orientation & ui::Transform::ROT_INVALID) {
- orientation = 0;
- }
+void Layer::updateTransformHint(ui::Transform::RotationFlags transformHint) {
+ if (mFlinger->mDebugDisableTransformHint || transformHint & ui::Transform::ROT_INVALID) {
+ transformHint = ui::Transform::ROT_0;
}
- setTransformHint(orientation);
+
+ setTransformHint(transformHint);
}
// ----------------------------------------------------------------------------
@@ -1482,7 +1477,7 @@
// ----------------------------------------------------------------------------
// TODO(marissaw): add new layer state info to layer debugging
-LayerDebugInfo Layer::getLayerDebugInfo() const {
+LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const {
using namespace std::string_literals;
LayerDebugInfo info;
@@ -1493,7 +1488,7 @@
info.mType = getType();
info.mTransparentRegion = ds.activeTransparentRegion_legacy;
- info.mVisibleRegion = debugGetVisibleRegionOnDefaultDisplay();
+ info.mVisibleRegion = getVisibleRegion(display);
info.mSurfaceDamageRegion = surfaceDamageRegion;
info.mLayerStack = getLayerStack();
info.mX = ds.active_legacy.transform.tx();
@@ -1534,21 +1529,37 @@
void Layer::miniDumpHeader(std::string& result) {
result.append("-------------------------------");
result.append("-------------------------------");
- result.append("-----------------------------\n");
+ result.append("-------------------------------");
+ result.append("-------------------------------");
+ result.append("---------\n");
result.append(" Layer name\n");
result.append(" Z | ");
result.append(" Window Type | ");
result.append(" Comp Type | ");
result.append(" Transform | ");
result.append(" Disp Frame (LTRB) | ");
- result.append(" Source Crop (LTRB)\n");
+ result.append(" Source Crop (LTRB) | ");
+ result.append(" Frame Rate (Explicit)\n");
result.append("-------------------------------");
result.append("-------------------------------");
- result.append("-----------------------------\n");
+ result.append("-------------------------------");
+ result.append("-------------------------------");
+ result.append("---------\n");
}
-void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice) const {
- auto outputLayer = findOutputLayerForDisplay(displayDevice);
+std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility compatibility) {
+ switch (compatibility) {
+ case FrameRateCompatibility::Default:
+ return "Default";
+ case FrameRateCompatibility::ExactOrMultiple:
+ return "ExactOrMultiple";
+ case FrameRateCompatibility::NoVote:
+ return "NoVote";
+ }
+}
+
+void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(&display);
if (!outputLayer) {
return;
}
@@ -1575,17 +1586,26 @@
StringAppendF(&result, " %10d | ", layerState.z);
}
StringAppendF(&result, " %10d | ", mWindowType);
- StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str());
+ StringAppendF(&result, "%10s | ", toString(getCompositionType(display)).c_str());
StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str());
const Rect& frame = outputLayerState.displayFrame;
StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
const FloatRect& crop = outputLayerState.sourceCrop;
- StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right,
+ StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right,
crop.bottom);
+ if (layerState.frameRate.rate != 0 ||
+ layerState.frameRate.type != FrameRateCompatibility::Default) {
+ StringAppendF(&result, "% 6.2ffps %15s\n", layerState.frameRate.rate,
+ frameRateCompatibilityString(layerState.frameRate.type).c_str());
+ } else {
+ StringAppendF(&result, "\n");
+ }
- result.append("- - - - - - - - - - - - - - - -");
- result.append("- - - - - - - - - - - - - - - -");
- result.append("- - - - - - - - - - - - - - -\n");
+ result.append("- - - - - - - - - - - - - - - - ");
+ result.append("- - - - - - - - - - - - - - - - ");
+ result.append("- - - - - - - - - - - - - - - - ");
+ result.append("- - - - - - - - - - - - - - - - ");
+ result.append("- - -\n");
}
void Layer::dumpFrameStats(std::string& result) const {
@@ -2053,6 +2073,16 @@
return parentAlpha * getDrawingState().color.a;
}
+ui::Transform::RotationFlags Layer::getFixedTransformHint() const {
+ ui::Transform::RotationFlags fixedTransformHint = mCurrentState.fixedTransformHint;
+ if (fixedTransformHint != ui::Transform::ROT_INVALID) {
+ return fixedTransformHint;
+ }
+ const auto& p = mCurrentParent.promote();
+ if (!p) return fixedTransformHint;
+ return p->getFixedTransformHint();
+}
+
half4 Layer::getColor() const {
const half4 color(getDrawingState().color);
return half4(color.r, color.g, color.b, getAlpha());
@@ -2129,27 +2159,28 @@
}
LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags,
- const sp<const DisplayDevice>& device) const {
+ const DisplayDevice* display) const {
LayerProto* layerProto = layersProto.add_layers();
- writeToProtoDrawingState(layerProto, traceFlags);
+ writeToProtoDrawingState(layerProto, traceFlags, display);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
// Only populate for the primary display.
- if (device) {
- const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device);
+ if (display) {
+ const Hwc2::IComposerClient::Composition compositionType = getCompositionType(*display);
layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
}
}
for (const sp<Layer>& layer : mDrawingChildren) {
- layer->writeToProto(layersProto, traceFlags, device);
+ layer->writeToProto(layersProto, traceFlags, display);
}
return layerProto;
}
-void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const {
+void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
+ const DisplayDevice* display) const {
ui::Transform transform = getTransform();
if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
@@ -2183,7 +2214,7 @@
[&]() { return layerInfo->mutable_position(); });
LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
- LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
+ LayerProtoHelper::writeToProto(getVisibleRegion(display),
[&]() { return layerInfo->mutable_visible_region(); });
}
LayerProtoHelper::writeToProto(surfaceDamageRegion,
@@ -2382,22 +2413,14 @@
}
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
- const sp<const DisplayDevice>& display) const {
+ const DisplayDevice* display) const {
+ if (!display) return nullptr;
return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionEngineLayerFE());
}
-Region Layer::debugGetVisibleRegionOnDefaultDisplay() const {
- sp<DisplayDevice> displayDevice = mFlinger->getDefaultDisplayDeviceLocked();
- if (displayDevice == nullptr) {
- return {};
- }
-
- auto outputLayer = findOutputLayerForDisplay(displayDevice);
- if (outputLayer == nullptr) {
- return {};
- }
-
- return outputLayer->getState().visibleRegion;
+Region Layer::getVisibleRegion(const DisplayDevice* display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ return outputLayer ? outputLayer->getState().visibleRegion : Region();
}
void Layer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
@@ -2545,32 +2568,6 @@
}
}
-bool Layer::maybeDirtyInput() {
- // No sense redirtying input.
- if (mFlinger->inputDirty()) return true;
-
- if (hasInput()) {
- mFlinger->dirtyInput();
- return true;
- }
-
- // If a child or relative dirties the input, no sense continuing to traverse
- // so we return early and halt the recursion. We traverse ourselves instead
- // of using traverse() so we can implement this early halt.
- for (const sp<Layer>& child : mDrawingChildren) {
- if (child->maybeDirtyInput()) {
- return true;
- }
- }
- for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
- sp<Layer> relative = weakRelative.promote();
- if (relative && relative->maybeDirtyInput()) {
- return true;
- }
- }
- return false;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 92ac015..3fa935f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_LAYER_H
-#define ANDROID_LAYER_H
+#pragma once
#include <compositionengine/LayerFE.h>
#include <gui/BufferQueue.h>
@@ -77,8 +76,8 @@
// ---------------------------------------------------------------------------
struct LayerCreationArgs {
- LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client> client, std::string name,
- uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata);
+ LayerCreationArgs(SurfaceFlinger*, sp<Client>, std::string name, uint32_t w, uint32_t h,
+ uint32_t flags, LayerMetadata);
SurfaceFlinger* flinger;
const sp<Client> client;
@@ -87,9 +86,9 @@
uint32_t h;
uint32_t flags;
LayerMetadata metadata;
+
pid_t callingPid;
uid_t callingUid;
- sp<const DisplayDevice> displayDevice;
uint32_t textureName;
};
@@ -262,6 +261,15 @@
// Indicates whether parents / children of this layer had set FrameRate
bool treeHasFrameRateVote;
+
+ // Set by window manager indicating the layer and all its children are
+ // in a different orientation than the display. The hint suggests that
+ // the graphic producers should receive a transform hint as if the
+ // display was in this orientation. When the display changes to match
+ // the layer orientation, the graphic producer may not need to allocate
+ // a buffer of a different size. ui::Transform::ROT_INVALID means the
+ // a fixed transform hint is not set.
+ ui::Transform::RotationFlags fixedTransformHint;
};
explicit Layer(const LayerCreationArgs& args);
@@ -388,6 +396,7 @@
virtual bool setColorSpaceAgnostic(const bool agnostic);
bool setShadowRadius(float shadowRadius);
virtual bool setFrameRateSelectionPriority(int32_t priority);
+ virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
// If the variable is not set on the layer, it traverses up the tree to inherit the frame
// rate priority from its parent.
virtual int32_t getFrameRateSelectionPriority() const;
@@ -509,15 +518,14 @@
bool isRemovedFromCurrentState() const;
- LayerProto* writeToProto(LayersProto& layersProto,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL,
- const sp<const DisplayDevice>& device = nullptr) const;
+ LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags,
+ const DisplayDevice*) const;
// Write states that are modified by the main thread. This includes drawing
// state as well as buffer data. This should be called in the main or tracing
// thread.
- void writeToProtoDrawingState(LayerProto* layerInfo,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ void writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
+ const DisplayDevice*) const;
// Write drawing or current state. If writing current state, the caller should hold the
// external mStateLock. If writing drawing state, this function should be called on the
// main or tracing thread.
@@ -534,7 +542,7 @@
return s.activeTransparentRegion_legacy;
}
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
- virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; }
+ virtual bool needsFiltering(const DisplayDevice*) const { return false; }
// True if this layer requires filtering
// This method is distinct from needsFiltering() in how the filter
// requirement is computed. needsFiltering() compares displayFrame and crop,
@@ -544,8 +552,7 @@
// different.
// If the parent transform needs to be undone when capturing the layer, then
// the inverse parent transform is also required.
- virtual bool needsFilteringForScreenshots(const sp<const DisplayDevice>&,
- const ui::Transform&) const {
+ virtual bool needsFilteringForScreenshots(const DisplayDevice*, const ui::Transform&) const {
return false;
}
@@ -606,21 +613,16 @@
virtual bool isHdrY410() const { return false; }
- Hwc2::IComposerClient::Composition getCompositionType(
- const sp<const DisplayDevice>& display) const;
- bool getClearClientTarget(const sp<const DisplayDevice>& display) const;
-
virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; }
- virtual void setTransformHint(uint32_t /*orientation*/) const { }
/*
* called after composition.
* returns true if the layer latched a new buffer this frame.
*/
- virtual bool onPostComposition(sp<const DisplayDevice> /*displayDevice*/,
+ virtual bool onPostComposition(const DisplayDevice*,
const std::shared_ptr<FenceTime>& /*glDoneFence*/,
const std::shared_ptr<FenceTime>& /*presentFence*/,
- const CompositorTiming& /*compositorTiming*/) {
+ const CompositorTiming&) {
return false;
}
@@ -672,9 +674,10 @@
*/
void addToCurrentState();
- // Updates the transform hint in our SurfaceFlingerConsumer to match
- // the current orientation of the display device.
- void updateTransformHint(const sp<const DisplayDevice>& display) const;
+ /*
+ * Sets display transform hint on BufferLayerConsumer.
+ */
+ void updateTransformHint(ui::Transform::RotationFlags);
/*
* returns the rectangle that crops the content of the layer and scales it
@@ -689,6 +692,8 @@
virtual sp<GraphicBuffer> getBuffer() const { return nullptr; }
+ virtual ui::Transform::RotationFlags getTransformHint() const { return ui::Transform::ROT_0; }
+
/*
* Returns if a frame is ready
*/
@@ -701,11 +706,10 @@
inline const State& getCurrentState() const { return mCurrentState; }
inline State& getCurrentState() { return mCurrentState; }
- LayerDebugInfo getLayerDebugInfo() const;
+ LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
- /* always call base class first */
static void miniDumpHeader(std::string& result);
- void miniDump(std::string& result, const sp<DisplayDevice>& display) const;
+ void miniDump(std::string& result, const DisplayDevice&) const;
void dumpFrameStats(std::string& result) const;
void dumpFrameEvents(std::string& result);
void dumpCallingUidPid(std::string& result) const;
@@ -733,6 +737,12 @@
int32_t getBackgroundBlurRadius() const;
bool drawShadows() const { return mEffectiveShadowRadius > 0.f; };
+ // Returns the transform hint set by Window Manager on the layer or one of its parents.
+ // This traverses the current state because the data is needed when creating
+ // the layer(off drawing thread) and the hint should be available before the producer
+ // is ready to acquire a buffer.
+ ui::Transform::RotationFlags getFixedTransformHint() const;
+
// Returns how rounded corners should be drawn for this layer.
// This will traverse the hierarchy until it reaches its root, finding topmost rounded
// corner definition and converting it into current layer's coordinates.
@@ -804,11 +814,6 @@
return parentBounds;
}
- compositionengine::OutputLayer* findOutputLayerForDisplay(
- const sp<const DisplayDevice>& display) const;
-
- Region debugGetVisibleRegionOnDefaultDisplay() const;
-
/**
* Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
* INVALID_RECT if the layer has no buffer and no crop.
@@ -819,6 +824,7 @@
bool setFrameRate(FrameRate frameRate);
virtual FrameRate getFrameRateForLayerTree() const;
+ static std::string frameRateCompatibilityString(FrameRateCompatibility compatibility);
protected:
// constant
@@ -944,7 +950,8 @@
bool hasInput() const;
protected:
- // -----------------------------------------------------------------------
+ compositionengine::OutputLayer* findOutputLayerForDisplay(const DisplayDevice*) const;
+
bool usingRelativeZ(LayerVector::StateSet stateSet) const;
bool mPremultipliedAlpha{true};
@@ -1015,11 +1022,12 @@
// Window types from WindowManager.LayoutParams
const int mWindowType;
- // Called when mDrawingState has changed. If we or one of our children/relatives hasInput()
- // then we will dirty the setInputWindows cache.
- bool maybeDirtyInput();
-
private:
+ virtual void setTransformHint(ui::Transform::RotationFlags) {}
+
+ Hwc2::IComposerClient::Composition getCompositionType(const DisplayDevice&) const;
+ Region getVisibleRegion(const DisplayDevice*) const;
+
/**
* Returns an unsorted vector of all layers that are part of this tree.
* That includes the current layer and all its descendants.
@@ -1083,14 +1091,3 @@
};
} // namespace android
-
-#define RETURN_IF_NO_HWC_LAYER(displayDevice, ...) \
- do { \
- if (!hasHwcLayer(displayDevice)) { \
- ALOGE("[%s] %s failed: no HWC layer found for display %s", mName.string(), \
- __FUNCTION__, displayDevice->getDebugName().c_str()); \
- return __VA_ARGS__; \
- } \
- } while (false)
-
-#endif // ANDROID_LAYER_H
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 5009e10..18a2891 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -38,13 +38,7 @@
// because we don't know where this destructor is called from. It could be
// called with the mStateLock held, leading to a dead-lock (it actually
// happens).
- sp<LambdaMessage> cleanUpListMessage =
- new LambdaMessage([flinger = mFlinger, asBinder = wp<IBinder>(onAsBinder())]() {
- Mutex::Autolock lock(flinger->mStateLock);
- flinger->mGraphicBufferProducerList.erase(asBinder);
- });
-
- mFlinger->postMessageAsync(cleanUpListMessage);
+ mFlinger->removeGraphicBufferProducerAsync(onAsBinder());
}
status_t MonitoredProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
diff --git a/services/surfaceflinger/Promise.h b/services/surfaceflinger/Promise.h
new file mode 100644
index 0000000..a80d441
--- /dev/null
+++ b/services/surfaceflinger/Promise.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 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 <future>
+#include <type_traits>
+#include <utility>
+
+namespace android::promise {
+namespace impl {
+
+template <typename T>
+struct FutureResult {
+ using Type = T;
+};
+
+template <typename T>
+struct FutureResult<std::future<T>> {
+ using Type = T;
+};
+
+} // namespace impl
+
+template <typename T>
+using FutureResult = typename impl::FutureResult<T>::Type;
+
+template <typename... Args>
+inline auto defer(Args... args) {
+ return std::async(std::launch::deferred, std::forward<Args>(args)...);
+}
+
+template <typename T>
+inline std::future<T> yield(T&& v) {
+ return defer([](T&& v) { return std::forward<T>(v); }, std::forward<T>(v));
+}
+
+template <typename T>
+struct Chain {
+ Chain(std::future<T>&& f) : future(std::move(f)) {}
+ operator std::future<T>&&() && { return std::move(future); }
+
+ T get() && { return future.get(); }
+
+ template <typename F, typename R = std::invoke_result_t<F, T>>
+ auto then(F&& op) && -> Chain<FutureResult<R>> {
+ return defer(
+ [](auto&& f, F&& op) {
+ R r = op(f.get());
+ if constexpr (std::is_same_v<R, FutureResult<R>>) {
+ return r;
+ } else {
+ return r.get();
+ }
+ },
+ std::move(future), std::forward<F>(op));
+ }
+
+ std::future<T> future;
+};
+
+template <typename T>
+inline Chain<T> chain(std::future<T>&& f) {
+ return std::move(f);
+}
+
+} // namespace android::promise
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index c675971..f602412 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -116,9 +116,13 @@
sp<GraphicBuffer> buffer =
new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_WRITE_RARELY, "RefreshRateOverlayBuffer");
+ GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "RefreshRateOverlayBuffer");
uint8_t* pixels;
buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
+ // Clear buffer content
+ drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels);
int left = 0;
if (hundreds != 0) {
drawDigit(hundreds, left, color, buffer, pixels);
@@ -170,7 +174,7 @@
void RefreshRateOverlay::primeCache() {
auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
if (allRefreshRates.size() == 1) {
- auto fps = allRefreshRates.begin()->second->fps;
+ auto fps = allRefreshRates.begin()->second->getFps();
half4 color = {LOW_FPS_COLOR, ALPHA};
mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
return;
@@ -179,7 +183,7 @@
std::vector<uint32_t> supportedFps;
supportedFps.reserve(allRefreshRates.size());
for (auto& [ignored, refreshRate] : allRefreshRates) {
- supportedFps.push_back(refreshRate->fps);
+ supportedFps.push_back(refreshRate->getFps());
}
std::sort(supportedFps.begin(), supportedFps.end());
@@ -196,26 +200,22 @@
}
}
-void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
- const auto display = mFlinger.getDefaultDisplayDeviceLocked();
- if (!display) {
- return;
- }
-
- const int32_t left = display->getWidth() / 32;
- const int32_t top = display->getHeight() / 32;
- const int32_t right = left + display->getWidth() / 8;
- const int32_t buttom = top + display->getHeight() / 32;
-
- auto buffer = mBufferCache[refreshRate.fps];
- mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});
-
- mLayer->setFrame(Rect(left, top, right, buttom));
+void RefreshRateOverlay::setViewport(ui::Size viewport) {
+ Rect frame(viewport.width >> 3, viewport.height >> 5);
+ frame.offsetBy(viewport.width >> 5, viewport.height >> 4);
+ mLayer->setFrame(frame);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
-}; // namespace android
+void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
+ auto buffer = mBufferCache[refreshRate.getFps()];
+ mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});
+
+ mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
+}
+
+} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index 6d34df2..35c8020 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -13,19 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#pragma once
-#include "SurfaceFlinger.h"
+#include <unordered_map>
+
+#include <math/vec4.h>
+#include <ui/Rect.h>
+#include <ui/Size.h>
+#include <utils/StrongPointer.h>
+
+#include "Scheduler/RefreshRateConfigs.h"
namespace android {
+class Client;
+class GraphicBuffer;
+class IBinder;
+class IGraphicBufferProducer;
+class Layer;
+class SurfaceFlinger;
+
using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
class RefreshRateOverlay {
public:
- RefreshRateOverlay(SurfaceFlinger& flinger);
+ explicit RefreshRateOverlay(SurfaceFlinger&);
- void changeRefreshRate(const RefreshRate& refreshRate);
+ void setViewport(ui::Size);
+ void changeRefreshRate(const RefreshRate&);
private:
class SevenSegmentDrawer {
@@ -56,7 +72,7 @@
void primeCache();
SurfaceFlinger& mFlinger;
- sp<Client> mClient;
+ const sp<Client> mClient;
sp<Layer> mLayer;
sp<IBinder> mIBinder;
sp<IGraphicBufferProducer> mGbp;
@@ -68,4 +84,4 @@
const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f);
};
-}; // namespace android
+} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 68cd84f..27353d8 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -130,7 +130,7 @@
mVsyncListening = false;
}
- void onDispSyncEvent(nsecs_t /* when */) final {
+ void onDispSyncEvent(nsecs_t /*when*/, nsecs_t /*expectedVSyncTimestamp*/) final {
std::unique_lock<decltype(mMutex)> lock(mMutex);
if (mPhaseIntervalSetting == Phase::ZERO) {
@@ -199,13 +199,8 @@
}
}
-void RegionSamplingThread::addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+void RegionSamplingThread::addListener(const Rect& samplingArea, const wp<Layer>& stopLayer,
const sp<IRegionSamplingListener>& listener) {
- wp<Layer> stopLayer;
- if (stopLayerHandle != nullptr && stopLayerHandle->localBinder() != nullptr) {
- stopLayer = static_cast<Layer::Handle*>(stopLayerHandle.get())->owner;
- }
-
sp<IBinder> asBinder = IInterface::asBinder(listener);
asBinder->linkToDeath(this);
std::lock_guard lock(mSamplingMutex);
@@ -430,7 +425,8 @@
}
bool ignored;
- mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false, ignored);
+ mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false /* identityTransform */,
+ true /* regionSampling */, ignored);
std::vector<Descriptor> activeDescriptors;
for (const auto& descriptor : descriptors) {
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 99c07c2..b9b7a3c 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -69,7 +69,7 @@
// Add a listener to receive luma notifications. The luma reported via listener will
// report the median luma for the layers under the stopLayerHandle, in the samplingArea region.
- void addListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
+ void addListener(const Rect& samplingArea, const wp<Layer>& stopLayer,
const sp<IRegionSamplingListener>& listener);
// Remove the listener to stop receiving median luma notifications.
void removeListener(const sp<IRegionSamplingListener>& listener);
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 809a0e5..ff91bf7 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -200,7 +200,8 @@
}
}
- callbackInvocations = gatherCallbackInvocationsLocked(now);
+ callbackInvocations =
+ gatherCallbackInvocationsLocked(now, computeNextRefreshLocked(0, now));
}
if (callbackInvocations.size() > 0) {
@@ -303,6 +304,11 @@
return BAD_VALUE;
}
+ nsecs_t computeNextRefresh(int periodOffset, nsecs_t now) const {
+ Mutex::Autolock lock(mMutex);
+ return computeNextRefreshLocked(periodOffset, now);
+ }
+
private:
struct EventListener {
const char* mName;
@@ -315,6 +321,7 @@
struct CallbackInvocation {
DispSync::Callback* mCallback;
nsecs_t mEventTime;
+ nsecs_t mExpectedVSyncTime;
};
nsecs_t computeNextEventTimeLocked(nsecs_t now) {
@@ -340,7 +347,8 @@
return duration < (3 * mPeriod) / 5;
}
- std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
+ std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now,
+ nsecs_t expectedVSyncTime) {
if (mTraceDetailedInfo) ATRACE_CALL();
ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));
@@ -361,6 +369,10 @@
CallbackInvocation ci;
ci.mCallback = eventListener.mCallback;
ci.mEventTime = t;
+ ci.mExpectedVSyncTime = expectedVSyncTime;
+ if (eventListener.mPhase < 0) {
+ ci.mExpectedVSyncTime += mPeriod;
+ }
ALOGV("[%s] [%s] Preparing to fire, latency: %" PRId64, mName, eventListener.mName,
t - eventListener.mLastEventTime);
callbackInvocations.push_back(ci);
@@ -426,10 +438,19 @@
void fireCallbackInvocations(const std::vector<CallbackInvocation>& callbacks) {
if (mTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
- callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
+ callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime,
+ callbacks[i].mExpectedVSyncTime);
}
}
+ nsecs_t computeNextRefreshLocked(int periodOffset, nsecs_t now) const {
+ nsecs_t phase = mReferenceTime + mPhase;
+ if (mPeriod == 0) {
+ return 0;
+ }
+ return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+ }
+
const char* const mName;
bool mStop;
@@ -444,7 +465,7 @@
std::vector<EventListener> mEventListeners;
- Mutex mMutex;
+ mutable Mutex mMutex;
Condition mCond;
// Flag to turn on logging in systrace.
@@ -458,7 +479,7 @@
public:
ZeroPhaseTracer() : mParity("ZERO_PHASE_VSYNC", false) {}
- virtual void onDispSyncEvent(nsecs_t /*when*/) {
+ virtual void onDispSyncEvent(nsecs_t /*when*/, nsecs_t /*expectedVSyncTimestamp*/) {
mParity = !mParity;
}
@@ -768,9 +789,8 @@
}
}
-nsecs_t DispSync::computeNextRefresh(int periodOffset) const {
+nsecs_t DispSync::computeNextRefresh(int periodOffset, nsecs_t now) const {
Mutex::Autolock lock(mMutex);
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_t phase = mReferenceTime + mPhase;
if (mPeriod == 0) {
return 0;
@@ -837,7 +857,7 @@
StringAppendF(&result, "current monotonic time: %" PRId64 "\n", now);
}
-nsecs_t DispSync::expectedPresentTime() {
+nsecs_t DispSync::expectedPresentTime(nsecs_t now) {
// The HWC doesn't currently have a way to report additional latency.
// Assume that whatever we submit now will appear right after the flip.
// For a smart panel this might be 1. This is expressed in frames,
@@ -846,7 +866,7 @@
const uint32_t hwcLatency = 0;
// Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
- return computeNextRefresh(hwcLatency);
+ return mThread->computeNextRefresh(hwcLatency, now);
}
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index 2d9afc9..832f08e 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -36,7 +36,7 @@
public:
Callback() = default;
virtual ~Callback();
- virtual void onDispSyncEvent(nsecs_t when) = 0;
+ virtual void onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) = 0;
protected:
Callback(Callback const&) = delete;
@@ -58,9 +58,9 @@
nsecs_t lastCallbackTime) = 0;
virtual status_t removeEventListener(Callback* callback, nsecs_t* outLastCallback) = 0;
virtual status_t changePhaseOffset(Callback* callback, nsecs_t phase) = 0;
- virtual nsecs_t computeNextRefresh(int periodOffset) const = 0;
+ virtual nsecs_t computeNextRefresh(int periodOffset, nsecs_t now) const = 0;
virtual void setIgnorePresentFences(bool ignore) = 0;
- virtual nsecs_t expectedPresentTime() = 0;
+ virtual nsecs_t expectedPresentTime(nsecs_t now) = 0;
virtual void dump(std::string& result) const = 0;
@@ -167,7 +167,7 @@
// The periodOffset value can be used to move forward or backward; an
// offset of zero is the next refresh, -1 is the previous refresh, 1 is
// the refresh after next. etc.
- nsecs_t computeNextRefresh(int periodOffset) const override;
+ nsecs_t computeNextRefresh(int periodOffset, nsecs_t now) const override;
// In certain situations the present fences aren't a good indicator of vsync
// time, e.g. when vr flinger is active, or simply aren't available,
@@ -178,7 +178,7 @@
void setIgnorePresentFences(bool ignore) override;
// Determine the expected present time when a buffer acquired now will be displayed.
- nsecs_t expectedPresentTime();
+ nsecs_t expectedPresentTime(nsecs_t now);
// dump appends human-readable debug info to the result string.
void dump(std::string& result) const override;
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 4e3f85f..8752b66 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -92,7 +92,7 @@
}
}
-void DispSyncSource::onDispSyncEvent(nsecs_t when) {
+void DispSyncSource::onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) {
VSyncSource::Callback* callback;
{
std::lock_guard lock(mCallbackMutex);
@@ -104,7 +104,7 @@
}
if (callback != nullptr) {
- callback->onVSyncEvent(when);
+ callback->onVSyncEvent(when, expectedVSyncTimestamp);
}
}
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index f278712..2aee3f6 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -40,7 +40,7 @@
private:
// The following method is the implementation of the DispSync::Callback.
- virtual void onDispSyncEvent(nsecs_t when);
+ void onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) override;
const char* const mName;
TracedOrdinal<int> mValue;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 8347650..cee36a1 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -79,8 +79,9 @@
event.hotplug.connected ? "connected" : "disconnected");
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
- ", count=%u}",
- event.header.displayId, event.vsync.count);
+ ", count=%u, expectedVSyncTimestamp=%" PRId64 "}",
+ event.header.displayId, event.vsync.count,
+ event.vsync.expectedVSyncTimestamp);
case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
return StringPrintf("ConfigChanged{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
", configId=%u}",
@@ -99,10 +100,11 @@
}
DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
- uint32_t count) {
+ uint32_t count, nsecs_t expectedVSyncTimestamp) {
DisplayEventReceiver::Event event;
event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
event.vsync.count = count;
+ event.vsync.expectedVSyncTimestamp = expectedVSyncTimestamp;
return event;
}
@@ -150,16 +152,9 @@
mEventThread->requestNextVsync(this);
}
-void EventThreadConnection::toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) {
- ATRACE_NAME("enableConfigEvents");
- mConfigChanged = configChangeFlag;
-
- // In principle it's possible for rapidly toggling config events to drop an
- // event here, but it's unlikely in practice.
- if (configChangeFlag == ISurfaceComposer::eConfigChangedDispatch) {
- mForcedConfigChangeDispatch = true;
- mEventThread->requestLatestConfig();
- }
+void EventThreadConnection::requestLatestConfig() {
+ ATRACE_NAME("requestLatestConfig");
+ mEventThread->requestLatestConfig(this);
}
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
@@ -274,8 +269,12 @@
}
}
-void EventThread::requestLatestConfig() {
+void EventThread::requestLatestConfig(const sp<EventThreadConnection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
+ if (connection->mForcedConfigChangeDispatch) {
+ return;
+ }
+ connection->mForcedConfigChangeDispatch = true;
auto pendingConfigChange =
std::find_if(std::begin(mPendingEvents), std::end(mPendingEvents),
[&](const DisplayEventReceiver::Event& event) {
@@ -312,11 +311,12 @@
mCondition.notify_all();
}
-void EventThread::onVSyncEvent(nsecs_t timestamp) {
+void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp) {
std::lock_guard<std::mutex> lock(mMutex);
LOG_FATAL_IF(!mVSyncState);
- mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count));
+ mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
+ expectedVSyncTimestamp));
mCondition.notify_all();
}
@@ -381,6 +381,10 @@
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
if (event && shouldConsumeEvent(*event, connection)) {
+ if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
+ connection->mForcedConfigChangeDispatch) {
+ connection->mForcedConfigChangeDispatch = false;
+ }
consumers.push_back(connection);
}
@@ -423,7 +427,8 @@
} else {
// Generate a fake VSYNC after a long timeout in case the driver stalls. When the
// display is off, keep feeding clients at 60 Hz.
- const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
+ const std::chrono::nanoseconds timeout =
+ mState == State::SyntheticVSync ? 16ms : 1000ms;
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
if (mState == State::VSync) {
ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
@@ -439,9 +444,10 @@
}
LOG_FATAL_IF(!mVSyncState);
- mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
- systemTime(SYSTEM_TIME_MONOTONIC),
- ++mVSyncState->count));
+ const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
+ const auto expectedVSyncTime = now + timeout.count();
+ mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
+ ++mVSyncState->count, expectedVSyncTime));
}
}
}
@@ -454,8 +460,8 @@
return true;
case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: {
- const bool forcedDispatch = connection->mForcedConfigChangeDispatch.exchange(false);
- return forcedDispatch ||
+ const bool oneTimeDispatch = connection->mForcedConfigChangeDispatch;
+ return oneTimeDispatch ||
connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch;
}
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 98b1876..64acbd7 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -57,7 +57,7 @@
class Callback {
public:
virtual ~Callback() {}
- virtual void onVSyncEvent(nsecs_t when) = 0;
+ virtual void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) = 0;
};
virtual ~VSyncSource() {}
@@ -81,19 +81,19 @@
status_t stealReceiveChannel(gui::BitTube* outChannel) override;
status_t setVsyncRate(uint32_t rate) override;
void requestNextVsync() override; // asynchronous
- void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag) override;
+ void requestLatestConfig() override; // asynchronous
// Called in response to requestNextVsync.
const ResyncCallback resyncCallback;
VSyncRequest vsyncRequest = VSyncRequest::None;
- std::atomic<ISurfaceComposer::ConfigChanged> mConfigChanged =
+ ISurfaceComposer::ConfigChanged mConfigChanged =
ISurfaceComposer::ConfigChanged::eConfigChangedSuppress;
// Store whether we need to force dispatching a config change separately -
// if mConfigChanged ever changes before the config change is dispatched
// then we still need to propagate an initial config to the app if we
// haven't already.
- std::atomic<bool> mForcedConfigChangeDispatch = false;
+ bool mForcedConfigChangeDispatch = false;
private:
virtual void onFirstRef();
@@ -129,11 +129,10 @@
virtual void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) = 0;
// Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0;
-
// Dispatches the most recent configuration
// Usage of this method assumes that only the primary internal display
// supports multiple display configurations.
- virtual void requestLatestConfig() = 0;
+ virtual void requestLatestConfig(const sp<EventThreadConnection>& connection) = 0;
// Retrieves the number of event connections tracked by this EventThread.
virtual size_t getEventThreadConnectionCount() = 0;
@@ -154,7 +153,7 @@
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
void requestNextVsync(const sp<EventThreadConnection>& connection) override;
- void requestLatestConfig() override;
+ void requestLatestConfig(const sp<EventThreadConnection>& connection) override;
// called before the screen is turned off from main thread
void onScreenReleased() override;
@@ -189,7 +188,7 @@
REQUIRES(mMutex);
// Implements VSyncSource::Callback
- void onVSyncEvent(nsecs_t timestamp) override;
+ void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp) override;
const std::unique_ptr<VSyncSource> mVSyncSource GUARDED_BY(mMutex);
diff --git a/services/surfaceflinger/Scheduler/HwcStrongTypes.h b/services/surfaceflinger/Scheduler/HwcStrongTypes.h
index cfbbdfe..8ba4f20 100644
--- a/services/surfaceflinger/Scheduler/HwcStrongTypes.h
+++ b/services/surfaceflinger/Scheduler/HwcStrongTypes.h
@@ -22,6 +22,5 @@
// Strong types for the different indexes as they are referring to a different base.
using HwcConfigIndexType = StrongTyping<int, struct HwcConfigIndexTypeTag, Compare, Add, Hash>;
-using HwcConfigGroupType = StrongTyping<int, struct HwcConfigGroupTypeTag, Compare>;
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/InjectVSyncSource.h b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
index 31da588..975c9db 100644
--- a/services/surfaceflinger/Scheduler/InjectVSyncSource.h
+++ b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
@@ -35,10 +35,10 @@
mCallback = callback;
}
- void onInjectSyncEvent(nsecs_t when) {
+ void onInjectSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) {
std::lock_guard<std::mutex> lock(mCallbackMutex);
if (mCallback) {
- mCallback->onVSyncEvent(when);
+ mCallback->onVSyncEvent(when, expectedVSyncTimestamp);
}
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index 8b08592..e6c5cc9 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -40,9 +40,11 @@
namespace {
bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) {
+ // Layers with an explicit vote are always kept active
if (layer.getFrameRateForLayerTree().rate > 0) {
- return layer.isVisible();
+ return true;
}
+
return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
}
@@ -127,29 +129,24 @@
// an additional parameter.
ALOGV("Layer has priority: %d", strong->getFrameRateSelectionPriority());
- const bool recent = info->isRecentlyActive(now);
- if (recent) {
- const auto [type, refreshRate] = info->getRefreshRate(now);
- // Skip NoVote layer as those don't have any requirements
- if (type == LayerHistory::LayerVoteType::NoVote) {
- continue;
- }
+ const auto [type, refreshRate] = info->getRefreshRate(now);
+ // Skip NoVote layer as those don't have any requirements
+ if (type == LayerHistory::LayerVoteType::NoVote) {
+ continue;
+ }
- // Compute the layer's position on the screen
- const Rect bounds = Rect(strong->getBounds());
- const ui::Transform transform = strong->getTransform();
- constexpr bool roundOutwards = true;
- Rect transformed = transform.transform(bounds, roundOutwards);
+ // Compute the layer's position on the screen
+ const Rect bounds = Rect(strong->getBounds());
+ const ui::Transform transform = strong->getTransform();
+ constexpr bool roundOutwards = true;
+ Rect transformed = transform.transform(bounds, roundOutwards);
- const float layerArea = transformed.getWidth() * transformed.getHeight();
- float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
- summary.push_back({strong->getName(), type, refreshRate, weight});
+ const float layerArea = transformed.getWidth() * transformed.getHeight();
+ float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
+ summary.push_back({strong->getName(), type, refreshRate, weight});
- if (CC_UNLIKELY(mTraceEnabled)) {
- trace(layer, type, static_cast<int>(std::round(refreshRate)));
- }
- } else if (CC_UNLIKELY(mTraceEnabled)) {
- trace(layer, LayerHistory::LayerVoteType::NoVote, 0);
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ trace(layer, type, static_cast<int>(std::round(refreshRate)));
}
}
@@ -177,8 +174,10 @@
return LayerVoteType::NoVote;
}
}();
+
if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
- info->setLayerVote(voteType, frameRate.rate);
+ const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote;
+ info->setLayerVote(type, frameRate.rate);
} else {
info->resetLayerVote();
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index b4365bf..b7d0bdd 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -45,15 +45,6 @@
}
}
-// Returns whether the earliest present time is within the active threshold.
-bool LayerInfoV2::isRecentlyActive(nsecs_t now) const {
- if (mFrameTimes.empty()) {
- return false;
- }
-
- return mFrameTimes.back().queueTime >= getActiveLayerThreshold(now);
-}
-
bool LayerInfoV2::isFrameTimeValid(const FrameTimeData& frameTime) const {
return frameTime.queueTime >= std::chrono::duration_cast<std::chrono::nanoseconds>(
mFrameTimeValidSince.time_since_epoch())
@@ -120,23 +111,46 @@
// Calculate the refresh rate by finding the average delta between frames
nsecs_t totalPresentTimeDeltas = 0;
+ nsecs_t totalQueueTimeDeltas = 0;
+ auto missingPresentTime = false;
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
- // If there are no presentation timestamp provided we can't calculate the refresh rate
+ totalQueueTimeDeltas +=
+ std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
+
if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
- return std::nullopt;
+ missingPresentTime = true;
+ continue;
}
totalPresentTimeDeltas +=
std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
}
+
+ // If there are no presentation timestamps provided we can't calculate the refresh rate
+ if (missingPresentTime && mLastReportedRefreshRate == 0) {
+ return std::nullopt;
+ }
+
+ // Calculate the average frame time based on presentation timestamps. If those
+ // doesn't exist, we look at the time the buffer was queued only. We can do that only if
+ // we calculated a refresh rate based on presentation timestamps in the past. The reason
+ // we look at the queue time is to handle cases where hwui attaches presentation timestamps
+ // when implementing render ahead for specific refresh rates. When hwui no longer provides
+ // presentation timestamps we look at the queue time to see if the current refresh rate still
+ // matches the content.
const float averageFrameTime =
- static_cast<float>(totalPresentTimeDeltas) / (mFrameTimes.size() - 1);
+ static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
+ (mFrameTimes.size() - 1);
// Now once we calculated the refresh rate we need to make sure that all the frames we captured
// are evenly distributed and we don't calculate the average across some burst of frames.
for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
- const nsecs_t presentTimeDeltas =
- std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
+ const auto presentTimeDeltas = [&] {
+ const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
+ : (it + 1)->presetTime - it->presetTime;
+ return std::max(delta, mHighRefreshRatePeriod);
+ }();
+
if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
return std::nullopt;
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h
index 25fb95a..e36b7f7 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.h
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h
@@ -64,8 +64,6 @@
// updated time, the updated time is the present time.
void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now);
- bool isRecentlyActive(nsecs_t now) const;
-
// Sets an explicit layer vote. This usually comes directly from the application via
// ANativeWindow_setFrameRate API
void setLayerVote(LayerHistory::LayerVoteType type, float fps) { mLayerVote = {type, fps}; }
@@ -90,6 +88,7 @@
// buffer as Max as we don't know anything about this layer or Min as this layer is
// posting infrequent updates.
mFrameTimeValidSince = std::chrono::steady_clock::now();
+ mLastReportedRefreshRate = 0.0f;
}
private:
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 005d157..6067e69 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -18,10 +18,6 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-#include <errno.h>
-#include <stdint.h>
-#include <sys/types.h>
-
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
@@ -35,26 +31,7 @@
#include "MessageQueue.h"
#include "SurfaceFlinger.h"
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-MessageBase::MessageBase() : MessageHandler() {}
-
-MessageBase::~MessageBase() {}
-
-void MessageBase::handleMessage(const Message&) {
- this->handler();
- barrier.open();
-};
-
-// ---------------------------------------------------------------------------
-
-MessageQueue::~MessageQueue() = default;
-
-// ---------------------------------------------------------------------------
-
-namespace impl {
+namespace android::impl {
void MessageQueue::Handler::dispatchRefresh() {
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
@@ -62,8 +39,9 @@
}
}
-void MessageQueue::Handler::dispatchInvalidate() {
+void MessageQueue::Handler::dispatchInvalidate(nsecs_t expectedVSyncTimestamp) {
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
+ mExpectedVSyncTime = expectedVSyncTimestamp;
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}
}
@@ -72,11 +50,11 @@
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
- mQueue.mFlinger->onMessageReceived(message.what);
+ mQueue.mFlinger->onMessageReceived(message.what, mExpectedVSyncTime);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
- mQueue.mFlinger->onMessageReceived(message.what);
+ mQueue.mFlinger->onMessageReceived(message.what, mExpectedVSyncTime);
break;
}
}
@@ -122,14 +100,8 @@
} while (true);
}
-status_t MessageQueue::postMessage(const sp<MessageBase>& messageHandler, nsecs_t relTime) {
- const Message dummyMessage;
- if (relTime > 0) {
- mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
- } else {
- mLooper->sendMessage(messageHandler, dummyMessage);
- }
- return NO_ERROR;
+void MessageQueue::postMessage(sp<MessageHandler>&& handler) {
+ mLooper->sendMessage(handler, Message());
}
void MessageQueue::invalidate() {
@@ -151,7 +123,7 @@
while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- mHandler->dispatchInvalidate();
+ mHandler->dispatchInvalidate(buffer[i].vsync.expectedVSyncTimestamp);
break;
}
}
@@ -159,10 +131,7 @@
return 1;
}
-// ---------------------------------------------------------------------------
-
-} // namespace impl
-} // namespace android
+} // namespace android::impl
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index fcfc4aa..132b416 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#ifndef ANDROID_MESSAGE_QUEUE_H
-#define ANDROID_MESSAGE_QUEUE_H
+#pragma once
-#include <errno.h>
-#include <stdint.h>
-#include <sys/types.h>
+#include <cstdint>
+#include <future>
+#include <type_traits>
+#include <utility>
#include <utils/Looper.h>
#include <utils/Timers.h>
@@ -28,52 +28,30 @@
#include <gui/IDisplayEventConnection.h>
#include <private/gui/BitTube.h>
-#include "Barrier.h"
#include "EventThread.h"
-#include <functional>
-
namespace android {
class SurfaceFlinger;
-// ---------------------------------------------------------------------------
+template <typename F>
+class Task : public MessageHandler {
+ template <typename G>
+ friend auto makeTask(G&&);
-class MessageBase : public MessageHandler {
-public:
- MessageBase();
+ explicit Task(F&& f) : mTask(std::move(f)) {}
- // return true if message has a handler
- virtual bool handler() = 0;
+ void handleMessage(const Message&) override { mTask(); }
- // waits for the handler to be processed
- void wait() const { barrier.wait(); }
-
-protected:
- virtual ~MessageBase();
-
-private:
- virtual void handleMessage(const Message& message);
-
- mutable Barrier barrier;
+ using T = std::invoke_result_t<F>;
+ std::packaged_task<T()> mTask;
};
-class LambdaMessage : public MessageBase {
-public:
- explicit LambdaMessage(std::function<void()> handler)
- : MessageBase(), mHandler(std::move(handler)) {}
-
- bool handler() override {
- mHandler();
- // This return value is no longer checked, so it's always safe to return true
- return true;
- }
-
-private:
- const std::function<void()> mHandler;
-};
-
-// ---------------------------------------------------------------------------
+template <typename F>
+inline auto makeTask(F&& f) {
+ sp<Task<F>> task = new Task<F>(std::move(f));
+ return std::make_pair(task, task->mTask.get_future());
+}
class MessageQueue {
public:
@@ -82,12 +60,12 @@
REFRESH = 1,
};
- virtual ~MessageQueue();
+ virtual ~MessageQueue() = default;
virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
virtual void setEventConnection(const sp<EventThreadConnection>& connection) = 0;
virtual void waitMessage() = 0;
- virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
+ virtual void postMessage(sp<MessageHandler>&&) = 0;
virtual void invalidate() = 0;
virtual void refresh() = 0;
};
@@ -101,12 +79,13 @@
enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
MessageQueue& mQueue;
int32_t mEventMask;
+ std::atomic<nsecs_t> mExpectedVSyncTime;
public:
explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {}
virtual void handleMessage(const Message& message);
void dispatchRefresh();
- void dispatchInvalidate();
+ void dispatchInvalidate(nsecs_t expectedVSyncTimestamp);
};
friend class Handler;
@@ -126,7 +105,7 @@
void setEventConnection(const sp<EventThreadConnection>& connection) override;
void waitMessage() override;
- status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) override;
+ void postMessage(sp<MessageHandler>&&) override;
// sends INVALIDATE message at next VSYNC
void invalidate() override;
@@ -135,9 +114,5 @@
void refresh() override;
};
-// ---------------------------------------------------------------------------
-
} // namespace impl
} // namespace android
-
-#endif /* ANDROID_MESSAGE_QUEUE_H */
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 43883fb..fe2e406 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -43,7 +43,7 @@
refreshRates.reserve(allRefreshRates.size());
for (const auto& [ignored, refreshRate] : allRefreshRates) {
- refreshRates.emplace_back(refreshRate->fps);
+ refreshRates.emplace_back(refreshRate->getFps());
}
return refreshRates;
@@ -59,7 +59,13 @@
PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs)
: PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs),
- refreshRateConfigs.getCurrentRefreshRate().fps,
+ refreshRateConfigs.getCurrentRefreshRate().getFps(),
+ sysprop::vsync_event_phase_offset_ns(1000000),
+ sysprop::vsync_sf_event_phase_offset_ns(1000000),
+ getProperty("debug.sf.early_phase_offset_ns"),
+ getProperty("debug.sf.early_gl_phase_offset_ns"),
+ getProperty("debug.sf.early_app_phase_offset_ns"),
+ getProperty("debug.sf.early_gl_app_phase_offset_ns"),
// Below defines the threshold when an offset is considered to be negative,
// i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset
// < threshold, SF wake up (vsync_duration - offset) before HW vsync. For
@@ -69,8 +75,18 @@
.value_or(std::numeric_limits<nsecs_t>::max())) {}
PhaseOffsets::PhaseOffsets(const std::vector<float>& refreshRates, float currentFps,
- nsecs_t thresholdForNextVsync)
- : mThresholdForNextVsync(thresholdForNextVsync),
+ nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
+ std::optional<nsecs_t> earlySfOffsetNs,
+ std::optional<nsecs_t> earlyGlSfOffsetNs,
+ std::optional<nsecs_t> earlyAppOffsetNs,
+ std::optional<nsecs_t> earlyGlAppOffsetNs, nsecs_t thresholdForNextVsync)
+ : mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs),
+ mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs),
+ mEarlySfOffsetNs(earlySfOffsetNs),
+ mEarlyGlSfOffsetNs(earlyGlSfOffsetNs),
+ mEarlyAppOffsetNs(earlyAppOffsetNs),
+ mEarlyGlAppOffsetNs(earlyGlAppOffsetNs),
+ mThresholdForNextVsync(thresholdForNextVsync),
mOffsets(initializeOffsets(refreshRates)),
mRefreshRateFps(currentFps) {}
@@ -106,35 +122,27 @@
}
PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t vsyncDuration) const {
- const int64_t vsyncPhaseOffsetNs = sysprop::vsync_event_phase_offset_ns(1000000);
- const int64_t sfVsyncPhaseOffsetNs = sysprop::vsync_sf_event_phase_offset_ns(1000000);
-
- const auto earlySfOffsetNs = getProperty("debug.sf.early_phase_offset_ns");
- const auto earlyGlSfOffsetNs = getProperty("debug.sf.early_gl_phase_offset_ns");
- const auto earlyAppOffsetNs = getProperty("debug.sf.early_app_phase_offset_ns");
- const auto earlyGlAppOffsetNs = getProperty("debug.sf.early_gl_app_phase_offset_ns");
-
return {
{
- earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs) < mThresholdForNextVsync
- ? earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs)
- : earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs) - vsyncDuration,
+ mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
+ ? mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs)
+ : mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration,
- earlyAppOffsetNs.value_or(vsyncPhaseOffsetNs),
+ mEarlyAppOffsetNs.value_or(mVSyncPhaseOffsetNs),
},
{
- earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs) < mThresholdForNextVsync
- ? earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs)
- : earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs) - vsyncDuration,
+ mEarlyGlSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
+ ? mEarlyGlSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs)
+ : mEarlyGlSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration,
- earlyGlAppOffsetNs.value_or(vsyncPhaseOffsetNs),
+ mEarlyGlAppOffsetNs.value_or(mVSyncPhaseOffsetNs),
},
{
- sfVsyncPhaseOffsetNs < mThresholdForNextVsync
- ? sfVsyncPhaseOffsetNs
- : sfVsyncPhaseOffsetNs - vsyncDuration,
+ mSfVSyncPhaseOffsetNs < mThresholdForNextVsync
+ ? mSfVSyncPhaseOffsetNs
+ : mSfVSyncPhaseOffsetNs - vsyncDuration,
- vsyncPhaseOffsetNs,
+ mVSyncPhaseOffsetNs,
},
};
}
@@ -275,7 +283,7 @@
PhaseDurations::PhaseDurations(const scheduler::RefreshRateConfigs& refreshRateConfigs)
: PhaseDurations(getRefreshRatesFromConfigs(refreshRateConfigs),
- refreshRateConfigs.getCurrentRefreshRate().fps,
+ refreshRateConfigs.getCurrentRefreshRate().getFps(),
getProperty("debug.sf.late.sf.duration").value_or(-1),
getProperty("debug.sf.late.app.duration").value_or(-1),
getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index fa8011d..9ec6d56 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -69,6 +69,9 @@
protected:
// Used for unit tests
PhaseOffsets(const std::vector<float>& refreshRates, float currentFps,
+ nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
+ std::optional<nsecs_t> earlySfOffsetNs, std::optional<nsecs_t> earlyGlSfOffsetNs,
+ std::optional<nsecs_t> earlyAppOffsetNs, std::optional<nsecs_t> earlyGlAppOffsetNs,
nsecs_t thresholdForNextVsync);
std::unordered_map<float, Offsets> initializeOffsets(
const std::vector<float>& refreshRates) const;
@@ -76,6 +79,12 @@
Offsets getHighFpsOffsets(nsecs_t vsyncPeriod) const;
Offsets getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const;
+ const nsecs_t mVSyncPhaseOffsetNs;
+ const nsecs_t mSfVSyncPhaseOffsetNs;
+ const std::optional<nsecs_t> mEarlySfOffsetNs;
+ const std::optional<nsecs_t> mEarlyGlSfOffsetNs;
+ const std::optional<nsecs_t> mEarlyAppOffsetNs;
+ const std::optional<nsecs_t> mEarlyGlAppOffsetNs;
const nsecs_t mThresholdForNextVsync;
const std::unordered_map<float, Offsets> mOffsets;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 14ef733..8d958df 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -53,12 +53,12 @@
if (explicitContentFramerate != 0) {
contentFramerate = explicitContentFramerate;
} else if (contentFramerate == 0) {
- contentFramerate = round<int>(mMaxSupportedRefreshRate->fps);
+ contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps());
}
ATRACE_INT("ContentFPS", contentFramerate);
// Find the appropriate refresh rate with minimal error
- auto iter = min_element(mAvailableRefreshRates.cbegin(), mAvailableRefreshRates.cend(),
+ auto iter = min_element(mPrimaryRefreshRates.cbegin(), mPrimaryRefreshRates.cend(),
[contentFramerate](const auto& lhs, const auto& rhs) -> bool {
return std::abs(lhs->fps - contentFramerate) <
std::abs(rhs->fps - contentFramerate);
@@ -71,7 +71,7 @@
constexpr float MARGIN = 0.05f;
float ratio = (*iter)->fps / contentFramerate;
if (std::abs(std::round(ratio) - ratio) > MARGIN) {
- while (iter != mAvailableRefreshRates.cend()) {
+ while (iter != mPrimaryRefreshRates.cend()) {
ratio = (*iter)->fps / contentFramerate;
if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
@@ -97,8 +97,8 @@
return {displayFramesQuot, displayFramesRem};
}
-const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2(
- const std::vector<LayerRequirement>& layers, bool touchActive,
+const RefreshRate& RefreshRateConfigs::getBestRefreshRate(
+ const std::vector<LayerRequirement>& layers, bool touchActive, bool idle,
bool* touchConsidered) const {
ATRACE_CALL();
ALOGV("getRefreshRateForContent %zu layers", layers.size());
@@ -106,13 +106,6 @@
*touchConsidered = false;
std::lock_guard lock(mLock);
- // If there are not layers, there is not content detection, so return the current
- // refresh rate.
- if (layers.empty()) {
- *touchConsidered = touchActive;
- return touchActive ? *mAvailableRefreshRates.back() : getCurrentRefreshRateByPolicyLocked();
- }
-
int noVoteLayers = 0;
int minVoteLayers = 0;
int maxVoteLayers = 0;
@@ -135,25 +128,33 @@
}
}
- // Consider the touch event if there are no ExplicitDefault layers.
- // ExplicitDefault are mostly interactive (as opposed to ExplicitExactOrMultiple)
- // and therefore if those posted an explicit vote we should not change it
- // if get get a touch event.
- if (touchActive && explicitDefaultVoteLayers == 0) {
+ // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
+ // selected a refresh rate to see if we should apply touch boost.
+ if (touchActive && explicitDefaultVoteLayers == 0 && explicitExactOrMultipleVoteLayers == 0) {
*touchConsidered = true;
- return *mAvailableRefreshRates.back();
+ return getMaxRefreshRateByPolicyLocked();
+ }
+
+ if (!touchActive && idle) {
+ return getMinRefreshRateByPolicyLocked();
+ }
+
+ if (layers.empty()) {
+ return getCurrentRefreshRateByPolicyLocked();
}
// Only if all layers want Min we should return Min
if (noVoteLayers + minVoteLayers == layers.size()) {
- return *mAvailableRefreshRates.front();
+ return getMinRefreshRateByPolicyLocked();
}
+ const Policy* policy = getCurrentPolicyLocked();
+
// Find the best refresh rate based on score
std::vector<std::pair<const RefreshRate*, float>> scores;
- scores.reserve(mAvailableRefreshRates.size());
+ scores.reserve(mAppRequestRefreshRates.size());
- for (const auto refreshRate : mAvailableRefreshRates) {
+ for (const auto refreshRate : mAppRequestRefreshRates) {
scores.emplace_back(refreshRate, 0.0f);
}
@@ -166,6 +167,15 @@
auto weight = layer.weight;
for (auto i = 0u; i < scores.size(); i++) {
+ bool inPrimaryRange =
+ scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max);
+ if (!inPrimaryRange && layer.vote != LayerVoteType::ExplicitDefault &&
+ layer.vote != LayerVoteType::ExplicitExactOrMultiple) {
+ // Only layers with explicit frame rate settings are allowed to score refresh rates
+ // outside the primary range.
+ continue;
+ }
+
// If the layer wants Max, give higher score to the higher refresh rate
if (layer.vote == LayerVoteType::Max) {
const auto ratio = scores[i].first->fps / scores.back().first->fps;
@@ -177,7 +187,7 @@
continue;
}
- const auto displayPeriod = scores[i].first->vsyncPeriod;
+ const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod();
const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate);
if (layer.vote == LayerVoteType::ExplicitDefault) {
const auto layerScore = [&]() {
@@ -249,6 +259,17 @@
? getBestRefreshRate(scores.rbegin(), scores.rend())
: getBestRefreshRate(scores.begin(), scores.end());
+ // Consider the touch event if there are no ExplicitDefault layers. ExplicitDefault are mostly
+ // interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
+ // vote we should not change it if we get a touch event. Only apply touch boost if it will
+ // actually increase the refresh rate over the normal selection.
+ const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
+ if (touchActive && explicitDefaultVoteLayers == 0 &&
+ bestRefreshRate->fps < touchRefreshRate.fps) {
+ *touchConsidered = true;
+ return touchRefreshRate;
+ }
+
return *bestRefreshRate;
}
@@ -278,12 +299,20 @@
const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
- return *mAvailableRefreshRates.front();
+ return getMinRefreshRateByPolicyLocked();
+}
+
+const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
+ return *mPrimaryRefreshRates.front();
}
const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
- return *mAvailableRefreshRates.back();
+ return getMaxRefreshRateByPolicyLocked();
+}
+
+const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
+ return *mPrimaryRefreshRates.back();
}
const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const {
@@ -297,8 +326,8 @@
}
const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() const {
- if (std::find(mAvailableRefreshRates.begin(), mAvailableRefreshRates.end(),
- mCurrentRefreshRate) != mAvailableRefreshRates.end()) {
+ if (std::find(mAppRequestRefreshRates.begin(), mAppRequestRefreshRates.end(),
+ mCurrentRefreshRate) != mAppRequestRefreshRates.end()) {
return *mCurrentRefreshRate;
}
return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig);
@@ -309,21 +338,30 @@
mCurrentRefreshRate = mRefreshRates.at(configId).get();
}
-RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs,
- HwcConfigIndexType currentHwcConfig) {
- init(configs, currentHwcConfig);
-}
-
RefreshRateConfigs::RefreshRateConfigs(
const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
HwcConfigIndexType currentConfigId) {
- std::vector<InputConfig> inputConfigs;
- for (size_t configId = 0; configId < configs.size(); ++configId) {
- auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup());
- inputConfigs.push_back({HwcConfigIndexType(static_cast<int>(configId)), configGroup,
- configs[configId]->getVsyncPeriod()});
+ LOG_ALWAYS_FATAL_IF(configs.empty());
+ LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());
+
+ for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) {
+ const auto& config = configs.at(static_cast<size_t>(configId.value()));
+ const float fps = 1e9f / config->getVsyncPeriod();
+ mRefreshRates.emplace(configId,
+ std::make_unique<RefreshRate>(configId, config,
+ base::StringPrintf("%.0ffps", fps), fps,
+ RefreshRate::ConstructorTag(0)));
+ if (configId == currentConfigId) {
+ mCurrentRefreshRate = mRefreshRates.at(configId).get();
+ }
}
- init(inputConfigs, currentConfigId);
+
+ std::vector<const RefreshRate*> sortedConfigs;
+ getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
+ mDisplayManagerPolicy.defaultConfig = currentConfigId;
+ mMinSupportedRefreshRate = sortedConfigs.front();
+ mMaxSupportedRefreshRate = sortedConfigs.back();
+ constructAvailableRefreshRates();
}
bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
@@ -333,10 +371,11 @@
return false;
}
const RefreshRate& refreshRate = *iter->second;
- if (!refreshRate.inPolicy(policy.minRefreshRate, policy.maxRefreshRate)) {
+ if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) {
return false;
}
- return true;
+ return policy.appRequestRange.min <= policy.primaryRange.min &&
+ policy.appRequestRange.max >= policy.primaryRange.max;
}
status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
@@ -383,7 +422,7 @@
bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
std::lock_guard lock(mLock);
- for (const RefreshRate* refreshRate : mAvailableRefreshRates) {
+ for (const RefreshRate* refreshRate : mAppRequestRefreshRates) {
if (refreshRate->configId == config) {
return true;
}
@@ -406,10 +445,13 @@
std::sort(outRefreshRates->begin(), outRefreshRates->end(),
[](const auto refreshRate1, const auto refreshRate2) {
- if (refreshRate1->vsyncPeriod != refreshRate2->vsyncPeriod) {
- return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
+ if (refreshRate1->hwcConfig->getVsyncPeriod() !=
+ refreshRate2->hwcConfig->getVsyncPeriod()) {
+ return refreshRate1->hwcConfig->getVsyncPeriod() >
+ refreshRate2->hwcConfig->getVsyncPeriod();
} else {
- return refreshRate1->configGroup > refreshRate2->configGroup;
+ return refreshRate1->hwcConfig->getConfigGroup() >
+ refreshRate2->hwcConfig->getConfigGroup();
}
});
}
@@ -417,53 +459,45 @@
void RefreshRateConfigs::constructAvailableRefreshRates() {
// Filter configs based on current policy and sort based on vsync period
const Policy* policy = getCurrentPolicyLocked();
- HwcConfigGroupType group = mRefreshRates.at(policy->defaultConfig)->configGroup;
- ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
- policy->defaultConfig.value(), group.value(), policy->minRefreshRate,
- policy->maxRefreshRate);
- getSortedRefreshRateList(
- [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
- return (policy->allowGroupSwitching || refreshRate.configGroup == group) &&
- refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate);
- },
- &mAvailableRefreshRates);
+ const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig;
+ ALOGV("constructAvailableRefreshRates: default %d group %d primaryRange=[%.2f %.2f]"
+ " appRequestRange=[%.2f %.2f]",
+ policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->primaryRange.min,
+ policy->primaryRange.max, policy->appRequestRange.min, policy->appRequestRange.max);
- std::string availableRefreshRates;
- for (const auto& refreshRate : mAvailableRefreshRates) {
- base::StringAppendF(&availableRefreshRates, "%s ", refreshRate->name.c_str());
- }
+ auto filterRefreshRates = [&](float min, float max, const char* listName,
+ std::vector<const RefreshRate*>* outRefreshRates) {
+ getSortedRefreshRateList(
+ [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
+ const auto& hwcConfig = refreshRate.hwcConfig;
- ALOGV("Available refresh rates: %s", availableRefreshRates.c_str());
- LOG_ALWAYS_FATAL_IF(mAvailableRefreshRates.empty(),
- "No compatible display configs for default=%d min=%.0f max=%.0f",
- policy->defaultConfig.value(), policy->minRefreshRate,
- policy->maxRefreshRate);
-}
+ return hwcConfig->getHeight() == defaultConfig->getHeight() &&
+ hwcConfig->getWidth() == defaultConfig->getWidth() &&
+ hwcConfig->getDpiX() == defaultConfig->getDpiX() &&
+ hwcConfig->getDpiY() == defaultConfig->getDpiY() &&
+ (policy->allowGroupSwitching ||
+ hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) &&
+ refreshRate.inPolicy(min, max);
+ },
+ outRefreshRates);
-// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor
-void RefreshRateConfigs::init(const std::vector<InputConfig>& configs,
- HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS {
- LOG_ALWAYS_FATAL_IF(configs.empty());
- LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size());
+ LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(),
+ "No matching configs for %s range: min=%.0f max=%.0f", listName, min,
+ max);
+ auto stringifyRefreshRates = [&]() -> std::string {
+ std::string str;
+ for (auto refreshRate : *outRefreshRates) {
+ base::StringAppendF(&str, "%s ", refreshRate->name.c_str());
+ }
+ return str;
+ };
+ ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str());
+ };
- for (const auto& config : configs) {
- const float fps = 1e9f / config.vsyncPeriod;
- mRefreshRates.emplace(config.configId,
- std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod,
- config.configGroup,
- base::StringPrintf("%2.ffps", fps),
- fps));
- if (config.configId == currentHwcConfig) {
- mCurrentRefreshRate = mRefreshRates.at(config.configId).get();
- }
- }
-
- std::vector<const RefreshRate*> sortedConfigs;
- getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
- mDisplayManagerPolicy.defaultConfig = currentHwcConfig;
- mMinSupportedRefreshRate = sortedConfigs.front();
- mMaxSupportedRefreshRate = sortedConfigs.back();
- constructAvailableRefreshRates();
+ filterRefreshRates(policy->primaryRange.min, policy->primaryRange.max, "primary",
+ &mPrimaryRefreshRates);
+ filterRefreshRates(policy->appRequestRange.min, policy->appRequestRange.max, "app request",
+ &mAppRequestRefreshRates);
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index e749f8f..2657dee 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -29,6 +29,8 @@
#include "Scheduler/StrongTyping.h"
namespace android::scheduler {
+class RefreshRateConfigsTest;
+
using namespace std::chrono_literals;
enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 };
@@ -49,30 +51,27 @@
static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
std::chrono::nanoseconds(800us).count();
- struct RefreshRate {
- // The tolerance within which we consider FPS approximately equals.
- static constexpr float FPS_EPSILON = 0.001f;
+ class RefreshRate {
+ private:
+ // Effectively making the constructor private while allowing
+ // std::make_unique to create the object
+ struct ConstructorTag {
+ explicit ConstructorTag(int) {}
+ };
- RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod,
- HwcConfigGroupType configGroup, std::string name, float fps)
- : configId(configId),
- vsyncPeriod(vsyncPeriod),
- configGroup(configGroup),
- name(std::move(name)),
- fps(fps) {}
+ public:
+ RefreshRate(HwcConfigIndexType configId,
+ std::shared_ptr<const HWC2::Display::Config> config, std::string name,
+ float fps, ConstructorTag)
+ : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {}
RefreshRate(const RefreshRate&) = delete;
- // This config ID corresponds to the position of the config in the vector that is stored
- // on the device.
- const HwcConfigIndexType configId;
- // Vsync period in nanoseconds.
- const nsecs_t vsyncPeriod;
- // This configGroup for the config.
- const HwcConfigGroupType configGroup;
- // Human readable name of the refresh rate.
- const std::string name;
- // Refresh rate in frames per second
- const float fps = 0;
+
+ HwcConfigIndexType getConfigId() const { return configId; }
+ nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); }
+ int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); }
+ const std::string& getName() const { return name; }
+ float getFps() const { return fps; }
// Checks whether the fps of this RefreshRate struct is within a given min and max refresh
// rate passed in. FPS_EPSILON is applied to the boundaries for approximation.
@@ -81,29 +80,73 @@
}
bool operator!=(const RefreshRate& other) const {
- return configId != other.configId || vsyncPeriod != other.vsyncPeriod ||
- configGroup != other.configGroup;
+ return configId != other.configId || hwcConfig != other.hwcConfig;
}
bool operator==(const RefreshRate& other) const { return !(*this != other); }
+
+ private:
+ friend RefreshRateConfigs;
+ friend RefreshRateConfigsTest;
+
+ // The tolerance within which we consider FPS approximately equals.
+ static constexpr float FPS_EPSILON = 0.001f;
+
+ // This config ID corresponds to the position of the config in the vector that is stored
+ // on the device.
+ const HwcConfigIndexType configId;
+ // The config itself
+ std::shared_ptr<const HWC2::Display::Config> hwcConfig;
+ // Human readable name of the refresh rate.
+ const std::string name;
+ // Refresh rate in frames per second
+ const float fps = 0;
};
using AllRefreshRatesMapType =
std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>;
struct Policy {
+ struct Range {
+ float min = 0;
+ float max = std::numeric_limits<float>::max();
+
+ bool operator==(const Range& other) const {
+ return min == other.min && max == other.max;
+ }
+
+ bool operator!=(const Range& other) const { return !(*this == other); }
+ };
+
// The default config, used to ensure we only initiate display config switches within the
// same config group as defaultConfigId's group.
HwcConfigIndexType defaultConfig;
- // The min and max FPS allowed by the policy.
- float minRefreshRate = 0;
- float maxRefreshRate = std::numeric_limits<float>::max();
+ // The primary refresh rate range represents display manager's general guidance on the
+ // display configs we'll consider when switching refresh rates. Unless we get an explicit
+ // signal from an app, we should stay within this range.
+ Range primaryRange;
+ // The app request refresh rate range allows us to consider more display configs when
+ // switching refresh rates. Although we should generally stay within the primary range,
+ // specific considerations, such as layer frame rate settings specified via the
+ // setFrameRate() api, may cause us to go outside the primary range. We never go outside the
+ // app request range. The app request range will be greater than or equal to the primary
+ // refresh rate range, never smaller.
+ Range appRequestRange;
// Whether or not we switch config groups to get the best frame rate. Only used by tests.
bool allowGroupSwitching = false;
+ Policy() = default;
+ Policy(HwcConfigIndexType defaultConfig, const Range& range)
+ : Policy(defaultConfig, range, range) {}
+ Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange,
+ const Range& appRequestRange)
+ : defaultConfig(defaultConfig),
+ primaryRange(primaryRange),
+ appRequestRange(appRequestRange) {}
+
bool operator==(const Policy& other) const {
- return defaultConfig == other.defaultConfig && minRefreshRate == other.minRefreshRate &&
- maxRefreshRate == other.maxRefreshRate &&
+ return defaultConfig == other.defaultConfig && primaryRange == other.primaryRange &&
+ appRequestRange == other.appRequestRange &&
allowGroupSwitching == other.allowGroupSwitching;
}
@@ -169,12 +212,14 @@
const RefreshRate& getRefreshRateForContent(const std::vector<LayerRequirement>& layers) const
EXCLUDES(mLock);
- // Returns the refresh rate that fits best to the given layers. This function also gets a
- // boolean flag that indicates whether user touched the screen recently to be factored in when
- // choosing the refresh rate and returns whether the refresh rate was chosen as a result of
- // a touch event.
- const RefreshRate& getRefreshRateForContentV2(const std::vector<LayerRequirement>& layers,
- bool touchActive, bool* touchConsidered) const
+ // Returns the refresh rate that fits best to the given layers.
+ // layers - The layer requirements to consider.
+ // touchActive - Whether the user touched the screen recently. Used to apply touch boost.
+ // idle - True if the system hasn't seen any buffers posted to layers recently.
+ // touchConsidered - An output param that tells the caller whether the refresh rate was chosen
+ // based on touch boost.
+ const RefreshRate& getBestRefreshRate(const std::vector<LayerRequirement>& layers,
+ bool touchActive, bool idle, bool* touchConsidered) const
EXCLUDES(mLock);
// Returns all the refresh rates supported by the device. This won't change at runtime.
@@ -183,13 +228,15 @@
// Returns the lowest refresh rate supported by the device. This won't change at runtime.
const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; }
- // Returns the lowest refresh rate according to the current policy. May change in runtime.
+ // Returns the lowest refresh rate according to the current policy. May change at runtime. Only
+ // uses the primary range, not the app request range.
const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock);
// Returns the highest refresh rate supported by the device. This won't change at runtime.
const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; }
- // Returns the highest refresh rate according to the current policy. May change in runtime.
+ // Returns the highest refresh rate according to the current policy. May change at runtime. Only
+ // uses the primary range, not the app request range.
const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock);
// Returns the current refresh rate
@@ -208,20 +255,10 @@
// Stores the current configId the device operates at
void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock);
- struct InputConfig {
- HwcConfigIndexType configId = HwcConfigIndexType(0);
- HwcConfigGroupType configGroup = HwcConfigGroupType(0);
- nsecs_t vsyncPeriod = 0;
- };
-
- RefreshRateConfigs(const std::vector<InputConfig>& configs,
- HwcConfigIndexType currentHwcConfig);
RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
HwcConfigIndexType currentConfigId);
private:
- void init(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig);
-
void constructAvailableRefreshRates() REQUIRES(mLock);
void getSortedRefreshRateList(
@@ -238,6 +275,14 @@
// display refresh period.
std::pair<nsecs_t, nsecs_t> getDisplayFrames(nsecs_t layerPeriod, nsecs_t displayPeriod) const;
+ // Returns the lowest refresh rate according to the current policy. May change at runtime. Only
+ // uses the primary range, not the app request range.
+ const RefreshRate& getMinRefreshRateByPolicyLocked() const REQUIRES(mLock);
+
+ // Returns the highest refresh rate according to the current policy. May change at runtime. Only
+ // uses the primary range, not the app request range.
+ const RefreshRate& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock);
+
// Returns the current refresh rate, if allowed. Otherwise the default that is allowed by
// the policy.
const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock);
@@ -249,9 +294,13 @@
// object is initialized.
AllRefreshRatesMapType mRefreshRates;
- // The list of refresh rates which are available in the current policy, ordered by vsyncPeriod
- // (the first element is the lowest refresh rate)
- std::vector<const RefreshRate*> mAvailableRefreshRates GUARDED_BY(mLock);
+ // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod
+ // (the first element is the lowest refresh rate).
+ std::vector<const RefreshRate*> mPrimaryRefreshRates GUARDED_BY(mLock);
+
+ // The list of refresh rates in the app request range of the current policy, ordered by
+ // vsyncPeriod (the first element is the lowest refresh rate).
+ std::vector<const RefreshRate*> mAppRequestRefreshRates GUARDED_BY(mLock);
// The current config. This will change at runtime. This is set by SurfaceFlinger on
// the main thread, and read by the Scheduler (and other objects) on other threads.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index e44cd52..d9e7b37 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -41,14 +41,15 @@
public:
RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats,
- HwcConfigIndexType currentConfigId, int currentPowerMode)
+ HwcConfigIndexType currentConfigId,
+ android::hardware::graphics::composer::hal::PowerMode currentPowerMode)
: mRefreshRateConfigs(refreshRateConfigs),
mTimeStats(timeStats),
mCurrentConfigMode(currentConfigId),
mCurrentPowerMode(currentPowerMode) {}
// Sets power mode.
- void setPowerMode(int mode) {
+ void setPowerMode(android::hardware::graphics::composer::hal::PowerMode mode) {
if (mCurrentPowerMode == mode) {
return;
}
@@ -78,10 +79,10 @@
// Multiple configs may map to the same name, e.g. "60fps". Add the
// times for such configs together.
for (const auto& [configId, time] : mConfigModesTotalTime) {
- totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] = 0;
+ totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] = 0;
}
for (const auto& [configId, time] : mConfigModesTotalTime) {
- totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] += time;
+ totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] += time;
}
totalTime["ScreenOff"] = mScreenOffTime;
return totalTime;
@@ -108,14 +109,14 @@
mPreviousRecordedTime = currentTime;
uint32_t fps = 0;
- if (mCurrentPowerMode == HWC_POWER_MODE_NORMAL) {
+ if (mCurrentPowerMode == android::hardware::graphics::composer::hal::PowerMode::ON) {
// Normal power mode is counted under different config modes.
if (mConfigModesTotalTime.find(mCurrentConfigMode) == mConfigModesTotalTime.end()) {
mConfigModesTotalTime[mCurrentConfigMode] = 0;
}
mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs;
fps = static_cast<uint32_t>(std::round(
- mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps));
+ mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).getFps()));
} else {
mScreenOffTime += timeElapsedMs;
}
@@ -140,7 +141,7 @@
TimeStats& mTimeStats;
HwcConfigIndexType mCurrentConfigMode;
- int32_t mCurrentPowerMode;
+ android::hardware::graphics::composer::hal::PowerMode mCurrentPowerMode;
std::unordered_map<HwcConfigIndexType /* configId */, int64_t /* duration in ms */>
mConfigModesTotalTime;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 6828d7a..f87c1f8 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -250,7 +250,7 @@
}
void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
- stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+ stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0, systemTime());
stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
}
@@ -276,12 +276,12 @@
return mInjectorConnectionHandle;
}
-bool Scheduler::injectVSync(nsecs_t when) {
+bool Scheduler::injectVSync(nsecs_t when, nsecs_t expectedVSyncTime) {
if (!mInjectVSyncs || !mVSyncInjector) {
return false;
}
- mVSyncInjector->onInjectSyncEvent(when);
+ mVSyncInjector->onInjectSyncEvent(when, expectedVSyncTime);
return true;
}
@@ -332,7 +332,7 @@
const nsecs_t last = mLastResyncTime.exchange(now);
if (now - last > kIgnoreDelay) {
- resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().vsyncPeriod);
+ resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod());
}
}
@@ -378,8 +378,8 @@
mPrimaryDispSync->setIgnorePresentFences(ignore);
}
-nsecs_t Scheduler::getDispSyncExpectedPresentTime() {
- return mPrimaryDispSync->expectedPresentTime();
+nsecs_t Scheduler::getDispSyncExpectedPresentTime(nsecs_t now) {
+ return mPrimaryDispSync->expectedPresentTime(now);
}
void Scheduler::registerLayer(Layer* layer) {
@@ -389,34 +389,34 @@
// keep the layer history, since we use it for other features (like Frame Rate API), so layers
// still need to be registered.
if (!mUseContentDetection) {
- mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps,
- mRefreshRateConfigs.getMaxRefreshRate().fps,
+ mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(),
+ mRefreshRateConfigs.getMaxRefreshRate().getFps(),
scheduler::LayerHistory::LayerVoteType::NoVote);
return;
}
// In V1 of content detection, all layers are registered as Heuristic (unless it's wallpaper).
if (!mUseContentDetectionV2) {
- const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps;
+ const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().getFps();
const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER
? lowFps
- : mRefreshRateConfigs.getMaxRefreshRate().fps;
+ : mRefreshRateConfigs.getMaxRefreshRate().getFps();
mLayerHistory->registerLayer(layer, lowFps, highFps,
scheduler::LayerHistory::LayerVoteType::Heuristic);
} else {
if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) {
// Running Wallpaper at Min is considered as part of content detection.
- mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps,
- mRefreshRateConfigs.getMaxRefreshRate().fps,
+ mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(),
+ mRefreshRateConfigs.getMaxRefreshRate().getFps(),
scheduler::LayerHistory::LayerVoteType::Min);
} else if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) {
- mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps,
- mRefreshRateConfigs.getMaxRefreshRate().fps,
+ mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(),
+ mRefreshRateConfigs.getMaxRefreshRate().getFps(),
scheduler::LayerHistory::LayerVoteType::NoVote);
} else {
- mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps,
- mRefreshRateConfigs.getMaxRefreshRate().fps,
+ mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(),
+ mRefreshRateConfigs.getMaxRefreshRate().getFps(),
scheduler::LayerHistory::LayerVoteType::Heuristic);
}
}
@@ -469,7 +469,7 @@
// that is currently on top. b/142507166 will give us this capability.
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (mLayerHistory) {
- // Layer History will be cleared based on RefreshRateConfigs::getRefreshRateForContentV2
+ // Layer History will be cleared based on RefreshRateConfigs::getBestRefreshRate
mTouchTimer->reset();
@@ -503,12 +503,13 @@
// magic number
const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f;
- if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
+ if (state == TimerState::Reset && refreshRate.getFps() > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// If we're not in performance mode then the kernel timer shouldn't do
// anything, as the refresh rate during DPU power collapse will be the
// same.
- resyncToHardwareVsync(true /* makeAvailable */, refreshRate.vsyncPeriod);
- } else if (state == TimerState::Expired && refreshRate.fps <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
+ resyncToHardwareVsync(true /* makeAvailable */, refreshRate.getVsyncPeriod());
+ } else if (state == TimerState::Expired &&
+ refreshRate.getFps() <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
// Disable HW VSYNC if the timer expired, as we don't need it enabled if
// we're not pushing frames, and if we're in PERFORMANCE mode then we'll
// need to update the DispSync model anyway.
@@ -573,47 +574,44 @@
HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() {
ATRACE_CALL();
- // NOTE: If we remove the kernel idle timer, and use our internal idle timer, this
- // code will have to be refactored. If Display Power is not in normal operation we want to be in
- // performance mode. When coming back to normal mode, a grace period is given with
- // DisplayPowerTimer.
+ // If Display Power is not in normal operation we want to be in performance mode. When coming
+ // back to normal mode, a grace period is given with DisplayPowerTimer.
if (mDisplayPowerTimer &&
(!mFeatures.isDisplayPowerStateNormal ||
mFeatures.displayPowerTimer == TimerState::Reset)) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
}
+ const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
+ const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
+
if (!mUseContentDetectionV2) {
// As long as touch is active we want to be in performance mode.
- if (mTouchTimer && mFeatures.touch == TouchState::Active) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+ if (touchActive) {
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
}
- }
- // If timer has expired as it means there is no new content on the screen.
- if (mIdleTimer && mFeatures.idleTimer == TimerState::Expired) {
- return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId;
- }
+ // If timer has expired as it means there is no new content on the screen.
+ if (idle) {
+ return mRefreshRateConfigs.getMinRefreshRateByPolicy().getConfigId();
+ }
- if (!mUseContentDetectionV2) {
// If content detection is off we choose performance as we don't know the content fps.
if (mFeatures.contentDetectionV1 == ContentDetectionState::Off) {
// NOTE: V1 always calls this, but this is not a default behavior for V2.
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
}
// Content detection is on, find the appropriate refresh rate with minimal error
- return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId;
+ return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements)
+ .getConfigId();
}
bool touchConsidered;
- const auto& ret =
- mRefreshRateConfigs
- .getRefreshRateForContentV2(mFeatures.contentRequirements,
- mTouchTimer &&
- mFeatures.touch == TouchState::Active,
- &touchConsidered)
- .configId;
+ const auto& ret = mRefreshRateConfigs
+ .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle,
+ &touchConsidered)
+ .getConfigId();
if (touchConsidered) {
// Clear layer history if refresh rate was selected based on touch to allow
// the hueristic to pick up with the new rate.
@@ -632,7 +630,7 @@
return mFeatures.configId;
}
-void Scheduler::onNewVsyncPeriodChangeTimeline(const HWC2::VsyncPeriodChangeTimeline& timeline) {
+void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
if (timeline.refreshRequired) {
mSchedulerCallback.repaintEverythingForHWC();
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 04cc96a..4a0280f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -95,7 +95,7 @@
ConnectionHandle enableVSyncInjection(bool enable);
// Returns false if injection is disabled.
- bool injectVSync(nsecs_t when);
+ bool injectVSync(nsecs_t when, nsecs_t expectedVSyncTime);
void enableHardwareVsync();
void disableHardwareVsync(bool makeUnavailable);
@@ -114,7 +114,7 @@
bool* periodFlushed);
void addPresentFence(const std::shared_ptr<FenceTime>&);
void setIgnorePresentFences(bool ignore);
- nsecs_t getDispSyncExpectedPresentTime();
+ nsecs_t getDispSyncExpectedPresentTime(nsecs_t now);
// Layers are registered on creation, and unregistered when the weak reference expires.
void registerLayer(Layer*);
@@ -138,7 +138,7 @@
std::optional<HwcConfigIndexType> getPreferredConfigId();
// Notifies the scheduler about a refresh rate timeline change.
- void onNewVsyncPeriodChangeTimeline(const HWC2::VsyncPeriodChangeTimeline& timeline);
+ void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline);
// Notifies the scheduler when the display was refreshed
void onDisplayRefreshed(nsecs_t timestamp);
@@ -242,7 +242,7 @@
const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
std::mutex mVsyncTimelineLock;
- std::optional<HWC2::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
+ std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
GUARDED_BY(mVsyncTimelineLock);
static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 892ae62..5f0c9ce 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -128,7 +128,7 @@
mLastCallTime = vsynctime;
}
- mCallback->onDispSyncEvent(wakeupTime);
+ mCallback->onDispSyncEvent(wakeupTime, vsynctime);
{
std::lock_guard<std::mutex> lk(mMutex);
@@ -221,14 +221,13 @@
}
}
-nsecs_t VSyncReactor::computeNextRefresh(int periodOffset) const {
- auto const now = mClock->now();
+nsecs_t VSyncReactor::computeNextRefresh(int periodOffset, nsecs_t now) const {
auto const currentPeriod = periodOffset ? mTracker->currentPeriod() : 0;
return mTracker->nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod);
}
-nsecs_t VSyncReactor::expectedPresentTime() {
- return mTracker->nextAnticipatedVSyncTimeFrom(mClock->now());
+nsecs_t VSyncReactor::expectedPresentTime(nsecs_t now) {
+ return mTracker->nextAnticipatedVSyncTimeFrom(now);
}
void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h
index 5ee29f8..31ddf5a 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.h
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.h
@@ -42,8 +42,8 @@
bool addPresentFence(const std::shared_ptr<FenceTime>& fence) final;
void setIgnorePresentFences(bool ignoration) final;
- nsecs_t computeNextRefresh(int periodOffset) const final;
- nsecs_t expectedPresentTime() final;
+ nsecs_t computeNextRefresh(int periodOffset, nsecs_t now) const final;
+ nsecs_t expectedPresentTime(nsecs_t now) final;
void setPeriod(nsecs_t period) final;
nsecs_t getPeriod() final;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 952edb4..4cd1c9b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -108,6 +108,7 @@
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "NativeWindowSurface.h"
+#include "Promise.h"
#include "RefreshRateOverlay.h"
#include "RegionSamplingThread.h"
#include "Scheduler/DispSync.h"
@@ -140,6 +141,8 @@
using ui::Hdr;
using ui::RenderIntent;
+namespace hal = android::hardware::graphics::composer::hal;
+
namespace {
#pragma clang diagnostic push
@@ -169,21 +172,24 @@
#pragma clang diagnostic pop
-class ConditionalLock {
-public:
- ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
- if (lock) {
- mMutex.lock();
- }
+template <typename Mutex>
+struct ConditionalLockGuard {
+ ConditionalLockGuard(Mutex& mutex, bool lock) : mutex(mutex), lock(lock) {
+ if (lock) mutex.lock();
}
- ~ConditionalLock() { if (mLocked) mMutex.unlock(); }
-private:
- Mutex& mMutex;
- bool mLocked;
+
+ ~ConditionalLockGuard() {
+ if (lock) mutex.unlock();
+ }
+
+ Mutex& mutex;
+ const bool lock;
};
+using ConditionalLock = ConditionalLockGuard<Mutex>;
+
// TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity.
-constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV / 160.f;
+constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
float getDensityFromProperty(const char* property, bool required) {
char value[PROPERTY_VALUE_MAX];
@@ -192,7 +198,7 @@
ALOGE("%s must be defined as a build property", property);
return FALLBACK_DENSITY;
}
- return density / 160.f;
+ return density;
}
// Currently we only support V0_SRGB and DISPLAY_P3 as composition preference.
@@ -405,15 +411,13 @@
useFrameRateApi = use_frame_rate_api(true);
}
-void SurfaceFlinger::onFirstRef()
-{
+SurfaceFlinger::~SurfaceFlinger() = default;
+
+void SurfaceFlinger::onFirstRef() {
mEventQueue->init(this);
}
-SurfaceFlinger::~SurfaceFlinger() = default;
-
-void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
-{
+void SurfaceFlinger::binderDied(const wp<IBinder>&) {
// the window manager died on us. prepare its eulogy.
mBootFinished = false;
@@ -424,21 +428,25 @@
startBootAnim();
}
-static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
- status_t err = client->initCheck();
- if (err == NO_ERROR) {
- return client;
+void SurfaceFlinger::run() {
+ while (true) {
+ mEventQueue->waitMessage();
}
- return nullptr;
+}
+
+template <typename F, typename T>
+inline std::future<T> SurfaceFlinger::schedule(F&& f) {
+ auto [task, future] = makeTask(std::move(f));
+ mEventQueue->postMessage(std::move(task));
+ return std::move(future);
}
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
- return initClient(new Client(this));
+ const sp<Client> client = new Client(this);
+ return client->initCheck() == NO_ERROR ? client : nullptr;
}
-sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
- bool secure)
-{
+sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secure) {
class DisplayToken : public BBinder {
sp<SurfaceFlinger> flinger;
virtual ~DisplayToken() {
@@ -466,17 +474,17 @@
}
void SurfaceFlinger::destroyDisplay(const sp<IBinder>& displayToken) {
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
- ssize_t index = mCurrentState.displays.indexOfKey(displayToken);
+ const ssize_t index = mCurrentState.displays.indexOfKey(displayToken);
if (index < 0) {
- ALOGE("destroyDisplay: Invalid display token %p", displayToken.get());
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
return;
}
const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
- if (!state.isVirtual()) {
- ALOGE("destroyDisplay called for non-virtual display");
+ if (state.physical) {
+ ALOGE("%s: Invalid operation on physical display", __FUNCTION__);
return;
}
mInterceptor->saveDisplayDeletion(state.sequenceId);
@@ -574,14 +582,13 @@
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
- postMessageAsync(new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS {
+ static_cast<void>(schedule([this] {
readPersistentProperties();
mPowerAdvisor.onBootFinished();
mBootStage = BootStage::FINISHED;
if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
- mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
- mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
+ enableRefreshRateOverlay(true);
}
}));
}
@@ -602,9 +609,12 @@
// The pool was empty, so we need to get a new texture name directly using a
// blocking call to the main thread
- uint32_t name = 0;
- postMessageSync(new LambdaMessage([&]() { getRenderEngine().genTextures(1, &name); }));
- return name;
+ return schedule([this] {
+ uint32_t name = 0;
+ getRenderEngine().genTextures(1, &name);
+ return name;
+ })
+ .get();
}
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -658,7 +668,7 @@
// mStateLock from the vr flinger dispatch thread might trigger a
// deadlock in surface flinger (see b/66916578), so post a message
// to be handled on the main thread instead.
- postMessageAsync(new LambdaMessage([=] {
+ static_cast<void>(schedule([=] {
ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
mVrFlingerRequestsDisplay = requestDisplay;
signalTransaction();
@@ -689,7 +699,7 @@
// Inform native graphics APIs whether the present timestamp is supported:
const bool presentFenceReliable =
- !getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable);
+ !getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE);
mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
if (mStartPropertySetThread->Start() != NO_ERROR) {
@@ -767,8 +777,7 @@
};
ConditionalLock _l(mStateLock,
std::this_thread::get_id() != mMainThreadId);
- if (!getHwComposer().hasCapability(
- HWC2::Capability::PresentFenceIsNotReliable)) {
+ if (!getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
}
return NO_ERROR;
@@ -820,6 +829,7 @@
? mInternalDisplayDensity
: FALLBACK_DENSITY;
}
+ info->density /= ACONFIGURATION_DENSITY_MEDIUM;
info->secure = display->isSecure();
info->deviceProductInfo = getDeviceProductInfoLocked(*display);
@@ -908,26 +918,34 @@
}
int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
- const auto display = getDisplayDevice(displayToken);
- if (!display) {
- ALOGE("getActiveConfig: Invalid display token %p", displayToken.get());
- return BAD_VALUE;
- }
+ int activeConfig;
+ bool isPrimary;
- if (display->isPrimary()) {
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (mDesiredActiveConfigChanged) {
- return mDesiredActiveConfig.configId.value();
+ {
+ Mutex::Autolock lock(mStateLock);
+
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
+ activeConfig = display->getActiveConfig().value();
+ isPrimary = display->isPrimary();
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return NAME_NOT_FOUND;
}
}
- return display->getActiveConfig().value();
+ if (isPrimary) {
+ if (const auto config = getDesiredActiveConfig()) {
+ return config->configId.value();
+ }
+ }
+
+ return activeConfig;
}
void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
ATRACE_CALL();
auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
- ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str());
+ ALOGV("setDesiredActiveConfig(%s)", refreshRate.getName().c_str());
std::lock_guard<std::mutex> lock(mActiveConfigLock);
if (mDesiredActiveConfigChanged) {
@@ -939,7 +957,7 @@
} else {
// Check is we are already at the desired config
const auto display = getDefaultDisplayDeviceLocked();
- if (!display || display->getActiveConfig() == refreshRate.configId) {
+ if (!display || display->getActiveConfig() == refreshRate.getConfigId()) {
return;
}
@@ -951,12 +969,12 @@
repaintEverythingForHWC();
// Start receiving vsync samples now, so that we can detect a period
// switch.
- mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod);
+ mScheduler->resyncToHardwareVsync(true, refreshRate.getVsyncPeriod());
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// DispSync model is locked.
mVSyncModulator->onRefreshRateChangeInitiated();
- mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
+ mPhaseConfiguration->setRefreshRateFps(refreshRate.getFps());
mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
}
@@ -972,29 +990,26 @@
return BAD_VALUE;
}
- status_t result = NO_ERROR;
-
- postMessageSync(new LambdaMessage([&]() {
+ auto future = schedule([=]() -> status_t {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set allowed display configs for invalid display token %p",
displayToken.get());
- result = BAD_VALUE;
+ return NAME_NOT_FOUND;
} else if (display->isVirtual()) {
ALOGW("Attempt to set allowed display configs for virtual display");
- result = BAD_VALUE;
+ return INVALID_OPERATION;
} else {
- HwcConfigIndexType config(mode);
- const auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(config);
- result = setDesiredDisplayConfigSpecsInternal(display,
- scheduler::RefreshRateConfigs::
- Policy{config, refreshRate.fps,
- refreshRate.fps},
- /*overridePolicy=*/false);
- }
- }));
+ const HwcConfigIndexType config(mode);
+ const float fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps();
+ const scheduler::RefreshRateConfigs::Policy policy{config, {fps, fps}};
+ constexpr bool kOverridePolicy = false;
- return result;
+ return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy);
+ }
+ });
+
+ return future.get();
}
void SurfaceFlinger::setActiveConfigInternal() {
@@ -1015,17 +1030,17 @@
auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId);
- if (refreshRate.vsyncPeriod != oldRefreshRate.vsyncPeriod) {
+ if (refreshRate.getVsyncPeriod() != oldRefreshRate.getVsyncPeriod()) {
mTimeStats->incrementRefreshRateSwitches();
}
- mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
+ mPhaseConfiguration->setRefreshRateFps(refreshRate.getFps());
mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
- ATRACE_INT("ActiveConfigFPS", refreshRate.fps);
+ ATRACE_INT("ActiveConfigFPS", refreshRate.getFps());
if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
const nsecs_t vsyncPeriod =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId)
- .vsyncPeriod;
+ .getVsyncPeriod();
mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
mUpcomingActiveConfig.configId, vsyncPeriod);
}
@@ -1038,69 +1053,53 @@
const auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId);
- mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod);
- mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
+ mScheduler->resyncToHardwareVsync(true, refreshRate.getVsyncPeriod());
+ mPhaseConfiguration->setRefreshRateFps(refreshRate.getFps());
mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
}
-bool SurfaceFlinger::performSetActiveConfig() {
+void SurfaceFlinger::performSetActiveConfig() {
ATRACE_CALL();
ALOGV("performSetActiveConfig");
- if (mCheckPendingFence) {
- if (previousFramePending()) {
- // fence has not signaled yet. wait for the next invalidate
- mEventQueue->invalidate();
- return true;
- }
-
- // We received the present fence from the HWC, so we assume it successfully updated
- // the config, hence we update SF.
- mCheckPendingFence = false;
- setActiveConfigInternal();
- }
-
// Store the local variable to release the lock.
- ActiveConfigInfo desiredActiveConfig;
- {
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (!mDesiredActiveConfigChanged) {
- return false;
- }
- desiredActiveConfig = mDesiredActiveConfig;
+ const auto desiredActiveConfig = getDesiredActiveConfig();
+ if (!desiredActiveConfig) {
+ // No desired active config pending to be applied
+ return;
}
auto& refreshRate =
- mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId);
- ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(),
- refreshRate.name.c_str());
+ mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId);
+ ALOGV("performSetActiveConfig changing active config to %d(%s)",
+ refreshRate.getConfigId().value(), refreshRate.getName().c_str());
const auto display = getDefaultDisplayDeviceLocked();
- if (!display || display->getActiveConfig() == desiredActiveConfig.configId) {
+ if (!display || display->getActiveConfig() == desiredActiveConfig->configId) {
// display is not valid or we are already in the requested mode
// on both cases there is nothing left to do
desiredActiveConfigChangeDone();
- return false;
+ return;
}
// Desired active config was set, it is different than the config currently in use, however
// allowed configs might have change by the time we process the refresh.
// Make sure the desired config is still allowed
- if (!isDisplayConfigAllowed(desiredActiveConfig.configId)) {
+ if (!isDisplayConfigAllowed(desiredActiveConfig->configId)) {
desiredActiveConfigChangeDone();
- return false;
+ return;
}
- mUpcomingActiveConfig = desiredActiveConfig;
+ mUpcomingActiveConfig = *desiredActiveConfig;
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
- ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.fps);
+ ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps());
// TODO(b/142753666) use constrains
- HWC2::VsyncPeriodChangeConstraints constraints;
+ hal::VsyncPeriodChangeConstraints constraints;
constraints.desiredTimeNanos = systemTime();
constraints.seamlessRequired = false;
- HWC2::VsyncPeriodChangeTimeline outTimeline;
+ hal::VsyncPeriodChangeTimeline outTimeline;
auto status =
getHwComposer().setActiveConfigWithConstraints(*displayId,
mUpcomingActiveConfig.configId.value(),
@@ -1109,13 +1108,12 @@
// setActiveConfigWithConstraints may fail if a hotplug event is just about
// to be sent. We just log the error in this case.
ALOGW("setActiveConfigWithConstraints failed: %d", status);
- return false;
+ return;
}
mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
// Scheduler will submit an empty frame to HWC if needed.
- mCheckPendingFence = true;
- return false;
+ mSetActiveConfigPending = true;
}
status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1161,7 +1159,7 @@
// Currently we only support this API for a single internal display.
if (getInternalDisplayToken() != displayToken) {
- return BAD_VALUE;
+ return NAME_NOT_FOUND;
}
memcpy(&primaries, &mInternalDisplayPrimaries, sizeof(ui::DisplayPrimaries));
@@ -1169,14 +1167,16 @@
}
ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) {
- if (const auto display = getDisplayDevice(displayToken)) {
+ Mutex::Autolock lock(mStateLock);
+
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
return display->getCompositionDisplay()->getState().colorMode;
}
return static_cast<ColorMode>(BAD_VALUE);
}
status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
- postMessageSync(new LambdaMessage([&] {
+ schedule([=] {
Vector<ColorMode> modes;
getDisplayColorModes(displayToken, &modes);
bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes);
@@ -1185,7 +1185,7 @@
decodeColorMode(mode).c_str(), mode, displayToken.get());
return;
}
- const auto display = getDisplayDevice(displayToken);
+ const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set active color mode %s (%d) for invalid display token %p",
decodeColorMode(mode).c_str(), mode, displayToken.get());
@@ -1198,89 +1198,69 @@
RenderIntent::COLORIMETRIC,
Dataspace::UNKNOWN});
}
- }));
+ }).wait();
return NO_ERROR;
}
status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp<IBinder>& displayToken,
bool* outSupport) const {
- Mutex::Autolock _l(mStateLock);
-
if (!displayToken) {
- ALOGE("getAutoLowLatencyModeSupport() failed. Missing display token.");
return BAD_VALUE;
}
+
+ Mutex::Autolock lock(mStateLock);
+
const auto displayId = getPhysicalDisplayIdLocked(displayToken);
if (!displayId) {
- ALOGE("getAutoLowLatencyModeSupport() failed. Display id for display token %p not found.",
- displayToken.get());
return NAME_NOT_FOUND;
}
- *outSupport = getHwComposer().hasDisplayCapability(displayId,
- HWC2::DisplayCapability::AutoLowLatencyMode);
+ *outSupport =
+ getHwComposer().hasDisplayCapability(*displayId,
+ hal::DisplayCapability::AUTO_LOW_LATENCY_MODE);
return NO_ERROR;
}
void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) {
- postMessageAsync(new LambdaMessage([=] { setAutoLowLatencyModeInternal(displayToken, on); }));
-}
-
-void SurfaceFlinger::setAutoLowLatencyModeInternal(const sp<IBinder>& displayToken, bool on) {
- if (!displayToken) {
- ALOGE("setAutoLowLatencyMode() failed. Missing display token.");
- return;
- }
- const auto displayId = getPhysicalDisplayIdLocked(displayToken);
- if (!displayId) {
- ALOGE("setAutoLowLatencyMode() failed. Display id for display token %p not found.",
- displayToken.get());
- return;
- }
-
- getHwComposer().setAutoLowLatencyMode(*displayId, on);
+ static_cast<void>(schedule([=] {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ getHwComposer().setAutoLowLatencyMode(*displayId, on);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
}
status_t SurfaceFlinger::getGameContentTypeSupport(const sp<IBinder>& displayToken,
bool* outSupport) const {
- Mutex::Autolock _l(mStateLock);
-
if (!displayToken) {
- ALOGE("getGameContentTypeSupport() failed. Missing display token.");
return BAD_VALUE;
}
+
+ Mutex::Autolock lock(mStateLock);
+
const auto displayId = getPhysicalDisplayIdLocked(displayToken);
if (!displayId) {
- ALOGE("getGameContentTypeSupport() failed. Display id for display token %p not found.",
- displayToken.get());
return NAME_NOT_FOUND;
}
- std::vector<HWC2::ContentType> outSupportedContentTypes;
- getHwComposer().getSupportedContentTypes(*displayId, &outSupportedContentTypes);
- *outSupport = std::find(outSupportedContentTypes.begin(), outSupportedContentTypes.end(),
- HWC2::ContentType::Game) != outSupportedContentTypes.end();
+ std::vector<hal::ContentType> types;
+ getHwComposer().getSupportedContentTypes(*displayId, &types);
+
+ *outSupport = std::any_of(types.begin(), types.end(),
+ [](auto type) { return type == hal::ContentType::GAME; });
return NO_ERROR;
}
void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) {
- postMessageAsync(new LambdaMessage([=] { setGameContentTypeInternal(displayToken, on); }));
-}
-
-void SurfaceFlinger::setGameContentTypeInternal(const sp<IBinder>& displayToken, bool on) {
- if (!displayToken) {
- ALOGE("setGameContentType() failed. Missing display token.");
- return;
- }
- const auto displayId = getPhysicalDisplayIdLocked(displayToken);
- if (!displayId) {
- ALOGE("setGameContentType() failed. Display id for display token %p not found.",
- displayToken.get());
- return;
- }
-
- const HWC2::ContentType type = on ? HWC2::ContentType::Game : HWC2::ContentType::None;
- getHwComposer().setContentType(*displayId, type);
+ static_cast<void>(schedule([=] {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE;
+ getHwComposer().setContentType(*displayId, type);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
}
status_t SurfaceFlinger::clearAnimationFrameStats() {
@@ -1297,15 +1277,15 @@
status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& displayToken,
HdrCapabilities* outCapabilities) const {
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
- ALOGE("getHdrCapabilities: Invalid display token %p", displayToken.get());
- return BAD_VALUE;
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return NAME_NOT_FOUND;
}
- // At this point the DisplayDeivce should already be set up,
+ // At this point the DisplayDevice should already be set up,
// meaning the luminance information is already queried from
// hardware composer and stored properly.
const HdrCapabilities& capabilities = display->getHdrCapabilities();
@@ -1348,39 +1328,45 @@
if (!outFormat || !outDataspace || !outComponentMask) {
return BAD_VALUE;
}
- const auto display = getDisplayDevice(displayToken);
- if (!display || !display->getId()) {
- ALOGE("getDisplayedContentSamplingAttributes: Bad display token: %p", display.get());
- return BAD_VALUE;
+
+ Mutex::Autolock lock(mStateLock);
+
+ const auto displayId = getPhysicalDisplayIdLocked(displayToken);
+ if (!displayId) {
+ return NAME_NOT_FOUND;
}
- return getHwComposer().getDisplayedContentSamplingAttributes(*display->getId(), outFormat,
+
+ return getHwComposer().getDisplayedContentSamplingAttributes(*displayId, outFormat,
outDataspace, outComponentMask);
}
status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken,
bool enable, uint8_t componentMask,
- uint64_t maxFrames) const {
- const auto display = getDisplayDevice(displayToken);
- if (!display || !display->getId()) {
- ALOGE("setDisplayContentSamplingEnabled: Bad display token: %p", display.get());
- return BAD_VALUE;
- }
-
- return getHwComposer().setDisplayContentSamplingEnabled(*display->getId(), enable,
- componentMask, maxFrames);
+ uint64_t maxFrames) {
+ return schedule([=]() -> status_t {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable,
+ componentMask,
+ maxFrames);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return NAME_NOT_FOUND;
+ }
+ })
+ .get();
}
status_t SurfaceFlinger::getDisplayedContentSample(const sp<IBinder>& displayToken,
uint64_t maxFrames, uint64_t timestamp,
DisplayedFrameStats* outStats) const {
- const auto display = getDisplayDevice(displayToken);
- if (!display || !display->getId()) {
- ALOGE("getDisplayContentSample: Bad display token: %p", displayToken.get());
- return BAD_VALUE;
+ Mutex::Autolock lock(mStateLock);
+
+ const auto displayId = getPhysicalDisplayIdLocked(displayToken);
+ if (!displayId) {
+ return NAME_NOT_FOUND;
}
- return getHwComposer().getDisplayedContentSample(*display->getId(), maxFrames, timestamp,
- outStats);
+ return getHwComposer().getDisplayedContentSample(*displayId, maxFrames, timestamp, outStats);
}
status_t SurfaceFlinger::getProtectedContentSupport(bool* outSupported) const {
@@ -1396,38 +1382,34 @@
if (!displayToken || !outIsWideColorDisplay) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mStateLock);
+
+ Mutex::Autolock lock(mStateLock);
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
- return BAD_VALUE;
+ return NAME_NOT_FOUND;
}
- // Use hasWideColorDisplay to override built-in display.
- const auto displayId = display->getId();
- if (displayId && displayId == getInternalDisplayIdLocked()) {
- *outIsWideColorDisplay = hasWideColorDisplay;
- return NO_ERROR;
- }
- *outIsWideColorDisplay = display->hasWideColorGamut();
+ *outIsWideColorDisplay =
+ display->isPrimary() ? hasWideColorDisplay : display->hasWideColorGamut();
return NO_ERROR;
}
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
- postMessageSync(new LambdaMessage([&] {
+ schedule([=] {
Mutex::Autolock lock(mStateLock);
if (const auto handle = mScheduler->enableVSyncInjection(enable)) {
mEventQueue->setEventConnection(
mScheduler->getEventConnection(enable ? handle : mSfConnectionHandle));
}
- }));
+ }).wait();
return NO_ERROR;
}
status_t SurfaceFlinger::injectVSync(nsecs_t when) {
Mutex::Autolock lock(mStateLock);
- return mScheduler->injectVSync(when) ? NO_ERROR : BAD_VALUE;
+ return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE;
}
status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
@@ -1440,10 +1422,10 @@
return TIMED_OUT;
}
+ const auto display = getDefaultDisplayDeviceLocked();
outLayers->clear();
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- outLayers->push_back(layer->getLayerDebugInfo());
- });
+ mCurrentState.traverseInZOrder(
+ [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); });
mStateLock.unlock();
return NO_ERROR;
@@ -1466,7 +1448,9 @@
if (!listener || samplingArea == Rect::INVALID_RECT) {
return BAD_VALUE;
}
- mRegionSamplingThread->addListener(samplingArea, stopLayerHandle, listener);
+
+ const wp<Layer> stopLayer = fromHandle(stopLayerHandle);
+ mRegionSamplingThread->addListener(samplingArea, stopLayer, listener);
return NO_ERROR;
}
@@ -1483,25 +1467,33 @@
if (!displayToken || !outSupport) {
return BAD_VALUE;
}
+
+ Mutex::Autolock lock(mStateLock);
+
const auto displayId = getPhysicalDisplayIdLocked(displayToken);
if (!displayId) {
return NAME_NOT_FOUND;
}
*outSupport =
- getHwComposer().hasDisplayCapability(displayId, HWC2::DisplayCapability::Brightness);
+ getHwComposer().hasDisplayCapability(*displayId, hal::DisplayCapability::BRIGHTNESS);
return NO_ERROR;
}
-status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken,
- float brightness) const {
+status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) {
if (!displayToken) {
return BAD_VALUE;
}
- const auto displayId = getPhysicalDisplayIdLocked(displayToken);
- if (!displayId) {
- return NAME_NOT_FOUND;
- }
- return getHwComposer().setDisplayBrightness(*displayId, brightness);
+
+ return promise::chain(schedule([=] {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ return getHwComposer().setDisplayBrightness(*displayId, brightness);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return promise::yield<status_t>(NAME_NOT_FOUND);
+ }
+ }))
+ .then([](std::future<status_t> task) { return task; })
+ .get();
}
status_t SurfaceFlinger::notifyPowerHint(int32_t hintId) {
@@ -1524,12 +1516,6 @@
return mScheduler->createDisplayEventConnection(handle, configChanged);
}
-// ----------------------------------------------------------------------------
-
-void SurfaceFlinger::waitForEvent() {
- mEventQueue->waitMessage();
-}
-
void SurfaceFlinger::signalTransaction() {
mScheduler->resetIdleTimer();
mPowerAdvisor.notifyDisplayUpdateImminent();
@@ -1547,26 +1533,6 @@
mEventQueue->refresh();
}
-status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t /* flags */) {
- return mEventQueue->postMessage(msg, reltime);
-}
-
-status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t /* flags */) {
- status_t res = mEventQueue->postMessage(msg, reltime);
- if (res == NO_ERROR) {
- msg->wait();
- }
- return res;
-}
-
-void SurfaceFlinger::run() {
- do {
- waitForEvent();
- } while (true);
-}
-
nsecs_t SurfaceFlinger::getVsyncPeriod() const {
const auto displayId = getInternalDisplayIdLocked();
if (!displayId || !getHwComposer().isConnected(*displayId)) {
@@ -1576,9 +1542,9 @@
return getHwComposer().getDisplayVsyncPeriod(*displayId);
}
-void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
int64_t timestamp,
- std::optional<hwc2_vsync_period_t> vsyncPeriod) {
+ std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
ATRACE_NAME("SF onVsync");
Mutex::Autolock lock(mStateLock);
@@ -1621,19 +1587,19 @@
ATRACE_CALL();
// Don't do any updating if the current fps is the same as the new one.
- if (!isDisplayConfigAllowed(refreshRate.configId)) {
+ if (!isDisplayConfigAllowed(refreshRate.getConfigId())) {
ALOGV("Skipping config %d as it is not part of allowed configs",
- refreshRate.configId.value());
+ refreshRate.getConfigId().value());
return;
}
- setDesiredActiveConfig({refreshRate.configId, event});
+ setDesiredActiveConfig({refreshRate.getConfigId(), event});
}
-void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
- HWC2::Connection connection) {
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
+ hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS {
ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
- connection == HWC2::Connection::Connected ? "connected" : "disconnected");
+ connection == hal::Connection::CONNECTED ? "connected" : "disconnected");
// Ignore events that do not have the right sequenceId.
if (sequenceId != getBE().mComposerSequenceId) {
@@ -1657,8 +1623,8 @@
}
void SurfaceFlinger::onVsyncPeriodTimingChangedReceived(
- int32_t sequenceId, hwc2_display_t /*display*/,
- const hwc_vsync_period_change_timeline_t& updatedTimeline) {
+ int32_t sequenceId, hal::HWDisplayId /*display*/,
+ const hal::VsyncPeriodChangeTimeline& updatedTimeline) {
Mutex::Autolock lock(mStateLock);
if (sequenceId != getBE().mComposerSequenceId) {
return;
@@ -1666,12 +1632,12 @@
mScheduler->onNewVsyncPeriodChangeTimeline(updatedTimeline);
}
-void SurfaceFlinger::onSeamlessPossible(int32_t /*sequenceId*/, hwc2_display_t /*display*/) {
+void SurfaceFlinger::onSeamlessPossible(int32_t /*sequenceId*/, hal::HWDisplayId /*display*/) {
// TODO(b/142753666): use constraints when calling to setActiveConfigWithConstrains and
// use this callback to know when to retry in case of SEAMLESS_NOT_POSSIBLE.
}
-void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId, hal::HWDisplayId /*hwcDisplayId*/) {
Mutex::Autolock lock(mStateLock);
if (sequenceId != getBE().mComposerSequenceId) {
return;
@@ -1684,14 +1650,14 @@
// Enable / Disable HWVsync from the main thread to avoid race conditions with
// display power state.
- postMessageAsync(new LambdaMessage(
- [=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
+ static_cast<void>(
+ schedule([=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
}
void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
ATRACE_CALL();
- mHWCVsyncPendingState = enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable;
+ mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
if (const auto displayId = getInternalDisplayIdLocked()) {
sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
@@ -1734,7 +1700,7 @@
sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
LOG_ALWAYS_FATAL_IF(!display);
- const int currentDisplayPowerMode = display->getPowerMode();
+ const hal::PowerMode currentDisplayPowerMode = display->getPowerMode();
// Clear out all the output layers from the composition engine for all
// displays before destroying the hardware composer interface. This ensures
@@ -1810,11 +1776,10 @@
return false;
}
- if (graceTimeMs > 0 && fence->getStatus() == Fence::Status::Unsignaled) {
- fence->wait(graceTimeMs);
- }
-
- return (fence->getStatus() == Fence::Status::Unsignaled);
+ const status_t status = fence->wait(graceTimeMs);
+ // This is the same as Fence::Status::Unsignaled, but it saves a getStatus() call,
+ // which calls wait(0) again internally
+ return status == -ETIME;
}
nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS {
@@ -1827,178 +1792,204 @@
return fence->getSignalTime();
}
-void SurfaceFlinger::populateExpectedPresentTime() {
+nsecs_t SurfaceFlinger::calculateExpectedPresentTime(nsecs_t now) const {
DisplayStatInfo stats;
mScheduler->getDisplayStatInfo(&stats);
- const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime();
+ const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime(now);
// Inflate the expected present time if we're targetting the next vsync.
- mExpectedPresentTime.store(
- mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod);
+ return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod;
}
-void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::onMessageReceived(int32_t what,
+ nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
- const nsecs_t frameStart = systemTime();
- // calculate the expected present time once and use the cached
- // value throughout this frame to make sure all layers are
- // seeing this same value.
- const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load();
- populateExpectedPresentTime();
-
- // When Backpressure propagation is enabled we want to give a small grace period
- // for the present fence to fire instead of just giving up on this frame to handle cases
- // where present fence is just about to get signaled.
- const int graceTimeForPresentFenceMs =
- (mPropagateBackpressure &&
- (mPropagateBackpressureClientComposition || !mHadClientComposition))
- ? 1
- : 0;
-
- // Pending frames may trigger backpressure propagation.
- const TracedOrdinal<bool> framePending = {"PrevFramePending",
- previousFramePending(
- graceTimeForPresentFenceMs)};
-
- // Frame missed counts for metrics tracking.
- // A frame is missed if the prior frame is still pending. If no longer pending,
- // then we still count the frame as missed if the predicted present time
- // was further in the past than when the fence actually fired.
-
- // Add some slop to correct for drift. This should generally be
- // smaller than a typical frame duration, but should not be so small
- // that it reports reasonable drift as a missed frame.
- DisplayStatInfo stats;
- mScheduler->getDisplayStatInfo(&stats);
- const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2;
- const nsecs_t previousPresentTime = previousFramePresentTime();
- const TracedOrdinal<bool> frameMissed =
- {"PrevFrameMissed",
- framePending ||
- (previousPresentTime >= 0 &&
- (lastExpectedPresentTime < previousPresentTime - frameMissedSlop))};
- const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed",
- mHadDeviceComposition && frameMissed};
- const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed",
- mHadClientComposition && frameMissed};
-
- if (frameMissed) {
- mFrameMissedCount++;
- mTimeStats->incrementMissedFrames();
- if (mMissedFrameJankCount == 0) {
- mMissedFrameJankStart = systemTime();
- }
- mMissedFrameJankCount++;
- }
-
- if (hwcFrameMissed) {
- mHwcFrameMissedCount++;
- }
-
- if (gpuFrameMissed) {
- mGpuFrameMissedCount++;
- }
-
- if (framePending && mPropagateBackpressure) {
- if ((hwcFrameMissed && !gpuFrameMissed) ||
- mPropagateBackpressureClientComposition) {
- signalLayerUpdate();
- break;
- }
- }
-
- // Our jank window is always at least 100ms since we missed a
- // frame...
- static constexpr nsecs_t kMinJankyDuration =
- std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count();
- // ...but if it's larger than 1s then we missed the trace cutoff.
- static constexpr nsecs_t kMaxJankyDuration =
- std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
- // If we're in a user build then don't push any atoms
- if (!mIsUserBuild && mMissedFrameJankCount > 0) {
- const auto displayDevice = getDefaultDisplayDeviceLocked();
- // Only report jank when the display is on, as displays in DOZE
- // power mode may operate at a different frame rate than is
- // reported in their config, which causes noticeable (but less
- // severe) jank.
- if (displayDevice && displayDevice->getPowerMode() == HWC_POWER_MODE_NORMAL) {
- const nsecs_t currentTime = systemTime();
- const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
- if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
- ATRACE_NAME("Jank detected");
- ALOGD("Detected janky event. Missed frames: %d", mMissedFrameJankCount);
- const int32_t jankyDurationMillis = jankDuration / (1000 * 1000);
- android::util::stats_write(android::util::DISPLAY_JANK_REPORTED,
- jankyDurationMillis, mMissedFrameJankCount);
- }
-
- // We either reported a jank event or we missed the trace
- // window, so clear counters here.
- if (jankDuration > kMinJankyDuration) {
- mMissedFrameJankCount = 0;
- mMissedFrameJankStart = 0;
- }
- }
- }
-
- // Now that we're going to make it to the handleMessageTransaction()
- // call below it's safe to call updateVrFlinger(), which will
- // potentially trigger a display handoff.
- updateVrFlinger();
-
- bool refreshNeeded;
- withTracingLock([&]() {
- refreshNeeded = handleMessageTransaction();
- refreshNeeded |= handleMessageInvalidate();
- if (mTracingEnabled) {
- mAddCompositionStateToTrace =
- mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
- if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
- mTracing.notifyLocked("visibleRegionsDirty");
- }
- }
- });
-
- // Layers need to get updated (in the previous line) before we can use them for
- // choosing the refresh rate.
- // Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
- // and may eventually call to ~Layer() if it holds the last reference
- {
- Mutex::Autolock _l(mStateLock);
- mScheduler->chooseRefreshRateForContent();
- }
-
- if (performSetActiveConfig()) {
- break;
- }
-
- updateCursorAsync();
- updateInputFlinger();
-
- refreshNeeded |= mRepaintEverything;
- if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
- // Signal a refresh if a transaction modified the window state,
- // a new buffer was latched, or if HWC has requested a full
- // repaint
- if (mFrameStartTime <= 0) {
- // We should only use the time of the first invalidate
- // message that signals a refresh as the beginning of the
- // frame. Otherwise the real frame time will be
- // underestimated.
- mFrameStartTime = frameStart;
- }
- signalRefresh();
- }
+ onMessageInvalidate(expectedVSyncTime);
break;
}
case MessageQueue::REFRESH: {
- handleMessageRefresh();
+ onMessageRefresh();
break;
}
}
}
+void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS {
+ ATRACE_CALL();
+
+ const nsecs_t frameStart = systemTime();
+ // calculate the expected present time once and use the cached
+ // value throughout this frame to make sure all layers are
+ // seeing this same value.
+ const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load();
+ mExpectedPresentTime = expectedVSyncTime;
+
+ // When Backpressure propagation is enabled we want to give a small grace period
+ // for the present fence to fire instead of just giving up on this frame to handle cases
+ // where present fence is just about to get signaled.
+ const int graceTimeForPresentFenceMs =
+ (mPropagateBackpressure &&
+ (mPropagateBackpressureClientComposition || !mHadClientComposition))
+ ? 1
+ : 0;
+
+ // Pending frames may trigger backpressure propagation.
+ const TracedOrdinal<bool> framePending = {"PrevFramePending",
+ previousFramePending(graceTimeForPresentFenceMs)};
+
+ // Frame missed counts for metrics tracking.
+ // A frame is missed if the prior frame is still pending. If no longer pending,
+ // then we still count the frame as missed if the predicted present time
+ // was further in the past than when the fence actually fired.
+
+ // Add some slop to correct for drift. This should generally be
+ // smaller than a typical frame duration, but should not be so small
+ // that it reports reasonable drift as a missed frame.
+ DisplayStatInfo stats;
+ mScheduler->getDisplayStatInfo(&stats);
+ const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2;
+ const nsecs_t previousPresentTime = previousFramePresentTime();
+ const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed",
+ framePending ||
+ (previousPresentTime >= 0 &&
+ (lastExpectedPresentTime <
+ previousPresentTime - frameMissedSlop))};
+ const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed",
+ mHadDeviceComposition && frameMissed};
+ const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed",
+ mHadClientComposition && frameMissed};
+
+ if (frameMissed) {
+ mFrameMissedCount++;
+ mTimeStats->incrementMissedFrames();
+ if (mMissedFrameJankCount == 0) {
+ mMissedFrameJankStart = systemTime();
+ }
+ mMissedFrameJankCount++;
+ }
+
+ if (hwcFrameMissed) {
+ mHwcFrameMissedCount++;
+ }
+
+ if (gpuFrameMissed) {
+ mGpuFrameMissedCount++;
+ }
+
+ // If we are in the middle of a config change and the fence hasn't
+ // fired yet just wait for the next invalidate
+ if (mSetActiveConfigPending) {
+ if (framePending) {
+ mEventQueue->invalidate();
+ return;
+ }
+
+ // We received the present fence from the HWC, so we assume it successfully updated
+ // the config, hence we update SF.
+ mSetActiveConfigPending = false;
+ setActiveConfigInternal();
+ }
+
+ if (framePending && mPropagateBackpressure) {
+ if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) {
+ signalLayerUpdate();
+ return;
+ }
+ }
+
+ // Our jank window is always at least 100ms since we missed a
+ // frame...
+ static constexpr nsecs_t kMinJankyDuration =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count();
+ // ...but if it's larger than 1s then we missed the trace cutoff.
+ static constexpr nsecs_t kMaxJankyDuration =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
+ // If we're in a user build then don't push any atoms
+ if (!mIsUserBuild && mMissedFrameJankCount > 0) {
+ const auto displayDevice = getDefaultDisplayDeviceLocked();
+ // Only report jank when the display is on, as displays in DOZE
+ // power mode may operate at a different frame rate than is
+ // reported in their config, which causes noticeable (but less
+ // severe) jank.
+ if (displayDevice && displayDevice->getPowerMode() == hal::PowerMode::ON) {
+ const nsecs_t currentTime = systemTime();
+ const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
+ if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
+ ATRACE_NAME("Jank detected");
+ ALOGD("Detected janky event. Missed frames: %d", mMissedFrameJankCount);
+ const int32_t jankyDurationMillis = jankDuration / (1000 * 1000);
+ {
+ ATRACE_NAME("Pushing to statsd");
+ android::util::stats_write(android::util::DISPLAY_JANK_REPORTED,
+ jankyDurationMillis, mMissedFrameJankCount);
+ }
+ }
+
+ // We either reported a jank event or we missed the trace
+ // window, so clear counters here.
+ if (jankDuration > kMinJankyDuration) {
+ mMissedFrameJankCount = 0;
+ mMissedFrameJankStart = 0;
+ }
+ }
+ }
+
+ // Now that we're going to make it to the handleMessageTransaction()
+ // call below it's safe to call updateVrFlinger(), which will
+ // potentially trigger a display handoff.
+ updateVrFlinger();
+
+ if (mTracingEnabledChanged) {
+ mTracingEnabled = mTracing.isEnabled();
+ mTracingEnabledChanged = false;
+ }
+
+ bool refreshNeeded;
+ {
+ ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);
+
+ refreshNeeded = handleMessageTransaction();
+ refreshNeeded |= handleMessageInvalidate();
+ if (mTracingEnabled) {
+ mAddCompositionStateToTrace =
+ mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
+ if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
+ mTracing.notifyLocked("visibleRegionsDirty");
+ }
+ }
+ }
+
+ // Layers need to get updated (in the previous line) before we can use them for
+ // choosing the refresh rate.
+ // Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
+ // and may eventually call to ~Layer() if it holds the last reference
+ {
+ Mutex::Autolock _l(mStateLock);
+ mScheduler->chooseRefreshRateForContent();
+ }
+
+ performSetActiveConfig();
+
+ updateCursorAsync();
+ updateInputFlinger();
+
+ refreshNeeded |= mRepaintEverything;
+ if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
+ // Signal a refresh if a transaction modified the window state,
+ // a new buffer was latched, or if HWC has requested a full
+ // repaint
+ if (mFrameStartTime <= 0) {
+ // We should only use the time of the first invalidate
+ // message that signals a refresh as the beginning of the
+ // frame. Otherwise the real frame time will be
+ // underestimated.
+ mFrameStartTime = frameStart;
+ }
+ signalRefresh();
+ }
+}
+
bool SurfaceFlinger::handleMessageTransaction() {
ATRACE_CALL();
uint32_t transactionFlags = peekTransactionFlags();
@@ -2021,7 +2012,7 @@
return runHandleTransaction;
}
-void SurfaceFlinger::handleMessageRefresh() {
+void SurfaceFlinger::onMessageRefresh() {
ATRACE_CALL();
mRefreshPending = false;
@@ -2051,6 +2042,7 @@
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
refreshArgs.updatingGeometryThisFrame = mGeometryInvalid || mVisibleRegionsDirty;
refreshArgs.blursAreExpensive = mBlursAreExpensive;
+ refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags();
if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
@@ -2080,6 +2072,8 @@
postFrame();
postComposition();
+ const bool prevFrameHadDeviceComposition = mHadDeviceComposition;
+
mHadClientComposition =
std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
auto& displayDevice = tokenDisplayPair.second;
@@ -2097,6 +2091,11 @@
return displayDevice->getCompositionDisplay()->getState().reusedClientComposition;
});
+ // Only report a strategy change if we move in and out of composition with hw overlays
+ if (prevFrameHadDeviceComposition != mHadDeviceComposition) {
+ mTimeStats->incrementCompositionStrategyChanges();
+ }
+
mVSyncModulator->onRefreshed(mHadClientComposition);
mLayersWithQueuedFrames.clear();
@@ -2112,7 +2111,6 @@
}
}
-
bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL();
bool refreshNeeded = handlePageFlip();
@@ -2234,15 +2232,19 @@
}
mDrawingState.traverse([&](Layer* layer) {
- bool frameLatched = layer->onPostComposition(displayDevice, glCompositionDoneFenceTime,
- presentFenceTime, compositorTiming);
+ const bool frameLatched =
+ layer->onPostComposition(displayDevice.get(), glCompositionDoneFenceTime,
+ presentFenceTime, compositorTiming);
if (frameLatched) {
recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
}
});
+ mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
+ mTransactionCompletedThread.sendCallbacks();
+
if (displayDevice && displayDevice->isPrimary() &&
- displayDevice->getPowerMode() == HWC_POWER_MODE_NORMAL && presentFenceTime->isValid()) {
+ displayDevice->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) {
mScheduler->addPresentFence(presentFenceTime);
}
@@ -2304,6 +2306,9 @@
}
getBE().mLastSwapTime = currentTime;
+ // Cleanup any outstanding resources due to rendering a prior frame.
+ getRenderEngine().cleanupPostRender();
+
{
std::lock_guard lock(mTexturePoolMutex);
if (mTexturePool.size() < mTexturePoolSize) {
@@ -2321,9 +2326,6 @@
}
}
- mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
- mTransactionCompletedThread.sendCallbacks();
-
if (mLumaSampling && mRegionSamplingThread) {
mRegionSamplingThread->notifyNewContent();
}
@@ -2336,6 +2338,10 @@
}
}
+FloatRect SurfaceFlinger::getLayerClipBoundsForDisplay(const DisplayDevice& displayDevice) const {
+ return displayDevice.getViewport().toFloatRect();
+}
+
void SurfaceFlinger::computeLayerBounds() {
for (const auto& pair : mDisplays) {
const auto& displayDevice = pair.second;
@@ -2346,7 +2352,7 @@
continue;
}
- layer->computeBounds(displayDevice->getViewport().toFloatRect(), ui::Transform(),
+ layer->computeBounds(getLayerClipBoundsForDisplay(*displayDevice), ui::Transform(),
0.f /* shadowRadius */);
}
}
@@ -2404,7 +2410,7 @@
const DisplayId displayId = info->id;
const auto it = mPhysicalDisplayTokens.find(displayId);
- if (event.connection == HWC2::Connection::Connected) {
+ if (event.connection == hal::Connection::CONNECTED) {
if (it == mPhysicalDisplayTokens.end()) {
ALOGV("Creating display %s", to_string(displayId).c_str());
@@ -2508,7 +2514,7 @@
isInternalDisplay ? internalDisplayOrientation : ui::ROTATION_0;
// virtual displays are always considered enabled
- creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
+ creationArgs.initialPowerMode = state.isVirtual() ? hal::PowerMode::ON : hal::PowerMode::OFF;
sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
@@ -2669,9 +2675,14 @@
if (currentState.width != drawingState.width ||
currentState.height != drawingState.height) {
display->setDisplaySize(currentState.width, currentState.height);
+
if (display->isPrimary()) {
mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height);
}
+
+ if (mRefreshRateOverlay) {
+ mRefreshRateOverlay->setViewport(display->getSize());
+ }
}
}
}
@@ -2755,7 +2766,7 @@
processDisplayHotplugEventsLocked();
}
- if (transactionFlags & (eDisplayLayerStackChanged|eDisplayTransactionNeeded)) {
+ if (transactionFlags & (eTransformHintUpdateNeeded | eDisplayTransactionNeeded)) {
// The transform hint might have changed for some layers
// (either because a display has changed, or because a layer
// as changed).
@@ -2816,14 +2827,13 @@
// could be null if there is no display available at all to get
// the transform hint from.
if (hintDisplay) {
- layer->updateTransformHint(hintDisplay);
+ layer->updateTransformHint(hintDisplay->getTransformHint());
}
first = false;
});
}
-
/*
* Perform our own transaction if needed
*/
@@ -2874,19 +2884,6 @@
void SurfaceFlinger::updateInputWindowInfo() {
std::vector<InputWindowInfo> inputHandles;
- // We use a simple caching algorithm here. mInputDirty begins as true,
- // after we call setInputWindows we set it to false, so
- // in the future we wont call it again.. We set input dirty to true again
- // when any layer that hasInput() has a transaction performed on it
- // or when any parent or relative parent of such a layer has a transaction
- // performed on it. Not all of these transactions will really result in
- // input changes but all input changes will spring from these transactions
- // so the cache is safe but not optimal. It seems like it might be annoyingly
- // costly to cache and comapre the actual InputWindowHandle vector though.
- if (!mInputDirty && !mInputWindowCommands.syncInputWindows) {
- return;
- }
-
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (layer->hasInput()) {
// When calculating the screen bounds we ignore the transparent region since it may
@@ -2898,8 +2895,6 @@
mInputFlinger->setInputWindows(inputHandles,
mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
: nullptr);
-
- mInputDirty = false;
}
void SurfaceFlinger::commitInputWindowCommands() {
@@ -2944,7 +2939,7 @@
currentConfig);
mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mRefreshRateConfigs, *mTimeStats,
- currentConfig, HWC_POWER_MODE_OFF);
+ currentConfig, hal::PowerMode::OFF);
mRefreshRateStats->setConfigMode(currentConfig);
mPhaseConfiguration = getFactory().createPhaseConfiguration(*mRefreshRateConfigs);
@@ -2977,7 +2972,7 @@
// classes from EventThread, and there should be no run-time binder cost
// anyway since there are no connected apps at this point.
const nsecs_t vsyncPeriod =
- mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).vsyncPeriod;
+ mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod();
mScheduler->onConfigChanged(mAppConnectionHandle, primaryDisplayId.value, currentConfig,
vsyncPeriod);
}
@@ -3033,26 +3028,6 @@
mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
}
-void SurfaceFlinger::withTracingLock(std::function<void()> lockedOperation) {
- if (mTracingEnabledChanged) {
- mTracingEnabled = mTracing.isEnabled();
- mTracingEnabledChanged = false;
- }
-
- // Synchronize with Tracing thread
- std::unique_lock<std::mutex> lock;
- if (mTracingEnabled) {
- lock = std::unique_lock<std::mutex>(mDrawingStateLock);
- }
-
- lockedOperation();
-
- // Synchronize with Tracing thread
- if (mTracingEnabled) {
- lock.unlock();
- }
-}
-
void SurfaceFlinger::commitOffscreenLayers() {
for (Layer* offscreenLayer : mOffscreenLayers) {
offscreenLayer->traverse(LayerVector::StateSet::Drawing, [](Layer* layer) {
@@ -3163,13 +3138,14 @@
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
const sp<IBinder>& parentHandle,
- const sp<Layer>& parentLayer, bool addToCurrentState) {
+ const sp<Layer>& parentLayer, bool addToCurrentState,
+ uint32_t* outTransformHint) {
// add this layer to the current state list
{
Mutex::Autolock _l(mStateLock);
sp<Layer> parent;
if (parentHandle != nullptr) {
- parent = fromHandle(parentHandle);
+ parent = fromHandleLocked(parentHandle).promote();
if (parent == nullptr) {
return NAME_NOT_FOUND;
}
@@ -3204,6 +3180,14 @@
mGraphicBufferProducerList.size(),
mMaxGraphicBufferProducerListSize, mNumLayers.load());
}
+
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
+ lbc->updateTransformHint(display->getTransformHint());
+ }
+ if (outTransformHint) {
+ *outTransformHint = lbc->getTransformHint();
+ }
+
mLayersAdded = true;
}
@@ -3213,6 +3197,13 @@
return NO_ERROR;
}
+void SurfaceFlinger::removeGraphicBufferProducerAsync(const wp<IBinder>& binder) {
+ static_cast<void>(schedule([=] {
+ Mutex::Autolock lock(mStateLock);
+ mGraphicBufferProducerList.erase(binder);
+ }));
+}
+
uint32_t SurfaceFlinger::peekTransactionFlags() {
return mTransactionFlags;
}
@@ -3251,7 +3242,6 @@
while (!transactionQueue.empty()) {
const auto& transaction = transactionQueue.front();
if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
- true /* useCachedExpectedPresentTime */,
transaction.states)) {
setTransactionFlags(eTransactionFlushNeeded);
break;
@@ -3283,10 +3273,7 @@
bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
- bool useCachedExpectedPresentTime,
const Vector<ComposerState>& states) {
- if (!useCachedExpectedPresentTime)
- populateExpectedPresentTime();
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
@@ -3338,9 +3325,13 @@
}
}
+ const bool pendingTransactions = itr != mTransactionQueues.end();
// Expected present time is computed and cached on invalidate, so it may be stale.
- if (itr != mTransactionQueues.end() || !transactionIsReadyToBeApplied(
- desiredPresentTime, false /* useCachedExpectedPresentTime */, states)) {
+ if (!pendingTransactions) {
+ mExpectedPresentTime = calculateExpectedPresentTime(systemTime());
+ }
+
+ if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
uncacheBuffer, postTime, privileged,
hasListenerCallbacks, listenerCallbacks);
@@ -3439,18 +3430,26 @@
: Scheduler::TransactionStart::NORMAL;
setTransactionFlags(transactionFlags, start);
- // if this is a synchronous transaction, wait for it to take effect
- // before returning.
- if (flags & eSynchronous) {
- mTransactionPending = true;
- }
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
- if (mPendingInputWindowCommands.syncInputWindows) {
+
+ // if this is a synchronous transaction, wait for it to take effect
+ // before returning.
+ const bool synchronous = flags & eSynchronous;
+ const bool syncInput = inputWindowCommands.syncInputWindows;
+ if (!synchronous && !syncInput) {
+ return;
+ }
+
+ if (synchronous) {
+ mTransactionPending = true;
+ }
+ if (syncInput) {
mPendingSyncInputWindows = true;
}
+
// applyTransactionState can be called by either the main SF thread or by
// another process through setTransactionState. While a given process may wish
// to wait on synchronous transactions, the main SF thread should never
@@ -3544,7 +3543,7 @@
sp<Layer> layer = nullptr;
if (s.surface) {
- layer = fromHandle(s.surface);
+ layer = fromHandleLocked(s.surface).promote();
} else {
// The client may provide us a null handle. Treat it as if the layer was removed.
ALOGW("Attempt to set client state with a null layer handle");
@@ -3690,7 +3689,7 @@
mCurrentState.layersSortedByZ.add(layer);
// we need traversal (state changed)
// AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded|eDisplayLayerStackChanged;
+ flags |= eTransactionNeeded | eTraversalNeeded | eTransformHintUpdateNeeded;
}
}
if (what & layer_state_t::eDeferTransaction_legacy) {
@@ -3787,6 +3786,11 @@
flags |= eTraversalNeeded;
}
}
+ if (what & layer_state_t::eFixedTransformHintChanged) {
+ if (layer->setFixedTransformHint(s.fixedTransformHint)) {
+ flags |= eTraversalNeeded | eTransformHintUpdateNeeded;
+ }
+ }
// This has to happen after we reparent children because when we reparent to null we remove
// child layers from current state and remove its relative z. If the children are reparented in
// the same transaction, then we have to make sure we reparent the children first so we do not
@@ -3860,7 +3864,7 @@
{
Mutex::Autolock _l(mStateLock);
- mirrorFrom = fromHandle(mirrorFromHandle);
+ mirrorFrom = fromHandleLocked(mirrorFromHandle).promote();
if (!mirrorFrom) {
return NAME_NOT_FOUND;
}
@@ -3874,7 +3878,8 @@
mirrorLayer->mClonedChild = mirrorFrom->createClone();
}
- return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false);
+ return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false,
+ nullptr /* outTransformHint */);
}
status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
@@ -3919,7 +3924,7 @@
break;
case ISurfaceComposerClient::eFXSurfaceBufferState:
result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
- std::move(metadata), handle, outTransformHint, &layer);
+ std::move(metadata), handle, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceEffect:
// check if buffer size is set for color layer.
@@ -3957,7 +3962,7 @@
bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
- addToCurrentState);
+ addToCurrentState, outTransformHint);
if (result != NO_ERROR) {
return result;
}
@@ -4034,14 +4039,10 @@
status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
- uint32_t* outTransformHint, sp<Layer>* outLayer) {
+ sp<Layer>* outLayer) {
LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
- args.displayDevice = getDefaultDisplayDevice();
args.textureName = getNewTexture();
sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
- if (outTransformHint) {
- *outTransformHint = layer->getTransformHint();
- }
*handle = layer->getHandle();
*outLayer = layer;
@@ -4123,7 +4124,7 @@
setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}, false,
{});
- setPowerModeInternal(display, HWC_POWER_MODE_NORMAL);
+ setPowerModeInternal(display, hal::PowerMode::ON);
const nsecs_t vsyncPeriod = getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
@@ -4136,18 +4137,17 @@
void SurfaceFlinger::initializeDisplays() {
// Async since we may be called from the main thread.
- postMessageAsync(
- new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
+ static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
}
-void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled) {
+void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled) {
if (mHWCVsyncState != enabled) {
getHwComposer().setVsyncEnabled(displayId, enabled);
mHWCVsyncState = enabled;
}
}
-void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
+void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
if (display->isVirtual()) {
ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
return;
@@ -4158,7 +4158,7 @@
ALOGD("Setting power mode %d on display %s", mode, to_string(*displayId).c_str());
- int currentMode = display->getPowerMode();
+ const hal::PowerMode currentMode = display->getPowerMode();
if (mode == currentMode) {
return;
}
@@ -4166,15 +4166,15 @@
display->setPowerMode(mode);
if (mInterceptor->isEnabled()) {
- mInterceptor->savePowerModeUpdate(display->getSequenceId(), mode);
+ mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
}
- if (currentMode == HWC_POWER_MODE_OFF) {
+ if (currentMode == hal::PowerMode::OFF) {
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
}
getHwComposer().setPowerMode(*displayId, mode);
- if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
@@ -4183,31 +4183,30 @@
mVisibleRegionsDirty = true;
mHasPoweredOff = true;
repaintEverything();
- } else if (mode == HWC_POWER_MODE_OFF) {
+ } else if (mode == hal::PowerMode::OFF) {
// Turn off the display
if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno));
}
- if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (display->isPrimary() && currentMode != hal::PowerMode::DOZE_SUSPEND) {
mScheduler->disableHardwareVsync(true);
mScheduler->onScreenReleased(mAppConnectionHandle);
}
// Make sure HWVsync is disabled before turning off the display
- setVsyncEnabledInHWC(*displayId, HWC2::Vsync::Disable);
+ setVsyncEnabledInHWC(*displayId, hal::Vsync::DISABLE);
getHwComposer().setPowerMode(*displayId, mode);
mVisibleRegionsDirty = true;
// from this point on, SF will stop drawing on this display
- } else if (mode == HWC_POWER_MODE_DOZE ||
- mode == HWC_POWER_MODE_NORMAL) {
+ } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) {
// Update display while dozing
getHwComposer().setPowerMode(*displayId, mode);
- if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
}
- } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+ } else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
if (display->isPrimary()) {
mScheduler->disableHardwareVsync(true);
@@ -4222,28 +4221,26 @@
if (display->isPrimary()) {
mTimeStats->setPowerMode(mode);
mRefreshRateStats->setPowerMode(mode);
- mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL);
+ mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON);
}
ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
}
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
- postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
- const auto display = getDisplayDevice(displayToken);
+ schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
+ const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
displayToken.get());
} else if (display->isVirtual()) {
ALOGW("Attempt to set power mode %d for virtual display", mode);
} else {
- setPowerModeInternal(display, mode);
+ setPowerModeInternal(display, static_cast<hal::PowerMode>(mode));
}
- }));
+ }).wait();
}
-// ---------------------------------------------------------------------------
-
status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,
bool asProto) NO_THREAD_SAFETY_ANALYSIS {
std::string result;
@@ -4397,11 +4394,21 @@
scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy();
StringAppendF(&result,
- "DesiredDisplayConfigSpecs: default config ID: %d"
- ", min: %.2f Hz, max: %.2f Hz",
- policy.defaultConfig.value(), policy.minRefreshRate, policy.maxRefreshRate);
+ "DesiredDisplayConfigSpecs (DisplayManager): default config ID: %d"
+ ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]\n\n",
+ policy.defaultConfig.value(), policy.primaryRange.min, policy.primaryRange.max,
+ policy.appRequestRange.min, policy.appRequestRange.max);
StringAppendF(&result, "(config override by backdoor: %s)\n\n",
mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
+ scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy();
+ if (currentPolicy != policy) {
+ StringAppendF(&result,
+ "DesiredDisplayConfigSpecs (Override): default config ID: %d"
+ ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]\n\n",
+ currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min,
+ currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min,
+ currentPolicy.appRequestRange.max);
+ }
mScheduler->dump(mAppConnectionHandle, result);
mScheduler->getPrimaryDispSync().dump(result);
@@ -4522,7 +4529,7 @@
void SurfaceFlinger::dumpRawDisplayIdentificationData(const DumpArgs& args,
std::string& result) const {
- hwc2_display_t hwcDisplayId;
+ hal::HWDisplayId hwcDisplayId;
uint8_t port;
DisplayIdentificationData data;
@@ -4559,11 +4566,13 @@
result.append("\n");
}
-LayersProto SurfaceFlinger::dumpDrawingStateProto(
- uint32_t traceFlags, const sp<const DisplayDevice>& displayDevice) const {
+LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
+ // If context is SurfaceTracing thread, mTracingLock blocks display transactions on main thread.
+ const auto display = getDefaultDisplayDeviceLocked();
+
LayersProto layersProto;
for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
- layer->writeToProto(layersProto, traceFlags, displayDevice);
+ layer->writeToProto(layersProto, traceFlags, display.get());
}
return layersProto;
@@ -4594,23 +4603,21 @@
}
LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
- LayersProto layersProto;
- postMessageSync(new LambdaMessage([&]() {
- const auto& displayDevice = getDefaultDisplayDeviceLocked();
- layersProto = dumpDrawingStateProto(traceFlags, displayDevice);
- }));
- return layersProto;
+ return schedule([=] { return dumpDrawingStateProto(traceFlags); }).get();
}
void SurfaceFlinger::dumpOffscreenLayers(std::string& result) {
result.append("Offscreen Layers:\n");
- postMessageSync(new LambdaMessage([&]() {
- for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- layer->dumpCallingUidPid(result);
- });
- }
- }));
+ result.append(schedule([this] {
+ std::string result;
+ for (Layer* offscreenLayer : mOffscreenLayers) {
+ offscreenLayer->traverse(LayerVector::StateSet::Drawing,
+ [&](Layer* layer) {
+ layer->dumpCallingUidPid(result);
+ });
+ }
+ return result;
+ }).get());
}
void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const {
@@ -4754,9 +4761,9 @@
StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
Layer::miniDumpHeader(result);
- const sp<DisplayDevice> displayDevice = display;
- mCurrentState.traverseInZOrder(
- [&](Layer* layer) { layer->miniDump(result, displayDevice); });
+
+ const DisplayDevice& ref = *display;
+ mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, ref); });
result.append("\n");
}
@@ -4927,9 +4934,9 @@
code == IBinder::SYSPROPS_TRANSACTION) {
return OK;
}
- // Numbers from 1000 to 1034 are currently used for backdoors. The code
+ // Numbers from 1000 to 1036 are currently used for backdoors. The code
// in onTransact verifies that the user is root, and has access to use SF.
- if (code >= 1000 && code <= 1035) {
+ if (code >= 1000 && code <= 1036) {
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
return OK;
}
@@ -5125,20 +5132,12 @@
n = data.readInt32();
if (n) {
ALOGD("LayerTracing enabled");
- Mutex::Autolock lock(mStateLock);
- mTracingEnabledChanged = true;
- mTracing.enable();
+ mTracingEnabledChanged = mTracing.enable();
reply->writeInt32(NO_ERROR);
} else {
ALOGD("LayerTracing disabled");
- bool writeFile = false;
- {
- Mutex::Autolock lock(mStateLock);
- mTracingEnabledChanged = true;
- writeFile = mTracing.disable();
- }
-
- if (writeFile) {
+ mTracingEnabledChanged = mTracing.disable();
+ if (mTracingEnabledChanged) {
reply->writeInt32(mTracing.writeToFile());
} else {
reply->writeInt32(NO_ERROR);
@@ -5241,15 +5240,15 @@
return NO_ERROR;
}
case 1034: {
- n = data.readInt32();
- if (n == 1 && !mRefreshRateOverlay) {
- mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
- auto& current = mRefreshRateConfigs->getCurrentRefreshRate();
- mRefreshRateOverlay->changeRefreshRate(current);
- } else if (n == 0) {
- mRefreshRateOverlay.reset();
- } else {
- reply->writeBool(mRefreshRateOverlay != nullptr);
+ switch (n = data.readInt32()) {
+ case 0:
+ case 1:
+ enableRefreshRateOverlay(static_cast<bool>(n));
+ break;
+ default: {
+ Mutex::Autolock lock(mStateLock);
+ reply->writeBool(mRefreshRateOverlay != nullptr);
+ }
}
return NO_ERROR;
}
@@ -5266,6 +5265,18 @@
}
return NO_ERROR;
}
+ case 1036: {
+ if (data.readInt32() > 0) {
+ status_t result =
+ acquireFrameRateFlexibilityToken(&mDebugFrameRateFlexibilityToken);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ } else {
+ mDebugFrameRateFlexibilityToken = nullptr;
+ }
+ return NO_ERROR;
+ }
}
}
return err;
@@ -5285,29 +5296,26 @@
void SurfaceFlinger::kernelTimerChanged(bool expired) {
static bool updateOverlay =
property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true);
- if (!updateOverlay || !mRefreshRateOverlay) return;
+ if (!updateOverlay) return;
+ if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return;
// Update the overlay on the main thread to avoid race conditions with
// mRefreshRateConfigs->getCurrentRefreshRate()
- postMessageAsync(new LambdaMessage([this, expired]() NO_THREAD_SAFETY_ANALYSIS {
- if (mRefreshRateOverlay) {
+ static_cast<void>(schedule([=] {
+ const auto desiredActiveConfig = getDesiredActiveConfig();
+ const auto& current = desiredActiveConfig
+ ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId)
+ : mRefreshRateConfigs->getCurrentRefreshRate();
+ const auto& min = mRefreshRateConfigs->getMinRefreshRate();
+
+ if (current != min) {
const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
const bool timerExpired = kernelTimerEnabled && expired;
- const auto& current = [this]() -> const RefreshRate& {
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (mDesiredActiveConfigChanged) {
- return mRefreshRateConfigs->getRefreshRateFromConfigId(
- mDesiredActiveConfig.configId);
- }
- return mRefreshRateConfigs->getCurrentRefreshRate();
- }();
- const auto& min = mRefreshRateConfigs->getMinRefreshRate();
-
- if (current != min) {
+ if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current);
- mEventQueue->invalidate();
}
+ mEventQueue->invalidate();
}
}));
}
@@ -5343,10 +5351,10 @@
sp<DisplayDevice> display;
{
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
display = getDisplayDeviceLocked(displayToken);
- if (!display) return BAD_VALUE;
+ if (!display) return NAME_NOT_FOUND;
// set the requested width/height to the logical display viewport size
// by default
@@ -5422,10 +5430,10 @@
uint32_t height;
ui::Transform::RotationFlags captureOrientation;
{
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
display = getDisplayByIdOrLayerStack(displayOrLayerStack);
if (!display) {
- return BAD_VALUE;
+ return NAME_NOT_FOUND;
}
width = uint32_t(display->getViewport().width());
@@ -5560,9 +5568,9 @@
std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
Rect displayViewport;
{
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
- parent = fromHandle(layerHandleBinder);
+ parent = fromHandleLocked(layerHandleBinder).promote();
if (parent == nullptr || parent->isRemovedFromCurrentState()) {
ALOGE("captureLayers called with an invalid or removed parent");
return NAME_NOT_FOUND;
@@ -5595,7 +5603,7 @@
reqHeight = crop.height() * frameScale;
for (const auto& handle : excludeHandles) {
- sp<Layer> excludeLayer = fromHandle(handle);
+ sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
if (excludeLayer != nullptr) {
excludeLayers.emplace(excludeLayer);
} else {
@@ -5604,9 +5612,9 @@
}
}
- auto display = getDisplayByLayerStack(parent->getLayerStack());
+ const auto display = getDisplayByLayerStack(parent->getLayerStack());
if (!display) {
- return BAD_VALUE;
+ return NAME_NOT_FOUND;
}
displayViewport = display->getViewport();
@@ -5665,68 +5673,41 @@
usage, "screenshot");
return captureScreenCommon(renderArea, traverseLayers, *outBuffer, useIdentityTransform,
- outCapturedSecureLayers);
+ false /* regionSampling */, outCapturedSecureLayers);
}
status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer,
- bool useIdentityTransform,
+ bool useIdentityTransform, bool regionSampling,
bool& outCapturedSecureLayers) {
- // This mutex protects syncFd and captureResult for communication of the return values from the
- // main thread back to this Binder thread
- std::mutex captureMutex;
- std::condition_variable captureCondition;
- std::unique_lock<std::mutex> captureLock(captureMutex);
- int syncFd = -1;
- std::optional<status_t> captureResult;
-
const int uid = IPCThreadState::self()->getCallingUid();
const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
- sp<LambdaMessage> message = new LambdaMessage([&] {
- // If there is a refresh pending, bug out early and tell the binder thread to try again
- // after the refresh.
- if (mRefreshPending) {
- ATRACE_NAME("Skipping screenshot for now");
- std::unique_lock<std::mutex> captureLock(captureMutex);
- captureResult = std::make_optional<status_t>(EAGAIN);
- captureCondition.notify_one();
- return;
- }
+ status_t result;
+ int syncFd;
- status_t result = NO_ERROR;
- int fd = -1;
- {
- Mutex::Autolock _l(mStateLock);
- renderArea.render([&] {
- result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(),
- useIdentityTransform, forSystem, &fd,
- outCapturedSecureLayers);
- });
- }
+ do {
+ std::tie(result, syncFd) =
+ schedule([&] {
+ if (mRefreshPending) {
+ ATRACE_NAME("Skipping screenshot for now");
+ return std::make_pair(EAGAIN, -1);
+ }
- {
- std::unique_lock<std::mutex> captureLock(captureMutex);
- syncFd = fd;
- captureResult = std::make_optional<status_t>(result);
- captureCondition.notify_one();
- }
- });
+ status_t result = NO_ERROR;
+ int fd = -1;
- status_t result = postMessageAsync(message);
- if (result == NO_ERROR) {
- captureCondition.wait(captureLock, [&] { return captureResult; });
- while (*captureResult == EAGAIN) {
- captureResult.reset();
- result = postMessageAsync(message);
- if (result != NO_ERROR) {
- return result;
- }
- captureCondition.wait(captureLock, [&] { return captureResult; });
- }
- result = *captureResult;
- }
+ Mutex::Autolock lock(mStateLock);
+ renderArea.render([&] {
+ result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(),
+ useIdentityTransform, forSystem, &fd,
+ regionSampling, outCapturedSecureLayers);
+ });
+
+ return std::make_pair(result, fd);
+ }).get();
+ } while (result == EAGAIN);
if (result == NO_ERROR) {
sync_wait(syncFd, -1);
@@ -5739,7 +5720,7 @@
void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
- int* outSyncFd) {
+ bool regionSampling, int* outSyncFd) {
ATRACE_CALL();
const auto reqWidth = renderArea.getReqWidth();
@@ -5756,7 +5737,6 @@
// buffer bounds.
clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
clientCompositionDisplay.clip = sourceCrop;
- clientCompositionDisplay.globalTransform = mat4();
clientCompositionDisplay.orientation = rotation;
clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
@@ -5772,6 +5752,7 @@
fillLayer.alpha = half(alpha);
clientCompositionLayers.push_back(fillLayer);
+ const auto display = renderArea.getDisplayDevice();
std::vector<Layer*> renderedLayers;
Region clearRegion = Region::INVALID_REGION;
traverseLayers([&](Layer* layer) {
@@ -5780,7 +5761,7 @@
compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
clip,
useIdentityTransform,
- layer->needsFilteringForScreenshots(renderArea.getDisplayDevice(), transform) ||
+ layer->needsFilteringForScreenshots(display.get(), transform) ||
renderArea.needsFiltering(),
renderArea.isSecure(),
supportProtectedContent,
@@ -5796,6 +5777,12 @@
for (auto& settings : results) {
settings.geometry.positionTransform =
transform.asMatrix4() * settings.geometry.positionTransform;
+ // There's no need to process blurs when we're executing region sampling,
+ // we're just trying to understand what we're drawing, and doing so without
+ // blurs is already a pretty good approximation.
+ if (regionSampling) {
+ settings.backgroundBlurRadius = 0;
+ }
}
clientCompositionLayers.insert(clientCompositionLayers.end(),
std::make_move_iterator(results.begin()),
@@ -5833,7 +5820,8 @@
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer,
bool useIdentityTransform, bool forSystem,
- int* outSyncFd, bool& outCapturedSecureLayers) {
+ int* outSyncFd, bool regionSampling,
+ bool& outCapturedSecureLayers) {
ATRACE_CALL();
traverseLayers([&](Layer* layer) {
@@ -5848,7 +5836,8 @@
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
- renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, outSyncFd);
+ renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, regionSampling,
+ outSyncFd);
return NO_ERROR;
}
@@ -5912,11 +5901,11 @@
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
- HWC2::VsyncPeriodChangeConstraints constraints;
+ hal::VsyncPeriodChangeConstraints constraints;
constraints.desiredTimeNanos = systemTime();
constraints.seamlessRequired = false;
- HWC2::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
+ hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
if (getHwComposer().setActiveConfigWithConstraints(*displayId,
policy->defaultConfig.value(),
constraints, &timeline) < 0) {
@@ -5951,15 +5940,18 @@
}
scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy();
- ALOGV("Setting desired display config specs: defaultConfig: %d min: %.f max: %.f",
- currentPolicy.defaultConfig.value(), currentPolicy.minRefreshRate,
- currentPolicy.maxRefreshRate);
+ ALOGV("Setting desired display config specs: defaultConfig: %d primaryRange: [%.0f %.0f]"
+ " expandedRange: [%.0f %.0f]",
+ currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min,
+ currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min,
+ currentPolicy.appRequestRange.max);
// TODO(b/140204874): This hack triggers a notification that something has changed, so
// that listeners that care about a change in allowed configs can get the notification.
// Giving current ActiveConfig so that most other listeners would just drop the event
const nsecs_t vsyncPeriod =
- mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig()).vsyncPeriod;
+ mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig())
+ .getVsyncPeriod();
mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
display->getActiveConfig(), vsyncPeriod);
@@ -5969,59 +5961,66 @@
// NOTE: Choose the default config ID, if Scheduler doesn't have one in mind.
: mRefreshRateConfigs->getRefreshRateFromConfigId(currentPolicy.defaultConfig);
ALOGV("trying to switch to Scheduler preferred config %d (%s)",
- preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str());
+ preferredRefreshRate.getConfigId().value(), preferredRefreshRate.getName().c_str());
- if (isDisplayConfigAllowed(preferredRefreshRate.configId)) {
- ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value());
- setDesiredActiveConfig({preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed});
+ if (isDisplayConfigAllowed(preferredRefreshRate.getConfigId())) {
+ ALOGV("switching to Scheduler preferred config %d",
+ preferredRefreshRate.getConfigId().value());
+ setDesiredActiveConfig(
+ {preferredRefreshRate.getConfigId(), Scheduler::ConfigEvent::Changed});
} else {
- LOG_ALWAYS_FATAL("Desired config not allowed: %d", preferredRefreshRate.configId.value());
+ LOG_ALWAYS_FATAL("Desired config not allowed: %d",
+ preferredRefreshRate.getConfigId().value());
}
return NO_ERROR;
}
status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, float minRefreshRate,
- float maxRefreshRate) {
+ int32_t defaultConfig,
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) {
ATRACE_CALL();
if (!displayToken) {
return BAD_VALUE;
}
- status_t result = NO_ERROR;
-
- postMessageSync(new LambdaMessage([&]() {
+ auto future = schedule([=]() -> status_t {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
- result = BAD_VALUE;
ALOGE("Attempt to set desired display configs for invalid display token %p",
displayToken.get());
+ return NAME_NOT_FOUND;
} else if (display->isVirtual()) {
- result = BAD_VALUE;
ALOGW("Attempt to set desired display configs for virtual display");
+ return INVALID_OPERATION;
} else {
- result = setDesiredDisplayConfigSpecsInternal(display,
- scheduler::RefreshRateConfigs::
- Policy{HwcConfigIndexType(
- defaultConfig),
- minRefreshRate,
- maxRefreshRate},
- /*overridePolicy=*/false);
- }
- }));
+ using Policy = scheduler::RefreshRateConfigs::Policy;
+ const Policy policy{HwcConfigIndexType(defaultConfig),
+ {primaryRefreshRateMin, primaryRefreshRateMax},
+ {appRequestRefreshRateMin, appRequestRefreshRateMax}};
+ constexpr bool kOverridePolicy = false;
- return result;
+ return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy);
+ }
+ });
+
+ return future.get();
}
status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
int32_t* outDefaultConfig,
- float* outMinRefreshRate,
- float* outMaxRefreshRate) {
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) {
ATRACE_CALL();
- if (!displayToken || !outDefaultConfig || !outMinRefreshRate || !outMaxRefreshRate) {
+ if (!displayToken || !outDefaultConfig || !outPrimaryRefreshRateMin ||
+ !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) {
return BAD_VALUE;
}
@@ -6035,20 +6034,23 @@
scheduler::RefreshRateConfigs::Policy policy =
mRefreshRateConfigs->getDisplayManagerPolicy();
*outDefaultConfig = policy.defaultConfig.value();
- *outMinRefreshRate = policy.minRefreshRate;
- *outMaxRefreshRate = policy.maxRefreshRate;
+ *outPrimaryRefreshRateMin = policy.primaryRange.min;
+ *outPrimaryRefreshRateMax = policy.primaryRange.max;
+ *outAppRequestRefreshRateMin = policy.appRequestRange.min;
+ *outAppRequestRefreshRateMax = policy.appRequestRange.max;
return NO_ERROR;
} else if (display->isVirtual()) {
- return BAD_VALUE;
+ return INVALID_OPERATION;
} else {
const auto displayId = display->getId();
- if (!displayId) {
- return BAD_VALUE;
- }
+ LOG_FATAL_IF(!displayId);
+
*outDefaultConfig = getHwComposer().getActiveConfigIndex(*displayId);
auto vsyncPeriod = getHwComposer().getActiveConfig(*displayId)->getVsyncPeriod();
- *outMinRefreshRate = 1e9f / vsyncPeriod;
- *outMaxRefreshRate = 1e9f / vsyncPeriod;
+ *outPrimaryRefreshRateMin = 1e9f / vsyncPeriod;
+ *outPrimaryRefreshRateMax = 1e9f / vsyncPeriod;
+ *outAppRequestRefreshRateMin = 1e9f / vsyncPeriod;
+ *outAppRequestRefreshRateMax = 1e9f / vsyncPeriod;
return NO_ERROR;
}
}
@@ -6057,7 +6059,12 @@
mFlinger->setInputWindowsFinished();
}
-sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
+ Mutex::Autolock _l(mStateLock);
+ return fromHandleLocked(handle);
+}
+
+wp<Layer> SurfaceFlinger::fromHandleLocked(const sp<IBinder>& handle) {
BBinder* b = nullptr;
if (handle) {
b = handle->localBinder();
@@ -6067,7 +6074,7 @@
}
auto it = mLayersByLocalBinderToken.find(b);
if (it != mLayersByLocalBinderToken.end()) {
- return it->second.promote();
+ return it->second;
}
return nullptr;
}
@@ -6137,7 +6144,7 @@
return BAD_VALUE;
}
- postMessageAsync(new LambdaMessage([=]() NO_THREAD_SAFETY_ANALYSIS {
+ static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
Mutex::Autolock lock(mStateLock);
if (authenticateSurfaceTextureLocked(surface)) {
sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
@@ -6160,8 +6167,11 @@
if (!outToken) {
return BAD_VALUE;
}
- status_t result = NO_ERROR;
- postMessageSync(new LambdaMessage([&]() {
+
+ auto future = schedule([this] {
+ status_t result = NO_ERROR;
+ sp<IBinder> token;
+
if (mFrameRateFlexibilityTokenCount == 0) {
// |mStateLock| not needed as we are on the main thread
const auto display = getDefaultDisplayDeviceLocked();
@@ -6175,8 +6185,8 @@
overridePolicy.defaultConfig =
mRefreshRateConfigs->getDisplayManagerPolicy().defaultConfig;
overridePolicy.allowGroupSwitching = true;
- result = setDesiredDisplayConfigSpecsInternal(display, overridePolicy,
- /*overridePolicy=*/true);
+ constexpr bool kOverridePolicy = true;
+ result = setDesiredDisplayConfigSpecsInternal(display, overridePolicy, kOverridePolicy);
}
if (result == NO_ERROR) {
@@ -6193,17 +6203,22 @@
// 2. The frame rate flexibility token is acquired/released only by CTS tests, so even
// if condition 1 were changed, the problem would only show up when running CTS tests,
// not on end user devices, so we could spot it and fix it without serious impact.
- *outToken = new FrameRateFlexibilityToken(
+ token = new FrameRateFlexibilityToken(
[this]() { onFrameRateFlexibilityTokenReleased(); });
ALOGD("Frame rate flexibility token acquired. count=%d",
mFrameRateFlexibilityTokenCount);
}
- }));
+
+ return std::make_pair(result, token);
+ });
+
+ status_t result;
+ std::tie(result, *outToken) = future.get();
return result;
}
void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() {
- postMessageAsync(new LambdaMessage([&]() {
+ static_cast<void>(schedule([this] {
LOG_ALWAYS_FATAL_IF(mFrameRateFlexibilityTokenCount == 0,
"Failed tracking frame rate flexibility tokens");
mFrameRateFlexibilityTokenCount--;
@@ -6211,13 +6226,36 @@
if (mFrameRateFlexibilityTokenCount == 0) {
// |mStateLock| not needed as we are on the main thread
const auto display = getDefaultDisplayDeviceLocked();
- status_t result =
- setDesiredDisplayConfigSpecsInternal(display, {}, /*overridePolicy=*/true);
+ constexpr bool kOverridePolicy = true;
+ status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy);
LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token");
}
}));
}
+void SurfaceFlinger::enableRefreshRateOverlay(bool enable) {
+ static_cast<void>(schedule([=] {
+ std::unique_ptr<RefreshRateOverlay> overlay;
+ if (enable) {
+ overlay = std::make_unique<RefreshRateOverlay>(*this);
+ }
+
+ {
+ Mutex::Autolock lock(mStateLock);
+
+ // Destroy the layer of the current overlay, if any, outside the lock.
+ mRefreshRateOverlay.swap(overlay);
+ if (!mRefreshRateOverlay) return;
+
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
+ mRefreshRateOverlay->setViewport(display->getSize());
+ }
+
+ mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
+ }
+ }));
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 12efca1..509de0f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -33,7 +33,6 @@
#include <gui/ITransactionCompletedListener.h>
#include <gui/LayerState.h>
#include <gui/OccupancyTracker.h>
-#include <hardware/hwcomposer_defs.h>
#include <input/ISetInputWindowsListener.h>
#include <layerproto/LayerProtoHeader.h>
#include <math/mat4.h>
@@ -69,6 +68,7 @@
#include <atomic>
#include <cstdint>
#include <functional>
+#include <future>
#include <map>
#include <memory>
#include <mutex>
@@ -117,7 +117,7 @@
eTransactionNeeded = 0x01,
eTraversalNeeded = 0x02,
eDisplayTransactionNeeded = 0x04,
- eDisplayLayerStackChanged = 0x08,
+ eTransformHintUpdateNeeded = 0x08,
eTransactionFlushNeeded = 0x10,
eTransactionMask = 0x1f,
};
@@ -277,12 +277,9 @@
// starts SurfaceFlinger main loop in the current thread
void run() ANDROID_API;
- // post an asynchronous message to the main thread
- status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0);
-
- // post a synchronous message to the main thread
- status_t postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0)
- EXCLUDES(mStateLock);
+ // Schedule an asynchronous or synchronous task on the main thread.
+ template <typename F, typename T = std::invoke_result_t<F>>
+ [[nodiscard]] std::future<T> schedule(F&&);
// force full composition on all displays
void repaintEverything();
@@ -311,12 +308,12 @@
// main thread function to enable/disable h/w composer event
void setPrimaryVsyncEnabledInternal(bool enabled);
- void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
+ void setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled);
// called on the main thread by MessageQueue when an internal message
// is received
// TODO: this should be made accessible only to MessageQueue
- void onMessageReceived(int32_t what);
+ void onMessageReceived(int32_t what, nsecs_t expectedVSyncTime);
renderengine::RenderEngine& getRenderEngine() const;
@@ -332,7 +329,12 @@
return mTransactionCompletedThread;
}
- sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
+ // Converts from a binder handle to a Layer
+ // Returns nullptr if the handle does not point to an existing layer.
+ // Otherwise, returns a weak reference so that callers off the main-thread
+ // won't accidentally hold onto the last strong reference.
+ wp<Layer> fromHandle(const sp<IBinder>& handle);
+ wp<Layer> fromHandleLocked(const sp<IBinder>& handle) REQUIRES(mStateLock);
// Inherit from ClientCache::ErasedRecipient
void bufferErased(const client_cache_t& clientCacheId) override;
@@ -475,14 +477,13 @@
status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
ui::Dataspace* outWideColorGamutDataspace,
ui::PixelFormat* outWideColorGamutPixelFormat) const override;
- status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+ status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) const override;
- status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask,
- uint64_t maxFrames) const override;
- status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+ status_t setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken, bool enable,
+ uint8_t componentMask, uint64_t maxFrames) override;
+ status_t getDisplayedContentSample(const sp<IBinder>& displayToken, uint64_t maxFrames,
uint64_t timestamp,
DisplayedFrameStats* outStats) const override;
status_t getProtectedContentSupport(bool* outSupported) const override;
@@ -492,13 +493,18 @@
const sp<IRegionSamplingListener>& listener) override;
status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t displayModeId,
- float minRefreshRate, float maxRefreshRate) override;
+ float primaryRefreshRateMin, float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) override;
status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t* outDefaultConfig, float* outMinRefreshRate,
- float* outMaxRefreshRate) override;
+ int32_t* outDefaultConfig,
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) override;
status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
bool* outSupport) const override;
- status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) const override;
+ status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) override;
status_t notifyPowerHint(int32_t hintId) override;
status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ, float lightRadius) override;
@@ -518,15 +524,15 @@
/* ------------------------------------------------------------------------
* HWC2::ComposerCallback / HWComposer::EventHandler interface
*/
- void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, int64_t timestamp,
- std::optional<hwc2_vsync_period_t> vsyncPeriod) override;
- void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
- HWC2::Connection connection) override;
- void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override;
+ void onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, int64_t timestamp,
+ std::optional<hal::VsyncPeriodNanos> vsyncPeriod) override;
+ void onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
+ hal::Connection connection) override;
+ void onRefreshReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId) override;
void onVsyncPeriodTimingChangedReceived(
- int32_t sequenceId, hwc2_display_t display,
- const hwc_vsync_period_change_timeline_t& updatedTimeline) override;
- void onSeamlessPossible(int32_t sequenceId, hwc2_display_t display) override;
+ int32_t sequenceId, hal::HWDisplayId display,
+ const hal::VsyncPeriodChangeTimeline& updatedTimeline) override;
+ void onSeamlessPossible(int32_t sequenceId, hal::HWDisplayId display) override;
/* ------------------------------------------------------------------------
* ISchedulerCallback
@@ -539,7 +545,6 @@
/* ------------------------------------------------------------------------
* Message handling
*/
- void waitForEvent();
// Can only be called from the main thread or with mStateLock held
void signalTransaction();
// Can only be called from the main thread or with mStateLock held
@@ -565,15 +570,14 @@
// Once HWC has returned the present fence, this sets the active config and a new refresh
// rate in SF.
void setActiveConfigInternal() REQUIRES(mStateLock);
- // Active config is updated on INVALIDATE call in a state machine-like manner. When the
- // desired config was set, HWC needs to update the panel on the next refresh, and when
- // we receive the fence back, we know that the process was complete. It returns whether
- // we need to wait for the next invalidate
- bool performSetActiveConfig() REQUIRES(mStateLock);
+ // Calls to setActiveConfig on the main thread if there is a pending config
+ // that needs to be applied.
+ void performSetActiveConfig() REQUIRES(mStateLock);
// Called when active config is no longer is progress
void desiredActiveConfigChangeDone() REQUIRES(mStateLock);
// called on the main thread in response to setPowerMode()
- void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
+ void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
+ REQUIRES(mStateLock);
// Sets the desired display configs.
status_t setDesiredDisplayConfigSpecsInternal(
@@ -581,19 +585,20 @@
const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy)
EXCLUDES(mStateLock);
- // called on the main thread in response to setAutoLowLatencyMode()
- void setAutoLowLatencyModeInternal(const sp<IBinder>& displayToken, bool on);
- // called on the main thread in response to setGameContentType()
- void setGameContentTypeInternal(const sp<IBinder>& displayToken, bool on);
+ // Handle the INVALIDATE message queue event, latching new buffers and applying
+ // incoming transactions
+ void onMessageInvalidate(nsecs_t expectedVSyncTime);
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
+ // Handle the REFRESH message queue event, sending the current frame down to RenderEngine and
+ // the Composer HAL for presentation
+ void onMessageRefresh();
+
// Returns whether a new buffer has been latched (see handlePageFlip())
bool handleMessageInvalidate();
- void handleMessageRefresh();
-
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(uint32_t transactionFlags) REQUIRES(mStateLock);
@@ -633,7 +638,6 @@
void commitTransaction() REQUIRES(mStateLock);
void commitOffscreenLayers();
bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
- bool useCachedExpectedPresentTime,
const Vector<ComposerState>& states);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
@@ -647,6 +651,13 @@
REQUIRES(mStateLock);
virtual void commitTransactionLocked();
+ // Used internally by computeLayerBounds() to gets the clip rectangle to use for the
+ // root layers on a particular display in layer-coordinate space. The
+ // layers (and effectively their children) will be clipped against this
+ // rectangle. The base behavior is to clip to the visible region of the
+ // display.
+ virtual FloatRect getLayerClipBoundsForDisplay(const DisplayDevice&) const;
+
private:
/* ------------------------------------------------------------------------
* Layer management
@@ -664,8 +675,7 @@
status_t createBufferStateLayer(const sp<Client>& client, std::string name, uint32_t w,
uint32_t h, uint32_t flags, LayerMetadata metadata,
- sp<IBinder>* outHandle, uint32_t* outTransformHint,
- sp<Layer>* outLayer);
+ sp<IBinder>* outHandle, sp<Layer>* outLayer);
status_t createEffectLayer(const sp<Client>& client, std::string name, uint32_t w, uint32_t h,
uint32_t flags, LayerMetadata metadata, sp<IBinder>* outHandle,
@@ -690,7 +700,7 @@
status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer,
- bool addToCurrentState);
+ bool addToCurrentState, uint32_t* outTransformHint);
// Traverse through all the layers and compute and cache its bounds.
void computeLayerBounds();
@@ -705,19 +715,20 @@
void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
- int* outSyncFd);
+ bool regionSampling, int* outSyncFd);
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat,
bool useIdentityTransform, bool& outCapturedSecureLayers);
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer, bool useIdentityTransform,
- bool& outCapturedSecureLayers);
+ bool regionSampling, bool& outCapturedSecureLayers);
const sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack);
const sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack);
status_t captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
- bool forSystem, int* outSyncFd, bool& outCapturedSecureLayers);
+ bool forSystem, int* outSyncFd, bool regionSampling,
+ bool& outCapturedSecureLayers);
void traverseLayersInDisplay(const sp<const DisplayDevice>& display,
const LayerVector::Visitor& visitor);
@@ -740,16 +751,6 @@
// called when starting, or restarting after system_server death
void initializeDisplays();
- sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& displayToken) const {
- Mutex::Autolock _l(mStateLock);
- return getDisplayDeviceLocked(displayToken);
- }
-
- sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& displayToken) {
- Mutex::Autolock _l(mStateLock);
- return getDisplayDeviceLocked(displayToken);
- }
-
// NOTE: can only be called from the main thread or with mStateLock held
sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) const {
return const_cast<SurfaceFlinger*>(this)->getDisplayDeviceLocked(displayToken);
@@ -827,13 +828,13 @@
const DisplayDeviceState& state,
const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer);
- void processDisplayChangesLocked();
+ void processDisplayChangesLocked() REQUIRES(mStateLock);
void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state);
void processDisplayRemoved(const wp<IBinder>& displayToken);
void processDisplayChanged(const wp<IBinder>& displayToken,
const DisplayDeviceState& currentState,
- const DisplayDeviceState& drawingState);
- void processDisplayHotplugEventsLocked();
+ const DisplayDeviceState& drawingState) REQUIRES(mStateLock);
+ void processDisplayHotplugEventsLocked() REQUIRES(mStateLock);
void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected);
@@ -865,9 +866,9 @@
// Must be called on the main thread.
nsecs_t previousFramePresentTime();
- // Populates the expected present time for this frame. For negative offsets, performs a
+ // Calculates the expected present time for this frame. For negative offsets, performs a
// correction using the predicted vsync for the next frame instead.
- void populateExpectedPresentTime();
+ nsecs_t calculateExpectedPresentTime(nsecs_t now) const;
/*
* Display identification
@@ -947,8 +948,7 @@
void dumpDisplayIdentificationData(std::string& result) const;
void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
void dumpWideColorInfo(std::string& result) const;
- LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL,
- const sp<const DisplayDevice>& displayDevice = nullptr) const;
+ LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
void dumpOffscreenLayersProto(LayersProto& layersProto,
uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
// Dumps state from HW Composer
@@ -956,7 +956,6 @@
LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
EXCLUDES(mStateLock);
void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock);
- void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
@@ -998,9 +997,6 @@
SortedVector<sp<Layer>> mLayersPendingRemoval;
bool mTraversalNeededMainThread = false;
- // guards access to the mDrawing state if tracing is enabled.
- mutable std::mutex mDrawingStateLock;
-
// global color transform states
Daltonizer mDaltonizer;
float mGlobalSaturationFactor = 1.0f;
@@ -1010,6 +1006,8 @@
std::set<wp<IBinder>> mGraphicBufferProducerList;
size_t mMaxGraphicBufferProducerListSize = ISurfaceComposer::MAX_LAYERS;
+ void removeGraphicBufferProducerAsync(const wp<IBinder>&);
+
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved = false;
bool mLayersAdded = false;
@@ -1052,8 +1050,8 @@
BootStage mBootStage = BootStage::BOOTLOADER;
struct HotplugEvent {
- hwc2_display_t hwcDisplayId;
- HWC2::Connection connection = HWC2::Connection::Invalid;
+ hal::HWDisplayId hwcDisplayId;
+ hal::Connection connection = hal::Connection::INVALID;
};
// protected by mStateLock
std::vector<HotplugEvent> mPendingHotplugEvents;
@@ -1075,10 +1073,13 @@
bool mPropagateBackpressure = true;
bool mPropagateBackpressureClientComposition = false;
std::unique_ptr<SurfaceInterceptor> mInterceptor;
+
SurfaceTracing mTracing{*this};
+ std::mutex mTracingLock;
bool mTracingEnabled = false;
bool mAddCompositionStateToTrace = false;
- bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
+ std::atomic<bool> mTracingEnabledChanged = false;
+
const std::shared_ptr<TimeStats> mTimeStats;
const std::unique_ptr<FrameTracer> mFrameTracer;
bool mUseHwcVirtualDisplays = false;
@@ -1214,6 +1215,12 @@
* Misc
*/
+ std::optional<ActiveConfigInfo> getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) {
+ std::lock_guard<std::mutex> lock(mActiveConfigLock);
+ if (mDesiredActiveConfigChanged) return mDesiredActiveConfig;
+ return std::nullopt;
+ }
+
std::mutex mActiveConfigLock;
// This bit is set once we start setting the config. We read from this bit during the
// process. If at the end, this bit is different than mDesiredActiveConfig, we restart
@@ -1225,7 +1232,7 @@
// below flags are set by main thread only
TracedOrdinal<bool> mDesiredActiveConfigChanged
GUARDED_BY(mActiveConfigLock) = {"DesiredActiveConfigChanged", false};
- bool mCheckPendingFence = false;
+ bool mSetActiveConfigPending = false;
bool mLumaSampling = true;
sp<RegionSamplingThread> mRegionSamplingThread;
@@ -1256,7 +1263,8 @@
// This should only be accessed on the main thread.
nsecs_t mFrameStartTime = 0;
- std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay;
+ void enableRefreshRateOverlay(bool enable);
+ std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock);
// Flag used to set override allowed display configs from backdoor
bool mDebugDisplayConfigSetByBackdoor = false;
@@ -1268,20 +1276,17 @@
std::unordered_set<Layer*> mOffscreenLayers;
// Flags to capture the state of Vsync in HWC
- HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable;
- HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable;
+ hal::Vsync mHWCVsyncState = hal::Vsync::DISABLE;
+ hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE;
// Fields tracking the current jank event: when it started and how many
// janky frames there are.
nsecs_t mMissedFrameJankStart = 0;
int32_t mMissedFrameJankCount = 0;
- // See updateInputWindowInfo() for details
- std::atomic<bool> mInputDirty = true;
- void dirtyInput() { mInputDirty = true; }
- bool inputDirty() { return mInputDirty; }
-
int mFrameRateFlexibilityTokenCount = 0;
+
+ sp<IBinder> mDebugFrameRateFlexibilityToken;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index f0b895d..d84ce69 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -33,7 +33,7 @@
namespace android {
SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger)
- : mFlinger(flinger), mSfLock(flinger.mDrawingStateLock) {}
+ : mFlinger(flinger), mSfLock(flinger.mTracingLock) {}
void SurfaceTracing::mainLoop() {
bool enabled = addFirstEntry();
@@ -44,21 +44,19 @@
}
bool SurfaceTracing::addFirstEntry() {
- const auto displayDevice = mFlinger.getDefaultDisplayDevice();
LayersTraceProto entry;
{
std::scoped_lock lock(mSfLock);
- entry = traceLayersLocked("tracing.enable", displayDevice);
+ entry = traceLayersLocked("tracing.enable");
}
return addTraceToBuffer(entry);
}
LayersTraceProto SurfaceTracing::traceWhenNotified() {
- const auto displayDevice = mFlinger.getDefaultDisplayDevice();
std::unique_lock<std::mutex> lock(mSfLock);
mCanStartTrace.wait(lock);
android::base::ScopedLockAssertion assumeLock(mSfLock);
- LayersTraceProto entry = traceLayersLocked(mWhere, displayDevice);
+ LayersTraceProto entry = traceLayersLocked(mWhere);
mTracingInProgress = false;
mMissedTraceEntries = 0;
lock.unlock();
@@ -126,15 +124,17 @@
}
}
-void SurfaceTracing::enable() {
+bool SurfaceTracing::enable() {
std::scoped_lock lock(mTraceLock);
if (mEnabled) {
- return;
+ return false;
}
+
mBuffer.reset(mBufferSize);
mEnabled = true;
mThread = std::thread(&SurfaceTracing::mainLoop, this);
+ return true;
}
status_t SurfaceTracing::writeToFile() {
@@ -176,14 +176,13 @@
mTraceFlags = flags;
}
-LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where,
- const sp<const DisplayDevice>& displayDevice) {
+LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
ATRACE_CALL();
LayersTraceProto entry;
entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry.set_where(where);
- LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags, displayDevice));
+ LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
if (flagIsSetLocked(SurfaceTracing::TRACE_EXTRA)) {
mFlinger.dumpOffscreenLayersProto(layers);
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index e90fc4d..f208eb8 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -27,8 +27,6 @@
#include <queue>
#include <thread>
-#include "DisplayDevice.h"
-
using namespace android::surfaceflinger;
namespace android {
@@ -44,7 +42,7 @@
class SurfaceTracing {
public:
explicit SurfaceTracing(SurfaceFlinger& flinger);
- void enable();
+ bool enable();
bool disable();
status_t writeToFile();
bool isEnabled() const;
@@ -92,9 +90,7 @@
void mainLoop();
bool addFirstEntry();
LayersTraceProto traceWhenNotified();
- LayersTraceProto traceLayersLocked(const char* where,
- const sp<const DisplayDevice>& displayDevice)
- REQUIRES(mSfLock);
+ LayersTraceProto traceLayersLocked(const char* where) REQUIRES(mSfLock);
// Returns true if trace is enabled.
bool addTraceToBuffer(LayersTraceProto& entry);
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index d27fbb4..3901757 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -4,6 +4,7 @@
"TimeStats.cpp",
],
shared_libs: [
+ "android.hardware.graphics.composer@2.4",
"libbase",
"libcutils",
"liblog",
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 606e137..37194c6 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -290,6 +290,15 @@
mTimeStats.refreshRateSwitches++;
}
+void TimeStats::incrementCompositionStrategyChanges() {
+ if (!mEnabled.load()) return;
+
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ mTimeStats.compositionStrategyChanges++;
+}
+
void TimeStats::recordDisplayEventConnectionCount(int32_t count) {
if (!mEnabled.load()) return;
@@ -312,7 +321,7 @@
if (!mEnabled.load()) return;
std::lock_guard<std::mutex> lock(mMutex);
- if (mPowerTime.powerMode == HWC_POWER_MODE_NORMAL) {
+ if (mPowerTime.powerMode == PowerMode::ON) {
mTimeStats.frameDuration.insert(msBetween(startTime, endTime));
}
}
@@ -683,12 +692,13 @@
int64_t elapsedTime = (curTime - mPowerTime.prevTime) / 1000000;
switch (mPowerTime.powerMode) {
- case HWC_POWER_MODE_NORMAL:
+ case PowerMode::ON:
mTimeStats.displayOnTime += elapsedTime;
break;
- case HWC_POWER_MODE_OFF:
- case HWC_POWER_MODE_DOZE:
- case HWC_POWER_MODE_DOZE_SUSPEND:
+ case PowerMode::OFF:
+ case PowerMode::DOZE:
+ case PowerMode::DOZE_SUSPEND:
+ case PowerMode::ON_SUSPEND:
default:
break;
}
@@ -696,7 +706,7 @@
mPowerTime.prevTime = curTime;
}
-void TimeStats::setPowerMode(int32_t powerMode) {
+void TimeStats::setPowerMode(PowerMode powerMode) {
if (!mEnabled.load()) {
std::lock_guard<std::mutex> lock(mMutex);
mPowerTime.powerMode = powerMode;
@@ -784,8 +794,8 @@
return;
}
- if (mPowerTime.powerMode != HWC_POWER_MODE_NORMAL) {
- // Try flushing the last present fence on HWC_POWER_MODE_NORMAL.
+ if (mPowerTime.powerMode != PowerMode::ON) {
+ // Try flushing the last present fence on PowerMode::ON.
flushAvailableGlobalRecordsToStatsLocked();
mGlobalRecord.presentFences.clear();
mGlobalRecord.prevPresentTime = 0;
@@ -844,6 +854,7 @@
mTimeStats.clientCompositionFrames = 0;
mTimeStats.clientCompositionReusedFrames = 0;
mTimeStats.refreshRateSwitches = 0;
+ mTimeStats.compositionStrategyChanges = 0;
mTimeStats.displayEventConnectionsCount = 0;
mTimeStats.displayOnTime = 0;
mTimeStats.presentToPresent.hist.clear();
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 806b47e..8de5d0c 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -16,7 +16,15 @@
#pragma once
-#include <hardware/hwcomposer_defs.h>
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"
+
#include <stats_event.h>
#include <stats_pull_atom_callback.h>
#include <statslog.h>
@@ -54,6 +62,10 @@
virtual void incrementClientCompositionReusedFrames() = 0;
// Increments the number of times the display refresh rate changed.
virtual void incrementRefreshRateSwitches() = 0;
+ // Increments the number of changes in composition strategy
+ // The intention is to reflect the number of changes between hwc and gpu
+ // composition, where "gpu composition" may also include mixed composition.
+ virtual void incrementCompositionStrategyChanges() = 0;
// Records the most up-to-date count of display event connections.
// The stored count will be the maximum ever recoded.
virtual void recordDisplayEventConnectionCount(int32_t count) = 0;
@@ -101,7 +113,8 @@
// If SF skips or rejects a buffer, remove the corresponding TimeRecord.
virtual void removeTimeRecord(int32_t layerId, uint64_t frameNumber) = 0;
- virtual void setPowerMode(int32_t powerMode) = 0;
+ virtual void setPowerMode(
+ hardware::graphics::composer::V2_4::IComposerClient::PowerMode powerMode) = 0;
// Source of truth is RefrehRateStats.
virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0;
virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0;
@@ -110,6 +123,8 @@
namespace impl {
class TimeStats : public android::TimeStats {
+ using PowerMode = android::hardware::graphics::composer::V2_4::IComposerClient::PowerMode;
+
struct FrameTime {
uint64_t frameNumber = 0;
nsecs_t postTime = 0;
@@ -140,7 +155,7 @@
};
struct PowerTime {
- int32_t powerMode = HWC_POWER_MODE_OFF;
+ PowerMode powerMode = PowerMode::OFF;
nsecs_t prevTime = 0;
};
@@ -218,6 +233,7 @@
void incrementClientCompositionFrames() override;
void incrementClientCompositionReusedFrames() override;
void incrementRefreshRateSwitches() override;
+ void incrementCompositionStrategyChanges() override;
void recordDisplayEventConnectionCount(int32_t count) override;
void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) override;
@@ -242,7 +258,8 @@
// If SF skips or rejects a buffer, remove the corresponding TimeRecord.
void removeTimeRecord(int32_t layerId, uint64_t frameNumber) override;
- void setPowerMode(int32_t powerMode) override;
+ void setPowerMode(
+ hardware::graphics::composer::V2_4::IComposerClient::PowerMode powerMode) override;
// Source of truth is RefrehRateStats.
void recordRefreshRate(uint32_t fps, nsecs_t duration) override;
void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override;
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index 5305de9..c90b1b8 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -106,6 +106,7 @@
StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
StringAppendF(&result, "clientCompositionReusedFrames = %d\n", clientCompositionReusedFrames);
StringAppendF(&result, "refreshRateSwitches = %d\n", refreshRateSwitches);
+ StringAppendF(&result, "compositionStrategyChanges = %d\n", compositionStrategyChanges);
StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTime);
StringAppendF(&result, "displayConfigStats is as below:\n");
for (const auto& [fps, duration] : refreshRateStats) {
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index afb98e0..0c75f96 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -63,6 +63,7 @@
int32_t clientCompositionFrames = 0;
int32_t clientCompositionReusedFrames = 0;
int32_t refreshRateSwitches = 0;
+ int32_t compositionStrategyChanges = 0;
int32_t displayEventConnectionsCount = 0;
int64_t displayOnTime = 0;
Histogram presentToPresent;
diff --git a/services/surfaceflinger/TracedOrdinal.h b/services/surfaceflinger/TracedOrdinal.h
index c145a39..4e7f67d 100644
--- a/services/surfaceflinger/TracedOrdinal.h
+++ b/services/surfaceflinger/TracedOrdinal.h
@@ -16,10 +16,13 @@
#pragma once
#include <android-base/stringprintf.h>
+#include <cutils/compiler.h>
#include <utils/Trace.h>
#include <cmath>
#include <string>
+namespace android {
+
template <typename T>
class TracedOrdinal {
public:
@@ -27,9 +30,8 @@
"Type is not supported. Please test it with systrace before adding "
"it to the list.");
- TracedOrdinal(const std::string& name, T initialValue)
- : mName(name),
- mNameNegative(android::base::StringPrintf("%sNegative", name.c_str())),
+ TracedOrdinal(std::string name, T initialValue)
+ : mName(std::move(name)),
mHasGoneNegative(std::signbit(initialValue)),
mData(initialValue) {
trace();
@@ -46,6 +48,14 @@
private:
void trace() {
+ if (CC_LIKELY(!ATRACE_ENABLED())) {
+ return;
+ }
+
+ if (mNameNegative.empty()) {
+ mNameNegative = base::StringPrintf("%sNegative", mName.c_str());
+ }
+
if (!std::signbit(mData)) {
ATRACE_INT64(mName.c_str(), int64_t(mData));
if (mHasGoneNegative) {
@@ -58,7 +68,9 @@
}
const std::string mName;
- const std::string mNameNegative;
+ std::string mNameNegative;
bool mHasGoneNegative;
T mData;
};
+
+} // namespace android
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index d3942e8..575e70d 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -4,7 +4,7 @@
group graphics drmrpc readproc
capabilities SYS_NICE
onrestart restart zygote
- writepid /dev/stune/foreground/tasks
+ task_profiles HighPerformance
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index 507d28b..c136708 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -215,14 +215,21 @@
TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
const auto display = SurfaceComposerClient::getInternalDisplayToken();
int32_t defaultConfig;
- float minFps;
- float maxFps;
- status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
- &minFps, &maxFps);
+ float primaryFpsMin;
+ float primaryFpsMax;
+ float appRequestFpsMin;
+ float appRequestFpsMax;
+ status_t res =
+ SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
+ &primaryFpsMin, &primaryFpsMax,
+ &appRequestFpsMin,
+ &appRequestFpsMax);
ASSERT_EQ(res, NO_ERROR);
std::function<status_t()> condition = [=]() {
- return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, minFps,
- maxFps);
+ return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig,
+ primaryFpsMin, primaryFpsMax,
+ appRequestFpsMin,
+ appRequestFpsMax);
};
ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
}
diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
index 0ed2ffb..debfe83 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -39,11 +39,16 @@
TEST_F(RefreshRateRangeTest, setAllConfigs) {
int32_t initialDefaultConfig;
- float initialMin;
- float initialMax;
+ float initialPrimaryMin;
+ float initialPrimaryMax;
+ float initialAppRequestMin;
+ float initialAppRequestMax;
status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken,
&initialDefaultConfig,
- &initialMin, &initialMax);
+ &initialPrimaryMin,
+ &initialPrimaryMax,
+ &initialAppRequestMin,
+ &initialAppRequestMax);
ASSERT_EQ(res, NO_ERROR);
Vector<DisplayConfig> configs;
@@ -53,22 +58,33 @@
for (size_t i = 0; i < configs.size(); i++) {
res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, i,
configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate,
configs[i].refreshRate);
ASSERT_EQ(res, NO_ERROR);
int defaultConfig;
- float minRefreshRate;
- float maxRefreshRate;
+ float primaryRefreshRateMin;
+ float primaryRefreshRateMax;
+ float appRequestRefreshRateMin;
+ float appRequestRefreshRateMax;
res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig,
- &minRefreshRate, &maxRefreshRate);
+ &primaryRefreshRateMin,
+ &primaryRefreshRateMax,
+ &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax);
ASSERT_EQ(res, NO_ERROR);
ASSERT_EQ(defaultConfig, i);
- ASSERT_EQ(minRefreshRate, configs[i].refreshRate);
- ASSERT_EQ(maxRefreshRate, configs[i].refreshRate);
+ ASSERT_EQ(primaryRefreshRateMin, configs[i].refreshRate);
+ ASSERT_EQ(primaryRefreshRateMax, configs[i].refreshRate);
+ ASSERT_EQ(appRequestRefreshRateMin, configs[i].refreshRate);
+ ASSERT_EQ(appRequestRefreshRateMax, configs[i].refreshRate);
}
res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, initialDefaultConfig,
- initialMin, initialMax);
+ initialPrimaryMin, initialPrimaryMax,
+ initialAppRequestMin,
+ initialAppRequestMax);
ASSERT_EQ(res, NO_ERROR);
}
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 40ec502..f3e11d8 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -19,7 +19,6 @@
#include <gtest/gtest.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <hardware/hwcomposer_defs.h>
#include <private/gui/ComposerService.h>
#include <ui/DisplayConfig.h>
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index ff403f6..2861013 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -23,7 +23,6 @@
"libcutils",
"libfmq",
"libgui",
- "libhardware",
"libhidlbase",
"liblayers_proto",
"liblog",
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
index 5240b72..600e765 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
@@ -16,24 +16,16 @@
#pragma once
-#define HWC2_USE_CPP11
-#define HWC2_INCLUDE_STRINGIFICATION
+#include <chrono>
+
#include <composer-hal/2.1/ComposerClient.h>
#include <composer-hal/2.2/ComposerClient.h>
#include <composer-hal/2.3/ComposerClient.h>
#include <composer-hal/2.4/ComposerClient.h>
-#undef HWC2_USE_CPP11
-#undef HWC2_INCLUDE_STRINGIFICATION
-#include "RenderState.h"
-
-#include "MockComposerHal.h"
-
-// Needed for display type/ID enums
-#include <hardware/hwcomposer_defs.h>
-
#include <utils/Condition.h>
-#include <chrono>
+#include "MockComposerHal.h"
+#include "RenderState.h"
using namespace android::hardware::graphics::common;
using namespace android::hardware::graphics::composer;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
index 09a2a89..383a111 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
@@ -19,11 +19,7 @@
#include "FakeComposerClient.h"
#include <gui/SurfaceComposerClient.h>
-
-#include <hardware/hwcomposer_defs.h>
-
#include <log/log.h>
-
#include <gtest/gtest.h>
// clang-format off
diff --git a/services/surfaceflinger/tests/fakehwc/RenderState.h b/services/surfaceflinger/tests/fakehwc/RenderState.h
index 0059289..40193f2 100644
--- a/services/surfaceflinger/tests/fakehwc/RenderState.h
+++ b/services/surfaceflinger/tests/fakehwc/RenderState.h
@@ -16,8 +16,6 @@
#pragma once
-#include <hardware/hwcomposer2.h>
-
#include <vector>
namespace sftest {
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 32c58ad..a03fd89 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -443,6 +443,8 @@
EXPECT_EQ(NO_ERROR,
SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i,
config.refreshRate,
+ config.refreshRate,
+ config.refreshRate,
config.refreshRate));
waitForDisplayTransaction();
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
@@ -547,6 +549,8 @@
EXPECT_EQ(NO_ERROR,
SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i,
config.refreshRate,
+ config.refreshRate,
+ config.refreshRate,
config.refreshRate));
waitForDisplayTransaction();
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
@@ -659,9 +663,11 @@
const auto& config = configs[i];
if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) {
EXPECT_EQ(NO_ERROR,
- SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i,
- configs[i].refreshRate,
- configs[i].refreshRate));
+ SurfaceComposerClient::
+ setDesiredDisplayConfigSpecs(display, i, configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate));
waitForDisplayTransaction();
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
@@ -706,6 +712,8 @@
EXPECT_EQ(NO_ERROR,
SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i,
config.refreshRate,
+ config.refreshRate,
+ config.refreshRate,
config.refreshRate));
waitForDisplayTransaction();
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
@@ -751,6 +759,8 @@
EXPECT_EQ(NO_ERROR,
SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i,
config.refreshRate,
+ config.refreshRate,
+ config.refreshRate,
config.refreshRate));
waitForDisplayTransaction();
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
diff --git a/services/surfaceflinger/tests/hwc2/Android.bp b/services/surfaceflinger/tests/hwc2/Android.bp
deleted file mode 100644
index 1c8e396..0000000
--- a/services/surfaceflinger/tests/hwc2/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2018 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.
-
-cc_test {
- name: "test-hwc2",
- defaults: ["surfaceflinger_defaults"],
- cflags: [
- "-DEGL_EGLEXT_PROTOTYPES",
- "-DGL_GLEXT_PROTOTYPES",
- "-fno-builtin",
- "-fstack-protector-all",
- "-g",
- "-Wextra",
- ],
- srcs: [
- "Hwc2Test.cpp",
- "Hwc2TestProperties.cpp",
- "Hwc2TestLayer.cpp",
- "Hwc2TestLayers.cpp",
- "Hwc2TestBuffer.cpp",
- "Hwc2TestClientTarget.cpp",
- "Hwc2TestVirtualDisplay.cpp",
- "Hwc2TestPixelComparator.cpp",
- ],
- static_libs: [
- "libadf",
- "libadfhwc",
- "libbase",
- "libmath",
- ],
- shared_libs: [
- "android.hardware.graphics.common@1.1",
- "libcutils",
- "libEGL",
- "libGLESv2",
- "libgui",
- "libhardware",
- "libhwui",
- "liblog",
- "libsync",
- "libui",
- "libutils",
- ],
-}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
deleted file mode 100644
index f9a1fe9..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ /dev/null
@@ -1,4779 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include <array>
-#include <unordered_set>
-#include <unordered_map>
-#include <gtest/gtest.h>
-#include <dlfcn.h>
-#include <android-base/unique_fd.h>
-#include <hardware/hardware.h>
-#include <sync/sync.h>
-#include <ui/GraphicTypes.h>
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-#include "Hwc2TestLayer.h"
-#include "Hwc2TestLayers.h"
-#include "Hwc2TestClientTarget.h"
-#include "Hwc2TestVirtualDisplay.h"
-
-using android::ui::ColorMode;
-using android::ui::Dataspace;
-
-void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int32_t connected);
-void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int64_t timestamp);
-
-class Hwc2Test : public testing::Test {
-public:
-
- virtual void SetUp()
- {
- hw_module_t const* hwc2Module;
-
- int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwc2Module);
- ASSERT_GE(err, 0) << "failed to get hwc hardware module: "
- << strerror(-err);
-
- /* The following method will fail if you have not run
- * "adb shell stop" */
- err = hwc2_open(hwc2Module, &mHwc2Device);
- ASSERT_GE(err, 0) << "failed to open hwc hardware module: "
- << strerror(-err);
-
- populateDisplays();
- }
-
- virtual void TearDown()
- {
-
- for (auto itr = mLayers.begin(); itr != mLayers.end();) {
- hwc2_display_t display = itr->first;
- hwc2_layer_t layer = itr->second;
- itr++;
- /* Destroys and removes the layer from mLayers */
- destroyLayer(display, layer);
- }
-
- for (auto itr = mActiveDisplays.begin(); itr != mActiveDisplays.end();) {
- hwc2_display_t display = *itr;
- itr++;
- /* Sets power mode to off and removes the display from
- * mActiveDisplays */
- setPowerMode(display, HWC2_POWER_MODE_OFF);
- }
-
- for (auto itr = mVirtualDisplays.begin(); itr != mVirtualDisplays.end();) {
- hwc2_display_t display = *itr;
- itr++;
- /* Destroys virtual displays */
- destroyVirtualDisplay(display);
- }
-
- if (mHwc2Device)
- hwc2_close(mHwc2Device);
- }
-
- void registerCallback(hwc2_callback_descriptor_t descriptor,
- hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_REGISTER_CALLBACK>(
- getFunction(HWC2_FUNCTION_REGISTER_CALLBACK));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, descriptor,
- callbackData, pointer));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to register callback";
- }
- }
-
- void getDisplayType(hwc2_display_t display, hwc2_display_type_t* outType,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_TYPE>(
- getFunction(HWC2_FUNCTION_GET_DISPLAY_TYPE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- reinterpret_cast<int32_t*>(outType)));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display type";
- }
- }
-
- /* If the populateDisplays function is still receiving displays and the
- * display is connected, the display handle is stored in mDisplays. */
- void hotplugCallback(hwc2_display_t display, int32_t connected)
- {
- std::lock_guard<std::mutex> lock(mHotplugMutex);
-
- if (mHotplugStatus != Hwc2TestHotplugStatus::Receiving)
- return;
-
- if (connected == HWC2_CONNECTION_CONNECTED)
- mDisplays.insert(display);
-
- mHotplugCv.notify_all();
- }
-
- void createLayer(hwc2_display_t display, hwc2_layer_t* outLayer,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_CREATE_LAYER>(
- getFunction(HWC2_FUNCTION_CREATE_LAYER));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- outLayer));
-
- if (err == HWC2_ERROR_NONE)
- mLayers.insert(std::make_pair(display, *outLayer));
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
- }
- }
-
- void destroyLayer(hwc2_display_t display, hwc2_layer_t layer,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_LAYER>(
- getFunction(HWC2_FUNCTION_DESTROY_LAYER));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer));
-
- if (err == HWC2_ERROR_NONE)
- mLayers.erase(std::make_pair(display, layer));
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy layer "
- << layer;
- }
- }
-
- void getDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
- hwc2_attribute_t attribute, int32_t* outValue,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
- getFunction(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config,
- attribute, outValue));
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display attribute "
- << getAttributeName(attribute) << " for config " << config;
- }
- }
-
- void getDisplayConfigs(hwc2_display_t display,
- std::vector<hwc2_config_t>* outConfigs,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_CONFIGS>(
- getFunction(HWC2_FUNCTION_GET_DISPLAY_CONFIGS));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t numConfigs = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numConfigs, nullptr));
-
- if (err == HWC2_ERROR_NONE) {
- outConfigs->resize(numConfigs);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numConfigs, outConfigs->data()));
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get configs for"
- " display " << display;
- }
- }
-
- void getActiveConfig(hwc2_display_t display, hwc2_config_t* outConfig,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_ACTIVE_CONFIG>(
- getFunction(HWC2_FUNCTION_GET_ACTIVE_CONFIG));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- outConfig));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get active config on"
- " display " << display;
- }
- }
-
- void setActiveConfig(hwc2_display_t display, hwc2_config_t config,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_ACTIVE_CONFIG>(
- getFunction(HWC2_FUNCTION_SET_ACTIVE_CONFIG));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set active config "
- << config;
- }
- }
-
- void getDozeSupport(hwc2_display_t display, int32_t* outSupport,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_DOZE_SUPPORT>(
- getFunction(HWC2_FUNCTION_GET_DOZE_SUPPORT));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- outSupport));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get doze support on"
- " display " << display;
- }
- }
-
- void setPowerMode(hwc2_display_t display, hwc2_power_mode_t mode,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_POWER_MODE>(
- getFunction(HWC2_FUNCTION_SET_POWER_MODE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- mode));
- if (outErr) {
- *outErr = err;
- if (err != HWC2_ERROR_NONE)
- return;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set power mode "
- << getPowerModeName(mode) << " on display " << display;
- }
-
- if (mode == HWC2_POWER_MODE_OFF) {
- mActiveDisplays.erase(display);
- } else {
- mActiveDisplays.insert(display);
- }
- }
-
- void setVsyncEnabled(hwc2_display_t display, hwc2_vsync_t enabled,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_VSYNC_ENABLED>(
- getFunction(HWC2_FUNCTION_SET_VSYNC_ENABLED));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- enabled));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set vsync enabled "
- << getVsyncName(enabled);
- }
- }
-
- void vsyncCallback(hwc2_display_t display, int64_t timestamp)
- {
- std::lock_guard<std::mutex> lock(mVsyncMutex);
- mVsyncDisplay = display;
- mVsyncTimestamp = timestamp;
- mVsyncCv.notify_all();
- }
-
- void getDisplayName(hwc2_display_t display, std::string* outName,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_NAME>(
- getFunction(HWC2_FUNCTION_GET_DISPLAY_NAME));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t size = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
- nullptr));
-
- if (err == HWC2_ERROR_NONE) {
- std::vector<char> name(size);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
- name.data()));
-
- outName->assign(name.data());
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display name for "
- << display;
- }
- }
-
- void setLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
- hwc2_composition_t composition, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
- getFunction(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- composition));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer composition"
- " type " << getCompositionName(composition);
- }
- }
-
- void setCursorPosition(hwc2_display_t display, hwc2_layer_t layer,
- int32_t x, int32_t y, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_CURSOR_POSITION>(
- getFunction(HWC2_FUNCTION_SET_CURSOR_POSITION));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer, x,
- y));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_TRUE((err == HWC2_ERROR_NONE) ||
- (err == HWC2_ERROR_BAD_LAYER)) <<
- "failed to set cursor position";
- }
- }
-
- void setLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
- hwc2_blend_mode_t mode, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BLEND_MODE>(
- getFunction(HWC2_FUNCTION_SET_LAYER_BLEND_MODE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- mode));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer blend mode "
- << getBlendModeName(mode);
- }
- }
-
- void setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
- buffer_handle_t buffer, int32_t acquireFence,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BUFFER>(
- getFunction(HWC2_FUNCTION_SET_LAYER_BUFFER));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- buffer, acquireFence));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer buffer";
- }
- }
-
- void setLayerColor(hwc2_display_t display, hwc2_layer_t layer,
- hwc_color_t color, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COLOR>(
- getFunction(HWC2_FUNCTION_SET_LAYER_COLOR));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- color));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer color";
- }
- }
-
- void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
- Dataspace dataspace, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DATASPACE>(
- getFunction(HWC2_FUNCTION_SET_LAYER_DATASPACE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- layer, static_cast<int>(dataspace)));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer dataspace";
- }
- }
-
- void setLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
- const hwc_rect_t& displayFrame, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
- getFunction(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- displayFrame));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer display"
- " frame";
- }
- }
-
- void setLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer,
- float alpha, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
- getFunction(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- alpha));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer plane alpha "
- << alpha;
- }
- }
-
- void setLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
- const hwc_frect_t& sourceCrop, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
- getFunction(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- sourceCrop));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer source crop";
- }
- }
-
- void setLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
- const hwc_region_t& surfaceDamage, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
- getFunction(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- surfaceDamage));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer surface"
- " damage";
- }
- }
-
- void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
- hwc_transform_t transform, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_TRANSFORM>(
- getFunction(HWC2_FUNCTION_SET_LAYER_TRANSFORM));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- transform));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer transform "
- << getTransformName(transform);
- }
- }
-
- void setLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
- const hwc_region_t& visibleRegion, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
- getFunction(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- visibleRegion));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer visible"
- " region";
- }
- }
-
- void setLayerZOrder(hwc2_display_t display, hwc2_layer_t layer,
- uint32_t zOrder, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_Z_ORDER>(
- getFunction(HWC2_FUNCTION_SET_LAYER_Z_ORDER));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
- zOrder));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer z order "
- << zOrder;
- }
- }
-
- void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
- uint32_t* outNumRequests, hwc2_error_t* outErr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_VALIDATE_DISPLAY>(
- getFunction(HWC2_FUNCTION_VALIDATE_DISPLAY));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- *outErr = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- outNumTypes, outNumRequests));
- }
-
- void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
- uint32_t* outNumRequests, bool* outHasChanges)
- {
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- EXPECT_NO_FATAL_FAILURE(validateDisplay(display, outNumTypes,
- outNumRequests, &err));
-
- if (err != HWC2_ERROR_HAS_CHANGES) {
- *outHasChanges = false;
- EXPECT_EQ(err, HWC2_ERROR_NONE) << "failed to validate display";
- } else {
- *outHasChanges = true;
- }
- }
-
- void getDisplayRequests(hwc2_display_t display,
- hwc2_display_request_t* outDisplayRequests,
- std::vector<hwc2_layer_t>* outLayers,
- std::vector<hwc2_layer_request_t>* outLayerRequests,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_REQUESTS>(
- getFunction(HWC2_FUNCTION_GET_DISPLAY_REQUESTS));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t numElements = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
- nullptr, nullptr));
-
- if (err == HWC2_ERROR_NONE && numElements > 0) {
- outLayers->resize(numElements);
- outLayerRequests->resize(numElements);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
- reinterpret_cast<uint64_t*>(outLayers->data()),
- reinterpret_cast<int32_t*>(outLayerRequests->data())));
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display requests";
- }
- }
-
- void handleRequests(hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers, uint32_t numRequests,
- std::set<hwc2_layer_t>* outClearLayers = nullptr,
- bool* outFlipClientTarget = nullptr)
- {
- hwc2_display_request_t displayRequest =
- static_cast<hwc2_display_request_t>(0);
- std::vector<hwc2_layer_t> requestedLayers;
- std::vector<hwc2_layer_request_t> requests;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequest,
- &requestedLayers, &requests));
-
- EXPECT_EQ(numRequests, requests.size()) << "validate returned "
- << numRequests << " requests and get display requests returned "
- << requests.size() << " requests";
-
- for (size_t i = 0; i < requests.size(); i++) {
- hwc2_layer_t requestedLayer = requestedLayers.at(i);
- hwc2_layer_request_t request = requests.at(i);
-
- EXPECT_EQ(std::count(layers.begin(), layers.end(), requestedLayer),
- 1) << "get display requests returned an unknown layer";
- EXPECT_NE(request, 0) << "returned empty request for layer "
- << requestedLayer;
-
- if (outClearLayers && request
- == HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET)
- outClearLayers->insert(requestedLayer);
- }
-
- if (outFlipClientTarget)
- *outFlipClientTarget = displayRequest
- & HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET;
- }
-
- void getChangedCompositionTypes(hwc2_display_t display,
- std::vector<hwc2_layer_t>* outLayers,
- std::vector<hwc2_composition_t>* outTypes,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
- getFunction(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t numElements = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numElements, nullptr, nullptr));
-
- if (err == HWC2_ERROR_NONE && numElements > 0) {
- outLayers->resize(numElements);
- outTypes->resize(numElements);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numElements, reinterpret_cast<uint64_t*>(outLayers->data()),
- reinterpret_cast<int32_t*>(outTypes->data())));
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get changed"
- " composition types";
- }
- }
-
- void handleCompositionChanges(hwc2_display_t display,
- const Hwc2TestLayers& testLayers,
- const std::vector<hwc2_layer_t>& layers, uint32_t numTypes,
- std::set<hwc2_layer_t>* outClientLayers = nullptr)
- {
- std::vector<hwc2_layer_t> changedLayers;
- std::vector<hwc2_composition_t> types;
-
- ASSERT_NO_FATAL_FAILURE(getChangedCompositionTypes(display,
- &changedLayers, &types));
-
- EXPECT_EQ(numTypes, types.size()) << "validate returned "
- << numTypes << " types and get changed composition types"
- " returned " << types.size() << " types";
-
- for (size_t i = 0; i < types.size(); i++) {
-
- auto layer = std::find(layers.begin(), layers.end(),
- changedLayers.at(i));
-
- EXPECT_TRUE(layer != layers.end() || !testLayers.contains(*layer))
- << "get changed composition types returned an unknown layer";
-
- hwc2_composition_t requestedType = testLayers.getComposition(*layer);
- hwc2_composition_t returnedType = types.at(i);
-
- EXPECT_NE(returnedType, HWC2_COMPOSITION_INVALID) << "get changed"
- " composition types returned invalid composition";
-
- switch (requestedType) {
- case HWC2_COMPOSITION_CLIENT:
- EXPECT_TRUE(false) << getCompositionName(returnedType)
- << " cannot be changed";
- break;
- case HWC2_COMPOSITION_DEVICE:
- case HWC2_COMPOSITION_SOLID_COLOR:
- EXPECT_EQ(returnedType, HWC2_COMPOSITION_CLIENT)
- << "composition of type "
- << getCompositionName(requestedType)
- << " can only be changed to "
- << getCompositionName(HWC2_COMPOSITION_CLIENT);
- break;
- case HWC2_COMPOSITION_CURSOR:
- case HWC2_COMPOSITION_SIDEBAND:
- EXPECT_TRUE(returnedType == HWC2_COMPOSITION_CLIENT
- || returnedType == HWC2_COMPOSITION_DEVICE)
- << "composition of type "
- << getCompositionName(requestedType)
- << " can only be changed to "
- << getCompositionName(HWC2_COMPOSITION_CLIENT) << " or "
- << getCompositionName(HWC2_COMPOSITION_DEVICE);
- break;
- default:
- EXPECT_TRUE(false) << "unknown type "
- << getCompositionName(requestedType);
- break;
- }
-
- if (outClientLayers)
- if (returnedType == HWC2_COMPOSITION_CLIENT)
- outClientLayers->insert(*layer);
- }
-
- if (outClientLayers) {
- for (auto layer : layers) {
- if (testLayers.getComposition(layer) == HWC2_COMPOSITION_CLIENT)
- outClientLayers->insert(layer);
- }
- }
- }
-
- void acceptDisplayChanges(hwc2_display_t display,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
- getFunction(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to accept display changes";
- }
- }
-
- void getClientTargetSupport(hwc2_display_t display, int32_t width,
- int32_t height, android_pixel_format_t format,
- Dataspace dataspace, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
- getFunction(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, width,
- height, format, static_cast<int>(dataspace)));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get client target"
- " support";
- }
- }
-
- void setClientTarget(hwc2_display_t display, buffer_handle_t handle,
- int32_t acquireFence, Dataspace dataspace,
- hwc_region_t damage, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_CLIENT_TARGET>(
- getFunction(HWC2_FUNCTION_SET_CLIENT_TARGET));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, handle,
- acquireFence, static_cast<int>(dataspace), damage));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set client target";
- }
- }
-
- void presentDisplay(hwc2_display_t display, int32_t* outPresentFence,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_PRESENT_DISPLAY>(
- getFunction(HWC2_FUNCTION_PRESENT_DISPLAY));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- outPresentFence));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to present display";
- }
- }
-
- void getReleaseFences(hwc2_display_t display,
- std::vector<hwc2_layer_t>* outLayers,
- std::vector<int32_t>* outFences, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_RELEASE_FENCES>(
- getFunction(HWC2_FUNCTION_GET_RELEASE_FENCES));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t numElements = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numElements, nullptr, nullptr));
-
- if (err == HWC2_ERROR_NONE) {
- outLayers->resize(numElements);
- outFences->resize(numElements);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numElements, outLayers->data(), outFences->data()));
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get release fences";
- }
- }
-
- void getColorModes(hwc2_display_t display,
- std::vector<ColorMode>* outColorModes,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_COLOR_MODES>(
- getFunction(HWC2_FUNCTION_GET_COLOR_MODES));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t numColorModes = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numColorModes, nullptr));
- if (err == HWC2_ERROR_NONE) {
- outColorModes->resize(numColorModes);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numColorModes,
- reinterpret_cast<int32_t*>(outColorModes->data())));
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get color modes for"
- " display " << display;
- }
- }
-
- void setColorMode(hwc2_display_t display, ColorMode colorMode,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_MODE>(
- getFunction(HWC2_FUNCTION_SET_COLOR_MODE));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- static_cast<int32_t>(colorMode)));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode "
- << static_cast<int>(colorMode);
- }
- }
-
- void getHdrCapabilities(hwc2_display_t display,
- std::vector<android_hdr_t>* outTypes, float* outMaxLuminance,
- float* outMaxAverageLuminance, float* outMinLuminance,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_HDR_CAPABILITIES>(
- getFunction(HWC2_FUNCTION_GET_HDR_CAPABILITIES));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t numTypes = 0;
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- &numTypes, nullptr, outMaxLuminance, outMaxAverageLuminance,
- outMinLuminance));
-
- if (err == HWC2_ERROR_NONE) {
- outTypes->resize(numTypes);
-
- err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &numTypes,
- reinterpret_cast<int32_t*>(outTypes->data()), outMaxLuminance,
- outMaxAverageLuminance, outMinLuminance));
- }
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get hdr capabilities"
- " for display " << display;
- }
- }
-
- void setColorTransform(hwc2_display_t display,
- const std::array<float, 16>& matrix, android_color_transform_t hint,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_TRANSFORM>(
- getFunction(HWC2_FUNCTION_SET_COLOR_TRANSFORM));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
- matrix.data(), hint));
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color transform "
- << hint;
- }
- }
-
- void createVirtualDisplay(uint32_t width, uint32_t height,
- android_pixel_format_t* outFormat, hwc2_display_t* outDisplay,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
- getFunction(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, width, height,
- reinterpret_cast<int32_t*>(outFormat), outDisplay));
-
- if (err == HWC2_ERROR_NONE)
- mVirtualDisplays.insert(*outDisplay);
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create virtual display";
- }
- }
-
- void destroyVirtualDisplay(hwc2_display_t display,
- hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
- getFunction(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
-
- if (err == HWC2_ERROR_NONE)
- mVirtualDisplays.erase(display);
-
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy virtual display";
- }
- }
-
- void getMaxVirtualDisplayCount(uint32_t* outMaxCnt)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
- getFunction(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- *outMaxCnt = pfn(mHwc2Device);
- }
-
- void setOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
- int32_t releaseFence, hwc2_error_t* outErr = nullptr)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_SET_OUTPUT_BUFFER>(
- getFunction(HWC2_FUNCTION_SET_OUTPUT_BUFFER));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, buffer,
- releaseFence));
- if (outErr) {
- *outErr = err;
- } else {
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set output buffer";
- }
- }
-
- void dump(std::string* outBuffer)
- {
- auto pfn = reinterpret_cast<HWC2_PFN_DUMP>(
- getFunction(HWC2_FUNCTION_DUMP));
- ASSERT_TRUE(pfn) << "failed to get function";
-
- uint32_t size = 0;
-
- pfn(mHwc2Device, &size, nullptr);
-
- std::vector<char> buffer(size);
-
- pfn(mHwc2Device, &size, buffer.data());
-
- outBuffer->assign(buffer.data());
- }
-
- void getBadDisplay(hwc2_display_t* outDisplay)
- {
- for (hwc2_display_t display = 0; display < UINT64_MAX; display++) {
- if (mDisplays.count(display) == 0) {
- *outDisplay = display;
- return;
- }
- }
- ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays"
- " are registered. This should never happen.";
- }
-
- void waitForVsync(hwc2_display_t* outDisplay = nullptr,
- int64_t* outTimestamp = nullptr)
- {
- std::unique_lock<std::mutex> lock(mVsyncMutex);
- ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)),
- std::cv_status::no_timeout) << "timed out attempting to get"
- " vsync callback";
- if (outDisplay)
- *outDisplay = mVsyncDisplay;
- if (outTimestamp)
- *outTimestamp = mVsyncTimestamp;
- }
-
- void enableVsync(hwc2_display_t display)
- {
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this,
- reinterpret_cast<hwc2_function_pointer_t>(
- hwc2TestVsyncCallback)));
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
- }
-
- void disableVsync(hwc2_display_t display)
- {
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
- }
-
-protected:
- hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor)
- {
- return mHwc2Device->getFunction(mHwc2Device, descriptor);
- }
-
- void getCapabilities(std::vector<hwc2_capability_t>* outCapabilities)
- {
- uint32_t num = 0;
-
- mHwc2Device->getCapabilities(mHwc2Device, &num, nullptr);
-
- outCapabilities->resize(num);
-
- mHwc2Device->getCapabilities(mHwc2Device, &num,
- reinterpret_cast<int32_t*>(outCapabilities->data()));
- }
-
- /* Registers a hotplug callback and waits for hotplug callbacks. This
- * function will have no effect if called more than once. */
- void populateDisplays()
- {
- /* Sets the hotplug status to receiving */
- {
- std::lock_guard<std::mutex> lock(mHotplugMutex);
-
- if (mHotplugStatus != Hwc2TestHotplugStatus::Init)
- return;
- mHotplugStatus = Hwc2TestHotplugStatus::Receiving;
- }
-
- /* Registers the callback. This function call cannot be locked because
- * a callback could happen on the same thread */
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_HOTPLUG, this,
- reinterpret_cast<hwc2_function_pointer_t>(
- hwc2TestHotplugCallback)));
-
- /* Waits for hotplug events. If a hotplug event has not come within 1
- * second, stop waiting. */
- std::unique_lock<std::mutex> lock(mHotplugMutex);
-
- while (mHotplugCv.wait_for(lock, std::chrono::seconds(1)) !=
- std::cv_status::timeout) { }
-
- /* Sets the hotplug status to done. Future calls will have no effect */
- mHotplugStatus = Hwc2TestHotplugStatus::Done;
- }
-
- /* NOTE: will create min(newlayerCnt, max supported layers) layers */
- void createLayers(hwc2_display_t display,
- std::vector<hwc2_layer_t>* outLayers, size_t newLayerCnt)
- {
- std::vector<hwc2_layer_t> newLayers;
- hwc2_layer_t layer;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- for (size_t i = 0; i < newLayerCnt; i++) {
-
- EXPECT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
- if (err == HWC2_ERROR_NO_RESOURCES)
- break;
- if (err != HWC2_ERROR_NONE) {
- newLayers.clear();
- ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
- }
- newLayers.push_back(layer);
- }
-
- *outLayers = std::move(newLayers);
- }
-
- void destroyLayers(hwc2_display_t display,
- std::vector<hwc2_layer_t>&& layers)
- {
- for (hwc2_layer_t layer : layers) {
- EXPECT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
- }
-
- void getInvalidConfig(hwc2_display_t display, hwc2_config_t* outConfig)
- {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- hwc2_config_t CONFIG_MAX = UINT32_MAX;
-
- ASSERT_LE(configs.size() - 1, CONFIG_MAX) << "every config value"
- " (2^32 values) has been taken which shouldn't happen";
-
- hwc2_config_t config;
- for (config = 0; config < CONFIG_MAX; config++) {
- if (std::count(configs.begin(), configs.end(), config) == 0)
- break;
- }
-
- *outConfig = config;
- }
-
- /* Calls a set property function from Hwc2Test to set a property value from
- * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */
- using TestLayerPropertyFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
-
- /* Calls a set property function from Hwc2Test to set property values from
- * Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */
- using TestLayerPropertiesFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayers* testLayers);
-
- /* Calls a set property function from Hwc2Test to set a bad property value
- * on hwc2_layer_t on hwc2_display_t */
- using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
-
- /* Calls a set property function from Hwc2Test to set a bad property value
- * on hwc2_layer_t on hwc2_display_t */
- using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr);
-
- /* Is called after a display is powered on and all layer properties have
- * been set. It should be used to test functions such as validate, accepting
- * changes, present, etc. */
- using TestDisplayLayersFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* testLayers);
-
- /* It is called on an non validated display */
- using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, std::vector<hwc2_layer_t>* layers);
-
- /* Tests client target support on a particular display and config */
- using TestClientTargetSupportFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display,
- const Hwc2TestClientTargetSupport& testClientTargetSupport);
-
- /* Tests a particular active display config */
- using TestActiveDisplayConfigFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display);
-
- /* Tests a newly created virtual display */
- using TestCreateVirtualDisplayFunction = void (*)(Hwc2Test* test,
- hwc2_display_t display, Hwc2TestVirtualDisplay* testVirtualDisplay);
-
- /* Advances a property of Hwc2TestLayer */
- using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer);
-
- /* Advances properties of Hwc2TestLayers */
- using AdvanceProperties = bool (*)(Hwc2TestLayers* testLayer);
-
- /* Advances properties of Hwc2TestClientTargetSupport */
- using AdvanceClientTargetSupport = bool (*)(
- Hwc2TestClientTargetSupport* testClientTargetSupport);
-
- /* For each active display it cycles through each display config and tests
- * each property value. It creates a layer, sets the property and then
- * destroys the layer */
- void setLayerProperty(Hwc2TestCoverage coverage,
- TestLayerPropertyFunction function, AdvanceProperty advance)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- hwc2_layer_t layer;
- Area displayArea;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
- Hwc2TestLayer testLayer(coverage, displayArea);
-
- do {
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
- &testLayer, nullptr));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- } while (advance(&testLayer));
- }
- }
- }
-
- /* For each active display it cycles through each display config and tests
- * each property value. It creates a layer, cycles through each property
- * value and updates the layer property value and then destroys the layer */
- void setLayerPropertyUpdate(Hwc2TestCoverage coverage,
- TestLayerPropertyFunction function, AdvanceProperty advance)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- hwc2_layer_t layer;
- Area displayArea;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
- Hwc2TestLayer testLayer(coverage, displayArea);
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- do {
- ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
- &testLayer, nullptr));
- } while (advance(&testLayer));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
- }
- }
-
- /* For each active display it cycles through each display config and tests
- * each property value. It creates multiple layers, calls the
- * TestLayerPropertiesFunction to set property values and then
- * destroys the layers */
- void setLayerProperties(Hwc2TestCoverage coverage, size_t layerCnt,
- TestLayerPropertiesFunction function, AdvanceProperties advance)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- std::vector<hwc2_layer_t> layers;
- Area displayArea;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
-
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
- Hwc2TestLayers testLayers(layers, coverage, displayArea);
-
- do {
- for (auto layer : layers) {
- EXPECT_NO_FATAL_FAILURE(function(this, display, layer,
- &testLayers));
- }
- } while (advance(&testLayers));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
- }
- }
- }
-
- /* For each active display it cycles through each display config.
- * 1) It attempts to set a valid property value to bad layer handle.
- * 2) It creates a layer x and attempts to set a valid property value to
- * layer x + 1
- * 3) It destroys the layer x and attempts to set a valid property value to
- * the destroyed layer x.
- */
- void setLayerPropertyBadLayer(Hwc2TestCoverage coverage,
- TestLayerPropertyBadLayerFunction function)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- hwc2_layer_t layer = 0;
- Area displayArea;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
- Hwc2TestLayer testLayer(coverage, displayArea);
-
- ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
- &testLayer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1,
- &testLayer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
-
- ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
- &testLayer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
- }
- }
- }
-
- /* For each active display it cycles through each display config and tests
- * each property value. It creates a layer, sets a bad property value and
- * then destroys the layer */
- void setLayerPropertyBadParameter(TestLayerPropertyBadParameterFunction function)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- hwc2_layer_t layer;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- ASSERT_NO_FATAL_FAILURE(function(this, display, layer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong"
- " error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
- }
- }
-
- /* For each active display it powers on the display, cycles through each
- * config and creates a set of layers with a certain amount of coverage.
- * For each active display, for each config and for each set of layers,
- * it calls the TestDisplayLayersFunction */
- void displayLayers(Hwc2TestCoverage coverage, size_t layerCnt,
- TestDisplayLayersFunction function)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- Area displayArea;
- std::vector<hwc2_layer_t> layers;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
-
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
- Hwc2TestLayers testLayers(layers, coverage, displayArea);
-
- do {
- bool skip;
-
- ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
- &testLayers, &skip));
- if (!skip)
- EXPECT_NO_FATAL_FAILURE(function(this, display, layers,
- &testLayers));
-
- } while (testLayers.advance());
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
- std::move(layers)));
- }
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
- }
-
- /* For each active display, it calls the
- * TestDisplayNonValidatedLayersFunction on a variety on non-validated
- * layer combinations */
- void displayNonValidatedLayers(size_t layerCnt,
- TestDisplayNonValidatedLayersFunction function)
- {
- for (auto display : mDisplays) {
- uint32_t numTypes, numRequests;
- std::vector<hwc2_layer_t> layers;
- bool hasChanges;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
-
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
-
- EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
-
- for (auto layer : layers) {
- ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
- HWC2_COMPOSITION_CLIENT));
- }
-
- EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
-
- ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
-
- for (auto layer : layers) {
- ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
- HWC2_COMPOSITION_DEVICE));
- }
-
- EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
-
- EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
- }
-
- /* Test client target support on each config on each active display */
- void setClientTargetSupport(Hwc2TestCoverage coverage,
- TestClientTargetSupportFunction function,
- AdvanceClientTargetSupport advance)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- Area displayArea;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
- Hwc2TestClientTargetSupport testClientTargetSupport(coverage,
- displayArea);
-
- do {
- EXPECT_NO_FATAL_FAILURE(function(this, display,
- testClientTargetSupport));
-
- } while (advance(&testClientTargetSupport));
- }
- }
- }
-
- /* Cycles through each config on each active display and calls
- * a TestActiveDisplayConfigFunction */
- void setActiveDisplayConfig(TestActiveDisplayConfigFunction function)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
-
- EXPECT_NO_FATAL_FAILURE(function(this, display));
- }
- }
- }
-
- /* Creates a virtual display for testing */
- void createVirtualDisplay(Hwc2TestCoverage coverage,
- TestCreateVirtualDisplayFunction function)
- {
- Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
-
- do {
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- const UnsignedArea& dimension =
- testVirtualDisplay.getDisplayDimension();
- android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
- dimension.height, &desiredFormat, &display, &err));
-
- EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
- || err == HWC2_ERROR_UNSUPPORTED)
- << "returned wrong error code";
- EXPECT_GE(desiredFormat, 0) << "invalid format";
-
- if (err != HWC2_ERROR_NONE)
- continue;
-
- EXPECT_NO_FATAL_FAILURE(function(this, display,
- &testVirtualDisplay));
-
- ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
-
- } while (testVirtualDisplay.advance());
- }
-
-
- void getActiveConfigAttribute(hwc2_display_t display,
- hwc2_attribute_t attribute, int32_t* outValue)
- {
- hwc2_config_t config;
- ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &config));
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
- attribute, outValue));
- ASSERT_GE(*outValue, 0) << "failed to get valid "
- << getAttributeName(attribute);
- }
-
- void getActiveDisplayArea(hwc2_display_t display, Area* displayArea)
- {
- ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
- HWC2_ATTRIBUTE_WIDTH, &displayArea->width));
- ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
- HWC2_ATTRIBUTE_HEIGHT, &displayArea->height));
- }
-
- void closeFences(hwc2_display_t display, int32_t presentFence)
- {
- std::vector<hwc2_layer_t> layers;
- std::vector<int32_t> fences;
- const int msWait = 3000;
-
- if (presentFence >= 0) {
- ASSERT_GE(sync_wait(presentFence, msWait), 0);
- close(presentFence);
- }
-
- ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences));
- EXPECT_EQ(layers.size(), fences.size());
-
- for (int32_t fence : fences) {
- if (fence >= 0) {
- EXPECT_GE(sync_wait(fence, msWait), 0);
- close(fence);
- }
- }
- }
-
- void setLayerProperties(hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayers* testLayers, bool* outSkip)
- {
- hwc2_composition_t composition;
- buffer_handle_t handle = nullptr;
- int32_t acquireFence;
- hwc2_error_t err = HWC2_ERROR_NONE;
- *outSkip = true;
-
- if (!testLayers->contains(layer))
- return;
-
- composition = testLayers->getComposition(layer);
-
- /* If the device cannot support a buffer format, then do not continue */
- if ((composition == HWC2_COMPOSITION_DEVICE
- || composition == HWC2_COMPOSITION_CURSOR)
- && testLayers->getBuffer(layer, &handle, &acquireFence) < 0)
- return;
-
- EXPECT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
- composition, &err));
- if (err == HWC2_ERROR_UNSUPPORTED)
- EXPECT_TRUE(composition != HWC2_COMPOSITION_CLIENT
- && composition != HWC2_COMPOSITION_DEVICE);
-
- const hwc_rect_t cursor = testLayers->getCursorPosition(layer);
-
- EXPECT_NO_FATAL_FAILURE(setLayerBuffer(display, layer, handle,
- acquireFence));
- EXPECT_NO_FATAL_FAILURE(setLayerBlendMode(display, layer,
- testLayers->getBlendMode(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerColor(display, layer,
- testLayers->getColor(layer)));
- if (composition == HWC2_COMPOSITION_CURSOR)
- EXPECT_NO_FATAL_FAILURE(setCursorPosition(display, layer,
- cursor.left, cursor.top));
- EXPECT_NO_FATAL_FAILURE(setLayerDataspace(display, layer,
- testLayers->getDataspace(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerDisplayFrame(display, layer,
- testLayers->getDisplayFrame(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerPlaneAlpha(display, layer,
- testLayers->getPlaneAlpha(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerSourceCrop(display, layer,
- testLayers->getSourceCrop(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerSurfaceDamage(display, layer,
- testLayers->getSurfaceDamage(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerTransform(display, layer,
- testLayers->getTransform(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerVisibleRegion(display, layer,
- testLayers->getVisibleRegion(layer)));
- EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer,
- testLayers->getZOrder(layer)));
-
- *outSkip = false;
- }
-
- void setLayerProperties(hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* testLayers, bool* outSkip)
- {
- for (auto layer : layers) {
- EXPECT_NO_FATAL_FAILURE(setLayerProperties(display, layer,
- testLayers, outSkip));
- if (*outSkip)
- return;
- }
- }
-
- void setClientTarget(hwc2_display_t display,
- Hwc2TestClientTarget* testClientTarget,
- const Hwc2TestLayers& testLayers,
- const std::set<hwc2_layer_t>& clientLayers,
- const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
- const Area& displayArea)
- {
- Dataspace dataspace = Dataspace::UNKNOWN;
- hwc_region_t damage = { };
- buffer_handle_t handle;
- int32_t acquireFence;
-
- ASSERT_EQ(testClientTarget->getBuffer(testLayers, clientLayers,
- clearLayers, flipClientTarget, displayArea, &handle,
- &acquireFence), 0);
- EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
- dataspace, damage));
- }
-
- void presentDisplays(size_t layerCnt, Hwc2TestCoverage coverage,
- const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
- coverageExceptions, bool optimize)
- {
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
- ASSERT_NO_FATAL_FAILURE(enableVsync(display));
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- Area displayArea;
- std::vector<hwc2_layer_t> layers;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
-
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
- Hwc2TestLayers testLayers(layers, coverage, displayArea,
- coverageExceptions);
-
- if (optimize && !testLayers.optimizeLayouts())
- continue;
-
- std::set<hwc2_layer_t> clientLayers;
- std::set<hwc2_layer_t> clearLayers;
- Hwc2TestClientTarget testClientTarget;
-
- do {
- uint32_t numTypes, numRequests;
- bool hasChanges, skip;
- bool flipClientTarget;
- int32_t presentFence;
-
- ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
- &testLayers, &skip));
- if (skip)
- continue;
-
- ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
- << "wrong number of requests";
-
- ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
- testLayers, layers, numTypes, &clientLayers));
- ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
- numRequests, &clearLayers, &flipClientTarget));
- ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
- &testClientTarget, testLayers, clientLayers,
- clearLayers, flipClientTarget, displayArea));
- ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
-
- ASSERT_NO_FATAL_FAILURE(waitForVsync());
-
- EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
- &presentFence));
-
- ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
-
- } while (testLayers.advance());
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
- std::move(layers)));
- }
-
- ASSERT_NO_FATAL_FAILURE(disableVsync(display));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
- }
-
- void createAndPresentVirtualDisplay(size_t layerCnt,
- Hwc2TestCoverage coverage,
- const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
- coverageExceptions)
- {
- Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
- hwc2_display_t display;
- android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-
- do {
- // Items dependent on the display dimensions
- hwc2_error_t err = HWC2_ERROR_NONE;
- const UnsignedArea& dimension =
- testVirtualDisplay.getDisplayDimension();
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
- dimension.height, &desiredFormat, &display, &err));
- ASSERT_TRUE(err == HWC2_ERROR_NONE)
- << "Cannot allocate virtual display";
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
- ASSERT_NO_FATAL_FAILURE(enableVsync(display));
-
- std::vector<hwc2_config_t> configs;
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
-
- Area displayArea;
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
- &displayArea));
-
- std::vector<hwc2_layer_t> layers;
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers,
- layerCnt));
- Hwc2TestLayers testLayers(layers, coverage, displayArea,
- coverageExceptions);
-
- /*
- * Layouts that do not cover an entire virtual display will
- * cause undefined behavior.
- * Enable optimizeLayouts to avoid this.
- */
- testLayers.optimizeLayouts();
- do {
- // Items dependent on the testLayers properties
- std::set<hwc2_layer_t> clientLayers;
- std::set<hwc2_layer_t> clearLayers;
- uint32_t numTypes, numRequests;
- bool hasChanges, skip;
- bool flipClientTarget;
- int32_t presentFence;
- Hwc2TestClientTarget testClientTarget;
- buffer_handle_t outputBufferHandle;
- android::base::unique_fd outputBufferReleaseFence;
-
- ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
- &testLayers, &skip));
-
- if (skip)
- continue;
-
- ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
-
- if (hasChanges)
- EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
- << "wrong number of requests";
-
- ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
- testLayers, layers, numTypes, &clientLayers));
-
- ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
- numRequests, &clearLayers, &flipClientTarget));
- ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
- &testClientTarget, testLayers, clientLayers,
- clearLayers, flipClientTarget, displayArea));
- ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
-
- ASSERT_EQ(testVirtualDisplay.getOutputBuffer(
- &outputBufferHandle, &outputBufferReleaseFence), 0);
- ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display,
- outputBufferHandle, outputBufferReleaseFence));
-
- EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
- &presentFence));
- ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
-
- ASSERT_EQ(testVirtualDisplay.verifyOutputBuffer(&testLayers,
- &layers, &clearLayers), 0);
-
- /*
- * Upscaling the image causes minor pixel differences.
- * Work around this by using some threshold.
- *
- * Fail test if we are off by more than 1% of our
- * pixels.
- */
- ComparatorResult& comparatorResult = ComparatorResult::get();
- int threshold = (dimension.width * dimension.height) / 100;
- double diffPercent = (comparatorResult.getDifferentPixelCount() * 100.0) /
- (dimension.width * dimension.height);
-
- if (comparatorResult.getDifferentPixelCount() != 0)
- EXPECT_TRUE(false)
- << comparatorResult.getDifferentPixelCount() << " pixels ("
- << diffPercent << "%) are different.";
-
- if (comparatorResult.getDifferentPixelCount() > threshold) {
- EXPECT_TRUE(false)
- << "Mismatched pixel count exceeds threshold. "
- << "Writing buffers to file.";
-
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()
- ->current_test_info();
-
- EXPECT_EQ(testVirtualDisplay.writeBuffersToFile(
- test_info->name()), 0)
- << "Failed to write buffers.";
- }
-
- ASSERT_LE(comparatorResult.getDifferentPixelCount(), threshold)
- << comparatorResult.getDifferentPixelCount() << " pixels ("
- << diffPercent << "%) are different. "
- << "Exceeds 1% threshold, terminating test. "
- << "Test case: " << testLayers.dump();
-
- } while (testLayers.advance());
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
- std::move(layers)));
- }
- ASSERT_NO_FATAL_FAILURE(disableVsync(display));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
- } while (testVirtualDisplay.advance());
- }
-
- hwc2_device_t* mHwc2Device = nullptr;
-
- enum class Hwc2TestHotplugStatus {
- Init = 1,
- Receiving,
- Done,
- };
-
- std::mutex mHotplugMutex;
- std::condition_variable mHotplugCv;
- Hwc2TestHotplugStatus mHotplugStatus = Hwc2TestHotplugStatus::Init;
- std::unordered_set<hwc2_display_t> mDisplays;
-
- /* Store all created layers that have not been destroyed. If an ASSERT_*
- * fails, then destroy the layers on exit */
- std::set<std::pair<hwc2_display_t, hwc2_layer_t>> mLayers;
-
- /* Store the power mode state. If it is not HWC2_POWER_MODE_OFF when
- * tearing down the test cases, change it to HWC2_POWER_MODE_OFF */
- std::set<hwc2_display_t> mActiveDisplays;
-
- /* Store all created virtual displays that have not been destroyed. If an
- * ASSERT_* fails, then destroy the virtual displays on exit */
- std::set<hwc2_display_t> mVirtualDisplays;
-
- std::mutex mVsyncMutex;
- std::condition_variable mVsyncCv;
- hwc2_display_t mVsyncDisplay;
- int64_t mVsyncTimestamp = -1;
-};
-
-void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int32_t connection)
-{
- if (callbackData)
- static_cast<Hwc2Test*>(callbackData)->hotplugCallback(display,
- connection);
-}
-
-void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
- hwc2_display_t display, int64_t timestamp)
-{
- if (callbackData)
- static_cast<Hwc2Test*>(callbackData)->vsyncCallback(display,
- timestamp);
-}
-
-void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
- testLayer->getBlendMode(), outErr));
-}
-
-void setBuffer(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- buffer_handle_t handle;
- android::base::unique_fd acquireFence;
- hwc2_composition_t composition = testLayer->getComposition();
-
- if (composition == HWC2_COMPOSITION_CLIENT
- || composition == HWC2_COMPOSITION_SOLID_COLOR
- || composition == HWC2_COMPOSITION_SIDEBAND)
- return;
-
- if (testLayer->getBuffer(&handle, &acquireFence) < 0)
- return;
-
- ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
- composition));
- EXPECT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
- handle, acquireFence, outErr));
-}
-
-void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
- layer, HWC2_COMPOSITION_SOLID_COLOR));
- ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
- layer, testLayer->getPlaneAlpha()));
- ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
- layer, testLayer->getBlendMode()));
- EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
- testLayer->getColor(), outErr));
-}
-
-void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- hwc2_composition_t composition = testLayer->getComposition();
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
- composition, &err));
- if (outErr) {
- *outErr = err;
- return;
- }
-
- if (composition != HWC2_COMPOSITION_SIDEBAND) {
- EXPECT_EQ(err, HWC2_ERROR_NONE) << "returned wrong error code";
- } else {
- EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
- << "returned wrong error code";
- }
-}
-
-void setCursorPosition(Hwc2Test* test, hwc2_display_t display,
- hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
- layer, HWC2_COMPOSITION_CURSOR));
-
- const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
- EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
- cursorPosition.left, cursorPosition.top, outErr));
-}
-
-void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer,
- testLayer->getDataspace(), outErr));
-}
-
-void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer,
- testLayer->getDisplayFrame(), outErr));
-}
-
-void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t *outErr)
-{
- ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
- testLayer->getBlendMode()));
- EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer,
- testLayer->getPlaneAlpha(), outErr));
-}
-
-void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer,
- testLayer->getSourceCrop(), outErr));
-}
-
-void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer,
- testLayer->getSurfaceDamage(), outErr));
-}
-
-void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer,
- testLayer->getTransform(), outErr));
-}
-
-void setVisibleRegion(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display, layer,
- testLayer->getVisibleRegion(), outErr));
-}
-
-void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
-{
- EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
- testLayer->getZOrder(), outErr));
-}
-
-bool advanceBlendMode(Hwc2TestLayer* testLayer)
-{
- return testLayer->advanceBlendMode();
-}
-
-bool advanceBuffer(Hwc2TestLayer* testLayer)
-{
- if (testLayer->advanceComposition())
- return true;
- return testLayer->advanceBufferArea();
-}
-
-bool advanceColor(Hwc2TestLayer* testLayer)
-{
- /* Color depends on blend mode so advance blend mode last so color is not
- * force to update as often */
- if (testLayer->advancePlaneAlpha())
- return true;
- if (testLayer->advanceColor())
- return true;
- return testLayer->advanceBlendMode();
-}
-
-bool advanceComposition(Hwc2TestLayer* testLayer)
-{
- return testLayer->advanceComposition();
-}
-
-bool advanceCursorPosition(Hwc2TestLayer* testLayer)
-{
- return testLayer->advanceCursorPosition();
-}
-
-bool advanceDataspace(Hwc2TestLayer* testLayer)
-{
- return testLayer->advanceDataspace();
-}
-
-bool advanceDisplayFrame(Hwc2TestLayer* testLayer)
-{
- return testLayer->advanceDisplayFrame();
-}
-
-bool advancePlaneAlpha(Hwc2TestLayer* testLayer)
-{
- return testLayer->advancePlaneAlpha();
-}
-
-bool advanceSourceCrop(Hwc2TestLayer* testLayer)
-{
- if (testLayer->advanceSourceCrop())
- return true;
- return testLayer->advanceBufferArea();
-}
-
-bool advanceSurfaceDamage(Hwc2TestLayer* testLayer)
-{
- if (testLayer->advanceSurfaceDamage())
- return true;
- return testLayer->advanceBufferArea();
-}
-
-bool advanceTransform(Hwc2TestLayer* testLayer)
-{
- return testLayer->advanceTransform();
-}
-
-bool advanceVisibleRegions(Hwc2TestLayers* testLayers)
-{
- return testLayers->advanceVisibleRegions();
-}
-
-bool advanceClientTargetSupport(
- Hwc2TestClientTargetSupport* testClientTargetSupport)
-{
- return testClientTargetSupport->advance();
-}
-
-static const std::array<hwc2_function_descriptor_t, 42> requiredFunctions = {{
- HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
- HWC2_FUNCTION_CREATE_LAYER,
- HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
- HWC2_FUNCTION_DESTROY_LAYER,
- HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
- HWC2_FUNCTION_DUMP,
- HWC2_FUNCTION_GET_ACTIVE_CONFIG,
- HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
- HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
- HWC2_FUNCTION_GET_COLOR_MODES,
- HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
- HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
- HWC2_FUNCTION_GET_DISPLAY_NAME,
- HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
- HWC2_FUNCTION_GET_DISPLAY_TYPE,
- HWC2_FUNCTION_GET_DOZE_SUPPORT,
- HWC2_FUNCTION_GET_HDR_CAPABILITIES,
- HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
- HWC2_FUNCTION_GET_RELEASE_FENCES,
- HWC2_FUNCTION_PRESENT_DISPLAY,
- HWC2_FUNCTION_REGISTER_CALLBACK,
- HWC2_FUNCTION_SET_ACTIVE_CONFIG,
- HWC2_FUNCTION_SET_CLIENT_TARGET,
- HWC2_FUNCTION_SET_COLOR_MODE,
- HWC2_FUNCTION_SET_COLOR_TRANSFORM,
- HWC2_FUNCTION_SET_CURSOR_POSITION,
- HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
- HWC2_FUNCTION_SET_LAYER_BUFFER,
- HWC2_FUNCTION_SET_LAYER_COLOR,
- HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
- HWC2_FUNCTION_SET_LAYER_DATASPACE,
- HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
- HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
- HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
- HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
- HWC2_FUNCTION_SET_LAYER_TRANSFORM,
- HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
- HWC2_FUNCTION_SET_LAYER_Z_ORDER,
- HWC2_FUNCTION_SET_OUTPUT_BUFFER,
- HWC2_FUNCTION_SET_POWER_MODE,
- HWC2_FUNCTION_SET_VSYNC_ENABLED,
- HWC2_FUNCTION_VALIDATE_DISPLAY,
-}};
-
-/* TESTCASE: Tests that the HWC2 supports all required functions. */
-TEST_F(Hwc2Test, GET_FUNCTION)
-{
- for (hwc2_function_descriptor_t descriptor : requiredFunctions) {
- hwc2_function_pointer_t pfn = getFunction(descriptor);
- EXPECT_TRUE(pfn) << "failed to get function "
- << getFunctionDescriptorName(descriptor);
- }
-}
-
-/* TESTCASE: Tests that the HWC2 fails to retrieve and invalid function. */
-TEST_F(Hwc2Test, GET_FUNCTION_invalid_function)
-{
- hwc2_function_pointer_t pfn = getFunction(HWC2_FUNCTION_INVALID);
- EXPECT_FALSE(pfn) << "failed to get invalid function";
-}
-
-/* TESTCASE: Tests that the HWC2 does not return an invalid capability. */
-TEST_F(Hwc2Test, GET_CAPABILITIES)
-{
- std::vector<hwc2_capability_t> capabilities;
-
- getCapabilities(&capabilities);
-
- EXPECT_EQ(std::count(capabilities.begin(), capabilities.end(),
- HWC2_CAPABILITY_INVALID), 0);
-}
-
-static const std::array<hwc2_callback_descriptor_t, 3> callbackDescriptors = {{
- HWC2_CALLBACK_HOTPLUG,
- HWC2_CALLBACK_REFRESH,
- HWC2_CALLBACK_VSYNC,
-}};
-
-/* TESTCASE: Tests that the HWC2 can successfully register all required
- * callback functions. */
-TEST_F(Hwc2Test, REGISTER_CALLBACK)
-{
- hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
- const_cast<char*>("data"));
-
- for (auto descriptor : callbackDescriptors) {
- ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
- []() { return; }));
- }
-}
-
-/* TESTCASE: Test that the HWC2 fails to register invalid callbacks. */
-TEST_F(Hwc2Test, REGISTER_CALLBACK_bad_parameter)
-{
- hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
- const_cast<char*>("data"));
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_INVALID, data,
- []() { return; }, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can register a callback with null data. */
-TEST_F(Hwc2Test, REGISTER_CALLBACK_null_data)
-{
- hwc2_callback_data_t data = nullptr;
-
- for (auto descriptor : callbackDescriptors) {
- ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
- []() { return; }));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 returns the correct display type for each
- * physical display. */
-TEST_F(Hwc2Test, GET_DISPLAY_TYPE)
-{
- for (auto display : mDisplays) {
- hwc2_display_type_t type;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type));
- EXPECT_EQ(type, HWC2_DISPLAY_TYPE_PHYSICAL) << "failed to return"
- " correct display type";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 returns an error when the display type of a bad
- * display is requested. */
-TEST_F(Hwc2Test, GET_DISPLAY_TYPE_bad_display)
-{
- hwc2_display_t display;
- hwc2_display_type_t type;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can create and destroy layers. */
-TEST_F(Hwc2Test, CREATE_DESTROY_LAYER)
-{
- for (auto display : mDisplays) {
- hwc2_layer_t layer;
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot create a layer for a bad display */
-TEST_F(Hwc2Test, CREATE_LAYER_bad_display)
-{
- hwc2_display_t display;
- hwc2_layer_t layer;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 will either support a large number of resources
- * or will return no resources. */
-TEST_F(Hwc2Test, CREATE_LAYER_no_resources)
-{
- const size_t layerCnt = 1000;
-
- for (auto display : mDisplays) {
- std::vector<hwc2_layer_t> layers;
-
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot destroy a layer for a bad display */
-TEST_F(Hwc2Test, DESTROY_LAYER_bad_display)
-{
- hwc2_display_t badDisplay;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&badDisplay));
-
- for (auto display : mDisplays) {
- hwc2_layer_t layer = 0;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot destory a bad layer */
-TEST_F(Hwc2Test, DESTROY_LAYER_bad_layer)
-{
- for (auto display : mDisplays) {
- hwc2_layer_t layer;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX / 2, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 0, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX - 1, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 1, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer + 1, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
- }
-}
-
-static const std::array<hwc2_attribute_t, 2> requiredAttributes = {{
- HWC2_ATTRIBUTE_WIDTH,
- HWC2_ATTRIBUTE_HEIGHT,
-}};
-
-static const std::array<hwc2_attribute_t, 3> optionalAttributes = {{
- HWC2_ATTRIBUTE_VSYNC_PERIOD,
- HWC2_ATTRIBUTE_DPI_X,
- HWC2_ATTRIBUTE_DPI_Y,
-}};
-
-/* TESTCASE: Tests that the HWC2 can return display attributes for a valid
- * config. */
-TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- int32_t value;
-
- for (auto attribute : requiredAttributes) {
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
- attribute, &value));
- EXPECT_GE(value, 0) << "missing required attribute "
- << getAttributeName(attribute) << " for config "
- << config;
- }
- for (auto attribute : optionalAttributes) {
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
- attribute, &value));
- }
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 will return a value of -1 for an invalid
- * attribute */
-TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_invalid_attribute)
-{
- const hwc2_attribute_t attribute = HWC2_ATTRIBUTE_INVALID;
-
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- int32_t value;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
- attribute, &value, &err));
- EXPECT_EQ(value, -1) << "failed to return -1 for an invalid"
- " attribute for config " << config;
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad display */
-TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_display)
-{
- hwc2_display_t display;
- const hwc2_config_t config = 0;
- int32_t value;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- for (auto attribute : requiredAttributes) {
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
- &value, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
- }
-
- for (auto attribute : optionalAttributes) {
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
- &value, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad config */
-TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_config)
-{
- for (auto display : mDisplays) {
- hwc2_config_t config;
- int32_t value;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
-
- for (auto attribute : requiredAttributes) {
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
- attribute, &value, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
- }
-
- for (auto attribute : optionalAttributes) {
- ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
- attribute, &value, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 will get display configs for active displays */
-TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 will not get display configs for bad displays */
-TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_bad_display)
-{
- hwc2_display_t display;
- std::vector<hwc2_config_t> configs;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs, &err));
-
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
- EXPECT_TRUE(configs.empty()) << "returned configs for bad display";
-}
-
-/* TESTCASE: Tests that the HWC2 will return the same config list multiple
- * times in a row. */
-TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_same)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs1, configs2;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs1));
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs2));
-
- EXPECT_TRUE(std::is_permutation(configs1.begin(), configs1.end(),
- configs2.begin())) << "returned two different config sets";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 does not return duplicate display configs */
-TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_duplicate)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- std::unordered_set<hwc2_config_t> configsSet(configs.begin(),
- configs.end());
- EXPECT_EQ(configs.size(), configsSet.size()) << "returned duplicate"
- " configs";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 returns the active config for a display */
-TEST_F(Hwc2Test, GET_ACTIVE_CONFIG)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- hwc2_config_t activeConfig;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig));
-
- EXPECT_EQ(activeConfig, config) << "failed to get active config";
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 does not return an active config for a bad
- * display. */
-TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_display)
-{
- hwc2_display_t display;
- hwc2_config_t activeConfig;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
-
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 either begins with a valid active config
- * or returns an error when getActiveConfig is called. */
-TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_config)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
- hwc2_config_t activeConfig;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- if (configs.empty())
- return;
-
- ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
- if (err == HWC2_ERROR_NONE) {
- EXPECT_NE(std::count(configs.begin(), configs.end(),
- activeConfig), 0) << "active config is not found in "
- " configs for display";
- } else {
- EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can set every display config as an active
- * config */
-TEST_F(Hwc2Test, SET_ACTIVE_CONFIG)
-{
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- EXPECT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an active config for a bad display */
-TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_display)
-{
- hwc2_display_t display;
- const hwc2_config_t config = 0;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an invalid active config */
-TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_config)
-{
- for (auto display : mDisplays) {
- hwc2_config_t config;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 returns a valid value for getDozeSupport. */
-TEST_F(Hwc2Test, GET_DOZE_SUPPORT)
-{
- for (auto display : mDisplays) {
- int32_t support = -1;
-
- ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
-
- EXPECT_TRUE(support == 0 || support == 1) << "invalid doze support value";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get doze support for a bad display. */
-TEST_F(Hwc2Test, GET_DOZE_SUPPORT_bad_display)
-{
- hwc2_display_t display;
- int32_t support = -1;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
-
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can set all supported power modes */
-TEST_F(Hwc2Test, SET_POWER_MODE)
-{
- for (auto display : mDisplays) {
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
-
- int32_t support = -1;
- ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
- if (support != 1)
- return;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
- HWC2_POWER_MODE_DOZE_SUSPEND));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a power mode for a bad display. */
-TEST_F(Hwc2Test, SET_POWER_MODE_bad_display)
-{
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-
- int32_t support = -1;
- ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
- if (support != 1)
- return;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE_SUSPEND,
- &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an invalid power mode value. */
-TEST_F(Hwc2Test, SET_POWER_MODE_bad_parameter)
-{
- for (auto display : mDisplays) {
- hwc2_power_mode_t mode = static_cast<hwc2_power_mode_t>(
- HWC2_POWER_MODE_DOZE_SUSPEND + 1);
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, mode, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code "
- << mode;
- }
-}
-
-/* TESTCASE: Tests that the HWC2 will return unsupported if it does not support
- * an optional power mode. */
-TEST_F(Hwc2Test, SET_POWER_MODE_unsupported)
-{
- for (auto display : mDisplays) {
- int32_t support = -1;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
- if (support == 1)
- return;
-
- ASSERT_EQ(support, 0) << "invalid doze support value";
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE,
- &err));
- EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
- HWC2_POWER_MODE_DOZE_SUSPEND, &err));
- EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can set the same power mode multiple times. */
-TEST_F(Hwc2Test, SET_POWER_MODE_stress)
-{
- for (auto display : mDisplays) {
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
-
- int32_t support = -1;
- ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
- if (support != 1)
- return;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
- HWC2_POWER_MODE_DOZE_SUSPEND));
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
- HWC2_POWER_MODE_DOZE_SUSPEND));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can enable and disable vsync on active
- * displays */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED)
-{
- for (auto display : mDisplays) {
- hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
- const_cast<char*>("data"));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
- []() { return; }));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 issues a valid vsync callback. */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED_callback)
-{
- for (auto display : mDisplays) {
- hwc2_display_t receivedDisplay;
- int64_t receivedTimestamp;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(enableVsync(display));
-
- ASSERT_NO_FATAL_FAILURE(waitForVsync(&receivedDisplay,
- &receivedTimestamp));
-
- EXPECT_EQ(receivedDisplay, display) << "failed to get correct display";
- EXPECT_GE(receivedTimestamp, 0) << "failed to get valid timestamp";
-
- ASSERT_NO_FATAL_FAILURE(disableVsync(display));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot enable a vsync for a bad display */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_display)
-{
- hwc2_display_t display;
- hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
- const_cast<char*>("data"));
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
- []() { return; }));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot enable an invalid vsync value */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_parameter)
-{
- for (auto display : mDisplays) {
- hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
- const_cast<char*>("data"));
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
- []() { return; }));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_INVALID,
- &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can enable and disable a vsync value multiple
- * times. */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED_stress)
-{
- for (auto display : mDisplays) {
- hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
- const_cast<char*>("data"));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
- []() { return; }));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can set a vsync enable value when the display
- * is off and no callback is registered. */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback_no_power)
-{
- const uint secs = 1;
-
- for (auto display : mDisplays) {
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
-
- sleep(secs);
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can set a vsync enable value when no callback
- * is registered. */
-TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback)
-{
- const uint secs = 1;
-
- for (auto display : mDisplays) {
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
-
- sleep(secs);
-
- ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 returns a display name for each display */
-TEST_F(Hwc2Test, GET_DISPLAY_NAME)
-{
- for (auto display : mDisplays) {
- std::string name;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 does not return a display name for a bad
- * display */
-TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display)
-{
- hwc2_display_t display;
- std::string name;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can set basic composition types. */
-TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setComposition, advanceComposition));
-}
-
-/* TESTCASE: Tests that the HWC2 can update a basic composition type on a
- * layer. */
-TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setComposition, advanceComposition));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a composition type for a bad layer */
-TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setComposition));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a bad composition type */
-TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- hwc2_error_t* outErr) {
-
- ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
- layer, HWC2_COMPOSITION_INVALID, outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer. */
-TEST_F(Hwc2Test, SET_CURSOR_POSITION)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- ::setCursorPosition, advanceCursorPosition));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the cursor position of a layer. */
-TEST_F(Hwc2Test, SET_CURSOR_POSITION_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- ::setCursorPosition, advanceCursorPosition));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer when the
- * composition type has not been set to HWC2_COMPOSITION_CURSOR. */
-TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
- const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
- EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
- cursorPosition.left, cursorPosition.top, outErr));
- },
-
- advanceCursorPosition));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad
- * display. */
-TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_display)
-{
- hwc2_display_t display;
- hwc2_layer_t layer = 0;
- int32_t x = 0, y = 0;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(setCursorPosition(display, layer, x, y, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad layer. */
-TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
-
- const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
- EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display,
- badLayer, cursorPosition.left, cursorPosition.top,
- outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set a blend mode value of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setBlendMode, advanceBlendMode));
-}
-
-/* TESTCASE: Tests that the HWC2 can update a blend mode value of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setBlendMode, advanceBlendMode));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a blend mode for a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setBlendMode));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an invalid blend mode. */
-TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- hwc2_error_t* outErr) {
-
- ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
- layer, HWC2_BLEND_MODE_INVALID, outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the buffer of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_BUFFER)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setBuffer, advanceBuffer));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the buffer of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_BUFFER_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setBuffer, advanceBuffer));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the buffer of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
-
- buffer_handle_t handle = nullptr;
- android::base::unique_fd acquireFence;
-
- /* If there is not available buffer for the given buffer
- * properties, it should not fail this test case */
- if (testLayer->getBuffer(&handle, &acquireFence) == 0) {
- *outErr = HWC2_ERROR_BAD_LAYER;
- return;
- }
-
- ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, badLayer,
- handle, acquireFence, outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set an invalid buffer for a layer. */
-TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_parameter)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- hwc2_error_t* outErr) {
-
- buffer_handle_t handle = nullptr;
- int32_t acquireFence = -1;
-
- ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
- handle, acquireFence, outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the color of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_COLOR)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setColor, advanceColor));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the color of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_COLOR_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setColor, advanceColor));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the color of a layer when the
- * composition type has not been set to HWC2_COMPOSITION_SOLID_COLOR. */
-TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
-
- EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
- testLayer->getColor(), outErr));
- },
-
- advanceColor));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the color of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
- Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
-
- EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer,
- testLayer->getColor(), outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the dataspace of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_DATASPACE)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setDataspace, advanceDataspace));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the dataspace of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_DATASPACE_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setDataspace, advanceDataspace));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a dataspace for a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setDataspace));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the display frame of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setDisplayFrame, advanceDisplayFrame));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the display frame of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setDisplayFrame, advanceDisplayFrame));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the display frame of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setDisplayFrame));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the plane alpha of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setPlaneAlpha, advancePlaneAlpha));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the plane alpha of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setPlaneAlpha, advancePlaneAlpha));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a plane alpha for a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
- Hwc2TestLayer* testLayer, hwc2_error_t *outErr) {
-
- EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
- badLayer, testLayer->getPlaneAlpha(), outErr));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the source crop of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setSourceCrop, advanceSourceCrop));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the source crop of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setSourceCrop, advanceSourceCrop));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the source crop of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setSourceCrop));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the surface damage of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setSurfaceDamage, advanceSurfaceDamage));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the surface damage of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setSurfaceDamage, advanceSurfaceDamage));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the surface damage of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setSurfaceDamage));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_TRANSFORM)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
- setTransform, advanceTransform));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the transform value of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_update)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
- setTransform, advanceTransform));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the transform for a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setTransform));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the visible region of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Basic, 5,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayers* testLayers) {
-
- EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display,
- layer, testLayers->getVisibleRegion(layer)));
- },
-
- advanceVisibleRegions));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the visible region of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setVisibleRegion));
-}
-
-/* TESTCASE: Tests that the HWC2 can set the z order of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_Z_ORDER)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10,
- [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
- Hwc2TestLayers* testLayers) {
-
- EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
- testLayers->getZOrder(layer)));
- },
-
- /* TestLayer z orders are set during the construction of TestLayers
- * and cannot be updated. There is no need (or ability) to cycle
- * through additional z order configurations. */
- [] (Hwc2TestLayers* /*testLayers*/) {
- return false;
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can update the z order of a layer. */
-TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_update)
-{
- const std::vector<uint32_t> zOrders = { static_cast<uint32_t>(0),
- static_cast<uint32_t>(1), static_cast<uint32_t>(UINT32_MAX / 4),
- static_cast<uint32_t>(UINT32_MAX / 2),
- static_cast<uint32_t>(UINT32_MAX) };
-
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- hwc2_layer_t layer;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
-
- ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
-
- for (uint32_t zOrder : zOrders) {
- EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer, zOrder));
- }
-
- ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
- }
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the z order of a bad layer. */
-TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_bad_layer)
-{
- ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
- setZOrder));
-}
-
-/* TESTCASE: Tests that the HWC2 can display a layer with basic property
- * coverage */
-TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic)
-{
- ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
- [] (Hwc2Test* test, hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* /*testLayers*/) {
-
- uint32_t numTypes, numRequests;
- bool hasChanges = false;
-
- EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
- << "wrong number of requests";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can display 5 layers with default coverage. */
-TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5)
-{
- ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5,
- [] (Hwc2Test* test, hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* /*testLayers*/) {
-
- uint32_t numTypes, numRequests;
- bool hasChanges = false;
-
- EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
- << "wrong number of requests";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot validate a bad display */
-TEST_F(Hwc2Test, VALIDATE_DISPLAY_bad_display)
-{
- hwc2_display_t display;
- uint32_t numTypes, numRequests;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, &numRequests,
- &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can get display requests after validating a
- * basic layer. */
-TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_basic)
-{
- ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
- [] (Hwc2Test* test, hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* /*testLayers*/) {
-
- uint32_t numTypes, numRequests;
- bool hasChanges = false;
-
- ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, layers.size())
- << "wrong number of requests";
-
- EXPECT_NO_FATAL_FAILURE(test->handleRequests(display, layers,
- numRequests));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get display requests from a bad display */
-TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_bad_display)
-{
- hwc2_display_t display;
- hwc2_display_request_t displayRequests;
- std::vector<hwc2_layer_t> layers;
- std::vector<hwc2_layer_request_t> layerRequests;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- EXPECT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequests,
- &layers, &layerRequests, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get display requests from an non
- * validated display. */
-TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_not_validated)
-{
- ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
- [] (Hwc2Test* test, hwc2_display_t display,
- std::vector<hwc2_layer_t>* layers) {
-
- hwc2_display_request_t displayRequests;
- std::vector<hwc2_layer_request_t> layerRequests;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->getDisplayRequests(display,
- &displayRequests, layers, &layerRequests, &err));
- EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
- << "returned wrong error code";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can get changed composition types after
- * validating a basic layer. */
-TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic)
-{
- ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
- [] (Hwc2Test* test, hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* testLayers) {
-
- uint32_t numTypes, numRequests;
- bool hasChanges = false;
-
- ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, layers.size())
- << "wrong number of requests";
-
- EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
- *testLayers, layers, numTypes));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get changed composition types from a bad
- * display */
-TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_bad_display)
-{
- hwc2_display_t display;
- std::vector<hwc2_layer_t> layers;
- std::vector<hwc2_composition_t> types;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- EXPECT_NO_FATAL_FAILURE(getChangedCompositionTypes(display, &layers,
- &types, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get changed composition types from an non
- * validated display. */
-TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_not_validated)
-{
- ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
- [] (Hwc2Test* test, hwc2_display_t display,
- std::vector<hwc2_layer_t>* layers) {
-
- std::vector<hwc2_composition_t> types;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->getChangedCompositionTypes(
- display, layers, &types, &err));
- EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
- << "returned wrong error code";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can accept display changes after validating a
- * basic layer. */
-TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic)
-{
- ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
- [] (Hwc2Test* test, hwc2_display_t display,
- const std::vector<hwc2_layer_t>& layers,
- Hwc2TestLayers* testLayers) {
-
- uint32_t numTypes, numRequests;
- bool hasChanges = false;
-
- ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, layers.size())
- << "wrong number of requests";
-
- ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
- *testLayers, layers, numTypes));
-
- EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot accept display changes from a bad
- * display */
-TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_bad_display)
-{
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- EXPECT_NO_FATAL_FAILURE(acceptDisplayChanges(display, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot accept display changes from an non
- * validated display. */
-TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_not_validated)
-{
- ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
- [] (Hwc2Test* test, hwc2_display_t display,
- std::vector<hwc2_layer_t>* /*layers*/) {
-
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display, &err));
- EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
- << "returned wrong error code";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 supports client target with required values */
-TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT)
-{
- ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t display,
- const Hwc2TestClientTargetSupport& testClientTargetSupport) {
-
- const Area bufferArea = testClientTargetSupport.getBufferArea();
- const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
-
- ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
- bufferArea.width, bufferArea.height, format,
- testClientTargetSupport.getDataspace()));
- },
-
- advanceClientTargetSupport));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get client target support for a bad
- * display. */
-TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_bad_display)
-{
- ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t /*display*/,
- const Hwc2TestClientTargetSupport& testClientTargetSupport) {
-
- const Area bufferArea = testClientTargetSupport.getBufferArea();
- const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
- hwc2_display_t badDisplay;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
-
- ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(badDisplay,
- bufferArea.width, bufferArea.height, format,
- testClientTargetSupport.getDataspace(), &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
- },
-
- advanceClientTargetSupport));
-}
-
-/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
- * for a variety of client target values. */
-TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_unsupported)
-{
- ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Complete,
- [] (Hwc2Test* test, hwc2_display_t display,
- const Hwc2TestClientTargetSupport& testClientTargetSupport) {
-
- const Area bufferArea = testClientTargetSupport.getBufferArea();
- const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
- bufferArea.width, bufferArea.height, format,
- testClientTargetSupport.getDataspace(), &err));
- EXPECT_TRUE(err == HWC2_ERROR_NONE
- || err == HWC2_ERROR_UNSUPPORTED)
- << "returned wrong error code";
- },
-
- advanceClientTargetSupport));
-}
-
-/* TESTCASE: Tests that the HWC2 can set a client target buffer for a basic
- * layer. */
-TEST_F(Hwc2Test, SET_CLIENT_TARGET_basic)
-{
- const Dataspace dataspace = Dataspace::UNKNOWN;
- const hwc_region_t damage = { };
- const size_t layerCnt = 1;
-
- for (auto display : mDisplays) {
- std::vector<hwc2_config_t> configs;
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
-
- ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
-
- for (auto config : configs) {
- Area displayArea;
- std::vector<hwc2_layer_t> layers;
-
- ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
- ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
-
- ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
- Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Basic,
- displayArea);
-
- if (!testLayers.optimizeLayouts())
- continue;
-
- Hwc2TestClientTarget testClientTarget;
-
- do {
- std::set<hwc2_layer_t> clientLayers;
- std::set<hwc2_layer_t> clearLayers;
- uint32_t numTypes, numRequests;
- bool hasChanges, skip;
- bool flipClientTarget;
- buffer_handle_t handle;
- int32_t acquireFence;
-
- ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
- &testLayers, &skip));
- if (skip)
- continue;
-
- ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
- &numRequests, &hasChanges));
- if (hasChanges)
- EXPECT_LE(numTypes, layers.size())
- << "wrong number of requests";
-
- ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
- testLayers, layers, numTypes, &clientLayers));
- ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
- numRequests, &clearLayers, &flipClientTarget));
- ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
- clearLayers, flipClientTarget, displayArea, &handle,
- &acquireFence), 0);
- EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle,
- acquireFence, dataspace, damage));
-
- if (acquireFence >= 0)
- close(acquireFence);
-
- } while (testLayers.advance());
-
- ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
- }
-
- ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a client target for a bad display. */
-TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display)
-{
- hwc2_display_t display;
- std::vector<hwc2_layer_t> layers;
- const Area displayArea = {0, 0};
- Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Default, displayArea);
- std::set<hwc2_layer_t> clientLayers;
- std::set<hwc2_layer_t> flipClientTargetLayers;
- bool flipClientTarget = true;
- const Dataspace dataspace = Dataspace::UNKNOWN;
- const hwc_region_t damage = { };
- buffer_handle_t handle;
- int32_t acquireFence;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- Hwc2TestClientTarget testClientTarget;
-
- ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
- flipClientTargetLayers, flipClientTarget, displayArea, &handle,
- &acquireFence), 0);
-
- EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
- dataspace, damage, &err));
-
- if (acquireFence >= 0)
- close(acquireFence);
-
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 default layer. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_default_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 default layers. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_default_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 3 default layers. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_default_3)
-{
- const size_t layerCnt = 3;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 4 default layers. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_default_4)
-{
- const size_t layerCnt = 4;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 5 default layers. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_default_5)
-{
- const size_t layerCnt = 5;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 6 default layers. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_default_6)
-{
- const size_t layerCnt = 6;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * blend mode. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Basic},
- {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * blend mode. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * buffer. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_buffer_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * color. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_color_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * color. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_color_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
- {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic},
- {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Basic}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * composition. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_composition_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * cursor. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * cursor. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * dataspace. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_dataspace_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * display frame. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * display frame. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 3 layers with complete coverage of
- * display frame. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_3)
-{
- const size_t layerCnt = 3;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 4 layers with complete coverage of
- * display frame. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_4)
-{
- const size_t layerCnt = 4;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * plane alpha. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
- {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * plane alpha. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
- {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
- bool optimize = false;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * source crop. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * source crop. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * surface damage. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_surface_damage_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::SurfaceDamage, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * transform. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
- * transform. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_2)
-{
- const size_t layerCnt = 2;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
- {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete},
- {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
- * basic. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_basic_1)
-{
- const size_t layerCnt = 1;
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
- bool optimize = true;
-
- ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
- optimize));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot present a bad display. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_bad_display)
-{
- hwc2_display_t display;
- int32_t presentFence;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(presentDisplay(display, &presentFence, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot present an unvalidated display. */
-TEST_F(Hwc2Test, PRESENT_DISPLAY_not_validated)
-{
- ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 1,
- [] (Hwc2Test* test, hwc2_display_t display,
- const std::vector<hwc2_layer_t>& /*layers*/,
- Hwc2TestLayers* /*testLayers*/) {
-
- int32_t presentFence;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
- HWC2_POWER_MODE_ON));
- ASSERT_NO_FATAL_FAILURE(test->enableVsync(display));
-
- ASSERT_NO_FATAL_FAILURE(test->waitForVsync());
-
- ASSERT_NO_FATAL_FAILURE(test->presentDisplay(display,
- &presentFence, &err));
- EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
- << "returned wrong error code";
-
- ASSERT_NO_FATAL_FAILURE(test->disableVsync(display));
- ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
- HWC2_POWER_MODE_OFF));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get release fences from a bad display. */
-TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display)
-{
- hwc2_display_t display;
- std::vector<hwc2_layer_t> layers;
- std::vector<int32_t> fences;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-static const std::array<ColorMode, 9> androidColorModes = {{
- ColorMode::NATIVE,
- ColorMode::STANDARD_BT601_625,
- ColorMode::STANDARD_BT601_625_UNADJUSTED,
- ColorMode::STANDARD_BT601_525,
- ColorMode::STANDARD_BT601_525_UNADJUSTED,
- ColorMode::STANDARD_BT709,
- ColorMode::DCI_P3,
- ColorMode::SRGB,
- ColorMode::ADOBE_RGB,
-}};
-
-/* TESTCASE: Tests that the HWC2 can get the color modes for a display. The
- * display must support ColorMode::NATIVE */
-TEST_F(Hwc2Test, GET_COLOR_MODES)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- std::vector<ColorMode> colorModes;
-
- ASSERT_NO_FATAL_FAILURE(test->getColorModes(display,
- &colorModes));
-
- EXPECT_NE(std::count(colorModes.begin(), colorModes.end(),
- ColorMode::NATIVE), 0) << "all displays"
- " must support ColorMode::NATIVE";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get color modes from a bad display. */
-TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display)
-{
- hwc2_display_t display;
- std::vector<ColorMode> colorModes;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getColorModes(display, &colorModes, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 can set the required color mode on a display. */
-TEST_F(Hwc2Test, SET_COLOR_MODES)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- const ColorMode colorMode = ColorMode::NATIVE;
-
- EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set a color mode on a bad display. */
-TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display)
-{
- hwc2_display_t display;
- const ColorMode colorMode = ColorMode::NATIVE;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(setColorMode(display, colorMode, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an invalid color mode. */
-TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- const ColorMode colorMode = static_cast<ColorMode>(-1);
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode,
- &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
- << "returned wrong error code";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
- * for all valid color modes. */
-TEST_F(Hwc2Test, SET_COLOR_MODES_unsupported)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- for (auto colorMode : androidColorModes) {
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->setColorMode(display,
- colorMode, &err));
-
- EXPECT_TRUE(err == HWC2_ERROR_NONE
- || err == HWC2_ERROR_UNSUPPORTED)
- << "returned wrong error code";
- }
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 gets the HDR capabilities for a display and
- * test if they are valid. */
-TEST_F(Hwc2Test, GET_HDR_CAPABILITIES)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- std::vector<android_hdr_t> hdrCapabilities;
- float maxLuminance, maxAverageLuminance, minLuminance;
-
- EXPECT_NO_FATAL_FAILURE(test->getHdrCapabilities(display,
- &hdrCapabilities, &maxLuminance, &maxAverageLuminance,
- &minLuminance));
-
- if (hdrCapabilities.empty())
- return;
-
- EXPECT_GE(maxLuminance, maxAverageLuminance);
- EXPECT_GE(maxAverageLuminance, minLuminance);
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot get hdr capabilities from a bad display */
-TEST_F(Hwc2Test, GET_HDR_CAPABILITIES_bad_display)
-{
- hwc2_display_t display;
- std::vector<android_hdr_t> hdrCapabilities;
- float maxLuminance, maxAverageLuminance, minLuminance;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(getHdrCapabilities(display, &hdrCapabilities,
- &maxLuminance, &maxAverageLuminance, &minLuminance, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-static const std::array<float, 16> identityMatrix = {{
- 1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0,
-}};
-
-/* Values for the color transform matrices were precomputed using the source code
- * in surfaceflinger/Effects/Daltonizer.cpp. */
-
-static const std::array<const std::array<float, 16>, 5> exampleMatrices = {{
- identityMatrix,
- /* Converts RGB color to the XYZ space */
- {{ 0.4124, 0.2126, 0.0193, 0,
- 0.3576, 0.7152, 0.1192, 0,
- 0.1805, 0.0722, 0.9505, 0,
- 0 , 0 , 0 , 1 }},
- /* Protanomaly */
- {{ 0.068493, 0.931506, 0, 0,
- 0.068493, 0.931507, 0, 0,
- 0.013626, -0.013626, 1, 0,
- 0, 0, 0, 1 }},
- /* Deuteranomaly */
- {{ 0.288299, 0.711701, 0, 0,
- 0.052709, 0.947291, 0, 0,
- -0.257912, 0.257912, 1, 0,
- 0, 0, 0, 1 }},
- /* Tritanomaly */
- {{ 1, -0.805712, 0.805712, 0,
- 0, 0.378838, 0.621162, 0,
- 0, 0.104823, 0.895177, 0,
- 0, 0, 0, 1 }},
-}};
-
-/* TESTCASE: Tests that the HWC2 can set the identity color transform */
-TEST_F(Hwc2Test, SET_COLOR_TRANSFORM)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
- identityMatrix, HAL_COLOR_TRANSFORM_IDENTITY));
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set the color transform for a bad
- * display. */
-TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_display)
-{
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(setColorTransform(display, identityMatrix,
- HAL_COLOR_TRANSFORM_IDENTITY, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an invalid color transform. */
-TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_parameter)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- const android_color_transform_t hint =
- static_cast<android_color_transform_t>(-1);
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->setColorTransform(display,
- identityMatrix, hint, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
- << "returned wrong error code";
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 can set an arbitrary color matrix. */
-TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_arbitrary_matrix)
-{
- ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
- [] (Hwc2Test* test, hwc2_display_t display) {
-
- const android_color_transform_t hint =
- HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
-
- for (const std::array<float, 16>& matrix : exampleMatrices) {
- EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
- matrix, hint));
- }
- }
- ));
-}
-
-/* TESTCASE: Tests that the HWC2 create an destory virtual displays. */
-TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY)
-{
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
- [] (Hwc2Test* /*test*/, hwc2_display_t /*display*/,
- Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) { }));
-}
-
-/* TESTCASE: Tests that the HWC2 can create and destroy multiple virtual
- * displays. */
-TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY_multiple)
-{
- Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
- std::vector<hwc2_display_t> displays;
-
- do {
- const UnsignedArea& dimension =
- testVirtualDisplay.getDisplayDimension();
- android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
- dimension.height, &desiredFormat, &display, &err));
-
- EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
- || err == HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
- EXPECT_GE(desiredFormat, 0) << "invalid format";
-
- if (err == HWC2_ERROR_NONE)
- displays.push_back(display);
-
- } while (testVirtualDisplay.advance());
-
- for (hwc2_display_t display : displays) {
- EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 cannot destroy a bad virtual displays. */
-TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_display)
-{
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
-
- ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
-}
-
-/* TESTCASE: Tests that the HWC2 cannot destroy a physical display. */
-TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_parameter)
-{
- hwc2_error_t err = HWC2_ERROR_NONE;
- for (auto display : mDisplays) {
- ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can get the max virtual display count. */
-TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT)
-{
- uint32_t maxCnt;
-
- ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
-}
-
-/* TESTCASE: Tests that the HWC2 returns the same max virtual display count for
- * each call. */
-TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_duplicate)
-{
- uint32_t maxCnt1, maxCnt2;
-
- ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt1));
- ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt2));
-
- EXPECT_EQ(maxCnt1, maxCnt2) << "returned two different max virtual display"
- " counts";
-}
-
-/* TESTCASE: Tests that the HWC2 can create the max number of virtual displays
- * that it reports. */
-TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_create_max)
-{
- std::vector<hwc2_display_t> displays;
- uint32_t maxCnt;
-
- ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
-
- while (displays.size() < maxCnt) {
- uint32_t width = 1920, height = 1080;
- android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
- hwc2_display_t display;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(width, height,
- &desiredFormat, &display, &err));
-
- EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
- << "returned wrong error code";
- if (err != HWC2_ERROR_NONE)
- break;
-
- displays.push_back(display);
- }
-
- for (hwc2_display_t display : displays) {
- EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can set an output buffer for a virtual
- * display. */
-TEST_F(Hwc2Test, SET_OUTPUT_BUFFER)
-{
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
- [] (Hwc2Test* test, hwc2_display_t display,
- Hwc2TestVirtualDisplay* testVirtualDisplay) {
-
- buffer_handle_t handle;
- android::base::unique_fd acquireFence;
-
- if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) >= 0)
- EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display,
- handle, acquireFence));
- }));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an output buffer for a bad display */
-TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_display)
-{
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t /*display*/,
- Hwc2TestVirtualDisplay* testVirtualDisplay) {
-
- hwc2_display_t badDisplay;
- buffer_handle_t handle;
- android::base::unique_fd acquireFence;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
-
- if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) < 0)
- return;
-
- ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay,
- handle, acquireFence, &err));
- EXPECT_TRUE(err == HWC2_ERROR_BAD_DISPLAY)
- << "returned wrong error code";
- }));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an invalid output buffer. */
-TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_parameter)
-{
- ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
- [] (Hwc2Test* test, hwc2_display_t display,
- Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) {
-
- const buffer_handle_t handle = nullptr;
- uint32_t releaseFence = -1;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(display, handle,
- releaseFence, &err));
- EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
- << "returned wrong error code";
- }));
-}
-
-/* TESTCASE: Tests that the HWC2 cannot set an output buffer for non virtual
- * display */
-TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_unsupported)
-{
- for (auto display : mDisplays) {
- Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
-
- do {
- buffer_handle_t handle;
- android::base::unique_fd acquireFence;
- hwc2_error_t err = HWC2_ERROR_NONE;
-
- if (testVirtualDisplay.getOutputBuffer(&handle, &acquireFence) < 0)
- continue;
-
- ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle,
- acquireFence, &err));
- EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
-
- } while (testVirtualDisplay.advance());
- }
-}
-
-/* TESTCASE: Tests that the HWC2 can dump debug information. */
-TEST_F(Hwc2Test, DUMP)
-{
- std::string buffer;
-
- ASSERT_NO_FATAL_FAILURE(dump(&buffer));
-}
-
-/*
- * TODO(b/64724708): Hwc2TestPropertyName::BufferArea MUST be default for all
- * virtual display tests as we don't handle this case correctly.
- *
- * Only default dataspace is supported in our drawing code.
- */
-const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>
- virtualDisplayExceptions =
- {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Default},
- {Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Default}};
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with default coverage on a
- * virtual display. */
-TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_1)
-{
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- const size_t layerCnt = 1;
- ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
- virtualDisplayExceptions));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 1 layer with basic coverage on a
- * virtual display. */
-TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_basic_1)
-{
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
- const size_t layerCnt = 1;
- ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
- virtualDisplayExceptions));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 2 layers with default coverage on a
- * virtual display. */
-TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_2)
-{
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- const size_t layerCnt = 2;
- ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
- virtualDisplayExceptions));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 3 layers with default coverage on a
- * virtual display. */
-TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_3)
-{
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- const size_t layerCnt = 3;
- ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
- virtualDisplayExceptions));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 4 layers with default coverage on a
- * virtual display. */
-TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_4)
-{
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- const size_t layerCnt = 4;
- ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
- virtualDisplayExceptions));
-}
-
-/* TESTCASE: Tests that the HWC2 can present 5 layers with default coverage on a
- * virtual display. */
-TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_5)
-{
- Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
- const size_t layerCnt = 5;
- ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
- virtualDisplayExceptions));
-}
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
deleted file mode 100644
index fcd0d31..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include <mutex>
-#include <array>
-#include <sstream>
-#include <algorithm>
-
-#include <gui/Surface.h>
-#include <gui/BufferItemConsumer.h>
-
-#include <ui/GraphicBuffer.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <math/vec4.h>
-
-#include <GLES3/gl3.h>
-#include <SkImageEncoder.h>
-#include <SkStream.h>
-#include "Hwc2TestBuffer.h"
-#include "Hwc2TestLayers.h"
-
-using namespace android;
-using android::hardware::graphics::common::V1_0::BufferUsage;
-
-/* Returns a fence from egl */
-typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
-
-/* Returns fence to fence generator */
-static void setFence(int32_t fence, void* fenceGenerator);
-
-
-/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
- * away. The fences are sent to the requester via a callback */
-class Hwc2TestSurfaceManager {
-public:
- /* Listens for a new frame, detaches the buffer and returns the fence
- * through saved callback. */
- class BufferListener : public ConsumerBase::FrameAvailableListener {
- public:
- BufferListener(sp<IGraphicBufferConsumer> consumer,
- FenceCallback callback, void* callbackArgs)
- : mConsumer(consumer),
- mCallback(callback),
- mCallbackArgs(callbackArgs) { }
-
- void onFrameAvailable(const BufferItem& /*item*/)
- {
- BufferItem item;
-
- if (mConsumer->acquireBuffer(&item, 0))
- return;
- if (mConsumer->detachBuffer(item.mSlot))
- return;
-
- mCallback(item.mFence->dup(), mCallbackArgs);
- }
-
- private:
- sp<IGraphicBufferConsumer> mConsumer;
- FenceCallback mCallback;
- void* mCallbackArgs;
- };
-
- /* Creates a buffer listener that waits on a new frame from the buffer
- * queue. */
- void initialize(const Area& bufferArea, android_pixel_format_t format,
- FenceCallback callback, void* callbackArgs)
- {
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
-
- consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
- consumer->setDefaultBufferFormat(format);
-
- mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
-
- mListener = new BufferListener(consumer, callback, callbackArgs);
- mBufferItemConsumer->setFrameAvailableListener(mListener);
-
- mSurface = new Surface(producer, true);
- }
-
- /* Used by Egl manager. The surface is never displayed. */
- sp<Surface> getSurface() const
- {
- return mSurface;
- }
-
-private:
- sp<BufferItemConsumer> mBufferItemConsumer;
- sp<BufferListener> mListener;
- /* Used by Egl manager. The surface is never displayed */
- sp<Surface> mSurface;
-};
-
-
-/* Used to generate valid fences. It is not possible to create a dummy sync
- * fence for testing. Egl can generate buffers along with a valid fence.
- * The buffer cannot be guaranteed to be the same format across all devices so
- * a CPU filled buffer is used instead. The Egl fence is used along with the
- * CPU filled buffer. */
-class Hwc2TestEglManager {
-public:
- Hwc2TestEglManager()
- : mEglDisplay(EGL_NO_DISPLAY),
- mEglSurface(EGL_NO_SURFACE),
- mEglContext(EGL_NO_CONTEXT) { }
-
- ~Hwc2TestEglManager()
- {
- cleanup();
- }
-
- int initialize(sp<Surface> surface)
- {
- mSurface = surface;
-
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (mEglDisplay == EGL_NO_DISPLAY) return false;
-
- EGLint major;
- EGLint minor;
- if (!eglInitialize(mEglDisplay, &major, &minor)) {
- ALOGW("Could not initialize EGL");
- return false;
- }
-
- /* We're going to use a 1x1 pbuffer surface later on
- * The configuration distance doesn't really matter for what we're
- * trying to do */
- EGLint configAttrs[] = {
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 0,
- EGL_DEPTH_SIZE, 24,
- EGL_STENCIL_SIZE, 0,
- EGL_NONE
- };
-
- EGLConfig configs[1];
- EGLint configCnt;
- if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
- &configCnt)) {
- ALOGW("Could not select EGL configuration");
- eglReleaseThread();
- eglTerminate(mEglDisplay);
- return false;
- }
-
- if (configCnt <= 0) {
- ALOGW("Could not find EGL configuration");
- eglReleaseThread();
- eglTerminate(mEglDisplay);
- return false;
- }
-
- /* These objects are initialized below but the default "null" values are
- * used to cleanup properly at any point in the initialization sequence */
- EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
- attrs);
- if (mEglContext == EGL_NO_CONTEXT) {
- ALOGW("Could not create EGL context");
- cleanup();
- return false;
- }
-
- EGLint surfaceAttrs[] = { EGL_NONE };
- mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
- mSurface.get(), surfaceAttrs);
- if (mEglSurface == EGL_NO_SURFACE) {
- ALOGW("Could not create EGL surface");
- cleanup();
- return false;
- }
-
- if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- ALOGW("Could not change current EGL context");
- cleanup();
- return false;
- }
-
- return true;
- }
-
- void makeCurrent() const
- {
- eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
- }
-
- void present() const
- {
- eglSwapBuffers(mEglDisplay, mEglSurface);
- }
-
-private:
- void cleanup()
- {
- if (mEglDisplay == EGL_NO_DISPLAY)
- return;
- if (mEglSurface != EGL_NO_SURFACE)
- eglDestroySurface(mEglDisplay, mEglSurface);
- if (mEglContext != EGL_NO_CONTEXT)
- eglDestroyContext(mEglDisplay, mEglContext);
-
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglReleaseThread();
- eglTerminate(mEglDisplay);
- }
-
- sp<Surface> mSurface;
- EGLDisplay mEglDisplay;
- EGLSurface mEglSurface;
- EGLContext mEglContext;
-};
-
-
-static const std::array<vec2, 4> triangles = {{
- { 1.0f, 1.0f },
- { -1.0f, 1.0f },
- { 1.0f, -1.0f },
- { -1.0f, -1.0f },
-}};
-
-class Hwc2TestFenceGenerator {
-public:
-
- Hwc2TestFenceGenerator()
- {
- mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
- setFence, this);
-
- if (!mEglManager.initialize(mSurfaceManager.getSurface()))
- return;
-
- mEglManager.makeCurrent();
-
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glEnableVertexAttribArray(0);
- }
-
- ~Hwc2TestFenceGenerator()
- {
- if (mFence >= 0)
- close(mFence);
- mFence = -1;
-
- mEglManager.makeCurrent();
- }
-
- /* It is not possible to simply generate a fence. The easiest way is to
- * generate a buffer using egl and use the associated fence. The buffer
- * cannot be guaranteed to be a certain format across all devices using this
- * method. Instead the buffer is generated using the CPU */
- int32_t get()
- {
- if (mFence >= 0) {
- return dup(mFence);
- }
-
- std::unique_lock<std::mutex> lock(mMutex);
-
- /* If the pending is still set to false and times out, we cannot recover.
- * Set an error and return */
- while (mPending != false) {
- if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
- return -ETIME;
- }
-
- /* Generate a fence. The fence will be returned through the setFence
- * callback */
- mEglManager.makeCurrent();
-
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
- glClear(GL_COLOR_BUFFER_BIT);
-
- mEglManager.present();
-
- /* Wait for the setFence callback */
- while (mPending != true) {
- if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
- return -ETIME;
- }
-
- mPending = false;
-
- return dup(mFence);
- }
-
- /* Callback that sets the fence */
- void set(int32_t fence)
- {
- mFence = fence;
- mPending = true;
-
- mCv.notify_all();
- }
-
-private:
-
- Hwc2TestSurfaceManager mSurfaceManager;
- Hwc2TestEglManager mEglManager;
-
- std::mutex mMutex;
- std::condition_variable mCv;
-
- int32_t mFence = -1;
- bool mPending = false;
-};
-
-
-static void setFence(int32_t fence, void* fenceGenerator)
-{
- static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
-}
-
-
-/* Sets the pixel of a buffer given the location, format, stride and color.
- * Currently only supports RGBA_8888 */
-static void setColor(int32_t x, int32_t y,
- android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
- uint8_t g, uint8_t b, uint8_t a)
-{
- switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- img[(y * stride + x) * 4 + 0] = r;
- img[(y * stride + x) * 4 + 1] = g;
- img[(y * stride + x) * 4 + 2] = b;
- img[(y * stride + x) * 4 + 3] = a;
- break;
- default:
- break;
- }
-}
-
-Hwc2TestBuffer::Hwc2TestBuffer()
- : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
-
-Hwc2TestBuffer::~Hwc2TestBuffer() = default;
-
-/* When the buffer changes sizes, save the new size and invalidate the current
- * buffer */
-void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
-{
- if (mBufferArea.width == bufferArea.width
- && mBufferArea.height == bufferArea.height)
- return;
-
- mBufferArea.width = bufferArea.width;
- mBufferArea.height = bufferArea.height;
-
- mValidBuffer = false;
-}
-
-/* Returns a valid buffer handle and fence. The handle is filled using the CPU
- * to ensure the correct format across all devices. The fence is created using
- * egl. */
-int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
-{
- if (mBufferArea.width == -1 || mBufferArea.height == -1)
- return -EINVAL;
-
- /* If the current buffer is valid, the previous buffer can be reused.
- * Otherwise, create new buffer */
- if (!mValidBuffer) {
- int ret = generateBuffer();
- if (ret)
- return ret;
- }
-
- *outFence = mFenceGenerator->get();
- *outHandle = mHandle;
-
- mValidBuffer = true;
-
- return 0;
-}
-
-/* CPU fills a buffer to guarantee the correct buffer format across all
- * devices */
-int Hwc2TestBuffer::generateBuffer()
-{
- /* Create new graphic buffer with correct dimensions */
- mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
- mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
-
- int ret = mGraphicBuffer->initCheck();
- if (ret) {
- return ret;
- }
- if (!mGraphicBuffer->handle) {
- return -EINVAL;
- }
-
- /* Locks the buffer for writing */
- uint8_t* img;
- mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
- (void**)(&img));
-
- uint32_t stride = mGraphicBuffer->getStride();
-
- /* Iterate from the top row of the buffer to the bottom row */
- for (int32_t y = 0; y < mBufferArea.height; y++) {
-
- /* Will be used as R, G and B values for pixel colors */
- uint8_t max = 255;
- uint8_t min = 0;
-
- /* Divide the rows into 3 sections. The first section will contain
- * the lighest colors. The last section will contain the darkest
- * colors. */
- if (y < mBufferArea.height * 1.0 / 3.0) {
- min = 255 / 2;
- } else if (y >= mBufferArea.height * 2.0 / 3.0) {
- max = 255 / 2;
- }
-
- /* Divide the columns into 3 sections. The first section is red,
- * the second is green and the third is blue */
- int32_t x = 0;
- for (; x < mBufferArea.width / 3; x++) {
- setColor(x, y, mFormat, stride, img, max, min, min, 255);
- }
-
- for (; x < mBufferArea.width * 2 / 3; x++) {
- setColor(x, y, mFormat, stride, img, min, max, min, 255);
- }
-
- for (; x < mBufferArea.width; x++) {
- setColor(x, y, mFormat, stride, img, min, min, max, 255);
- }
- }
-
- /* Unlock the buffer for reading */
- mGraphicBuffer->unlock();
-
- mHandle = mGraphicBuffer->handle;
-
- return 0;
-}
-
-
-Hwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
- : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
-
-Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
-
-/* Generates a buffer from layersToDraw.
- * Takes into account the individual layer properties such as
- * transform, blend mode, source crop, etc. */
-static void compositeBufferFromLayers(
- const android::sp<android::GraphicBuffer>& graphicBuffer,
- android_pixel_format_t format, const Area& bufferArea,
- const Hwc2TestLayers* testLayers,
- const std::set<hwc2_layer_t>* layersToDraw,
- const std::set<hwc2_layer_t>* clearLayers)
-{
- /* Locks the buffer for writing */
- uint8_t* img;
- graphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
- (void**)(&img));
-
- uint32_t stride = graphicBuffer->getStride();
-
- float bWDiv3 = bufferArea.width / 3;
- float bW2Div3 = bufferArea.width * 2 / 3;
- float bHDiv3 = bufferArea.height / 3;
- float bH2Div3 = bufferArea.height * 2 / 3;
-
- /* Cycle through every pixel in the buffer and determine what color it
- * should be. */
- for (int32_t y = 0; y < bufferArea.height; y++) {
- for (int32_t x = 0; x < bufferArea.width; x++) {
-
- uint8_t r = 0, g = 0, b = 0;
- float a = 0.0f;
-
- /* Cycle through each layer from back to front and
- * update the pixel color. */
- for (auto layer = layersToDraw->rbegin();
- layer != layersToDraw->rend(); ++layer) {
-
- const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
-
- float dfL = df.left;
- float dfT = df.top;
- float dfR = df.right;
- float dfB = df.bottom;
-
- /* If the pixel location falls outside of the layer display
- * frame, skip the layer. */
- if (x < dfL || x >= dfR || y < dfT || y >= dfB)
- continue;
-
- /* If the device has requested the layer be clear, clear
- * the pixel and continue. */
- if (clearLayers->count(*layer) != 0) {
- r = 0;
- g = 0;
- b = 0;
- a = 0.0f;
- continue;
- }
-
- float planeAlpha = testLayers->getPlaneAlpha(*layer);
-
- /* If the layer is a solid color, fill the color and
- * continue. */
- if (testLayers->getComposition(*layer)
- == HWC2_COMPOSITION_SOLID_COLOR) {
- const auto color = testLayers->getColor(*layer);
- r = color.r;
- g = color.g;
- b = color.b;
- a = color.a * planeAlpha;
- continue;
- }
-
- float xPos = x;
- float yPos = y;
-
- hwc_transform_t transform = testLayers->getTransform(*layer);
-
- float dfW = dfR - dfL;
- float dfH = dfB - dfT;
-
- /* If a layer has a transform, find which location on the
- * layer will end up in the current pixel location. We
- * can calculate the color of the current pixel using that
- * location. */
- if (transform > 0) {
- /* Change origin to be the center of the layer. */
- xPos = xPos - dfL - dfW / 2.0;
- yPos = yPos - dfT - dfH / 2.0;
-
- /* Flip Horizontal by reflecting across the y axis. */
- if (transform & HWC_TRANSFORM_FLIP_H)
- xPos = -xPos;
-
- /* Flip vertical by reflecting across the x axis. */
- if (transform & HWC_TRANSFORM_FLIP_V)
- yPos = -yPos;
-
- /* Rotate 90 by using a basic linear algebra rotation
- * and scaling the result so the display frame remains
- * the same. For example, a buffer of size 100x50 should
- * rotate 90 degress but remain the same dimension
- * (100x50) at the end of the transformation. */
- if (transform & HWC_TRANSFORM_ROT_90) {
- float tmp = xPos;
- xPos = yPos * dfW / dfH;
- yPos = -tmp * dfH / dfW;
- }
-
- /* Change origin back to the top left corner of the
- * layer. */
- xPos = xPos + dfL + dfW / 2.0;
- yPos = yPos + dfT + dfH / 2.0;
- }
-
- hwc_frect_t sc = testLayers->getSourceCrop(*layer);
- float scL = sc.left, scT = sc.top;
-
- float dfWDivScW = dfW / (sc.right - scL);
- float dfHDivScH = dfH / (sc.bottom - scT);
-
- float max = 255, min = 0;
-
- /* Choose the pixel color. Similar to generateBuffer,
- * each layer will be divided into 3x3 colors. Because
- * both the source crop and display frame must be taken into
- * account, the formulas are more complicated.
- *
- * If the source crop and display frame were not taken into
- * account, we would simply divide the buffer into three
- * sections by height. Each section would get one color.
- * For example the formula for the first section would be:
- *
- * if (yPos < bufferArea.height / 3)
- * //Select first section color
- *
- * However the pixel color is chosen based on the source
- * crop and displayed based on the display frame.
- *
- * If the display frame top was 0 and the source crop height
- * and display frame height were the same. The only factor
- * would be the source crop top. To calculate the new
- * section boundary, the section boundary would be moved up
- * by the height of the source crop top. The formula would
- * be:
- * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
- * //Select first section color
- *
- * If the display frame top could also vary but source crop
- * and display frame heights were the same, the formula
- * would be:
- * if (yPos < (bufferArea.height / 3 - sourceCrop.top
- * + displayFrameTop)
- * //Select first section color
- *
- * If the heights were not the same, the conversion between
- * the source crop and display frame dimensions must be
- * taken into account. The formula would be:
- * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
- * * displayFrameHeight / sourceCropHeight
- * + displayFrameTop)
- * //Select first section color
- */
- if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
- min = 255 / 2;
- } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
- max = 255 / 2;
- }
-
- uint8_t rCur = min, gCur = min, bCur = min;
- float aCur = 1.0f;
-
- /* This further divides the color sections from 3 to 3x3.
- * The math behind it follows the same logic as the previous
- * comment */
- if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
- rCur = max;
- } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
- gCur = max;
- } else {
- bCur = max;
- }
-
-
- /* Blend the pixel color with the previous layers' pixel
- * colors using the plane alpha and blend mode. The final
- * pixel color is chosen using the plane alpha and blend
- * mode formulas found in hwcomposer2.h */
- hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
-
- if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
- rCur *= planeAlpha;
- gCur *= planeAlpha;
- bCur *= planeAlpha;
- }
-
- aCur *= planeAlpha;
-
- if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
- r = rCur + r * (1.0 - aCur);
- g = gCur + g * (1.0 - aCur);
- b = bCur + b * (1.0 - aCur);
- a = aCur + a * (1.0 - aCur);
- } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
- r = rCur * aCur + r * (1.0 - aCur);
- g = gCur * aCur + g * (1.0 - aCur);
- b = bCur * aCur + b * (1.0 - aCur);
- a = aCur * aCur + a * (1.0 - aCur);
- } else {
- r = rCur;
- g = gCur;
- b = bCur;
- a = aCur;
- }
- }
-
- /* Set the pixel color */
- setColor(x, y, format, stride, img, r, g, b, a * 255);
- }
- }
-
- graphicBuffer->unlock();
-}
-
-/* Generates a client target buffer using the layers assigned for client
- * composition. Takes into account the individual layer properties such as
- * transform, blend mode, source crop, etc. */
-int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
- int32_t* outFence, const Area& bufferArea,
- const Hwc2TestLayers* testLayers,
- const std::set<hwc2_layer_t>* clientLayers,
- const std::set<hwc2_layer_t>* clearLayers)
-{
- /* Create new graphic buffer with correct dimensions */
- mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
- mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
- BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
-
- int ret = mGraphicBuffer->initCheck();
- if (ret)
- return ret;
-
- if (!mGraphicBuffer->handle)
- return -EINVAL;
-
- compositeBufferFromLayers(mGraphicBuffer, mFormat, bufferArea, testLayers,
- clientLayers, clearLayers);
-
- *outFence = mFenceGenerator->get();
- *outHandle = mGraphicBuffer->handle;
-
- return 0;
-}
-
-void Hwc2TestVirtualBuffer::updateBufferArea(const Area& bufferArea)
-{
- mBufferArea.width = bufferArea.width;
- mBufferArea.height = bufferArea.height;
-}
-
-bool Hwc2TestVirtualBuffer::writeBufferToFile(std::string path)
-{
- SkFILEWStream file(path.c_str());
- const SkImageInfo info = SkImageInfo::Make(mBufferArea.width,
- mBufferArea.height, SkColorType::kRGBA_8888_SkColorType,
- SkAlphaType::kPremul_SkAlphaType);
-
- uint8_t* img;
- mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
- (void**)(&img));
-
- SkPixmap pixmap(info, img, mGraphicBuffer->getStride());
- bool result = file.isValid() && SkEncodeImage(&file, pixmap,
- SkEncodedImageFormat::kPNG, 100);
-
- mGraphicBuffer->unlock();
- return result;
-}
-
-/* Generates a buffer that holds the expected result of compositing all of our
- * layers */
-int Hwc2TestExpectedBuffer::generateExpectedBuffer(
- const Hwc2TestLayers* testLayers,
- const std::vector<hwc2_layer_t>* allLayers,
- const std::set<hwc2_layer_t>* clearLayers)
-{
- mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
- mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
- "hwc2_test_buffer");
-
- int ret = mGraphicBuffer->initCheck();
- if (ret)
- return ret;
-
- if (!mGraphicBuffer->handle)
- return -EINVAL;
-
- const std::set<hwc2_layer_t> allLayerSet(allLayers->begin(),
- allLayers->end());
-
- compositeBufferFromLayers(mGraphicBuffer, mFormat, mBufferArea, testLayers,
- &allLayerSet, clearLayers);
-
- return 0;
-}
-
-int Hwc2TestOutputBuffer::getOutputBuffer(buffer_handle_t* outHandle,
- int32_t* outFence)
-{
- if (mBufferArea.width == -1 || mBufferArea.height == -1)
- return -EINVAL;
-
- mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
- mFormat, BufferUsage::CPU_READ_OFTEN |
- BufferUsage::GPU_RENDER_TARGET, "hwc2_test_buffer");
-
- int ret = mGraphicBuffer->initCheck();
- if (ret)
- return ret;
-
- if (!mGraphicBuffer->handle)
- return -EINVAL;
-
- *outFence = -1;
- *outHandle = mGraphicBuffer->handle;
-
- return 0;
-}
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
deleted file mode 100644
index fd54fef..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _HWC2_TEST_BUFFER_H
-#define _HWC2_TEST_BUFFER_H
-
-#include <android-base/unique_fd.h>
-#include <set>
-
-#include <hardware/hwcomposer2.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "Hwc2TestProperties.h"
-
-class Hwc2TestFenceGenerator;
-class Hwc2TestLayers;
-
-class Hwc2TestBuffer {
-public:
- Hwc2TestBuffer();
- ~Hwc2TestBuffer();
-
- void updateBufferArea(const Area& bufferArea);
-
- int get(buffer_handle_t* outHandle, int32_t* outFence);
-
-protected:
- int generateBuffer();
-
- android::sp<android::GraphicBuffer> mGraphicBuffer;
-
- std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
-
- Area mBufferArea = {-1, -1};
- const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-
- bool mValidBuffer = false;
- buffer_handle_t mHandle = nullptr;
-};
-
-
-class Hwc2TestClientTargetBuffer {
-public:
- Hwc2TestClientTargetBuffer();
- ~Hwc2TestClientTargetBuffer();
-
- int get(buffer_handle_t* outHandle, int32_t* outFence,
- const Area& bufferArea, const Hwc2TestLayers* testLayers,
- const std::set<hwc2_layer_t>* clientLayers,
- const std::set<hwc2_layer_t>* clearLayers);
-
-protected:
- android::sp<android::GraphicBuffer> mGraphicBuffer;
-
- std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
-
- const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-};
-
-
-class Hwc2TestVirtualBuffer {
-public:
- void updateBufferArea(const Area& bufferArea);
-
- bool writeBufferToFile(std::string path);
-
- android::sp<android::GraphicBuffer>& graphicBuffer()
- {
- return mGraphicBuffer;
- }
-
-protected:
- android::sp<android::GraphicBuffer> mGraphicBuffer;
-
- Area mBufferArea = {-1, -1};
-
- const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-};
-
-
-class Hwc2TestExpectedBuffer : public Hwc2TestVirtualBuffer {
-public:
- int generateExpectedBuffer(const Hwc2TestLayers* testLayers,
- const std::vector<hwc2_layer_t>* allLayers,
- const std::set<hwc2_layer_t>* clearLayers);
-};
-
-
-class Hwc2TestOutputBuffer : public Hwc2TestVirtualBuffer {
-public:
- int getOutputBuffer(buffer_handle_t* outHandle, int32_t* outFence);
-};
-
-#endif /* ifndef _HWC2_TEST_BUFFER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp
deleted file mode 100644
index 14c60a7..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2016 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 <sstream>
-
-#include <ui/Rect.h>
-
-#include "Hwc2TestClientTarget.h"
-
-int Hwc2TestClientTarget::getBuffer(const Hwc2TestLayers& testLayers,
- const std::set<hwc2_layer_t>& clientLayers,
- const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
- const Area& displayArea, buffer_handle_t* outHandle,
- int32_t* outAcquireFence)
-{
- if (!flipClientTarget) {
- bool needsClientTarget = false;
-
- for (auto clientLayer : clientLayers) {
- if (testLayers.getVisibleRegion(clientLayer).numRects > 0) {
- needsClientTarget = true;
- break;
- }
- }
-
- if (!needsClientTarget) {
- *outHandle = nullptr;
- *outAcquireFence = -1;
- return 0;
- }
- }
-
- return mBuffer.get(outHandle, outAcquireFence, displayArea,
- &testLayers, &clientLayers, &clearLayers);
-}
-
-
-Hwc2TestClientTargetSupport::Hwc2TestClientTargetSupport(
- Hwc2TestCoverage coverage, const Area& displayArea)
- : mBufferArea(coverage, displayArea),
- mDataspace(coverage),
- mSurfaceDamage(coverage)
-{
- mBufferArea.setDependent(&mSurfaceDamage);
-}
-
-std::string Hwc2TestClientTargetSupport::dump() const
-{
- std::stringstream dmp;
-
- dmp << "client target: \n";
-
- for (auto property : properties) {
- dmp << property->dump();
- }
-
- return dmp.str();
-}
-
-void Hwc2TestClientTargetSupport::reset()
-{
- for (auto property : properties) {
- property->reset();
- }
-}
-
-bool Hwc2TestClientTargetSupport::advance()
-{
- for (auto property : properties) {
- if (property->advance())
- return true;
- }
- return false;
-}
-
-Area Hwc2TestClientTargetSupport::getBufferArea() const
-{
- return mBufferArea.get();
-}
-
-android::ui::Dataspace Hwc2TestClientTargetSupport::getDataspace() const
-{
- return mDataspace.get();
-}
-
-const hwc_region_t Hwc2TestClientTargetSupport::getSurfaceDamage() const
-{
- return mSurfaceDamage.get();
-}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h
deleted file mode 100644
index 6f4090f..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _HWC2_TEST_CLIENT_TARGET_H
-#define _HWC2_TEST_CLIENT_TARGET_H
-
-#include <set>
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-#include "Hwc2TestProperties.h"
-#include "Hwc2TestLayers.h"
-
-/* Generates client target buffers from client composition layers */
-class Hwc2TestClientTarget {
-public:
- int getBuffer(const Hwc2TestLayers& layers,
- const std::set<hwc2_layer_t>& clientLayers,
- const std::set<hwc2_layer_t>& clearLayers,
- bool clearClientTarget, const Area& displayArea,
- buffer_handle_t* outHandle, int32_t* outAcquireFence);
-
-private:
- Hwc2TestClientTargetBuffer mBuffer;
-};
-
-/* Generates valid client targets to test which ones the device will support */
-class Hwc2TestClientTargetSupport {
-public:
- Hwc2TestClientTargetSupport(Hwc2TestCoverage coverage,
- const Area& displayArea);
-
- std::string dump() const;
-
- void reset();
- bool advance();
-
- Area getBufferArea() const;
- android::ui::Dataspace getDataspace() const;
- const hwc_region_t getSurfaceDamage() const;
-
-private:
- std::array<Hwc2TestContainer*, 3> properties = {{
- &mDataspace, &mSurfaceDamage, &mBufferArea
- }};
-
- Hwc2TestBufferArea mBufferArea;
- Hwc2TestDataspace mDataspace;
- Hwc2TestSurfaceDamage mSurfaceDamage;
-};
-
-#endif /* ifndef _HWC2_TEST_CLIENT_TARGET_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
deleted file mode 100644
index c1c9cc8..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2016 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 <sstream>
-
-#include "Hwc2TestLayer.h"
-
-Hwc2TestCoverage getCoverage(Hwc2TestPropertyName property,
- Hwc2TestCoverage coverage, const std::unordered_map<Hwc2TestPropertyName,
- Hwc2TestCoverage>& coverageExceptions) {
- auto exception = coverageExceptions.find(property);
- return (exception != coverageExceptions.end())? exception->second : coverage;
-}
-
-Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage,
- const Area& displayArea)
- : Hwc2TestLayer(coverage, displayArea,
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { }
-
-Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage,
- const Area& displayArea, const std::unordered_map<Hwc2TestPropertyName,
- Hwc2TestCoverage>& coverageExceptions)
- : mBlendMode(getCoverage(Hwc2TestPropertyName::BlendMode, coverage,
- coverageExceptions)),
- mBufferArea(getCoverage(Hwc2TestPropertyName::BufferArea, coverage,
- coverageExceptions), displayArea),
- mColor(getCoverage(Hwc2TestPropertyName::Color, coverage,
- coverageExceptions)),
- mComposition(getCoverage(Hwc2TestPropertyName::Composition, coverage,
- coverageExceptions)),
- mDataspace(getCoverage(Hwc2TestPropertyName::Dataspace, coverage,
- coverageExceptions)),
- mDisplayFrame(getCoverage(Hwc2TestPropertyName::DisplayFrame, coverage,
- coverageExceptions), displayArea),
- mPlaneAlpha(getCoverage(Hwc2TestPropertyName::PlaneAlpha, coverage,
- coverageExceptions)),
- mSourceCrop(getCoverage(Hwc2TestPropertyName::SourceCrop, coverage,
- coverageExceptions)),
- mSurfaceDamage(getCoverage(Hwc2TestPropertyName::SurfaceDamage, coverage,
- coverageExceptions)),
- mTransform(getCoverage(Hwc2TestPropertyName::Transform, coverage,
- coverageExceptions))
-{
- mBufferArea.setDependent(&mBuffer);
- mBufferArea.setDependent(&mSourceCrop);
- mBufferArea.setDependent(&mSurfaceDamage);
- mBlendMode.setDependent(&mColor);
-}
-
-std::string Hwc2TestLayer::dump() const
-{
- std::stringstream dmp;
-
- dmp << "layer: \n";
-
- for (auto property : mProperties) {
- dmp << property->dump();
- }
-
- dmp << mVisibleRegion.dump();
- dmp << "\tz order: " << mZOrder << "\n";
-
- return dmp.str();
-}
-
-int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
- android::base::unique_fd* outAcquireFence)
-{
- int32_t acquireFence;
- int ret = mBuffer.get(outHandle, &acquireFence);
- outAcquireFence->reset(acquireFence);
- return ret;
-}
-
-int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
- int32_t* outAcquireFence)
-{
- return mBuffer.get(outHandle, outAcquireFence);
-}
-
-void Hwc2TestLayer::setZOrder(uint32_t zOrder)
-{
- mZOrder = zOrder;
-}
-
-void Hwc2TestLayer::setVisibleRegion(const android::Region& region)
-{
- return mVisibleRegion.set(region);
-}
-
-void Hwc2TestLayer::reset()
-{
- mVisibleRegion.release();
-
- for (auto property : mProperties) {
- property->reset();
- }
-}
-
-bool Hwc2TestLayer::advance()
-{
- for (auto property : mProperties) {
- if (property->isSupported(mComposition.get()))
- if (property->advance())
- return true;
- }
- return false;
-}
-
-hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const
-{
- return mBlendMode.get();
-}
-
-Area Hwc2TestLayer::getBufferArea() const
-{
- return mBufferArea.get();
-}
-
-hwc_color_t Hwc2TestLayer::getColor() const
-{
- return mColor.get();
-}
-
-hwc2_composition_t Hwc2TestLayer::getComposition() const
-{
- return mComposition.get();
-}
-
-/* The cursor position corresponds to {displayFrame.left, displayFrame.top} */
-hwc_rect_t Hwc2TestLayer::getCursorPosition() const
-{
- return mDisplayFrame.get();
-}
-
-android::ui::Dataspace Hwc2TestLayer::getDataspace() const
-{
- return mDataspace.get();
-}
-
-hwc_rect_t Hwc2TestLayer::getDisplayFrame() const
-{
- return mDisplayFrame.get();
-}
-
-float Hwc2TestLayer::getPlaneAlpha() const
-{
- return mPlaneAlpha.get();
-}
-
-hwc_frect_t Hwc2TestLayer::getSourceCrop() const
-{
- return mSourceCrop.get();
-}
-
-hwc_region_t Hwc2TestLayer::getSurfaceDamage() const
-{
- return mSurfaceDamage.get();
-}
-
-hwc_transform_t Hwc2TestLayer::getTransform() const
-{
- return mTransform.get();
-}
-
-hwc_region_t Hwc2TestLayer::getVisibleRegion() const
-{
- return mVisibleRegion.get();
-}
-
-uint32_t Hwc2TestLayer::getZOrder() const
-{
- return mZOrder;
-}
-
-bool Hwc2TestLayer::advanceBlendMode()
-{
- return mBlendMode.advance();
-}
-
-bool Hwc2TestLayer::advanceBufferArea()
-{
- return mBufferArea.advance();
-}
-
-bool Hwc2TestLayer::advanceColor()
-{
- return mColor.advance();
-}
-
-bool Hwc2TestLayer::advanceComposition()
-{
- return mComposition.advance();
-}
-
-bool Hwc2TestLayer::advanceCursorPosition()
-{
- return mDisplayFrame.advance();
-}
-
-bool Hwc2TestLayer::advanceDataspace()
-{
- return mDataspace.advance();
-}
-
-bool Hwc2TestLayer::advanceDisplayFrame()
-{
- return mDisplayFrame.advance();
-}
-
-bool Hwc2TestLayer::advancePlaneAlpha()
-{
- return mPlaneAlpha.advance();
-}
-
-bool Hwc2TestLayer::advanceSourceCrop()
-{
- return mSourceCrop.advance();
-}
-
-bool Hwc2TestLayer::advanceSurfaceDamage()
-{
- return mSurfaceDamage.advance();
-}
-
-bool Hwc2TestLayer::advanceTransform()
-{
- return mTransform.advance();
-}
-
-bool Hwc2TestLayer::advanceVisibleRegion()
-{
- if (mPlaneAlpha.advance())
- return true;
- return mDisplayFrame.advance();
-}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
deleted file mode 100644
index 29ae521..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _HWC2_TEST_LAYER_H
-#define _HWC2_TEST_LAYER_H
-
-#include <android-base/unique_fd.h>
-#include <unordered_map>
-
-#include "Hwc2TestBuffer.h"
-#include "Hwc2TestProperties.h"
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-class Hwc2TestLayer {
-public:
- Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea);
-
- Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea,
- const std::unordered_map<Hwc2TestPropertyName,
- Hwc2TestCoverage>& coverage_exceptions);
-
- std::string dump() const;
-
- int getBuffer(buffer_handle_t* outHandle,
- android::base::unique_fd* outAcquireFence);
- int getBuffer(buffer_handle_t* outHandle, int32_t* outAcquireFence);
-
- void setZOrder(uint32_t zOrder);
- void setVisibleRegion(const android::Region& region);
-
- void reset();
- bool advance();
-
- hwc2_blend_mode_t getBlendMode() const;
- Area getBufferArea() const;
- hwc_color_t getColor() const;
- hwc2_composition_t getComposition() const;
- hwc_rect_t getCursorPosition() const;
- android::ui::Dataspace getDataspace() const;
- hwc_rect_t getDisplayFrame() const;
- float getPlaneAlpha() const;
- hwc_frect_t getSourceCrop() const;
- hwc_region_t getSurfaceDamage() const;
- hwc_transform_t getTransform() const;
- hwc_region_t getVisibleRegion() const;
- uint32_t getZOrder() const;
-
- bool advanceBlendMode();
- bool advanceBufferArea();
- bool advanceColor();
- bool advanceComposition();
- bool advanceCursorPosition();
- bool advanceDataspace();
- bool advanceDisplayFrame();
- bool advancePlaneAlpha();
- bool advanceSourceCrop();
- bool advanceSurfaceDamage();
- bool advanceTransform();
- bool advanceVisibleRegion();
-
-private:
- std::array<Hwc2TestContainer*, 10> mProperties = {{
- &mTransform, &mColor, &mDataspace, &mPlaneAlpha, &mSourceCrop,
- &mSurfaceDamage, &mBlendMode, &mBufferArea, &mDisplayFrame,
- &mComposition
- }};
-
- Hwc2TestBuffer mBuffer;
-
- Hwc2TestBlendMode mBlendMode;
- Hwc2TestBufferArea mBufferArea;
- Hwc2TestColor mColor;
- Hwc2TestComposition mComposition;
- Hwc2TestDataspace mDataspace;
- Hwc2TestDisplayFrame mDisplayFrame;
- Hwc2TestPlaneAlpha mPlaneAlpha;
- Hwc2TestSourceCrop mSourceCrop;
- Hwc2TestSurfaceDamage mSurfaceDamage;
- Hwc2TestTransform mTransform;
- Hwc2TestVisibleRegion mVisibleRegion;
-
- uint32_t mZOrder = UINT32_MAX;
-};
-
-#endif /* ifndef _HWC2_TEST_LAYER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
deleted file mode 100644
index b76ace8..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/* * Copyright (C) 2016 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include <sstream>
-#include <gtest/gtest.h>
-
-#include "Hwc2TestLayers.h"
-
-Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
- Hwc2TestCoverage coverage, const Area& displayArea)
- : Hwc2TestLayers(layers, coverage, displayArea,
- std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { }
-
-Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
- Hwc2TestCoverage coverage, const Area& displayArea,
- const std::unordered_map<Hwc2TestPropertyName,
- Hwc2TestCoverage>& coverageExceptions)
- : mDisplayArea(displayArea)
-{
- for (auto layer : layers) {
- mTestLayers.emplace(std::piecewise_construct,
- std::forward_as_tuple(layer),
- std::forward_as_tuple(coverage, displayArea, coverageExceptions));
- }
-
- /* Iterate over the layers in order and assign z orders in the same order.
- * This allows us to iterate over z orders in the same way when computing
- * visible regions */
- uint32_t nextZOrder = layers.size();
-
- for (auto& testLayer : mTestLayers) {
- testLayer.second.setZOrder(nextZOrder--);
- }
-
- setVisibleRegions();
-}
-
-std::string Hwc2TestLayers::dump() const
-{
- std::stringstream dmp;
- for (auto& testLayer : mTestLayers) {
- dmp << testLayer.second.dump();
- }
- return dmp.str();
-}
-
-void Hwc2TestLayers::reset()
-{
- for (auto& testLayer : mTestLayers) {
- testLayer.second.reset();
- }
-
- setVisibleRegions();
-}
-
-bool Hwc2TestLayers::advance()
-{
- auto itr = mTestLayers.begin();
- bool optimized;
-
- while (itr != mTestLayers.end()) {
- if (itr->second.advance()) {
- optimized = setVisibleRegions();
- if (!mOptimize || optimized)
- return true;
- itr = mTestLayers.begin();
- } else {
- itr->second.reset();
- ++itr;
- }
- }
- return false;
-}
-
-bool Hwc2TestLayers::advanceVisibleRegions()
-{
- auto itr = mTestLayers.begin();
- bool optimized;
-
- while (itr != mTestLayers.end()) {
- if (itr->second.advanceVisibleRegion()) {
- optimized = setVisibleRegions();
- if (!mOptimize || optimized)
- return true;
- itr = mTestLayers.begin();
- } else {
- itr->second.reset();
- ++itr;
- }
- }
- return false;
-}
-
-/* Removes layouts that do not cover the entire display.
- * Also removes layouts where a layer is completely blocked from view.
- */
-bool Hwc2TestLayers::optimizeLayouts()
-{
- mOptimize = true;
-
- if (setVisibleRegions())
- return true;
- return advance();
-}
-
-bool Hwc2TestLayers::contains(hwc2_layer_t layer) const
-{
- return mTestLayers.count(layer) != 0;
-}
-
-int Hwc2TestLayers::getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle,
- int32_t* outAcquireFence)
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getBuffer(outHandle, outAcquireFence);
-}
-
-hwc2_blend_mode_t Hwc2TestLayers::getBlendMode(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getBlendMode();
-}
-
-Area Hwc2TestLayers::getBufferArea(hwc2_layer_t layer) const
-{
- auto testLayer = mTestLayers.find(layer);
- if (testLayer == mTestLayers.end())
- [] () { GTEST_FAIL(); }();
- return testLayer->second.getBufferArea();
-}
-
-hwc_color_t Hwc2TestLayers::getColor(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getColor();
-}
-
-hwc2_composition_t Hwc2TestLayers::getComposition(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getComposition();
-}
-
-hwc_rect_t Hwc2TestLayers::getCursorPosition(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getCursorPosition();
-}
-
-android::ui::Dataspace Hwc2TestLayers::getDataspace(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getDataspace();
-}
-
-hwc_rect_t Hwc2TestLayers::getDisplayFrame(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getDisplayFrame();
-}
-
-float Hwc2TestLayers::getPlaneAlpha(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getPlaneAlpha();
-}
-
-hwc_frect_t Hwc2TestLayers::getSourceCrop(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getSourceCrop();
-}
-
-hwc_region_t Hwc2TestLayers::getSurfaceDamage(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getSurfaceDamage();
-}
-
-hwc_transform_t Hwc2TestLayers::getTransform(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getTransform();
-}
-
-hwc_region_t Hwc2TestLayers::getVisibleRegion(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getVisibleRegion();
-}
-
-uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const
-{
- if (mTestLayers.count(layer) == 0) {
- []() { GTEST_FAIL(); }();
- }
- return mTestLayers.at(layer).getZOrder();
-}
-
-/* Sets the visible regions for a display. Returns false if the layers do not
- * cover the entire display or if a layer is not visible */
-bool Hwc2TestLayers::setVisibleRegions()
-{
- /* The region of the display that is covered by layers above the current
- * layer */
- android::Region aboveOpaqueLayers;
-
- bool optimized = true;
-
- /* Iterate over test layers from max z order to min z order. */
- for (auto& testLayer : mTestLayers) {
- android::Region visibleRegion;
-
- /* Set the visible region of this layer */
- const hwc_rect_t displayFrame = testLayer.second.getDisplayFrame();
-
- visibleRegion.set(android::Rect(displayFrame.left, displayFrame.top,
- displayFrame.right, displayFrame.bottom));
-
- /* Remove the area covered by opaque layers above this layer
- * from this layer's visible region */
- visibleRegion.subtractSelf(aboveOpaqueLayers);
-
- testLayer.second.setVisibleRegion(visibleRegion);
-
- /* If a layer is not visible, return false */
- if (visibleRegion.isEmpty())
- optimized = false;
-
- /* If this layer is opaque, store the region it covers */
- if (testLayer.second.getPlaneAlpha() == 1.0f)
- aboveOpaqueLayers.orSelf(visibleRegion);
- }
-
- /* If the opaque region does not cover the entire display return false */
- if (!aboveOpaqueLayers.isRect())
- return false;
-
- const auto rect = aboveOpaqueLayers.begin();
- if (rect->left != 0 || rect->top != 0 || rect->right != mDisplayArea.width
- || rect->bottom != mDisplayArea.height)
- return false;
-
- return optimized;
-}
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
deleted file mode 100644
index 909dd48..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _HWC2_TEST_LAYERS_H
-#define _HWC2_TEST_LAYERS_H
-
-#include <map>
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-#include "Hwc2TestProperties.h"
-#include "Hwc2TestLayer.h"
-
-class Hwc2TestLayers {
-public:
- Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
- Hwc2TestCoverage coverage, const Area& displayArea);
-
- Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
- Hwc2TestCoverage coverage, const Area& displayArea,
- const std::unordered_map<Hwc2TestPropertyName,
- Hwc2TestCoverage>& coverageExceptions);
-
- std::string dump() const;
-
- void reset();
-
- bool advance();
- bool advanceVisibleRegions();
-
- /* Test cases with multiple layers and property values can take quite some
- * time to run. A significant amount of time can be spent on test cases
- * where one layer is changing property values but is not visible. To
- * decrease runtime, this function can be called. Removes layouts where a
- * layer is completely blocked from view. It also removes layouts that do
- * not cover the entire display.*/
- bool optimizeLayouts();
-
- bool contains(hwc2_layer_t layer) const;
-
- int getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle,
- int32_t* outAcquireFence);
-
- hwc2_blend_mode_t getBlendMode(hwc2_layer_t layer) const;
- Area getBufferArea(hwc2_layer_t layer) const;
- hwc_color_t getColor(hwc2_layer_t layer) const;
- hwc2_composition_t getComposition(hwc2_layer_t layer) const;
- hwc_rect_t getCursorPosition(hwc2_layer_t layer) const;
- android::ui::Dataspace getDataspace(hwc2_layer_t layer) const;
- hwc_rect_t getDisplayFrame(hwc2_layer_t layer) const;
- android_pixel_format_t getFormat(hwc2_layer_t layer) const;
- float getPlaneAlpha(hwc2_layer_t layer) const;
- hwc_frect_t getSourceCrop(hwc2_layer_t layer) const;
- hwc_region_t getSurfaceDamage(hwc2_layer_t layer) const;
- hwc_transform_t getTransform(hwc2_layer_t layer) const;
- hwc_region_t getVisibleRegion(hwc2_layer_t layer) const;
- uint32_t getZOrder(hwc2_layer_t layer) const;
-
-private:
- bool setVisibleRegions();
-
- std::map<hwc2_layer_t, Hwc2TestLayer> mTestLayers;
-
- Area mDisplayArea;
-
- bool mOptimize = false;
-};
-
-#endif /* ifndef _HWC2_TEST_LAYERS_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp
deleted file mode 100644
index 8ca8815..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include <sstream>
-#include <android/hardware/graphics/common/1.0/types.h>
-
-#include "Hwc2TestPixelComparator.h"
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-
-uint32_t ComparatorResult::getPixel(int32_t x, int32_t y, uint32_t stride,
- uint8_t* img) const
-{
- uint32_t r = img[(y * stride + x) * 4 + 0];
- uint32_t g = img[(y * stride + x) * 4 + 1];
- uint32_t b = img[(y * stride + x) * 4 + 2];
- uint32_t a = img[(y * stride + x) * 4 + 3];
-
- uint32_t pixel = 0;
- pixel |= r;
- pixel |= g << 8;
- pixel |= b << 16;
- pixel |= a << 24;
- return pixel;
-}
-
-void ComparatorResult::CompareBuffers(
- android::sp<android::GraphicBuffer>& resultBuffer,
- android::sp<android::GraphicBuffer>& expectedBuffer)
-{
- uint8_t* resultBufferImg;
- uint8_t* expectedBufferImg;
- resultBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_READ_OFTEN),
- (void**)(&resultBufferImg));
-
- expectedBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_READ_OFTEN),
- (void**)(&expectedBufferImg));
- mComparisons.clear();
- int32_t mDifferentPixelCount = 0;
- int32_t mBlankPixelCount = 0;
-
- for (uint32_t y = 0; y < resultBuffer->getHeight(); y++) {
- for (uint32_t x = 0; x < resultBuffer->getWidth(); x++) {
- uint32_t result = getPixel(x, y, resultBuffer->getStride(),
- resultBufferImg);
- uint32_t expected = getPixel(x, y, expectedBuffer->getStride(),
- expectedBufferImg);
-
- if (result == 0)
- mBlankPixelCount++;
-
- if (result != expected)
- mDifferentPixelCount++;
-
- mComparisons.emplace_back(std::make_tuple(x, y, result, expected));
- }
- }
- resultBuffer->unlock();
- expectedBuffer->unlock();
-}
-
-std::string ComparatorResult::pixelDiff(uint32_t x, uint32_t y,
- uint32_t resultPixel, uint32_t expectedPixel) const
-{
- uint32_t resultAlpha = (resultPixel >> 24) & 0xFF;
- uint32_t resultBlue = (resultPixel >> 16) & 0xFF;
- uint32_t resultGreen = (resultPixel >> 8) & 0xFF;
- uint32_t resultRed = resultPixel & 0xFF;
-
- uint32_t expectedAlpha = (expectedPixel >> 24) & 0xFF;
- uint32_t expectedBlue = (expectedPixel >> 16) & 0xFF;
- uint32_t expectedGreen = (expectedPixel >> 8) & 0xFF;
- uint32_t expectedRed = expectedPixel & 0xFF;
-
- std::ostringstream stream;
-
- stream << "x: " << x << " y: " << y << std::endl;
- stream << std::hex;
- stream << "Result pixel: " << resultRed << "|" << resultGreen << "|"
- << resultBlue << "|" << resultAlpha << std::endl;
-
- stream << "Expected pixel: " << expectedRed << "|" << expectedGreen << "|"
- << expectedBlue << "|" << expectedAlpha << std::endl;
-
- return stream.str();
-}
-
-std::string ComparatorResult::dumpComparison() const
-{
- std::ostringstream stream;
- stream << "Number of different pixels: " << mDifferentPixelCount;
-
- for (const auto& comparison : mComparisons) {
- if (std::get<2>(comparison) != std::get<3>(comparison))
- stream << pixelDiff(std::get<0>(comparison),
- std::get<1>(comparison), std::get<2>(comparison),
- std::get<3>(comparison));
- }
- return stream.str();
-}
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h
deleted file mode 100644
index 55fa936..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-#ifndef _HWC2_TEST_PIXEL_COMPARATOR_H
-#define _HWC2_TEST_PIXEL_COMPARATOR_H
-
-#include <ui/GraphicBuffer.h>
-#include <cstdint>
-#include <string>
-#include <utility>
-#include <vector>
-
-class ComparatorResult {
-public:
- static ComparatorResult& get()
- {
- static ComparatorResult instance;
- return instance;
- }
-
- void CompareBuffers(android::sp<android::GraphicBuffer>& resultBuffer,
- android::sp<android::GraphicBuffer>& expectedBuffer);
-
- std::string dumpComparison() const;
-
- ComparatorResult(const ComparatorResult&) = delete;
- ComparatorResult(ComparatorResult&&) = delete;
- ComparatorResult& operator=(ComparatorResult const&) = delete;
- ComparatorResult& operator=(ComparatorResult&&) = delete;
-
- int32_t getDifferentPixelCount() const { return mDifferentPixelCount; }
- int32_t getBlankPixelCount() const { return mBlankPixelCount; }
-
-private:
- ComparatorResult() = default;
- uint32_t getPixel(int32_t x, int32_t y, uint32_t stride, uint8_t* img) const;
- std::string pixelDiff(uint32_t x, uint32_t y, uint32_t resultPixel,
- uint32_t expectedPixel) const;
-
- int32_t mDifferentPixelCount;
- int32_t mBlankPixelCount;
- /* std::tuple<X coordinate, Y coordinate, resultPixel, expectedPixel> */
- std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>>
- mComparisons;
-};
-
-#endif /* ifndef _HWC2_TEST_PIXEL_COMPARATOR_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
deleted file mode 100644
index 1efb21e..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include <sstream>
-#include <cutils/log.h>
-#include <ui/Rect.h>
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-#include "Hwc2TestBuffer.h"
-#include "Hwc2TestProperties.h"
-
-Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage,
- const Area& displayArea)
- : Hwc2TestProperty(mBufferAreas, mCompositionSupport),
- mScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteScalars:
- (coverage == Hwc2TestCoverage::Basic)? mBasicScalars:
- mDefaultScalars),
- mDisplayArea(displayArea)
-{
- update();
-}
-
-std::string Hwc2TestBufferArea::dump() const
-{
- std::stringstream dmp;
- const Area& curr = get();
- dmp << "\tbuffer area: width " << curr.width << ", height " << curr.height
- << "\n";
- return dmp.str();
-}
-
-void Hwc2TestBufferArea::setDependent(Hwc2TestBuffer* buffer)
-{
- mBuffer = buffer;
- if (buffer) {
- buffer->updateBufferArea(get());
- }
-}
-
-void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop)
-{
- mSourceCrop = sourceCrop;
- if (mSourceCrop) {
- mSourceCrop->updateBufferArea(get());
- }
-}
-
-void Hwc2TestBufferArea::setDependent(Hwc2TestSurfaceDamage* surfaceDamage)
-{
- mSurfaceDamage = surfaceDamage;
- if (mSurfaceDamage) {
- mSurfaceDamage->updateBufferArea(get());
- }
-}
-
-void Hwc2TestBufferArea::update()
-{
- mBufferAreas.clear();
-
- if (mDisplayArea.width == 0 && mDisplayArea.height == 0) {
- mBufferAreas.push_back({0, 0});
- return;
- }
-
- for (auto scalar : mScalars) {
- mBufferAreas.push_back({static_cast<int32_t>(scalar * mDisplayArea.width),
- static_cast<int32_t>(scalar * mDisplayArea.height)});
- }
-
- updateDependents();
-}
-
-void Hwc2TestBufferArea::updateDependents()
-{
- const Area& curr = get();
-
- if (mBuffer)
- mBuffer->updateBufferArea(curr);
- if (mSourceCrop)
- mSourceCrop->updateBufferArea(curr);
- if (mSurfaceDamage)
- mSurfaceDamage->updateBufferArea(curr);
-}
-
-const std::vector<float> Hwc2TestBufferArea::mDefaultScalars = {
- 1.0f,
-};
-
-const std::vector<float> Hwc2TestBufferArea::mBasicScalars = {
- 1.0f, 0.5f,
-};
-
-const std::vector<float> Hwc2TestBufferArea::mCompleteScalars = {
- 1.0f, 0.75f, 0.5f
-};
-
-
-Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes,
- mDefaultBlendModes, mCompositionSupport) { }
-
-std::string Hwc2TestBlendMode::dump() const
-{
- std::stringstream dmp;
- dmp << "\tblend mode: " << getBlendModeName(get()) << "\n";
- return dmp.str();
-}
-
-void Hwc2TestBlendMode::setDependent(Hwc2TestColor* color)
-{
- mColor = color;
- updateDependents();
-}
-
-void Hwc2TestBlendMode::updateDependents()
-{
- if (mColor)
- mColor->updateBlendMode(get());
-}
-
-const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mDefaultBlendModes = {
- HWC2_BLEND_MODE_NONE,
-};
-
-const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mBasicBlendModes = {
- HWC2_BLEND_MODE_NONE,
- HWC2_BLEND_MODE_PREMULTIPLIED,
-};
-
-const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mCompleteBlendModes = {
- HWC2_BLEND_MODE_NONE,
- HWC2_BLEND_MODE_PREMULTIPLIED,
- HWC2_BLEND_MODE_COVERAGE,
-};
-
-
-Hwc2TestColor::Hwc2TestColor(Hwc2TestCoverage coverage,
- hwc2_blend_mode_t blendMode)
- : Hwc2TestProperty(mColors, mCompositionSupport),
- mBaseColors((coverage == Hwc2TestCoverage::Complete)? mCompleteBaseColors:
- (coverage == Hwc2TestCoverage::Basic)? mBasicBaseColors:
- mDefaultBaseColors),
- mBlendMode(blendMode)
-{
- update();
-}
-
-std::string Hwc2TestColor::dump() const
-{
- std::stringstream dmp;
- const hwc_color_t& color = get();
- dmp << "\tcolor: r " << std::to_string(color.r) << ", g "
- << std::to_string(color.g) << ", b " << std::to_string(color.b)
- << ", a " << std::to_string(color.a) << "\n";
- return dmp.str();
-}
-
-void Hwc2TestColor::updateBlendMode(hwc2_blend_mode_t blendMode)
-{
- mBlendMode = blendMode;
- update();
-}
-
-void Hwc2TestColor::update()
-{
- if (mBlendMode != HWC2_BLEND_MODE_PREMULTIPLIED) {
- mColors = mBaseColors;
- return;
- }
-
- mColors.clear();
-
- for (const hwc_color_t& baseColor : mBaseColors) {
- if (baseColor.a >= baseColor.r && baseColor.a >= baseColor.g
- && baseColor.a >= baseColor.b) {
- mColors.push_back(baseColor);
- }
- }
-
-}
-
-const std::vector<hwc_color_t> Hwc2TestColor::mDefaultBaseColors = {
- {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
-};
-
-const std::vector<hwc_color_t> Hwc2TestColor::mBasicBaseColors = {
- {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
- { 0, 0, 0, 0},
-};
-
-const std::vector<hwc_color_t> Hwc2TestColor::mCompleteBaseColors = {
- {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
- {UINT8_MAX, UINT8_MAX, UINT8_MAX, 0},
- {UINT8_MAX, UINT8_MAX, 0, UINT8_MAX},
- {UINT8_MAX, UINT8_MAX, 0, 0},
- {UINT8_MAX, 0, UINT8_MAX, UINT8_MAX},
- {UINT8_MAX, 0, UINT8_MAX, 0},
- {UINT8_MAX, 0, 0, UINT8_MAX},
- {UINT8_MAX, 0, 0, 0},
- { 0, UINT8_MAX, UINT8_MAX, UINT8_MAX},
- { 0, UINT8_MAX, UINT8_MAX, 0},
- { 0, UINT8_MAX, 0, UINT8_MAX},
- { 0, UINT8_MAX, 0, 0},
- { 0, 0, UINT8_MAX, UINT8_MAX},
- { 0, 0, UINT8_MAX, 0},
- { 0, 0, 0, UINT8_MAX},
- { 0, 0, 0, 0},
-};
-
-
-Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions,
- mDefaultCompositions, mCompositionSupport) { }
-
-std::string Hwc2TestComposition::dump() const
-{
- std::stringstream dmp;
- dmp << "\tcomposition: " << getCompositionName(get()) << "\n";
- return dmp.str();
-}
-
-const std::vector<hwc2_composition_t> Hwc2TestComposition::mDefaultCompositions = {
- HWC2_COMPOSITION_DEVICE,
-};
-
-const std::vector<hwc2_composition_t> Hwc2TestComposition::mBasicCompositions = {
- HWC2_COMPOSITION_CLIENT,
- HWC2_COMPOSITION_DEVICE,
-};
-
-const std::vector<hwc2_composition_t> Hwc2TestComposition::mCompleteCompositions = {
- HWC2_COMPOSITION_CLIENT,
- HWC2_COMPOSITION_DEVICE,
- HWC2_COMPOSITION_SOLID_COLOR,
- HWC2_COMPOSITION_CURSOR,
- HWC2_COMPOSITION_SIDEBAND,
-};
-
-
-Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(coverage, completeDataspaces, basicDataspaces,
- defaultDataspaces, mCompositionSupport) { }
-
-std::string Hwc2TestDataspace::dump() const
-{
- std::stringstream dmp;
- dmp << "\tdataspace: " << static_cast<int32_t>(get()) << "\n";
- return dmp.str();
-}
-
-const std::vector<android::ui::Dataspace> Hwc2TestDataspace::defaultDataspaces = {
- android::ui::Dataspace::UNKNOWN,
-};
-
-const std::vector<android::ui::Dataspace> Hwc2TestDataspace::basicDataspaces = {
- android::ui::Dataspace::UNKNOWN,
- android::ui::Dataspace::V0_SRGB,
-};
-
-const std::vector<android::ui::Dataspace> Hwc2TestDataspace::completeDataspaces = {
- android::ui::Dataspace::UNKNOWN,
- android::ui::Dataspace::ARBITRARY,
- android::ui::Dataspace::STANDARD_SHIFT,
- android::ui::Dataspace::STANDARD_MASK,
- android::ui::Dataspace::STANDARD_UNSPECIFIED,
- android::ui::Dataspace::STANDARD_BT709,
- android::ui::Dataspace::STANDARD_BT601_625,
- android::ui::Dataspace::STANDARD_BT601_625_UNADJUSTED,
- android::ui::Dataspace::STANDARD_BT601_525,
- android::ui::Dataspace::STANDARD_BT601_525_UNADJUSTED,
- android::ui::Dataspace::STANDARD_BT2020,
- android::ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE,
- android::ui::Dataspace::STANDARD_BT470M,
- android::ui::Dataspace::STANDARD_FILM,
- android::ui::Dataspace::TRANSFER_SHIFT,
- android::ui::Dataspace::TRANSFER_MASK,
- android::ui::Dataspace::TRANSFER_UNSPECIFIED,
- android::ui::Dataspace::TRANSFER_LINEAR,
- android::ui::Dataspace::TRANSFER_SRGB,
- android::ui::Dataspace::TRANSFER_SMPTE_170M,
- android::ui::Dataspace::TRANSFER_GAMMA2_2,
- android::ui::Dataspace::TRANSFER_GAMMA2_8,
- android::ui::Dataspace::TRANSFER_ST2084,
- android::ui::Dataspace::TRANSFER_HLG,
- android::ui::Dataspace::RANGE_SHIFT,
- android::ui::Dataspace::RANGE_MASK,
- android::ui::Dataspace::RANGE_UNSPECIFIED,
- android::ui::Dataspace::RANGE_FULL,
- android::ui::Dataspace::RANGE_LIMITED,
- android::ui::Dataspace::SRGB_LINEAR,
- android::ui::Dataspace::V0_SRGB_LINEAR,
- android::ui::Dataspace::SRGB,
- android::ui::Dataspace::V0_SRGB,
- android::ui::Dataspace::JFIF,
- android::ui::Dataspace::V0_JFIF,
- android::ui::Dataspace::BT601_625,
- android::ui::Dataspace::V0_BT601_625,
- android::ui::Dataspace::BT601_525,
- android::ui::Dataspace::V0_BT601_525,
- android::ui::Dataspace::BT709,
- android::ui::Dataspace::V0_BT709,
- android::ui::Dataspace::DEPTH,
-};
-
-
-Hwc2TestDisplayDimension::Hwc2TestDisplayDimension(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(
- (coverage == Hwc2TestCoverage::Complete)? mCompleteDisplayDimensions:
- (coverage == Hwc2TestCoverage::Basic)? mBasicDisplayDimensions:
- mDefaultDisplayDimensions, mCompositionSupport) { }
-
-std::string Hwc2TestDisplayDimension::dump() const
-{
- std::stringstream dmp;
- const UnsignedArea& curr = get();
- dmp << "\tdisplay dimension: " << curr.width<< " x " << curr.height<< "\n";
- return dmp.str();
-}
-
-void Hwc2TestDisplayDimension::setDependent(Hwc2TestVirtualBuffer* buffer)
-{
- mBuffers.insert(buffer);
- updateDependents();
-}
-
-void Hwc2TestDisplayDimension::updateDependents()
-{
- const UnsignedArea& curr = get();
-
- for (Hwc2TestVirtualBuffer* buffer : mBuffers)
- buffer->updateBufferArea({static_cast<int32_t>(curr.width),
- static_cast<int32_t>(curr.height)});
-}
-
-const std::vector<UnsignedArea>
- Hwc2TestDisplayDimension::mDefaultDisplayDimensions = {
- {1920, 1080},
-};
-
-const std::vector<UnsignedArea>
- Hwc2TestDisplayDimension::mBasicDisplayDimensions = {
- {640, 480},
- {1280, 720},
- {1920, 1080},
- {1920, 1200},
-};
-
-const std::vector<UnsignedArea>
- Hwc2TestDisplayDimension::mCompleteDisplayDimensions = {
- {320, 240},
- {480, 320},
- {640, 480},
- {1280, 720},
- {1920, 1080},
- {1920, 1200},
- {2560, 1440},
- {2560, 1600},
- {3840, 2160},
- {4096, 2160},
-};
-
-
-Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage,
- const Area& displayArea)
- : Hwc2TestProperty(mDisplayFrames, mCompositionSupport),
- mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
- (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
- mDefaultFrectScalars),
- mDisplayArea(displayArea)
-{
- update();
-}
-
-std::string Hwc2TestDisplayFrame::dump() const
-{
- std::stringstream dmp;
- const hwc_rect_t& displayFrame = get();
- dmp << "\tdisplay frame: left " << displayFrame.left << ", top "
- << displayFrame.top << ", right " << displayFrame.right
- << ", bottom " << displayFrame.bottom << "\n";
- return dmp.str();
-}
-
-void Hwc2TestDisplayFrame::update()
-{
- mDisplayFrames.clear();
-
- if (mDisplayArea.width == 0 && mDisplayArea.height == 0) {
- mDisplayFrames.push_back({0, 0, 0, 0});
- return;
- }
-
- for (const auto& frectScalar : mFrectScalars) {
- mDisplayFrames.push_back({
- static_cast<int>(frectScalar.left * mDisplayArea.width),
- static_cast<int>(frectScalar.top * mDisplayArea.height),
- static_cast<int>(frectScalar.right * mDisplayArea.width),
- static_cast<int>(frectScalar.bottom * mDisplayArea.height)});
- }
-}
-
-const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mDefaultFrectScalars = {
- {0.0, 0.0, 1.0, 1.0},
-};
-
-const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mBasicFrectScalars = {
- {0.0, 0.0, 1.0, 1.0},
- {0.0, 0.0, 1.0, 0.05},
- {0.0, 0.95, 1.0, 1.0},
-};
-
-const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mCompleteFrectScalars = {
- {0.0, 0.0, 1.0, 1.0},
- {0.0, 0.05, 1.0, 0.95},
- {0.0, 0.05, 1.0, 1.0},
- {0.0, 0.0, 1.0, 0.05},
- {0.0, 0.95, 1.0, 1.0},
- {0.25, 0.0, 0.75, 0.35},
- {0.25, 0.25, 0.75, 0.75},
-};
-
-
-Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas,
- mDefaultPlaneAlphas, mCompositionSupport) { }
-
-std::string Hwc2TestPlaneAlpha::dump() const
-{
- std::stringstream dmp;
- dmp << "\tplane alpha: " << get() << "\n";
- return dmp.str();
-}
-
-const std::vector<float> Hwc2TestPlaneAlpha::mDefaultPlaneAlphas = {
- 1.0f,
-};
-
-const std::vector<float> Hwc2TestPlaneAlpha::mBasicPlaneAlphas = {
- 1.0f, 0.0f,
-};
-
-const std::vector<float> Hwc2TestPlaneAlpha::mCompletePlaneAlphas = {
- 1.0f, 0.75f, 0.5f, 0.25f, 0.0f,
-};
-
-
-Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage,
- const Area& bufferArea)
- : Hwc2TestProperty(mSourceCrops, mCompositionSupport),
- mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
- (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
- mDefaultFrectScalars),
- mBufferArea(bufferArea)
-{
- update();
-}
-
-std::string Hwc2TestSourceCrop::dump() const
-{
- std::stringstream dmp;
- const hwc_frect_t& sourceCrop = get();
- dmp << "\tsource crop: left " << sourceCrop.left << ", top "
- << sourceCrop.top << ", right " << sourceCrop.right << ", bottom "
- << sourceCrop.bottom << "\n";
- return dmp.str();
-}
-
-void Hwc2TestSourceCrop::updateBufferArea(const Area& bufferArea)
-{
- mBufferArea = bufferArea;
- update();
-}
-
-void Hwc2TestSourceCrop::update()
-{
- mSourceCrops.clear();
-
- if (mBufferArea.width == 0 && mBufferArea.height == 0) {
- mSourceCrops.push_back({0, 0, 0, 0});
- return;
- }
-
- for (const auto& frectScalar : mFrectScalars) {
- mSourceCrops.push_back({
- frectScalar.left * mBufferArea.width,
- frectScalar.top * mBufferArea.height,
- frectScalar.right * mBufferArea.width,
- frectScalar.bottom * mBufferArea.height});
- }
-}
-
-const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mDefaultFrectScalars = {
- {0.0, 0.0, 1.0, 1.0},
-};
-
-const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mBasicFrectScalars = {
- {0.0, 0.0, 1.0, 1.0},
- {0.0, 0.0, 0.5, 0.5},
- {0.5, 0.5, 1.0, 1.0},
-};
-
-const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mCompleteFrectScalars = {
- {0.0, 0.0, 1.0, 1.0},
- {0.0, 0.0, 0.5, 0.5},
- {0.5, 0.5, 1.0, 1.0},
- {0.0, 0.0, 0.25, 0.25},
- {0.25, 0.25, 0.75, 0.75},
-};
-
-
-Hwc2TestSurfaceDamage::Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(mSurfaceDamages, mCompositionSupport),
- mRegionScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteRegionScalars:
- (coverage == Hwc2TestCoverage::Basic)? mBasicRegionScalars:
- mDefaultRegionScalars)
-{
- update();
-}
-
-Hwc2TestSurfaceDamage::~Hwc2TestSurfaceDamage()
-{
- freeSurfaceDamages();
-}
-
-std::string Hwc2TestSurfaceDamage::dump() const
-{
- std::stringstream dmp;
-
- const hwc_region_t& curr = get();
- dmp << "\tsurface damage: region count " << curr.numRects << "\n";
- for (size_t i = 0; i < curr.numRects; i++) {
- const hwc_rect_t& rect = curr.rects[i];
- dmp << "\t\trect: left " << rect.left << ", top " << rect.top
- << ", right " << rect.right << ", bottom " << rect.bottom << "\n";
- }
-
- return dmp.str();
-}
-
-void Hwc2TestSurfaceDamage::updateBufferArea(const Area& bufferArea)
-{
- mBufferArea = bufferArea;
- update();
-}
-
-void Hwc2TestSurfaceDamage::update()
-{
- freeSurfaceDamages();
-
- if (mBufferArea.width == 0 && mBufferArea.height == 0) {
- mSurfaceDamages.push_back({0, nullptr});
- return;
- }
-
- hwc_region_t damage;
-
- for (const auto& regionScalar : mRegionScalars) {
- damage.numRects = regionScalar.size();
-
- if (damage.numRects > 0) {
- hwc_rect_t* rects = new hwc_rect_t[damage.numRects];
- if (!rects) {
- ALOGW("failed to allocate new hwc_rect_t array");
- continue;
- }
-
- for (size_t i = 0; i < damage.numRects; i++) {
- rects[i].left = regionScalar[i].left * mBufferArea.width;
- rects[i].top = regionScalar[i].top * mBufferArea.height;
- rects[i].right = regionScalar[i].right * mBufferArea.width;
- rects[i].bottom = regionScalar[i].bottom * mBufferArea.height;
- }
-
- damage.rects = static_cast<hwc_rect_t const*>(rects);
- } else {
- damage.rects = nullptr;
- }
-
- mSurfaceDamages.push_back(damage);
- }
-}
-
-void Hwc2TestSurfaceDamage::freeSurfaceDamages()
-{
- for (const auto& surfaceDamage : mSurfaceDamages) {
- if (surfaceDamage.numRects > 0 && surfaceDamage.rects)
- delete[] surfaceDamage.rects;
- }
- mSurfaceDamages.clear();
-}
-
-const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mDefaultRegionScalars = {
- {{}},
-};
-
-const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mBasicRegionScalars = {
- {{}},
- {{0.0, 0.0, 1.0, 1.0}},
-};
-
-const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mCompleteRegionScalars = {
- {{}},
- {{0.0, 0.0, 1.0, 1.0}},
- {{0.0, 0.0, 0.5, 0.5}, {0.5, 0.5, 1.0, 1.0}},
-};
-
-
-Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage)
- : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms,
- mDefaultTransforms, mCompositionSupport) { }
-
-std::string Hwc2TestTransform::dump() const
-{
- std::stringstream dmp;
- dmp << "\ttransform: " << getTransformName(get()) << "\n";
- return dmp.str();
-}
-
-const std::vector<hwc_transform_t> Hwc2TestTransform::mDefaultTransforms = {
- static_cast<hwc_transform_t>(0),
-};
-
-const std::vector<hwc_transform_t> Hwc2TestTransform::mBasicTransforms = {
- static_cast<hwc_transform_t>(0),
- HWC_TRANSFORM_FLIP_H,
- HWC_TRANSFORM_FLIP_V,
- HWC_TRANSFORM_ROT_90,
-};
-
-const std::vector<hwc_transform_t> Hwc2TestTransform::mCompleteTransforms = {
- static_cast<hwc_transform_t>(0),
- HWC_TRANSFORM_FLIP_H,
- HWC_TRANSFORM_FLIP_V,
- HWC_TRANSFORM_ROT_90,
- HWC_TRANSFORM_ROT_180,
- HWC_TRANSFORM_ROT_270,
- HWC_TRANSFORM_FLIP_H_ROT_90,
- HWC_TRANSFORM_FLIP_V_ROT_90,
-};
-
-
-Hwc2TestVisibleRegion::~Hwc2TestVisibleRegion()
-{
- release();
-}
-
-std::string Hwc2TestVisibleRegion::dump() const
-{
- std::stringstream dmp;
-
- const hwc_region_t& curr = get();
- dmp << "\tvisible region: region count " << curr.numRects << "\n";
- for (size_t i = 0; i < curr.numRects; i++) {
- const hwc_rect_t& rect = curr.rects[i];
- dmp << "\t\trect: left " << rect.left << ", top " << rect.top
- << ", right " << rect.right << ", bottom " << rect.bottom << "\n";
- }
-
- return dmp.str();
-}
-
-void Hwc2TestVisibleRegion::set(const android::Region& visibleRegion)
-{
- release();
-
- size_t size = 0;
- const android::Rect* rects = visibleRegion.getArray(&size);
-
- mVisibleRegion.numRects = size;
- mVisibleRegion.rects = nullptr;
-
- if (size > 0) {
- hwc_rect_t* hwcRects = new hwc_rect_t[size];
- for (size_t i = 0; i < size; i++) {
- hwcRects[i].left = rects[i].left;
- hwcRects[i].top = rects[i].top;
- hwcRects[i].right = rects[i].right;
- hwcRects[i].bottom = rects[i].bottom;
- }
- mVisibleRegion.rects = hwcRects;
- }
-}
-
-hwc_region_t Hwc2TestVisibleRegion::get() const
-{
- return mVisibleRegion;
-}
-
-void Hwc2TestVisibleRegion::release()
-{
- if (mVisibleRegion.numRects > 0 && mVisibleRegion.rects)
- delete[] mVisibleRegion.rects;
- mVisibleRegion.rects = nullptr;
- mVisibleRegion.numRects = 0;
-}
-
-/* Identifies which layer properties are supported by each composition type.
- * hwc2_composition_t values range from:
- * HWC2_COMPOSITION_INVALID = 0,
- * HWC2_COMPOSITION_CLIENT = 1,
- * HWC2_COMPOSITION_DEVICE = 2,
- * HWC2_COMPOSITION_SOLID_COLOR = 3,
- * HWC2_COMPOSITION_CURSOR = 4,
- * HWC2_COMPOSITION_SIDEBAND = 5,
- *
- * Each property array can be indexed by a hwc2_composition_t value.
- * By using an array instead of a more complex data structure, runtimes for
- * some test cases showed a noticeable improvement.
- */
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestBufferArea::mCompositionSupport = {{
- false, true, true, false, true, true,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestBlendMode::mCompositionSupport = {{
- false, true, true, false, true, true,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestColor::mCompositionSupport = {{
- false, false, false, true, false, false,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestComposition::mCompositionSupport = {{
- false, true, true, true, true, true,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestDataspace::mCompositionSupport = {{
- false, true, true, true, true, false,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestDisplayDimension::mCompositionSupport = {{
- false, true, true, true, true, true,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestDisplayFrame::mCompositionSupport = {{
- false, true, true, true, false, true,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestPlaneAlpha::mCompositionSupport = {{
- false, true, true, true, true, true,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestSourceCrop::mCompositionSupport = {{
- false, true, true, false, true, false,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestSurfaceDamage::mCompositionSupport = {{
- false, false, true, false, true, false,
-}};
-
-/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
-const std::array<bool, 6> Hwc2TestTransform::mCompositionSupport = {{
- false, true, true, false, true, true,
-}};
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
deleted file mode 100644
index 06ae314..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _HWC2_TEST_PROPERTIES_H
-#define _HWC2_TEST_PROPERTIES_H
-
-#include <array>
-#include <vector>
-
-#include <ui/GraphicTypes.h>
-#include <ui/Region.h>
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-enum class Hwc2TestCoverage {
- Default = 0,
- Basic,
- Complete,
-};
-
-enum class Hwc2TestPropertyName {
- BlendMode = 1,
- BufferArea,
- Color,
- Composition,
- CursorPosition,
- Dataspace,
- DisplayFrame,
- PlaneAlpha,
- SourceCrop,
- SurfaceDamage,
- Transform,
-};
-
-typedef struct {
- int32_t width;
- int32_t height;
-} Area;
-
-
-typedef struct {
- uint32_t width;
- uint32_t height;
-} UnsignedArea;
-
-
-class Hwc2TestContainer {
-public:
- virtual ~Hwc2TestContainer() = default;
-
- /* Resets the container */
- virtual void reset() = 0;
-
- /* Attempts to advance to the next valid value. Returns true if one can be
- * found */
- virtual bool advance() = 0;
-
- virtual std::string dump() const = 0;
-
- /* Returns true if the container supports the given composition type */
- virtual bool isSupported(hwc2_composition_t composition) = 0;
-};
-
-
-template <class T>
-class Hwc2TestProperty : public Hwc2TestContainer {
-public:
- Hwc2TestProperty(Hwc2TestCoverage coverage,
- const std::vector<T>& completeList, const std::vector<T>& basicList,
- const std::vector<T>& defaultList,
- const std::array<bool, 6>& compositionSupport)
- : Hwc2TestProperty((coverage == Hwc2TestCoverage::Complete)? completeList:
- (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList,
- compositionSupport) { }
-
- Hwc2TestProperty(const std::vector<T>& list,
- const std::array<bool, 6>& compositionSupport)
- : mList(list),
- mCompositionSupport(compositionSupport) { }
-
- void reset() override
- {
- mListIdx = 0;
- }
-
- bool advance() override
- {
- if (mListIdx + 1 < mList.size()) {
- mListIdx++;
- updateDependents();
- return true;
- }
- reset();
- updateDependents();
- return false;
- }
-
- T get() const
- {
- return mList.at(mListIdx);
- }
-
- virtual bool isSupported(hwc2_composition_t composition)
- {
- return mCompositionSupport.at(composition);
- }
-
-protected:
- /* If a derived class has dependents, override this function */
- virtual void updateDependents() { }
-
- const std::vector<T>& mList;
- size_t mListIdx = 0;
-
- const std::array<bool, 6>& mCompositionSupport;
-};
-
-class Hwc2TestBuffer;
-class Hwc2TestSourceCrop;
-class Hwc2TestSurfaceDamage;
-
-class Hwc2TestBufferArea : public Hwc2TestProperty<Area> {
-public:
- Hwc2TestBufferArea(Hwc2TestCoverage coverage, const Area& displayArea);
-
- std::string dump() const override;
-
- void setDependent(Hwc2TestBuffer* buffer);
- void setDependent(Hwc2TestSourceCrop* sourceCrop);
- void setDependent(Hwc2TestSurfaceDamage* surfaceDamage);
-
-protected:
- void update();
- void updateDependents() override;
-
- const std::vector<float>& mScalars;
- static const std::vector<float> mDefaultScalars;
- static const std::vector<float> mBasicScalars;
- static const std::vector<float> mCompleteScalars;
-
- Area mDisplayArea;
-
- Hwc2TestBuffer* mBuffer = nullptr;
- Hwc2TestSourceCrop* mSourceCrop = nullptr;
- Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr;
-
- std::vector<Area> mBufferAreas;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestColor;
-
-class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
-public:
- explicit Hwc2TestBlendMode(Hwc2TestCoverage coverage);
-
- std::string dump() const override;
-
- void setDependent(Hwc2TestColor* color);
-
-protected:
- void updateDependents() override;
-
- Hwc2TestColor* mColor = nullptr;
-
- static const std::vector<hwc2_blend_mode_t> mDefaultBlendModes;
- static const std::vector<hwc2_blend_mode_t> mBasicBlendModes;
- static const std::vector<hwc2_blend_mode_t> mCompleteBlendModes;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestColor : public Hwc2TestProperty<hwc_color_t> {
-public:
- explicit Hwc2TestColor(Hwc2TestCoverage coverage,
- hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
-
- std::string dump() const override;
-
- void updateBlendMode(hwc2_blend_mode_t blendMode);
-
-protected:
- void update();
-
- std::vector<hwc_color_t> mBaseColors;
- static const std::vector<hwc_color_t> mDefaultBaseColors;
- static const std::vector<hwc_color_t> mBasicBaseColors;
- static const std::vector<hwc_color_t> mCompleteBaseColors;
-
- hwc2_blend_mode_t mBlendMode;
-
- std::vector<hwc_color_t> mColors;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestComposition : public Hwc2TestProperty<hwc2_composition_t> {
-public:
- explicit Hwc2TestComposition(Hwc2TestCoverage coverage);
-
- std::string dump() const override;
-
-protected:
- static const std::vector<hwc2_composition_t> mDefaultCompositions;
- static const std::vector<hwc2_composition_t> mBasicCompositions;
- static const std::vector<hwc2_composition_t> mCompleteCompositions;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestDataspace : public Hwc2TestProperty<android::ui::Dataspace> {
-public:
- explicit Hwc2TestDataspace(Hwc2TestCoverage coverage);
-
- std::string dump() const override;
-
-protected:
- static const std::vector<android::ui::Dataspace> defaultDataspaces;
- static const std::vector<android::ui::Dataspace> basicDataspaces;
- static const std::vector<android::ui::Dataspace> completeDataspaces;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-class Hwc2TestVirtualBuffer;
-
-class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
-public:
- explicit Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
-
- std::string dump() const;
-
- void setDependent(Hwc2TestVirtualBuffer* buffer);
-
-private:
- void updateDependents();
-
- std::set<Hwc2TestVirtualBuffer*> mBuffers;
-
- static const std::vector<UnsignedArea> mDefaultDisplayDimensions;
- static const std::vector<UnsignedArea> mBasicDisplayDimensions;
- static const std::vector<UnsignedArea> mCompleteDisplayDimensions;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestDisplayFrame : public Hwc2TestProperty<hwc_rect_t> {
-public:
- Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea);
-
- std::string dump() const override;
-
-protected:
- void update();
-
- const std::vector<hwc_frect_t>& mFrectScalars;
- const static std::vector<hwc_frect_t> mDefaultFrectScalars;
- const static std::vector<hwc_frect_t> mBasicFrectScalars;
- const static std::vector<hwc_frect_t> mCompleteFrectScalars;
-
- Area mDisplayArea;
-
- std::vector<hwc_rect_t> mDisplayFrames;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestPlaneAlpha : public Hwc2TestProperty<float> {
-public:
- explicit Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
-
- std::string dump() const override;
-
-protected:
- static const std::vector<float> mDefaultPlaneAlphas;
- static const std::vector<float> mBasicPlaneAlphas;
- static const std::vector<float> mCompletePlaneAlphas;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestSourceCrop : public Hwc2TestProperty<hwc_frect_t> {
-public:
- explicit Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
-
- std::string dump() const override;
-
- void updateBufferArea(const Area& bufferArea);
-
-protected:
- void update();
-
- const std::vector<hwc_frect_t>& mFrectScalars;
- const static std::vector<hwc_frect_t> mDefaultFrectScalars;
- const static std::vector<hwc_frect_t> mBasicFrectScalars;
- const static std::vector<hwc_frect_t> mCompleteFrectScalars;
-
- Area mBufferArea;
-
- std::vector<hwc_frect_t> mSourceCrops;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestSurfaceDamage : public Hwc2TestProperty<hwc_region_t> {
-public:
- explicit Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
- ~Hwc2TestSurfaceDamage();
-
- std::string dump() const override;
-
- void updateBufferArea(const Area& bufferArea);
-
-protected:
- void update();
- void freeSurfaceDamages();
-
- const std::vector<std::vector<hwc_frect_t>> &mRegionScalars;
- const static std::vector<std::vector<hwc_frect_t>> mDefaultRegionScalars;
- const static std::vector<std::vector<hwc_frect_t>> mBasicRegionScalars;
- const static std::vector<std::vector<hwc_frect_t>> mCompleteRegionScalars;
-
- Area mBufferArea = {0, 0};
-
- std::vector<hwc_region_t> mSurfaceDamages;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
-public:
- explicit Hwc2TestTransform(Hwc2TestCoverage coverage);
-
- std::string dump() const override;
-
-protected:
- static const std::vector<hwc_transform_t> mDefaultTransforms;
- static const std::vector<hwc_transform_t> mBasicTransforms;
- static const std::vector<hwc_transform_t> mCompleteTransforms;
-
- static const std::array<bool, 6> mCompositionSupport;
-};
-
-
-class Hwc2TestVisibleRegion {
-public:
- ~Hwc2TestVisibleRegion();
-
- std::string dump() const;
-
- void set(const android::Region& visibleRegion);
- hwc_region_t get() const;
- void release();
-
-protected:
- hwc_region_t mVisibleRegion = {0, nullptr};
-};
-
-#endif /* ifndef _HWC2_TEST_PROPERTIES_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
deleted file mode 100644
index e6cceb8..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2016 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 <sstream>
-#include <sys/stat.h>
-
-#include "Hwc2TestVirtualDisplay.h"
-
-#define DIR_NAME "images"
-
-Hwc2TestVirtualDisplay::Hwc2TestVirtualDisplay(
- Hwc2TestCoverage coverage)
- : mDisplayDimension(coverage)
-{
- mDisplayDimension.setDependent(&mOutputBuffer);
- mDisplayDimension.setDependent(&mExpectedBuffer);
-}
-
-std::string Hwc2TestVirtualDisplay::dump() const
-{
- std::stringstream dmp;
-
- dmp << "virtual display: \n";
-
- mDisplayDimension.dump();
-
- return dmp.str();
-}
-
-int Hwc2TestVirtualDisplay::getOutputBuffer(buffer_handle_t* outHandle,
- android::base::unique_fd* outAcquireFence)
-{
- int32_t acquireFence;
- int ret = mOutputBuffer.getOutputBuffer(outHandle, &acquireFence);
- outAcquireFence->reset(acquireFence);
- return ret;
-}
-
-void Hwc2TestVirtualDisplay::reset()
-{
- return mDisplayDimension.reset();
-}
-
-bool Hwc2TestVirtualDisplay::advance()
-{
- return mDisplayDimension.advance();
-}
-
-UnsignedArea Hwc2TestVirtualDisplay::getDisplayDimension() const
-{
- return mDisplayDimension.get();
-}
-
-int Hwc2TestVirtualDisplay::verifyOutputBuffer(const Hwc2TestLayers* testLayers,
- const std::vector<hwc2_layer_t>* allLayers,
- const std::set<hwc2_layer_t>* clearLayers)
-{
- int ret = mExpectedBuffer.generateExpectedBuffer(testLayers, allLayers,
- clearLayers);
- if (ret)
- return ret;
-
- ComparatorResult::get().CompareBuffers(mOutputBuffer.graphicBuffer(),
- mExpectedBuffer.graphicBuffer());
-
- return 0;
-}
-
-int Hwc2TestVirtualDisplay::writeBuffersToFile(std::string name)
-{
- std::ostringstream expectedPath;
- std::ostringstream resultPath;
- int ret = mkdir(DIR_NAME, DEFFILEMODE);
- if (ret && errno != EEXIST)
- return ret;
-
- expectedPath << DIR_NAME << "/expected-" << name << ".png";
- resultPath << DIR_NAME << "/result-" << name << ".png";
-
- if (!mExpectedBuffer.writeBufferToFile(expectedPath.str()) ||
- !mOutputBuffer.writeBufferToFile(resultPath.str()))
- return -1;
-
- return 0;
-}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
deleted file mode 100644
index 5a74a6c..0000000
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H
-#define _HWC2_TEST_VIRTUAL_DISPLAY_H
-
-#include "Hwc2TestBuffer.h"
-#include "Hwc2TestPixelComparator.h"
-#include "Hwc2TestProperties.h"
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-class Hwc2TestVirtualDisplay {
-public:
- explicit Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
-
- std::string dump() const;
-
- int getOutputBuffer(buffer_handle_t* outHandle,
- android::base::unique_fd* outAcquireFence);
-
- int verifyOutputBuffer(const Hwc2TestLayers* testLayers,
- const std::vector<hwc2_layer_t>* allLayers,
- const std::set<hwc2_layer_t>* clearLayers);
-
- int writeBuffersToFile(std::string name);
- void reset();
- bool advance();
-
- UnsignedArea getDisplayDimension() const;
-
-private:
- Hwc2TestOutputBuffer mOutputBuffer;
- Hwc2TestExpectedBuffer mExpectedBuffer;
- Hwc2TestDisplayDimension mDisplayDimension;
-};
-
-#endif /* ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H */
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 2f2fb20..7574ff1 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -48,6 +48,7 @@
"LayerHistoryTestV2.cpp",
"LayerMetadataTest.cpp",
"PhaseOffsetsTest.cpp",
+ "PromiseTest.cpp",
"SchedulerTest.cpp",
"SchedulerUtilsTest.cpp",
"SetFrameRateTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 2dcaf63..32d722e 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -50,6 +50,14 @@
namespace android {
namespace {
+namespace hal = android::hardware::graphics::composer::hal;
+
+using hal::Error;
+using hal::IComposer;
+using hal::IComposerClient;
+using hal::PowerMode;
+using hal::Transform;
+
using testing::_;
using testing::AtLeast;
using testing::Between;
@@ -65,16 +73,11 @@
using testing::ReturnRef;
using testing::SetArgPointee;
-using android::Hwc2::Error;
-using android::Hwc2::IComposer;
-using android::Hwc2::IComposerClient;
-using android::Hwc2::Transform;
-
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
-constexpr hwc2_display_t HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
-constexpr hwc2_layer_t HWC_LAYER = 5000;
+constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
+constexpr hal::HWLayerId HWC_LAYER = 5000;
constexpr Transform DEFAULT_TRANSFORM = static_cast<Transform>(0);
constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
@@ -141,10 +144,10 @@
auto primaryDispSync = std::make_unique<mock::DispSync>();
- EXPECT_CALL(*primaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, computeNextRefresh(0, _)).WillRepeatedly(Return(0));
EXPECT_CALL(*primaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
- EXPECT_CALL(*primaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(primaryDispSync),
std::make_unique<mock::EventControlThread>(),
@@ -170,7 +173,7 @@
template <typename Case>
void captureScreenComposition();
- std::unordered_set<HWC2::Capability> mDefaultCapabilities = {HWC2::Capability::SidebandStream};
+ std::unordered_set<hal::Capability> mDefaultCapabilities = {hal::Capability::SIDEBAND_STREAM};
bool mDisplayOff = false;
TestableSurfaceFlinger mFlinger;
@@ -228,6 +231,7 @@
const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
constexpr bool useIdentityTransform = true;
constexpr bool forSystem = true;
+ constexpr bool regionSampling = false;
DisplayRenderArea renderArea(mDisplay, sourceCrop, DEFAULT_DISPLAY_WIDTH,
DEFAULT_DISPLAY_HEIGHT, ui::Dataspace::V0_SRGB,
@@ -246,7 +250,7 @@
int fd = -1;
status_t result =
mFlinger.captureScreenImplLocked(renderArea, traverseLayers, mCaptureScreenBuffer.get(),
- useIdentityTransform, forSystem, &fd);
+ useIdentityTransform, forSystem, &fd, regionSampling);
if (fd >= 0) {
close(fd);
}
@@ -263,17 +267,13 @@
template <typename Derived>
struct BaseDisplayVariant {
static constexpr bool IS_SECURE = true;
- static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
+ static constexpr hal::PowerMode INIT_POWER_MODE = hal::PowerMode::ON;
static void setupPreconditions(CompositionTest* test) {
- EXPECT_CALL(*test->mComposer,
- setPowerMode(HWC_DISPLAY,
- static_cast<Hwc2::IComposerClient::PowerMode>(
- Derived::INIT_POWER_MODE)))
+ EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY, Derived::INIT_POWER_MODE))
.WillOnce(Return(Error::NONE));
- FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, HWC2::DisplayType::Physical,
- true /* isPrimary */)
+ FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, true /* isPrimary */)
.setCapabilities(&test->mDefaultCapabilities)
.setPowerMode(Derived::INIT_POWER_MODE)
.inject(&test->mFlinger, test->mComposer);
@@ -437,7 +437,7 @@
};
struct PoweredOffDisplaySetupVariant : public BaseDisplayVariant<PoweredOffDisplaySetupVariant> {
- static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_OFF;
+ static constexpr hal::PowerMode INIT_POWER_MODE = hal::PowerMode::OFF;
template <typename Case>
static void setupPreconditionCallExpectations(CompositionTest*) {}
@@ -542,7 +542,7 @@
EXPECT_CALL(*test->mMessageQueue, invalidate()).Times(1);
enqueueBuffer(test, layer);
- Mock::VerifyAndClear(test->mMessageQueue);
+ Mock::VerifyAndClearExpectations(test->mMessageQueue);
EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
bool ignoredRecomputeVisibleRegions;
@@ -834,7 +834,7 @@
struct BaseLayerVariant {
template <typename L, typename F>
static sp<L> createLayerWithFactory(CompositionTest* test, F factory) {
- EXPECT_CALL(*test->mMessageQueue, postMessage(_, 0)).Times(0);
+ EXPECT_CALL(*test->mMessageQueue, postMessage(_)).Times(0);
sp<L> layer = factory();
@@ -843,7 +843,7 @@
Mock::VerifyAndClear(test->mComposer);
Mock::VerifyAndClear(test->mRenderEngine);
- Mock::VerifyAndClear(test->mMessageQueue);
+ Mock::VerifyAndClearExpectations(test->mMessageQueue);
auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
layerDrawingState.layerStack = DEFAULT_LAYER_STACK;
@@ -944,7 +944,7 @@
}
static void cleanupInjectedLayers(CompositionTest* test) {
- EXPECT_CALL(*test->mMessageQueue, postMessage(_, 0)).Times(1);
+ EXPECT_CALL(*test->mMessageQueue, postMessage(_)).Times(1);
Base::cleanupInjectedLayers(test);
}
@@ -989,7 +989,7 @@
template <IComposerClient::Composition CompositionType>
struct KeepCompositionTypeVariant {
- static constexpr HWC2::Composition TYPE = static_cast<HWC2::Composition>(CompositionType);
+ static constexpr hal::Composition TYPE = CompositionType;
static void setupHwcSetCallExpectations(CompositionTest* test) {
if (!test->mDisplayOff) {
@@ -1007,7 +1007,7 @@
template <IComposerClient::Composition InitialCompositionType,
IComposerClient::Composition FinalCompositionType>
struct ChangeCompositionTypeVariant {
- static constexpr HWC2::Composition TYPE = static_cast<HWC2::Composition>(FinalCompositionType);
+ static constexpr hal::Composition TYPE = FinalCompositionType;
static void setupHwcSetCallExpectations(CompositionTest* test) {
if (!test->mDisplayOff) {
@@ -1073,7 +1073,8 @@
struct ForcedClientCompositionResultVariant : public CompositionResultBaseVariant {
static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
- const auto outputLayer = layer->findOutputLayerForDisplay(test->mDisplay);
+ const auto outputLayer =
+ TestableSurfaceFlinger::findOutputLayerForDisplay(layer, test->mDisplay);
LOG_FATAL_IF(!outputLayer);
outputLayer->editState().forceClientComposition = true;
}
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 2e705da..afebc40 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -43,7 +43,7 @@
void createDispSync();
void createDispSyncSource();
- void onVSyncEvent(nsecs_t when) override;
+ void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) override;
std::unique_ptr<mock::DispSync> mDispSync;
std::unique_ptr<DispSyncSource> mDispSyncSource;
@@ -66,7 +66,7 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-void DispSyncSourceTest::onVSyncEvent(nsecs_t when) {
+void DispSyncSourceTest::onVSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) {
ALOGD("onVSyncEvent: %" PRId64, when);
mVSyncEventCallRecorder.recordCall(when);
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index cc11aa9..2a0e913 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -209,12 +209,11 @@
EXPECT_EQ(41, edid->manufactureWeek);
ASSERT_TRUE(edid->cea861Block);
ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
- ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock->physicalAddress);
auto physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
- EXPECT_EQ(2, physicalAddress->a);
- EXPECT_EQ(0, physicalAddress->b);
- EXPECT_EQ(0, physicalAddress->c);
- EXPECT_EQ(0, physicalAddress->d);
+ EXPECT_EQ(2, physicalAddress.a);
+ EXPECT_EQ(0, physicalAddress.b);
+ EXPECT_EQ(0, physicalAddress.c);
+ EXPECT_EQ(0, physicalAddress.d);
edid = parseEdid(getPanasonicTvEdid());
ASSERT_TRUE(edid);
@@ -227,12 +226,11 @@
EXPECT_EQ(0, edid->manufactureWeek);
ASSERT_TRUE(edid->cea861Block);
ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
- ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock->physicalAddress);
physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
- EXPECT_EQ(2, physicalAddress->a);
- EXPECT_EQ(0, physicalAddress->b);
- EXPECT_EQ(0, physicalAddress->c);
- EXPECT_EQ(0, physicalAddress->d);
+ EXPECT_EQ(2, physicalAddress.a);
+ EXPECT_EQ(0, physicalAddress.b);
+ EXPECT_EQ(0, physicalAddress.c);
+ EXPECT_EQ(0, physicalAddress.d);
edid = parseEdid(getHisenseTvEdid());
ASSERT_TRUE(edid);
@@ -245,12 +243,11 @@
EXPECT_EQ(18, edid->manufactureWeek);
ASSERT_TRUE(edid->cea861Block);
ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
- ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock->physicalAddress);
physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
- EXPECT_EQ(1, physicalAddress->a);
- EXPECT_EQ(2, physicalAddress->b);
- EXPECT_EQ(3, physicalAddress->c);
- EXPECT_EQ(4, physicalAddress->d);
+ EXPECT_EQ(1, physicalAddress.a);
+ EXPECT_EQ(2, physicalAddress.b);
+ EXPECT_EQ(3, physicalAddress.c);
+ EXPECT_EQ(4, physicalAddress.d);
edid = parseEdid(getCtlDisplayEdid());
ASSERT_TRUE(edid);
@@ -315,6 +312,7 @@
using ManufactureYear = DeviceProductInfo::ManufactureYear;
using ManufactureWeekAndYear = DeviceProductInfo::ManufactureWeekAndYear;
using ModelYear = DeviceProductInfo::ModelYear;
+ using RelativeAddress = DeviceProductInfo::RelativeAddress;
{
const auto displayIdInfo = parseDisplayIdentificationData(0, getInternalEdid());
@@ -326,6 +324,7 @@
EXPECT_STREQ("12610", info.productId.data());
ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate));
EXPECT_EQ(2011, std::get<ManufactureYear>(info.manufactureOrModelDate).year);
+ EXPECT_EQ(DeviceProductInfo::NO_RELATIVE_ADDRESS, info.relativeAddress);
}
{
const auto displayIdInfo = parseDisplayIdentificationData(0, getExternalEdid());
@@ -339,6 +338,7 @@
const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate);
EXPECT_EQ(2012, date.year);
EXPECT_EQ(2, date.week);
+ EXPECT_EQ(DeviceProductInfo::NO_RELATIVE_ADDRESS, info.relativeAddress);
}
{
const auto displayIdInfo = parseDisplayIdentificationData(0, getExternalEedid());
@@ -352,6 +352,7 @@
const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate);
EXPECT_EQ(2011, date.year);
EXPECT_EQ(41, date.week);
+ EXPECT_EQ((RelativeAddress{{2, 0, 0, 0}}), info.relativeAddress);
}
{
const auto displayIdInfo = parseDisplayIdentificationData(0, getPanasonicTvEdid());
@@ -364,6 +365,7 @@
ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate));
const auto& date = std::get<ManufactureYear>(info.manufactureOrModelDate);
EXPECT_EQ(2019, date.year);
+ EXPECT_EQ((RelativeAddress{{2, 0, 0, 0}}), info.relativeAddress);
}
{
const auto displayIdInfo = parseDisplayIdentificationData(0, getHisenseTvEdid());
@@ -377,6 +379,7 @@
const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate);
EXPECT_EQ(2019, date.year);
EXPECT_EQ(18, date.week);
+ EXPECT_EQ((RelativeAddress{{1, 2, 3, 4}}), info.relativeAddress);
}
{
const auto displayIdInfo = parseDisplayIdentificationData(0, getCtlDisplayEdid());
@@ -388,6 +391,7 @@
EXPECT_STREQ("9373", info.productId.data());
ASSERT_TRUE(std::holds_alternative<ModelYear>(info.manufactureOrModelDate));
EXPECT_EQ(2013, std::get<ModelYear>(info.manufactureOrModelDate).year);
+ EXPECT_EQ(DeviceProductInfo::NO_RELATIVE_ADDRESS, info.relativeAddress);
}
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index ea3d744..ce5f35c 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -55,6 +55,8 @@
namespace android {
namespace {
+namespace hal = android::hardware::graphics::composer::hal;
+
using testing::_;
using testing::AnyNumber;
using testing::DoAll;
@@ -65,13 +67,18 @@
using testing::SetArgPointee;
using testing::StrictMock;
-using android::Hwc2::ColorMode;
-using android::Hwc2::Error;
-using android::Hwc2::Hdr;
-using android::Hwc2::IComposer;
-using android::Hwc2::IComposerClient;
-using android::Hwc2::PerFrameMetadataKey;
-using android::Hwc2::RenderIntent;
+using hal::ColorMode;
+using hal::Connection;
+using hal::DisplayCapability;
+using hal::DisplayType;
+using hal::Error;
+using hal::Hdr;
+using hal::HWDisplayId;
+using hal::IComposer;
+using hal::IComposerClient;
+using hal::PerFrameMetadataKey;
+using hal::PowerMode;
+using hal::RenderIntent;
using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
@@ -82,7 +89,7 @@
constexpr int32_t DEFAULT_DPI = 320;
constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
-constexpr int HWC_POWER_MODE_LEET = 1337; // An out of range power mode value
+constexpr int POWER_MODE_LEET = 1337; // An out of range power mode value
/* ------------------------------------------------------------------------
* Boolean avoidance
@@ -120,7 +127,7 @@
// --------------------------------------------------------------------
// Postcondition helpers
- bool hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId);
+ bool hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId);
bool hasTransactionFlagSet(int flag);
bool hasDisplayDevice(sp<IBinder> displayToken);
sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
@@ -246,7 +253,7 @@
constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777};
constexpr int DEFAULT_DISPLAY_WIDTH = 1080;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1920;
- constexpr hwc2_display_t DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0;
+ constexpr HWDisplayId DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0;
// The DisplayDevice is required to have a framebuffer (behind the
// ANativeWindow interface) which uses the actual hardware display
@@ -285,7 +292,7 @@
return displayDevice;
}
-bool DisplayTransactionTest::hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId) {
+bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) {
return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1;
}
@@ -343,8 +350,8 @@
static std::optional<DisplayId> get() {
if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
return getFallbackDisplayId(static_cast<bool>(PhysicalDisplay::PRIMARY)
- ? HWC_DISPLAY_PRIMARY
- : HWC_DISPLAY_EXTERNAL);
+ ? LEGACY_DISPLAY_TYPE_PRIMARY
+ : LEGACY_DISPLAY_TYPE_EXTERNAL);
}
const auto info =
@@ -376,19 +383,19 @@
template <typename>
struct HwcDisplayIdGetter {
- static constexpr std::optional<hwc2_display_t> value;
+ static constexpr std::optional<HWDisplayId> value;
};
-constexpr hwc2_display_t HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
+constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
template <DisplayId::Type displayId>
struct HwcDisplayIdGetter<VirtualDisplayId<displayId>> {
- static constexpr std::optional<hwc2_display_t> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
+ static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
};
template <typename PhysicalDisplay>
struct HwcDisplayIdGetter<PhysicalDisplayId<PhysicalDisplay>> {
- static constexpr std::optional<hwc2_display_t> value = PhysicalDisplay::HWC_DISPLAY_ID;
+ static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
};
// DisplayIdType can be:
@@ -497,21 +504,20 @@
}
};
-template <hwc2_display_t hwcDisplayId, HWC2::DisplayType hwcDisplayType, typename DisplayVariant,
+template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant,
typename PhysicalDisplay = void>
struct HwcDisplayVariant {
// The display id supplied by the HWC
- static constexpr hwc2_display_t HWC_DISPLAY_ID = hwcDisplayId;
+ static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId;
// The HWC display type
- static constexpr HWC2::DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
+ static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
// The HWC active configuration id
static constexpr int HWC_ACTIVE_CONFIG_ID = 2001;
- static constexpr int INIT_POWER_MODE = HWC_POWER_MODE_NORMAL;
+ static constexpr PowerMode INIT_POWER_MODE = PowerMode::ON;
- static void injectPendingHotplugEvent(DisplayTransactionTest* test,
- HWC2::Connection connection) {
+ static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
test->mFlinger.mutablePendingHotplugEvents().emplace_back(
HotplugEvent{HWC_DISPLAY_ID, connection});
}
@@ -533,11 +539,9 @@
// Called by tests to inject a HWC display setup
static void injectHwcDisplay(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+ .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
Return(Error::NONE)));
- EXPECT_CALL(*test->mComposer,
- setPowerMode(HWC_DISPLAY_ID,
- static_cast<Hwc2::IComposerClient::PowerMode>(INIT_POWER_MODE)))
+ EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE))
.WillOnce(Return(Error::NONE));
injectHwcDisplayWithNoDefaultCapabilities(test);
}
@@ -568,10 +572,10 @@
: IComposerClient::DisplayConnectionType::EXTERNAL;
EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
- .WillOnce(
- DoAll(SetArgPointee<1>(CONNECTION_TYPE), Return(Hwc2::V2_4::Error::NONE)));
+ .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE), Return(hal::V2_4::Error::NONE)));
- EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
+ EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
+ .WillOnce(Return(hal::Error::NONE));
EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
.WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}),
Return(Error::NONE)));
@@ -626,7 +630,7 @@
struct PhysicalDisplayVariant
: DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height, critical, Async::FALSE,
Secure::TRUE, PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
- HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, HWC2::DisplayType::Physical,
+ HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height,
critical, Async::FALSE, Secure::TRUE,
PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
@@ -637,7 +641,7 @@
static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
static constexpr Primary PRIMARY = Primary::TRUE;
static constexpr uint8_t PORT = 255;
- static constexpr hwc2_display_t HWC_DISPLAY_ID = 1001;
+ static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
};
@@ -647,7 +651,7 @@
static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
static constexpr Primary PRIMARY = Primary::FALSE;
static constexpr uint8_t PORT = 254;
- static constexpr hwc2_display_t HWC_DISPLAY_ID = 1002;
+ static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
};
@@ -655,7 +659,7 @@
struct TertiaryDisplay {
static constexpr Primary PRIMARY = Primary::FALSE;
static constexpr uint8_t PORT = 253;
- static constexpr hwc2_display_t HWC_DISPLAY_ID = 1003;
+ static constexpr HWDisplayId HWC_DISPLAY_ID = 1003;
static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
};
@@ -716,7 +720,7 @@
: DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, secure,
Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
HwcDisplayVariant<
- HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, HWC2::DisplayType::Virtual,
+ HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE,
secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
using Base = DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE,
@@ -1046,8 +1050,8 @@
TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) {
constexpr int currentSequenceId = 123;
- constexpr hwc2_display_t hwcDisplayId1 = 456;
- constexpr hwc2_display_t hwcDisplayId2 = 654;
+ constexpr HWDisplayId hwcDisplayId1 = 456;
+ constexpr HWDisplayId hwcDisplayId2 = 654;
// --------------------------------------------------------------------
// Preconditions
@@ -1070,8 +1074,8 @@
// Invocation
// Simulate two hotplug events (a connect and a disconnect)
- mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, HWC2::Connection::Connected);
- mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, HWC2::Connection::Disconnected);
+ mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, Connection::CONNECTED);
+ mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, Connection::DISCONNECTED);
// --------------------------------------------------------------------
// Postconditions
@@ -1083,15 +1087,15 @@
const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
ASSERT_EQ(2u, pendingEvents.size());
EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
- EXPECT_EQ(HWC2::Connection::Connected, pendingEvents[0].connection);
+ EXPECT_EQ(Connection::CONNECTED, pendingEvents[0].connection);
EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
- EXPECT_EQ(HWC2::Connection::Disconnected, pendingEvents[1].connection);
+ EXPECT_EQ(Connection::DISCONNECTED, pendingEvents[1].connection);
}
TEST_F(DisplayTransactionTest, hotplugDiscardsUnexpectedEvents) {
constexpr int currentSequenceId = 123;
constexpr int otherSequenceId = 321;
- constexpr hwc2_display_t displayId = 456;
+ constexpr HWDisplayId displayId = 456;
// --------------------------------------------------------------------
// Preconditions
@@ -1113,7 +1117,7 @@
// Invocation
// Call with an unexpected sequence id
- mFlinger.onHotplugReceived(otherSequenceId, displayId, HWC2::Connection::Invalid);
+ mFlinger.onHotplugReceived(otherSequenceId, displayId, Connection::INVALID);
// --------------------------------------------------------------------
// Postconditions
@@ -1127,7 +1131,7 @@
TEST_F(DisplayTransactionTest, hotplugProcessesEnqueuedEventsIfCalledOnMainThread) {
constexpr int currentSequenceId = 123;
- constexpr hwc2_display_t displayId1 = 456;
+ constexpr HWDisplayId displayId1 = 456;
// --------------------------------------------------------------------
// Note:
@@ -1161,7 +1165,7 @@
// Simulate a disconnect on a display id that is not connected. This should
// be enqueued by onHotplugReceived(), and dequeued by
// processDisplayHotplugEventsLocked(), but then ignored as invalid.
- mFlinger.onHotplugReceived(currentSequenceId, displayId1, HWC2::Connection::Disconnected);
+ mFlinger.onHotplugReceived(currentSequenceId, displayId1, Connection::DISCONNECTED);
// --------------------------------------------------------------------
// Postconditions
@@ -1731,7 +1735,8 @@
ui::DisplayPrimaries primaries;
populateDummyDisplayNativePrimaries(primaries);
- EXPECT_EQ(BAD_VALUE, mFlinger.getDisplayNativePrimaries(notInternalDisplayToken, primaries));
+ EXPECT_EQ(NAME_NOT_FOUND,
+ mFlinger.getDisplayNativePrimaries(notInternalDisplayToken, primaries));
// Check primaries argument wasn't modified in case of failure
checkDummyDisplayNativePrimaries(primaries);
@@ -2009,7 +2014,7 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Connected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
// --------------------------------------------------------------------
// Call Expectations
@@ -2045,7 +2050,7 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Connected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
// --------------------------------------------------------------------
// Invocation
@@ -2067,7 +2072,7 @@
setupCommonPreconditions<Case>();
// A hotplug disconnect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Disconnected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
// The display is already completely set up.
Case::Display::injectHwcDisplay(this);
@@ -2165,9 +2170,9 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Connected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
// A hotplug disconnect event is also enqueued for the same display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Disconnected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
// --------------------------------------------------------------------
// Call Expectations
@@ -2213,9 +2218,9 @@
existing.inject();
// A hotplug disconnect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Disconnected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
// A hotplug connect event is also enqueued for the same display
- Case::Display::injectPendingHotplugEvent(this, HWC2::Connection::Connected);
+ Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
// --------------------------------------------------------------------
// Call Expectations
@@ -3092,7 +3097,7 @@
// processing.
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+ EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
// --------------------------------------------------------------------
// Invocation
@@ -3120,10 +3125,10 @@
EXPECT_EQ(0u, primaryDisplayState.width);
EXPECT_EQ(0u, primaryDisplayState.height);
- // The display should be set to HWC_POWER_MODE_NORMAL
+ // The display should be set to PowerMode::ON
ASSERT_TRUE(hasDisplayDevice(primaryDisplay.token()));
auto displayDevice = primaryDisplay.mutableDisplayDevice();
- EXPECT_EQ(HWC_POWER_MODE_NORMAL, displayDevice->getPowerMode());
+ EXPECT_EQ(PowerMode::ON, displayDevice->getPowerMode());
// The display refresh period should be set in the frame tracker.
FrameStats stats;
@@ -3155,8 +3160,8 @@
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getDisplayCapabilities(Display::HWC_DISPLAY_ID, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>(
- {Hwc2::DisplayCapability::DOZE})),
+ .WillOnce(DoAll(SetArgPointee<1>(
+ std::vector<DisplayCapability>({DisplayCapability::DOZE})),
Return(Error::NONE)));
}
};
@@ -3172,7 +3177,7 @@
static void setupComposerCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mComposer, getDisplayCapabilities(Display::HWC_DISPLAY_ID, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::DisplayCapability>({})),
+ .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
Return(Error::NONE)));
}
};
@@ -3246,7 +3251,7 @@
// selected subset which provides complete test coverage of the implementation.
// --------------------------------------------------------------------
-template <int initialPowerMode, int targetPowerMode>
+template <PowerMode initialPowerMode, PowerMode targetPowerMode>
struct TransitionVariantCommon {
static constexpr auto INITIAL_POWER_MODE = initialPowerMode;
static constexpr auto TARGET_POWER_MODE = targetPowerMode;
@@ -3254,8 +3259,7 @@
static void verifyPostconditions(DisplayTransactionTest*) {}
};
-struct TransitionOffToOnVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_OFF, HWC_POWER_MODE_NORMAL> {
+struct TransitionOffToOnVariant : public TransitionVariantCommon<PowerMode::OFF, PowerMode::ON> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
@@ -3271,7 +3275,7 @@
};
struct TransitionOffToDozeSuspendVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_OFF, HWC_POWER_MODE_DOZE_SUSPEND> {
+ : public TransitionVariantCommon<PowerMode::OFF, PowerMode::DOZE_SUSPEND> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
@@ -3285,8 +3289,7 @@
}
};
-struct TransitionOnToOffVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_NORMAL, HWC_POWER_MODE_OFF> {
+struct TransitionOnToOffVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::OFF> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
@@ -3300,7 +3303,7 @@
};
struct TransitionDozeSuspendToOffVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_DOZE_SUSPEND, HWC_POWER_MODE_OFF> {
+ : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
@@ -3312,8 +3315,7 @@
}
};
-struct TransitionOnToDozeVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_NORMAL, HWC_POWER_MODE_DOZE> {
+struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
@@ -3322,7 +3324,7 @@
};
struct TransitionDozeSuspendToDozeVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_DOZE_SUSPEND, HWC_POWER_MODE_DOZE> {
+ : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::DOZE> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
@@ -3331,8 +3333,7 @@
}
};
-struct TransitionDozeToOnVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_DOZE, HWC_POWER_MODE_NORMAL> {
+struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
@@ -3341,7 +3342,7 @@
};
struct TransitionDozeSuspendToOnVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_DOZE_SUSPEND, HWC_POWER_MODE_NORMAL> {
+ : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::ON> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
@@ -3351,7 +3352,7 @@
};
struct TransitionOnToDozeSuspendVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_NORMAL, HWC_POWER_MODE_DOZE_SUSPEND> {
+ : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE_SUSPEND> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
@@ -3361,7 +3362,7 @@
};
struct TransitionOnToUnknownVariant
- : public TransitionVariantCommon<HWC_POWER_MODE_NORMAL, HWC_POWER_MODE_LEET> {
+ : public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> {
template <typename Case>
static void setupCallExpectations(DisplayTransactionTest* test) {
Case::EventThread::setupEventAndEventControlThreadNoCallExpectations(test);
@@ -3386,7 +3387,7 @@
using DispSync = DispSyncVariant;
using Transition = TransitionVariant;
- static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, int mode) {
+ static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, PowerMode mode) {
Display::injectHwcDisplayWithNoDefaultCapabilities(test);
auto display = Display::makeFakeExistingDisplayInjector(test);
display.inject();
@@ -3402,13 +3403,14 @@
EXPECT_CALL(*test->mMessageQueue, invalidate()).Times(1);
}
- static void setupSurfaceInterceptorCallExpectations(DisplayTransactionTest* test, int mode) {
+ static void setupSurfaceInterceptorCallExpectations(DisplayTransactionTest* test,
+ PowerMode mode) {
EXPECT_CALL(*test->mSurfaceInterceptor, isEnabled()).WillOnce(Return(true));
- EXPECT_CALL(*test->mSurfaceInterceptor, savePowerModeUpdate(_, mode)).Times(1);
+ EXPECT_CALL(*test->mSurfaceInterceptor, savePowerModeUpdate(_, static_cast<int32_t>(mode)))
+ .Times(1);
}
- static void setupComposerCallExpectations(DisplayTransactionTest* test,
- IComposerClient::PowerMode mode) {
+ static void setupComposerCallExpectations(DisplayTransactionTest* test, PowerMode mode) {
// Any calls to get the active config will return a default value.
EXPECT_CALL(*test->mComposer, getActiveConfig(Display::HWC_DISPLAY_ID, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(Display::HWC_ACTIVE_CONFIG_ID),
@@ -3450,14 +3452,14 @@
void transitionDisplayCommon();
};
-template <int PowerMode>
+template <PowerMode PowerMode>
struct PowerModeInitialVSyncEnabled : public std::false_type {};
template <>
-struct PowerModeInitialVSyncEnabled<HWC_POWER_MODE_NORMAL> : public std::true_type {};
+struct PowerModeInitialVSyncEnabled<PowerMode::ON> : public std::true_type {};
template <>
-struct PowerModeInitialVSyncEnabled<HWC_POWER_MODE_DOZE> : public std::true_type {};
+struct PowerModeInitialVSyncEnabled<PowerMode::DOZE> : public std::true_type {};
template <typename Case>
void SetPowerModeInternalTest::transitionDisplayCommon() {
@@ -3500,18 +3502,18 @@
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.inject();
- // The display is already set to HWC_POWER_MODE_NORMAL
- display.mutableDisplayDevice()->setPowerMode(HWC_POWER_MODE_NORMAL);
+ // The display is already set to PowerMode::ON
+ display.mutableDisplayDevice()->setPowerMode(PowerMode::ON);
// --------------------------------------------------------------------
// Invocation
- mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_NORMAL);
+ mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), PowerMode::ON);
// --------------------------------------------------------------------
// Postconditions
- EXPECT_EQ(HWC_POWER_MODE_NORMAL, display.mutableDisplayDevice()->getPowerMode());
+ EXPECT_EQ(PowerMode::ON, display.mutableDisplayDevice()->getPowerMode());
}
TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay) {
@@ -3530,18 +3532,18 @@
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.inject();
- // The display is set to HWC_POWER_MODE_NORMAL
- getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_NORMAL);
+ // The display is set to PowerMode::ON
+ getDisplayDevice(display.token())->setPowerMode(PowerMode::ON);
// --------------------------------------------------------------------
// Invocation
- mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_OFF);
+ mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), PowerMode::OFF);
// --------------------------------------------------------------------
// Postconditions
- EXPECT_EQ(HWC_POWER_MODE_NORMAL, display.mutableDisplayDevice()->getPowerMode());
+ EXPECT_EQ(PowerMode::ON, display.mutableDisplayDevice()->getPowerMode());
}
TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToOnPrimaryDisplay) {
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index ba5c0c2..b90b566 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -258,14 +258,14 @@
// Use the received callback to signal a first vsync event.
// The interceptor should receive the event, as well as the connection.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
expectVsyncEventReceivedByConnection(123, 1u);
// Use the received callback to signal a second vsync event.
// The interceptor should receive the event, but the the connection should
// not as it was only interested in the first.
- mCallback->onVSyncEvent(456);
+ mCallback->onVSyncEvent(456, 123);
expectInterceptCallReceived(456);
EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
@@ -299,7 +299,7 @@
// Send a vsync event. EventThread should then make a call to the
// interceptor, and the second connection. The first connection should not
// get the event.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value());
expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123,
@@ -314,17 +314,17 @@
// Send a vsync event. EventThread should then make a call to the
// interceptor, and the connection.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
expectVsyncEventReceivedByConnection(123, 1u);
// A second event should go to the same places.
- mCallback->onVSyncEvent(456);
+ mCallback->onVSyncEvent(456, 123);
expectInterceptCallReceived(456);
expectVsyncEventReceivedByConnection(456, 2u);
// A third event should go to the same places.
- mCallback->onVSyncEvent(789);
+ mCallback->onVSyncEvent(789, 777);
expectInterceptCallReceived(789);
expectVsyncEventReceivedByConnection(789, 3u);
}
@@ -336,22 +336,22 @@
expectVSyncSetEnabledCallReceived(true);
// The first event will be seen by the interceptor, and not the connection.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
// The second event will be seen by the interceptor and the connection.
- mCallback->onVSyncEvent(456);
+ mCallback->onVSyncEvent(456, 123);
expectInterceptCallReceived(456);
expectVsyncEventReceivedByConnection(456, 2u);
// The third event will be seen by the interceptor, and not the connection.
- mCallback->onVSyncEvent(789);
+ mCallback->onVSyncEvent(789, 777);
expectInterceptCallReceived(789);
EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
// The fourth event will be seen by the interceptor and the connection.
- mCallback->onVSyncEvent(101112);
+ mCallback->onVSyncEvent(101112, 7847);
expectInterceptCallReceived(101112);
expectVsyncEventReceivedByConnection(101112, 4u);
}
@@ -366,7 +366,7 @@
mConnection = nullptr;
// The first event will be seen by the interceptor, and not the connection.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
@@ -386,13 +386,13 @@
// The first event will be seen by the interceptor, and by the connection,
// which then returns an error.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
// A subsequent event will be seen by the interceptor and not by the
// connection.
- mCallback->onVSyncEvent(456);
+ mCallback->onVSyncEvent(456, 123);
expectInterceptCallReceived(456);
EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value());
@@ -420,7 +420,7 @@
// The first event will be seen by the interceptor, and by the connection,
// which then returns an error.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
expectVsyncEventReceivedByConnection("successConnection", secondConnectionEventRecorder, 123,
@@ -440,13 +440,13 @@
// The first event will be seen by the interceptor, and by the connection,
// which then returns an non-fatal error.
- mCallback->onVSyncEvent(123);
+ mCallback->onVSyncEvent(123, 456);
expectInterceptCallReceived(123);
expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
// A subsequent event will be seen by the interceptor, and by the connection,
// which still then returns an non-fatal error.
- mCallback->onVSyncEvent(456);
+ mCallback->onVSyncEvent(456, 123);
expectInterceptCallReceived(456);
expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u);
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index c6fe205..91b304c 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -36,6 +36,8 @@
namespace android {
namespace {
+namespace hal = android::hardware::graphics::composer::hal;
+
using ::testing::_;
using ::testing::DoAll;
using ::testing::ElementsAreArray;
@@ -47,15 +49,15 @@
~MockHWC2ComposerCallback() = default;
MOCK_METHOD3(onHotplugReceived,
- void(int32_t sequenceId, hwc2_display_t display, HWC2::Connection connection));
- MOCK_METHOD2(onRefreshReceived, void(int32_t sequenceId, hwc2_display_t display));
+ void(int32_t sequenceId, hal::HWDisplayId display, hal::Connection connection));
+ MOCK_METHOD2(onRefreshReceived, void(int32_t sequenceId, hal::HWDisplayId display));
MOCK_METHOD4(onVsyncReceived,
- void(int32_t sequenceId, hwc2_display_t display, int64_t timestamp,
- std::optional<hwc2_vsync_period_t> vsyncPeriod));
+ void(int32_t sequenceId, hal::HWDisplayId display, int64_t timestamp,
+ std::optional<hal::VsyncPeriodNanos> vsyncPeriod));
MOCK_METHOD3(onVsyncPeriodTimingChangedReceived,
- void(int32_t sequenceId, hwc2_display_t display,
- const hwc_vsync_period_change_timeline_t& updatedTimeline));
- MOCK_METHOD2(onSeamlessPossible, void(int32_t sequenceId, hwc2_display_t display));
+ void(int32_t sequenceId, hal::HWDisplayId display,
+ const hal::VsyncPeriodChangeTimeline& updatedTimeline));
+ MOCK_METHOD2(onSeamlessPossible, void(int32_t sequenceId, hal::HWDisplayId display));
};
struct HWComposerTest : public testing::Test {
@@ -73,14 +75,12 @@
constexpr bool kMetadata2Mandatory = true;
EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
- EXPECT_CALL(*mHal, getCapabilities())
- .WillOnce(Return(std::vector<Hwc2::IComposer::Capability>{}));
+ EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_))
- .WillOnce(DoAll(SetArgPointee<0>(
- std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey>{
- {kMetadata1Name, kMetadata1Mandatory},
- {kMetadata2Name, kMetadata2Mandatory},
- }),
+ .WillOnce(DoAll(SetArgPointee<0>(std::vector<hal::LayerGenericMetadataKey>{
+ {kMetadata1Name, kMetadata1Mandatory},
+ {kMetadata2Name, kMetadata2Mandatory},
+ }),
Return(hardware::graphics::composer::V2_4::Error::NONE)));
EXPECT_CALL(*mHal, registerCallback(_));
EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported()).WillOnce(Return(false));
@@ -98,8 +98,7 @@
TEST_F(HWComposerSetConfigurationTest, handlesUnsupportedCallToGetLayerGenericMetadataKeys) {
EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
- EXPECT_CALL(*mHal, getCapabilities())
- .WillOnce(Return(std::vector<Hwc2::IComposer::Capability>{}));
+ EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_))
.WillOnce(Return(hardware::graphics::composer::V2_4::Error::UNSUPPORTED));
EXPECT_CALL(*mHal, registerCallback(_));
@@ -113,16 +112,16 @@
}
struct HWComposerLayerTest : public testing::Test {
- static constexpr hwc2_display_t kDisplayId = static_cast<hwc2_display_t>(1001);
- static constexpr hwc2_layer_t kLayerId = static_cast<hwc2_layer_t>(1002);
+ static constexpr hal::HWDisplayId kDisplayId = static_cast<hal::HWDisplayId>(1001);
+ static constexpr hal::HWLayerId kLayerId = static_cast<hal::HWLayerId>(1002);
- HWComposerLayerTest(const std::unordered_set<HWC2::Capability>& capabilities)
+ HWComposerLayerTest(const std::unordered_set<hal::Capability>& capabilities)
: mCapabilies(capabilities) {}
~HWComposerLayerTest() override { EXPECT_CALL(*mHal, destroyLayer(kDisplayId, kLayerId)); }
std::unique_ptr<Hwc2::mock::Composer> mHal{new StrictMock<Hwc2::mock::Composer>()};
- const std::unordered_set<HWC2::Capability> mCapabilies;
+ const std::unordered_set<hal::Capability> mCapabilies;
HWC2::impl::Layer mLayer{*mHal, mCapabilies, kDisplayId, kLayerId};
};
@@ -159,7 +158,7 @@
auto result = mLayer.setLayerGenericMetadata(kLayerGenericMetadata1Name,
kLayerGenericMetadata1Mandatory,
kLayerGenericMetadata1Value);
- EXPECT_EQ(HWC2::Error::None, result);
+ EXPECT_EQ(hal::Error::NONE, result);
EXPECT_CALL(*mHal,
setLayerGenericMetadata(kDisplayId, kLayerId, kLayerGenericMetadata2Name,
@@ -169,7 +168,7 @@
result = mLayer.setLayerGenericMetadata(kLayerGenericMetadata2Name,
kLayerGenericMetadata2Mandatory,
kLayerGenericMetadata2Value);
- EXPECT_EQ(HWC2::Error::Unsupported, result);
+ EXPECT_EQ(hal::Error::UNSUPPORTED, result);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 7557faf..71d17a9 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -63,14 +63,15 @@
auto createLayer() { return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger())); }
- RefreshRateConfigs mConfigs{{
- RefreshRateConfigs::InputConfig{HwcConfigIndexType(0),
- HwcConfigGroupType(0),
- LO_FPS_PERIOD},
- RefreshRateConfigs::InputConfig{HwcConfigIndexType(1),
- HwcConfigGroupType(0),
- HI_FPS_PERIOD},
- },
+ Hwc2::mock::Display mDisplay;
+ RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0)
+ .setVsyncPeriod(int32_t(LO_FPS_PERIOD))
+ .setConfigGroup(0)
+ .build(),
+ HWC2::Display::Config::Builder(mDisplay, 1)
+ .setVsyncPeriod(int32_t(HI_FPS_PERIOD))
+ .setConfigGroup(0)
+ .build()},
HwcConfigIndexType(0)};
TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, false)};
TestableSurfaceFlinger mFlinger;
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 8559a5e..431cf0f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -72,14 +72,15 @@
auto createLayer() { return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger())); }
- RefreshRateConfigs mConfigs{{
- RefreshRateConfigs::InputConfig{HwcConfigIndexType(0),
- HwcConfigGroupType(0),
- LO_FPS_PERIOD},
- RefreshRateConfigs::InputConfig{HwcConfigIndexType(1),
- HwcConfigGroupType(0),
- HI_FPS_PERIOD},
- },
+ Hwc2::mock::Display mDisplay;
+ RefreshRateConfigs mConfigs{{HWC2::Display::Config::Builder(mDisplay, 0)
+ .setVsyncPeriod(int32_t(LO_FPS_PERIOD))
+ .setConfigGroup(0)
+ .build(),
+ HWC2::Display::Config::Builder(mDisplay, 1)
+ .setVsyncPeriod(int32_t(HI_FPS_PERIOD))
+ .setConfigGroup(0)
+ .build()},
HwcConfigIndexType(0)};
TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, true)};
TestableSurfaceFlinger mFlinger;
@@ -269,12 +270,12 @@
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
- // layer became inactive
+ // layer became inactive, but the vote stays
setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_TRUE(history().summarize(time).empty());
- // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRateForLayerTree() returns a
- // value > 0
+ ASSERT_EQ(1, history().summarize(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote);
+ EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -302,12 +303,13 @@
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
- // layer became inactive
+ // layer became inactive, but the vote stays
setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_TRUE(history().summarize(time).empty());
- // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRateForLayerTree() returns a
- // value > 0
+ ASSERT_EQ(1, history().summarize(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+ history().summarize(time)[0].vote);
+ EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -510,5 +512,34 @@
EXPECT_EQ(1, frequentLayerCount(time));
}
+TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) {
+ auto explicitVisiblelayer = createLayer();
+ auto explicitInvisiblelayer = createLayer();
+
+ EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree())
+ .WillRepeatedly(Return(
+ Layer::FrameRate(60.0f, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+ EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree())
+ .WillRepeatedly(Return(
+ Layer::FrameRate(90.0f, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+ nsecs_t time = systemTime();
+
+ // Post a buffer to the layers to make them active
+ history().record(explicitVisiblelayer.get(), time, time);
+ history().record(explicitInvisiblelayer.get(), time, time);
+
+ EXPECT_EQ(2, layerCount());
+ ASSERT_EQ(1, history().summarize(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+ history().summarize(time)[0].vote);
+ EXPECT_FLOAT_EQ(60.0f, history().summarize(time)[0].desiredRefreshRate);
+ EXPECT_EQ(2, activeLayerCount());
+ EXPECT_EQ(2, frequentLayerCount(time));
+}
+
} // namespace
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp
index ce5993a..0b74682 100644
--- a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp
@@ -145,7 +145,9 @@
class TestablePhaseOffsets : public impl::PhaseOffsets {
public:
- TestablePhaseOffsets() : impl::PhaseOffsets({60.0f, 90.0f}, 60.0f, 10'000'000) {}
+ TestablePhaseOffsets()
+ : impl::PhaseOffsets({60.0f, 90.0f}, 60.0f, 1'000'000, 1'000'000, {}, {}, {}, {},
+ 10'000'000) {}
};
class PhaseOffsetsTest : public testing::Test {
diff --git a/services/surfaceflinger/tests/unittests/PromiseTest.cpp b/services/surfaceflinger/tests/unittests/PromiseTest.cpp
new file mode 100644
index 0000000..e4dc1fe
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/PromiseTest.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2020 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 <algorithm>
+#include <future>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "Promise.h"
+
+namespace android {
+namespace {
+
+using Bytes = std::vector<uint8_t>;
+
+Bytes decrement(Bytes bytes) {
+ std::transform(bytes.begin(), bytes.end(), bytes.begin(), [](auto b) { return b - 1; });
+ return bytes;
+}
+
+} // namespace
+
+TEST(PromiseTest, yield) {
+ EXPECT_EQ(42, promise::yield(42).get());
+
+ auto ptr = std::make_unique<char>('!');
+ auto future = promise::yield(std::move(ptr));
+ EXPECT_EQ('!', *future.get());
+}
+
+TEST(PromiseTest, chain) {
+ std::packaged_task<const char*()> fetchString([] { return "ifmmp-"; });
+
+ std::packaged_task<Bytes(std::string)> appendString([](std::string str) {
+ str += "!xpsme";
+ return Bytes{str.begin(), str.end()};
+ });
+
+ std::packaged_task<std::future<Bytes>(Bytes)> decrementBytes(
+ [](Bytes bytes) { return promise::defer(decrement, std::move(bytes)); });
+
+ auto fetch = fetchString.get_future();
+ std::thread fetchThread(std::move(fetchString));
+
+ std::thread appendThread, decrementThread;
+
+ EXPECT_EQ("hello, world",
+ promise::chain(std::move(fetch))
+ .then([](const char* str) { return std::string(str); })
+ .then([&](std::string str) {
+ auto append = appendString.get_future();
+ appendThread = std::thread(std::move(appendString), std::move(str));
+ return append;
+ })
+ .then([&](Bytes bytes) {
+ auto decrement = decrementBytes.get_future();
+ decrementThread = std::thread(std::move(decrementBytes),
+ std::move(bytes));
+ return decrement;
+ })
+ .then([](std::future<Bytes> bytes) { return bytes; })
+ .then([](const Bytes& bytes) {
+ return std::string(bytes.begin(), bytes.end());
+ })
+ .get());
+
+ fetchThread.join();
+ appendThread.join();
+ decrementThread.join();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index ce41291..2b168b2 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -24,6 +24,7 @@
#include "../../Scheduler/RefreshRateConfigs.h"
#include "DisplayHardware/HWC2.h"
#include "Scheduler/RefreshRateConfigs.h"
+#include "mock/DisplayHardware/MockDisplay.h"
using namespace std::chrono_literals;
using testing::_;
@@ -31,30 +32,103 @@
namespace android {
namespace scheduler {
+namespace hal = android::hardware::graphics::composer::hal;
+
using RefreshRate = RefreshRateConfigs::RefreshRate;
using LayerVoteType = RefreshRateConfigs::LayerVoteType;
using LayerRequirement = RefreshRateConfigs::LayerRequirement;
class RefreshRateConfigsTest : public testing::Test {
protected:
- static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0);
- static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(1);
- static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(2);
- static inline const HwcConfigIndexType HWC_CONFIG_ID_120 = HwcConfigIndexType(3);
- static inline const HwcConfigIndexType HWC_CONFIG_ID_30 = HwcConfigIndexType(4);
- static inline const HwcConfigGroupType HWC_GROUP_ID_0 = HwcConfigGroupType(0);
- static inline const HwcConfigGroupType HWC_GROUP_ID_1 = HwcConfigGroupType(1);
- static constexpr auto VSYNC_30 = static_cast<int64_t>(1e9f / 30);
- static constexpr auto VSYNC_60 = static_cast<int64_t>(1e9f / 60);
- static constexpr auto VSYNC_72 = static_cast<int64_t>(1e9f / 72);
- static constexpr auto VSYNC_90 = static_cast<int64_t>(1e9f / 90);
- static constexpr auto VSYNC_120 = static_cast<int64_t>(1e9f / 120);
- static constexpr int64_t VSYNC_60_POINT_4 = 16666665;
-
RefreshRateConfigsTest();
~RefreshRateConfigsTest();
+
+ // Test config IDs
+ static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0);
+ static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1);
+ static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(2);
+ static inline const HwcConfigIndexType HWC_CONFIG_ID_120 = HwcConfigIndexType(3);
+ static inline const HwcConfigIndexType HWC_CONFIG_ID_30 = HwcConfigIndexType(4);
+
+ // Test configs
+ std::shared_ptr<const HWC2::Display::Config> mConfig60 =
+ createConfig(HWC_CONFIG_ID_60, 0, static_cast<int64_t>(1e9f / 60));
+ std::shared_ptr<const HWC2::Display::Config> mConfig90 =
+ createConfig(HWC_CONFIG_ID_90, 0, static_cast<int64_t>(1e9f / 90));
+ std::shared_ptr<const HWC2::Display::Config> mConfig90DifferentGroup =
+ createConfig(HWC_CONFIG_ID_90, 1, static_cast<int64_t>(1e9f / 90));
+ std::shared_ptr<const HWC2::Display::Config> mConfig90DifferentResolution =
+ createConfig(HWC_CONFIG_ID_90, 0, static_cast<int64_t>(1e9f / 90), 111, 222);
+ std::shared_ptr<const HWC2::Display::Config> mConfig72 =
+ createConfig(HWC_CONFIG_ID_72, 0, static_cast<int64_t>(1e9f / 72));
+ std::shared_ptr<const HWC2::Display::Config> mConfig72DifferentGroup =
+ createConfig(HWC_CONFIG_ID_72, 1, static_cast<int64_t>(1e9f / 72));
+ std::shared_ptr<const HWC2::Display::Config> mConfig120 =
+ createConfig(HWC_CONFIG_ID_120, 0, static_cast<int64_t>(1e9f / 120));
+ std::shared_ptr<const HWC2::Display::Config> mConfig120DifferentGroup =
+ createConfig(HWC_CONFIG_ID_120, 1, static_cast<int64_t>(1e9f / 120));
+ std::shared_ptr<const HWC2::Display::Config> mConfig30 =
+ createConfig(HWC_CONFIG_ID_30, 0, static_cast<int64_t>(1e9f / 30));
+
+ // Test device configurations
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m60OnlyConfigDevice = {mConfig60};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m60_90Device = {mConfig60, mConfig90};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m60_90DeviceWithDifferentGroups =
+ {mConfig60, mConfig90DifferentGroup};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m60_90DeviceWithDifferentResolutions =
+ {mConfig60, mConfig90DifferentResolution};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m60_72_90Device = {mConfig60,
+ mConfig90,
+ mConfig72};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m60_90_72_120Device = {mConfig60,
+ mConfig90,
+ mConfig72,
+ mConfig120};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m30_60_72_90_120Device = {mConfig60,
+ mConfig90,
+ mConfig72,
+ mConfig120,
+ mConfig30};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m30_60Device =
+ {mConfig60, mConfig90DifferentGroup, mConfig72DifferentGroup, mConfig120DifferentGroup,
+ mConfig30};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m30_60_72_90Device =
+ {mConfig60, mConfig90, mConfig72, mConfig120DifferentGroup, mConfig30};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> m30_60_90Device =
+ {mConfig60, mConfig90, mConfig72DifferentGroup, mConfig120DifferentGroup, mConfig30};
+
+ // Expected RefreshRate objects
+ RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, "60fps", 60,
+ RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60,
+ createConfig(HWC_CONFIG_ID_60, 0, 16666665), "60fps", 60,
+ RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, "90fps", 90,
+ RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup,
+ "90fps", 90, RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpected90DifferentResolutionConfig = {HWC_CONFIG_ID_90,
+ mConfig90DifferentResolution, "90fps", 90,
+ RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, "72fps", 72,
+ RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, "30fps", 30,
+ RefreshRate::ConstructorTag(0)};
+ RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, "120fps", 120,
+ RefreshRate::ConstructorTag(0)};
+
+ Hwc2::mock::Display mDisplay;
+
+private:
+ std::shared_ptr<const HWC2::Display::Config> createConfig(HwcConfigIndexType configId,
+ int32_t configGroup,
+ int64_t vsyncPeriod,
+ int32_t hight = -1,
+ int32_t width = -1);
};
+using Builder = HWC2::Display::Config::Builder;
+
RefreshRateConfigsTest::RefreshRateConfigsTest() {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
@@ -67,41 +141,45 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
+std::shared_ptr<const HWC2::Display::Config> RefreshRateConfigsTest::createConfig(
+ HwcConfigIndexType configId, int32_t configGroup, int64_t vsyncPeriod, int32_t hight,
+ int32_t width) {
+ return HWC2::Display::Config::Builder(mDisplay, hal::HWConfigId(configId.value()))
+ .setVsyncPeriod(int32_t(vsyncPeriod))
+ .setConfigGroup(configGroup)
+ .setHeight(hight)
+ .setWidth(width)
+ .build();
+}
+
namespace {
/* ------------------------------------------------------------------------
* Test cases
*/
TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingSupported) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60OnlyConfigDevice,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
}
TEST_F(RefreshRateConfigsTest, invalidPolicy) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
- ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), 60, 60}), 0);
- ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 20, 40}), 0);
+ std::make_unique<RefreshRateConfigs>(m60OnlyConfigDevice,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+ ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), {60, 60}}), 0);
+ ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {20, 40}}), 0);
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
const auto& minRate = refreshRateConfigs->getMinRefreshRate();
const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
- RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- ASSERT_EQ(expectedDefaultConfig, minRate);
- RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps",
- 90};
- ASSERT_EQ(expectedPerformanceConfig, performanceRate);
+ ASSERT_EQ(mExpected60Config, minRate);
+ ASSERT_EQ(mExpected90Config, performanceRate);
const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy();
const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy();
@@ -110,411 +188,390 @@
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differentGroups) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentGroups,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
- RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- ASSERT_EQ(expectedDefaultConfig, minRate);
- ASSERT_EQ(expectedDefaultConfig, minRate60);
- ASSERT_EQ(expectedDefaultConfig, performanceRate60);
+ ASSERT_EQ(mExpected60Config, minRate);
+ ASSERT_EQ(mExpected60Config, minRate60);
+ ASSERT_EQ(mExpected60Config, performanceRate60);
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 60, 90}), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0);
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
- RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps",
- 90};
- ASSERT_EQ(expectedPerformanceConfig, performanceRate);
- ASSERT_EQ(expectedPerformanceConfig, minRate90);
- ASSERT_EQ(expectedPerformanceConfig, performanceRate90);
+ ASSERT_EQ(mExpected90DifferentGroupConfig, performanceRate);
+ ASSERT_EQ(mExpected90DifferentGroupConfig, minRate90);
+ ASSERT_EQ(mExpected90DifferentGroupConfig, performanceRate90);
+}
+
+TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differentResolutions) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentResolutions,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate();
+ const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+
+ ASSERT_EQ(mExpected60Config, minRate);
+ ASSERT_EQ(mExpected60Config, minRate60);
+ ASSERT_EQ(mExpected60Config, performanceRate60);
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0);
+ refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+
+ const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy();
+ const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
+
+ ASSERT_EQ(mExpected90DifferentResolutionConfig, performanceRate);
+ ASSERT_EQ(mExpected90DifferentResolutionConfig, minRate90);
+ ASSERT_EQ(mExpected90DifferentResolutionConfig, performanceRate90);
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy();
auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy();
- RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- ASSERT_EQ(expectedDefaultConfig, minRate);
- RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps",
- 90};
- ASSERT_EQ(expectedPerformanceConfig, performanceRate);
+ ASSERT_EQ(mExpected60Config, minRate);
+ ASSERT_EQ(mExpected90Config, performanceRate);
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0);
auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy();
auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy();
- ASSERT_EQ(expectedDefaultConfig, minRate60);
- ASSERT_EQ(expectedDefaultConfig, performanceRate60);
+ ASSERT_EQ(mExpected60Config, minRate60);
+ ASSERT_EQ(mExpected60Config, performanceRate60);
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
{
auto& current = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_EQ(current.configId, HWC_CONFIG_ID_60);
+ EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_60);
}
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
{
auto& current = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_EQ(current.configId, HWC_CONFIG_ID_90);
+ EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90);
}
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0);
{
auto& current = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_EQ(current.configId, HWC_CONFIG_ID_90);
+ EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90);
}
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
const auto makeLayerRequirements = [](float refreshRate) -> std::vector<LayerRequirement> {
return {{"testLayer", LayerVoteType::Heuristic, refreshRate, 1.0f}};
};
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f)));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f)));
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0);
- EXPECT_EQ(expected60Config,
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0);
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f)));
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0);
- EXPECT_EQ(expected90Config,
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0);
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f)));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f)));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f)));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f)));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f)));
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0);
- EXPECT_EQ(expected90Config,
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0);
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f)));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f)));
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f)));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
- auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/
- HWC_CONFIG_ID_72);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 72};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_72_90Device, /*currentConfigId=*/
+ HWC_CONFIG_ID_72);
// If there are not layers, there is not content detection, so return the current
// refresh rate.
auto layers = std::vector<LayerRequirement>{};
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
- false, &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/
+ false, /*idle*/ false, &ignored));
// Current refresh rate can always be changed.
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60);
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
- false, &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/
+ false, /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.name = "";
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
- ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_72_90) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_72_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90_120) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
- {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
- {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
- RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120};
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -525,43 +582,32 @@
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_90_120_DifferentTypes) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
- {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
- {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 72};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
- RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120};
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -574,9 +620,9 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -584,9 +630,9 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -594,9 +640,9 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
- EXPECT_EQ(expected120Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected120Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -604,9 +650,9 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -614,9 +660,9 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -624,9 +670,9 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::Heuristic;
@@ -634,9 +680,9 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -644,9 +690,9 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.desiredRefreshRate = 24.0f;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -654,158 +700,137 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
+ std::make_unique<RefreshRateConfigs>(m30_60Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected30Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected30Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_30_60_72_90) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
- {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected30Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(expected30Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
- &ignored));
+ EXPECT_EQ(mExpected30Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
+ /*idle*/ false, &ignored));
lr.desiredRefreshRate = 24.0f;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
- EXPECT_EQ(expected72Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
- &ignored));
+ EXPECT_EQ(mExpected72Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_PriorityTest) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30},
- {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m30_60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -814,66 +839,60 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 15.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 30.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_24FpsVideo) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
@@ -882,22 +901,17 @@
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored);
- printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
- EXPECT_EQ(expected60Config, refreshRate);
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored);
+ printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str());
+ EXPECT_EQ(mExpected60Config, refreshRate);
}
}
TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explicit) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -908,25 +922,20 @@
lr1.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90.0f;
- EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(layers));
+ EXPECT_EQ(mExpected90Config, refreshRateConfigs->getRefreshRateForContent(layers));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(layers));
+ EXPECT_EQ(mExpected60Config, refreshRateConfigs->getRefreshRateForContent(layers));
}
-TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) {
+TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getBestRefreshRate_Explicit) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -937,48 +946,40 @@
lr1.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
TEST_F(RefreshRateConfigsTest, testInPolicy) {
- RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60_POINT_4, HWC_GROUP_ID_0,
- "60fps", 60};
- ASSERT_TRUE(expectedDefaultConfig.inPolicy(60.000004f, 60.000004f));
- ASSERT_TRUE(expectedDefaultConfig.inPolicy(59.0f, 60.1f));
- ASSERT_FALSE(expectedDefaultConfig.inPolicy(75.0f, 90.0f));
- ASSERT_FALSE(expectedDefaultConfig.inPolicy(60.0011f, 90.0f));
- ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0f, 59.998f));
+ ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(60.000004f, 60.000004f));
+ ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(59.0f, 60.1f));
+ ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(75.0f, 90.0f));
+ ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(60.0011f, 90.0f));
+ ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(50.0f, 59.998f));
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_75HzContent) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
@@ -987,23 +988,18 @@
for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
lr.desiredRefreshRate = fps;
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored);
- printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
- EXPECT_EQ(expected90Config, refreshRate);
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored);
+ printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str());
+ EXPECT_EQ(mExpected90Config, refreshRate);
}
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_Multiples) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -1016,9 +1012,9 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
@@ -1026,18 +1022,18 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
@@ -1045,30 +1041,25 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30.0f;
lr1.name = "30Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
- &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false,
+ /*idle*/ false, &ignored));
}
TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
-
- RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
- RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
LayerRequirement{.weight = 1.0f}};
@@ -1080,32 +1071,32 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected60Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored));
// The other layer starts to provide buffers
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1114,22 +1105,20 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
- refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored));
}
TEST_F(RefreshRateConfigsTest, touchConsidered) {
bool touchConsidered;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
- refreshRateConfigs->getRefreshRateForContentV2({}, false, &touchConsidered);
+ refreshRateConfigs->getBestRefreshRate({}, false, /*idle*/ false, &touchConsidered);
EXPECT_EQ(false, touchConsidered);
- refreshRateConfigs->getRefreshRateForContentV2({}, true, &touchConsidered);
+ refreshRateConfigs->getBestRefreshRate({}, true, /*idle*/ false, &touchConsidered);
EXPECT_EQ(true, touchConsidered);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
@@ -1141,45 +1130,44 @@
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Heuristic;
- lr2.name = "NoVote";
- refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ lr2.desiredRefreshRate = 60.0f;
+ lr2.name = "60Hz Heuristic";
+ refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
EXPECT_EQ(true, touchConsidered);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Heuristic;
- lr2.name = "NoVote";
- refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ lr2.desiredRefreshRate = 60.0f;
+ lr2.name = "60Hz Heuristic";
+ refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
EXPECT_EQ(false, touchConsidered);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60.0f;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Heuristic;
- lr2.name = "NoVote";
- refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ lr2.desiredRefreshRate = 60.0f;
+ lr2.name = "60Hz Heuristic";
+ refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
EXPECT_EQ(true, touchConsidered);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 60.0f;
- lr1.name = "60Hz ExplicitExactrMultiple";
+ lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Heuristic;
- lr2.name = "NoVote";
- refreshRateConfigs->getRefreshRateForContentV2(layers, true, &touchConsidered);
+ lr2.desiredRefreshRate = 60.0f;
+ lr2.name = "60Hz Heuristic";
+ refreshRateConfigs->getBestRefreshRate(layers, true, /*idle*/ false, &touchConsidered);
EXPECT_EQ(false, touchConsidered);
}
-TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_ExplicitDefault) {
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) {
bool ignored;
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90},
- {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}};
-
- auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/
- HWC_CONFIG_ID_60);
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90_72_120Device, /*currentConfigId=*/
+ HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& lr = layers[0];
@@ -1212,18 +1200,16 @@
lr.name = ss.str();
const auto& refreshRate =
- refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored);
- EXPECT_FLOAT_EQ(refreshRate.fps, test.second)
+ refreshRateConfigs->getBestRefreshRate(layers, false, /*idle*/ false, &ignored);
+ EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second)
<< "Expecting " << test.first << "fps => " << test.second << "Hz";
}
}
TEST_F(RefreshRateConfigsTest, groupSwitching) {
- std::vector<RefreshRateConfigs::InputConfig> configs{
- {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
- {HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}};
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60);
+ std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentGroups,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
auto& layer = layers[0];
@@ -1233,16 +1219,127 @@
bool touchConsidered;
ASSERT_EQ(HWC_CONFIG_ID_60,
- refreshRateConfigs->getRefreshRateForContentV2(layers, false, &touchConsidered)
- .configId);
+ refreshRateConfigs
+ ->getBestRefreshRate(layers, false, /*idle*/ false, &touchConsidered)
+ .getConfigId());
RefreshRateConfigs::Policy policy;
policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig;
policy.allowGroupSwitching = true;
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0);
ASSERT_EQ(HWC_CONFIG_ID_90,
- refreshRateConfigs->getRefreshRateForContentV2(layers, false, &touchConsidered)
- .configId);
+ refreshRateConfigs
+ ->getBestRefreshRate(layers, false, /*idle*/ false, &touchConsidered)
+ .getConfigId());
+}
+
+TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ layers[0].name = "Test layer";
+
+ // Return the config ID from calling getBestRefreshRate() for a single layer with the
+ // given voteType and fps.
+ auto getFrameRate = [&](LayerVoteType voteType, float fps,
+ bool touchActive = false) -> HwcConfigIndexType {
+ layers[0].vote = voteType;
+ layers[0].desiredRefreshRate = fps;
+ bool touchConsidered;
+ return refreshRateConfigs
+ ->getBestRefreshRate(layers, touchActive, /*idle*/ false, &touchConsidered)
+ .getConfigId();
+ };
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 90.f}}),
+ 0);
+ bool touchConsidered;
+ EXPECT_EQ(HWC_CONFIG_ID_60,
+ refreshRateConfigs
+ ->getBestRefreshRate({}, /*touchActive=*/false, /*idle*/ false,
+ &touchConsidered)
+ .getConfigId());
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f));
+
+ // Touch boost should be restricted to the primary range.
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f, /*touch=*/true));
+ // When we're higher than the primary range max due to a layer frame rate setting, touch boost
+ // shouldn't drag us back down to the primary range max.
+ EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/true));
+ EXPECT_EQ(HWC_CONFIG_ID_90,
+ getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/true));
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 60.f}}),
+ 0);
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitDefault, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f));
+}
+
+TEST_F(RefreshRateConfigsTest, idle) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ layers[0].name = "Test layer";
+
+ auto getIdleFrameRate = [&](LayerVoteType voteType, bool touchActive) -> HwcConfigIndexType {
+ layers[0].vote = voteType;
+ layers[0].desiredRefreshRate = 90.f;
+ bool touchConsidered;
+ return refreshRateConfigs
+ ->getBestRefreshRate(layers, touchActive, /*idle=*/true, &touchConsidered)
+ .getConfigId();
+ };
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_60, {60.f, 90.f}, {60.f, 90.f}}),
+ 0);
+
+ // Idle should be lower priority than touch boost.
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::NoVote, true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Min, true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Max, true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::Heuristic, true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::ExplicitDefault, true));
+ EXPECT_EQ(HWC_CONFIG_ID_90, getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, true));
+
+ // With no layers, idle should still be lower priority than touch boost.
+ bool touchConsidered;
+ EXPECT_EQ(HWC_CONFIG_ID_90,
+ refreshRateConfigs
+ ->getBestRefreshRate({}, /*touchActive=*/true, /*idle=*/true,
+ &touchConsidered)
+ .getConfigId());
+
+ // Idle should be higher precedence than other layer frame rate considerations.
+ refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::NoVote, false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Min, false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Max, false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Heuristic, false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::ExplicitDefault, false));
+ EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, false));
+
+ // Idle should be applied rather than the current config when there are no layers.
+ EXPECT_EQ(HWC_CONFIG_ID_60,
+ refreshRateConfigs
+ ->getBestRefreshRate({}, /*touchActive=*/false, /*idle=*/true,
+ &touchConsidered)
+ .getConfigId());
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index 18b1063..43b8e01 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -142,10 +142,10 @@
auto primaryDispSync = std::make_unique<mock::DispSync>();
- EXPECT_CALL(*primaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, computeNextRefresh(0, _)).WillRepeatedly(Return(0));
EXPECT_CALL(*primaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
- EXPECT_CALL(*primaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(primaryDispSync),
std::make_unique<mock::EventControlThread>(), std::move(eventThread),
std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 18d6bd2..de66f8f 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -26,9 +26,11 @@
#include <thread>
#include "Scheduler/RefreshRateStats.h"
+#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockTimeStats.h"
using namespace std::chrono_literals;
+using android::hardware::graphics::composer::hal::PowerMode;
using testing::_;
using testing::AtLeast;
@@ -39,25 +41,29 @@
protected:
static inline const auto CONFIG_ID_0 = HwcConfigIndexType(0);
static inline const auto CONFIG_ID_1 = HwcConfigIndexType(1);
- static inline const auto CONFIG_GROUP_0 = HwcConfigGroupType(0);
+ static inline const auto CONFIG_GROUP_0 = 0;
static constexpr int64_t VSYNC_90 = 11111111;
static constexpr int64_t VSYNC_60 = 16666667;
RefreshRateStatsTest();
~RefreshRateStatsTest();
- void init(const std::vector<RefreshRateConfigs::InputConfig>& configs) {
+ void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
mRefreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfig=*/CONFIG_ID_0);
- mRefreshRateStats =
- std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
- /*currentConfigId=*/CONFIG_ID_0,
- /*currentPowerMode=*/HWC_POWER_MODE_OFF);
+ mRefreshRateStats = std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
+ /*currentConfigId=*/CONFIG_ID_0,
+ /*currentPowerMode=*/PowerMode::OFF);
}
+ Hwc2::mock::Display mDisplay;
mock::TimeStats mTimeStats;
std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
std::unique_ptr<RefreshRateStats> mRefreshRateStats;
+
+ std::shared_ptr<const HWC2::Display::Config> createConfig(HwcConfigIndexType configId,
+ int32_t configGroup,
+ int64_t vsyncPeriod);
};
RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -72,12 +78,20 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
+std::shared_ptr<const HWC2::Display::Config> RefreshRateStatsTest::createConfig(
+ HwcConfigIndexType configId, int32_t configGroup, int64_t vsyncPeriod) {
+ return HWC2::Display::Config::Builder(mDisplay, configId.value())
+ .setVsyncPeriod(int32_t(vsyncPeriod))
+ .setConfigGroup(configGroup)
+ .build();
+}
+
namespace {
/* ------------------------------------------------------------------------
* Test cases
*/
TEST_F(RefreshRateStatsTest, oneConfigTest) {
- init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}}});
+ init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
@@ -97,7 +111,7 @@
EXPECT_EQ(0u, times.count("90fps"));
mRefreshRateStats->setConfigMode(CONFIG_ID_0);
- mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mRefreshRateStats->setPowerMode(PowerMode::ON);
screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -105,7 +119,7 @@
ASSERT_EQ(1u, times.count("90fps"));
EXPECT_LT(0, times["90fps"]);
- mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ mRefreshRateStats->setPowerMode(PowerMode::DOZE);
int ninety = mRefreshRateStats->getTotalTimes()["90fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -116,14 +130,15 @@
screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
- // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
+ // Because the power mode is not PowerMode::ON, switching the config
// does not update refresh rates that come from the config.
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(ninety, times["90fps"]);
}
TEST_F(RefreshRateStatsTest, twoConfigsTest) {
- init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}, {CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60}}});
+ init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90),
+ createConfig(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
@@ -143,7 +158,7 @@
EXPECT_LT(screenOff, times["ScreenOff"]);
mRefreshRateStats->setConfigMode(CONFIG_ID_0);
- mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mRefreshRateStats->setPowerMode(PowerMode::ON);
screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
times = mRefreshRateStats->getTotalTimes();
@@ -177,9 +192,9 @@
EXPECT_EQ(ninety, times["90fps"]);
EXPECT_LT(sixty, times["60fps"]);
- // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
+ // Because the power mode is not PowerMode::ON, switching the config
// does not update refresh rates that come from the config.
- mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ mRefreshRateStats->setPowerMode(PowerMode::DOZE);
mRefreshRateStats->setConfigMode(CONFIG_ID_0);
sixty = mRefreshRateStats->getTotalTimes()["60fps"];
std::this_thread::sleep_for(std::chrono::milliseconds(2));
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 5db11ec..1aa7320 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -31,6 +31,7 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/RefreshRateConfigs.h"
#include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockEventThread.h"
using testing::_;
@@ -63,6 +64,7 @@
Scheduler::ConnectionHandle mConnectionHandle;
mock::EventThread* mEventThread;
sp<MockEventThreadConnection> mEventThreadConnection;
+ Hwc2::mock::Display mDisplay;
};
SchedulerTest::SchedulerTest() {
@@ -70,8 +72,11 @@
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
- std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{
- {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> configs{
+ HWC2::Display::Config::Builder(mDisplay, 0)
+ .setVsyncPeriod(int32_t(16666667))
+ .setConfigGroup(0)
+ .build()};
mRefreshRateConfigs = std::make_unique<
scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index b069085..0d6c799 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -178,10 +178,10 @@
auto primaryDispSync = std::make_unique<mock::DispSync>();
- EXPECT_CALL(*primaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, computeNextRefresh(0, _)).WillRepeatedly(Return(0));
EXPECT_CALL(*primaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
- EXPECT_CALL(*primaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0));
+ EXPECT_CALL(*primaryDispSync, expectedPresentTime(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(primaryDispSync),
std::make_unique<mock::EventControlThread>(), std::move(eventThread),
std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 058c5cc..1c067cb 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -39,6 +39,7 @@
#include "SurfaceFlingerDefaultFactory.h"
#include "SurfaceInterceptor.h"
#include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockDisplay.h"
namespace android {
@@ -56,6 +57,8 @@
} // namespace Hwc2
+namespace hal = android::hardware::graphics::composer::hal;
+
namespace surfaceflinger::test {
class Factory final : public surfaceflinger::Factory {
@@ -174,6 +177,8 @@
class TestableSurfaceFlinger {
public:
+ using HotplugEvent = SurfaceFlinger::HotplugEvent;
+
SurfaceFlinger* flinger() { return mFlinger.get(); }
TestableScheduler* scheduler() { return mScheduler; }
@@ -198,14 +203,18 @@
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
bool useContentDetectionV2 = false) {
- std::vector<scheduler::RefreshRateConfigs::InputConfig> configs{
- {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}};
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> configs{
+ HWC2::Display::Config::Builder(mDisplay, 0)
+ .setVsyncPeriod(int32_t(16666667))
+ .setConfigGroup(0)
+ .build()};
+
mFlinger->mRefreshRateConfigs = std::make_unique<
scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
mFlinger->mRefreshRateStats = std::make_unique<
scheduler::RefreshRateStats>(*mFlinger->mRefreshRateConfigs, *mFlinger->mTimeStats,
/*currentConfig=*/HwcConfigIndexType(0),
- /*powerMode=*/HWC_POWER_MODE_OFF);
+ /*powerMode=*/hal::PowerMode::OFF);
mFlinger->mPhaseConfiguration =
mFactory.createPhaseConfiguration(*mFlinger->mRefreshRateConfigs);
@@ -239,28 +248,32 @@
memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
}
- using HotplugEvent = SurfaceFlinger::HotplugEvent;
-
- auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mCurrentState; }
- auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; }
+ static auto& mutableLayerCurrentState(const sp<Layer>& layer) { return layer->mCurrentState; }
+ static auto& mutableLayerDrawingState(const sp<Layer>& layer) { return layer->mDrawingState; }
auto& mutableStateLock() { return mFlinger->mStateLock; }
- void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
+ static auto findOutputLayerForDisplay(const sp<Layer>& layer,
+ const sp<const DisplayDevice>& display) {
+ return layer->findOutputLayerForDisplay(display.get());
+ }
+
+ static void setLayerSidebandStream(const sp<Layer>& layer,
+ const sp<NativeHandle>& sidebandStream) {
layer->mDrawingState.sidebandStream = sidebandStream;
layer->mSidebandStream = sidebandStream;
layer->editCompositionState()->sidebandStream = sidebandStream;
}
- void setLayerCompositionType(sp<Layer> layer, HWC2::Composition type) {
- auto outputLayer = layer->findOutputLayerForDisplay(mFlinger->getDefaultDisplayDevice());
+ void setLayerCompositionType(const sp<Layer>& layer, hal::Composition type) {
+ auto outputLayer = findOutputLayerForDisplay(layer, mFlinger->getDefaultDisplayDevice());
LOG_ALWAYS_FATAL_IF(!outputLayer);
auto& state = outputLayer->editState();
LOG_ALWAYS_FATAL_IF(!outputLayer->getState().hwc);
- (*state.hwc).hwcCompositionType = static_cast<Hwc2::IComposerClient::Composition>(type);
- };
+ (*state.hwc).hwcCompositionType = type;
+ }
- void setLayerPotentialCursor(sp<Layer> layer, bool potentialCursor) {
+ static void setLayerPotentialCursor(const sp<Layer>& layer, bool potentialCursor) {
layer->mPotentialCursor = potentialCursor;
}
@@ -293,8 +306,8 @@
return mFlinger->handleTransactionLocked(transactionFlags);
}
- auto onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
- HWC2::Connection connection) {
+ auto onHotplugReceived(int32_t sequenceId, hal::HWDisplayId display,
+ hal::Connection connection) {
return mFlinger->onHotplugReceived(sequenceId, display, connection);
}
@@ -310,19 +323,20 @@
// Allow reading display state without locking, as if called on the SF main thread.
auto setPowerModeInternal(const sp<DisplayDevice>& display,
- int mode) NO_THREAD_SAFETY_ANALYSIS {
+ hal::PowerMode mode) NO_THREAD_SAFETY_ANALYSIS {
return mFlinger->setPowerModeInternal(display, mode);
}
- auto onMessageReceived(int32_t what) { return mFlinger->onMessageReceived(what); }
+ auto onMessageReceived(int32_t what) { return mFlinger->onMessageReceived(what, systemTime()); }
- auto captureScreenImplLocked(
- const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers,
- ANativeWindowBuffer* buffer, bool useIdentityTransform, bool forSystem, int* outSyncFd) {
+ auto captureScreenImplLocked(const RenderArea& renderArea,
+ SurfaceFlinger::TraverseLayersFunction traverseLayers,
+ ANativeWindowBuffer* buffer, bool useIdentityTransform,
+ bool forSystem, int* outSyncFd, bool regionSampling) {
bool ignored;
return mFlinger->captureScreenImplLocked(renderArea, traverseLayers, buffer,
useIdentityTransform, forSystem, outSyncFd,
- ignored);
+ regionSampling, ignored);
}
auto traverseLayersInDisplay(const sp<const DisplayDevice>& display,
@@ -397,7 +411,6 @@
auto& mutableUseFrameRateApi() { return mFlinger->useFrameRateApi; }
auto fromHandle(const sp<IBinder>& handle) {
- Mutex::Autolock _l(mFlinger->mStateLock);
return mFlinger->fromHandle(handle);
}
@@ -423,12 +436,12 @@
*/
struct HWC2Display : public HWC2::impl::Display {
HWC2Display(Hwc2::Composer& composer,
- const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
- HWC2::DisplayType type)
+ const std::unordered_set<hal::Capability>& capabilities, hal::HWDisplayId id,
+ hal::DisplayType type)
: HWC2::impl::Display(composer, capabilities, id, type) {}
~HWC2Display() {
// Prevents a call to disable vsyncs.
- mType = HWC2::DisplayType::Invalid;
+ mType = hal::DisplayType::INVALID;
}
auto& mutableIsConnected() { return this->mIsConnected; }
@@ -438,20 +451,19 @@
class FakeHwcDisplayInjector {
public:
- static constexpr hwc2_display_t DEFAULT_HWC_DISPLAY_ID = 1000;
+ static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
static constexpr int32_t DEFAULT_WIDTH = 1920;
static constexpr int32_t DEFAULT_HEIGHT = 1280;
static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
static constexpr int32_t DEFAULT_DPI = 320;
- static constexpr hwc2_config_t DEFAULT_ACTIVE_CONFIG = 0;
- static constexpr int32_t DEFAULT_POWER_MODE = 2;
+ static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
+ static constexpr hal::PowerMode DEFAULT_POWER_MODE = hal::PowerMode::ON;
- FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType,
- bool isPrimary)
+ FakeHwcDisplayInjector(DisplayId displayId, hal::DisplayType hwcDisplayType, bool isPrimary)
: mDisplayId(displayId), mHwcDisplayType(hwcDisplayType), mIsPrimary(isPrimary) {}
- auto& setHwcDisplayId(hwc2_display_t displayId) {
+ auto& setHwcDisplayId(hal::HWDisplayId displayId) {
mHwcDisplayId = displayId;
return *this;
}
@@ -481,23 +493,23 @@
return *this;
}
- auto& setActiveConfig(hwc2_config_t config) {
+ auto& setActiveConfig(hal::HWConfigId config) {
mActiveConfig = config;
return *this;
}
- auto& setCapabilities(const std::unordered_set<HWC2::Capability>* capabilities) {
+ auto& setCapabilities(const std::unordered_set<hal::Capability>* capabilities) {
mCapabilities = capabilities;
return *this;
}
- auto& setPowerMode(int mode) {
+ auto& setPowerMode(hal::PowerMode mode) {
mPowerMode = mode;
return *this;
}
void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
- static const std::unordered_set<HWC2::Capability> defaultCapabilities;
+ static const std::unordered_set<hal::Capability> defaultCapabilities;
if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
// Caution - Make sure that any values passed by reference here do
@@ -516,11 +528,11 @@
config.setConfigGroup(mConfigGroup);
display->mutableConfigs().emplace(static_cast<int32_t>(mActiveConfig), config.build());
display->mutableIsConnected() = true;
- display->setPowerMode(static_cast<HWC2::PowerMode>(mPowerMode));
+ display->setPowerMode(mPowerMode);
flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
- if (mHwcDisplayType == HWC2::DisplayType::Physical) {
+ if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, mDisplayId);
(mIsPrimary ? flinger->mutableInternalHwcDisplayId()
: flinger->mutableExternalHwcDisplayId()) = mHwcDisplayId;
@@ -529,19 +541,19 @@
private:
const DisplayId mDisplayId;
- const HWC2::DisplayType mHwcDisplayType;
+ const hal::DisplayType mHwcDisplayType;
const bool mIsPrimary;
- hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
+ hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
int32_t mWidth = DEFAULT_WIDTH;
int32_t mHeight = DEFAULT_HEIGHT;
int32_t mRefreshRate = DEFAULT_REFRESH_RATE;
int32_t mDpiX = DEFAULT_DPI;
int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
int32_t mDpiY = DEFAULT_DPI;
- hwc2_config_t mActiveConfig = DEFAULT_ACTIVE_CONFIG;
- int32_t mPowerMode = DEFAULT_POWER_MODE;
- const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr;
+ hal::HWConfigId mActiveConfig = DEFAULT_ACTIVE_CONFIG;
+ hal::PowerMode mPowerMode = DEFAULT_POWER_MODE;
+ const std::unordered_set<hal::Capability>* mCapabilities = nullptr;
};
class FakeDisplayDeviceInjector {
@@ -549,7 +561,7 @@
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
std::shared_ptr<compositionengine::Display> compositionDisplay,
std::optional<DisplayConnectionType> connectionType,
- std::optional<hwc2_display_t> hwcDisplayId, bool isPrimary)
+ std::optional<hal::HWDisplayId> hwcDisplayId, bool isPrimary)
: mFlinger(flinger),
mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay),
mHwcDisplayId(hwcDisplayId) {
@@ -592,7 +604,7 @@
return *this;
}
- auto& setPowerMode(int mode) {
+ auto& setPowerMode(hal::PowerMode mode) {
mCreationArgs.initialPowerMode = mode;
return *this;
}
@@ -642,12 +654,13 @@
TestableSurfaceFlinger& mFlinger;
sp<BBinder> mDisplayToken = new BBinder();
DisplayDeviceCreationArgs mCreationArgs;
- const std::optional<hwc2_display_t> mHwcDisplayId;
+ const std::optional<hal::HWDisplayId> mHwcDisplayId;
};
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
TestableScheduler* mScheduler = nullptr;
+ Hwc2::mock::Display mDisplay;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index 1f04673..7a1c7c6 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -51,6 +51,8 @@
using testing::StrEq;
using testing::UnorderedElementsAre;
+using PowerMode = hardware::graphics::composer::V2_4::IComposerClient::PowerMode;
+
// clang-format off
#define FMT_PROTO true
#define FMT_STRING false
@@ -377,9 +379,24 @@
EXPECT_THAT(result, HasSubstr(expectedResult));
}
+TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) {
+ // this stat is not in the proto so verify by checking the string dump
+ constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2;
+
+ EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
+ for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) {
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
+ }
+
+ const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
+ const std::string expectedResult =
+ "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES);
+ EXPECT_THAT(result, HasSubstr(expectedResult));
+}
+
TEST_F(TimeStatsTest, canAverageFrameDuration) {
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats
->recordFrameDuration(std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(6ms)
@@ -408,7 +425,7 @@
.count());
// Push a dummy present fence to trigger flushing the RenderEngine timings.
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(
std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count()));
@@ -424,13 +441,13 @@
ASSERT_NO_FATAL_FAILURE(
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
- ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
ASSERT_NO_FATAL_FAILURE(
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
ASSERT_NO_FATAL_FAILURE(
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
- ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_OFF));
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::OFF));
ASSERT_NO_FATAL_FAILURE(
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
ASSERT_NO_FATAL_FAILURE(
@@ -448,12 +465,12 @@
TEST_F(TimeStatsTest, canInsertGlobalFrameDuration) {
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
- mTimeStats->setPowerMode(HWC_POWER_MODE_OFF);
+ mTimeStats->setPowerMode(PowerMode::OFF);
mTimeStats
->recordFrameDuration(std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(5ms)
.count());
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats
->recordFrameDuration(std::chrono::duration_cast<std::chrono::nanoseconds>(3ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(6ms)
@@ -489,7 +506,7 @@
ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
// Push a dummy present fence to trigger flushing the RenderEngine timings.
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(
std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count()));
@@ -724,7 +741,7 @@
ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
- ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
mTimeStats
->recordFrameDuration(std::chrono::duration_cast<std::chrono::nanoseconds>(3ms).count(),
@@ -760,7 +777,8 @@
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats
->recordFrameDuration(std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(5ms)
@@ -776,6 +794,7 @@
const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
EXPECT_THAT(result, HasSubstr("clientCompositionReusedFrames = 0"));
EXPECT_THAT(result, HasSubstr("refreshRateSwitches = 0"));
+ EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
}
@@ -877,7 +896,7 @@
}
mTimeStats->recordDisplayEventConnectionCount(DISPLAY_EVENT_CONNECTIONS);
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats->recordFrameDuration(1000000, 3000000);
mTimeStats->recordRenderEngineDuration(2000000, 4000000);
mTimeStats->recordRenderEngineDuration(2000000, std::make_shared<FenceTime>(3000000));
@@ -1057,7 +1076,7 @@
insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
// Now make sure that TimeStats flushes global stats to set the callback.
- mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ mTimeStats->setPowerMode(PowerMode::ON);
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
EXPECT_THAT(mDelegate->mAtomTags,
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index f1739e5..2a48a22 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -76,7 +76,7 @@
new EventThreadConnection(sfEventThread.get(), ResyncCallback(),
ISurfaceComposer::eConfigChangedSuppress)));
- EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0, _)).WillRepeatedly(Return(0));
EXPECT_CALL(*mPrimaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
@@ -126,7 +126,7 @@
ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime()).WillOnce(Return(systemTime()));
+ EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime(_)).WillOnce(Return(systemTime()));
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
/*desiredPresentTime*/ -1);
@@ -159,7 +159,7 @@
// first check will see desired present time has not passed,
// but afterwards it will look like the desired present time has passed
nsecs_t time = systemTime();
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime())
+ EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime(_))
.WillOnce(Return(time + nsecs_t(5 * 1e8)));
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
@@ -182,7 +182,7 @@
// called in SurfaceFlinger::signalTransaction
nsecs_t time = systemTime();
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime())
+ EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime(_))
.WillOnce(Return(time + nsecs_t(5 * 1e8)));
// transaction that should go on the pending thread
TransactionInfo transactionA;
@@ -247,7 +247,7 @@
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
// nsecs_t time = systemTime();
- EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime())
+ EXPECT_CALL(*mPrimaryDispSync, expectedPresentTime(_))
.WillOnce(Return(nsecs_t(5 * 1e8)))
.WillOnce(Return(s2ns(2)));
TransactionInfo transactionA; // transaction to go on pending queue
@@ -322,7 +322,7 @@
TEST_F(TransactionApplicationTest, FromHandle) {
sp<IBinder> badHandle;
auto ret = mFlinger.fromHandle(badHandle);
- EXPECT_EQ(nullptr, ret.get());
+ EXPECT_EQ(nullptr, ret.promote().get());
}
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index 4f150ef..3f14d65 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -135,7 +135,7 @@
class StubCallback : public DispSync::Callback {
public:
- void onDispSyncEvent(nsecs_t when) final {
+ void onDispSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) final {
std::lock_guard<std::mutex> lk(mMutex);
mLastCallTime = when;
}
@@ -270,7 +270,7 @@
.Times(1)
.WillOnce(Return(fakeTimestamp));
- EXPECT_THAT(mReactor.computeNextRefresh(0), Eq(fakeTimestamp));
+ EXPECT_THAT(mReactor.computeNextRefresh(0, mMockClock->now()), Eq(fakeTimestamp));
}
TEST_F(VSyncReactorTest, queriesTrackerForExpectedPresentTime) {
@@ -280,7 +280,7 @@
.Times(1)
.WillOnce(Return(fakeTimestamp));
- EXPECT_THAT(mReactor.expectedPresentTime(), Eq(fakeTimestamp));
+ EXPECT_THAT(mReactor.expectedPresentTime(mMockClock->now()), Eq(fakeTimestamp));
}
TEST_F(VSyncReactorTest, queriesTrackerForNextRefreshFuture) {
@@ -292,7 +292,7 @@
EXPECT_CALL(*mMockTracker, currentPeriod()).WillOnce(Return(fakePeriod));
EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(mFakeNow + numPeriodsOut * fakePeriod))
.WillOnce(Return(fakeTimestamp));
- EXPECT_THAT(mReactor.computeNextRefresh(numPeriodsOut), Eq(fakeTimestamp));
+ EXPECT_THAT(mReactor.computeNextRefresh(numPeriodsOut, mMockClock->now()), Eq(fakeTimestamp));
}
TEST_F(VSyncReactorTest, getPeriod) {
@@ -544,7 +544,9 @@
class SelfRemovingCallback : public DispSync::Callback {
public:
SelfRemovingCallback(VSyncReactor& vsr) : mVsr(vsr) {}
- void onDispSyncEvent(nsecs_t when) final { mVsr.removeEventListener(this, &when); }
+ void onDispSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) final {
+ mVsr.removeEventListener(this, &when);
+ }
private:
VSyncReactor& mVsr;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 5cbba81..2a31078 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -45,6 +45,7 @@
class Composer : public Hwc2::Composer {
public:
+ using Display = android::hardware::graphics::composer::V2_1::Display;
Composer();
~Composer() override;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
index 6dc28bc..dade9fc 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
@@ -20,66 +20,81 @@
#include "DisplayHardware/HWC2.h"
-using HWC2::Error;
-using HWC2::Layer;
+using android::HWC2::Layer;
namespace android {
namespace Hwc2 {
namespace mock {
+namespace hal = android::hardware::graphics::composer::hal;
+
class Display : public HWC2::Display {
public:
+ using Layer = ::Layer;
+
Display();
~Display();
- MOCK_CONST_METHOD0(getId, hwc2_layer_t());
+ MOCK_CONST_METHOD0(getId, hal::HWDisplayId());
MOCK_CONST_METHOD0(isConnected, bool());
MOCK_METHOD1(setConnected, void(bool));
- MOCK_CONST_METHOD0(getCapabilities, const std::unordered_set<HWC2::DisplayCapability>&());
+ MOCK_CONST_METHOD0(getCapabilities, const std::unordered_set<hal::DisplayCapability>&());
- MOCK_METHOD0(acceptChanges, Error());
- MOCK_METHOD1(createLayer, Error(Layer**));
- MOCK_METHOD1(destroyLayer, Error(Layer*));
- MOCK_CONST_METHOD1(getActiveConfig, Error(std::shared_ptr<const Config>*));
- MOCK_CONST_METHOD1(getActiveConfigIndex, Error(int* outIndex));
- MOCK_METHOD1(getChangedCompositionTypes, Error(std::unordered_map<Layer*, HWC2::Composition>*));
- MOCK_CONST_METHOD1(getColorModes, Error(std::vector<android::ui::ColorMode>*));
+ MOCK_METHOD0(acceptChanges, hal::Error());
+ MOCK_METHOD1(createLayer, hal::Error(Layer**));
+ MOCK_METHOD1(destroyLayer, hal::Error(Layer*));
+ MOCK_CONST_METHOD1(getActiveConfig, hal::Error(std::shared_ptr<const Config>*));
+ MOCK_CONST_METHOD1(getActiveConfigIndex, hal::Error(int* outIndex));
+ MOCK_METHOD1(getChangedCompositionTypes,
+ hal::Error(std::unordered_map<Layer*, hal::Composition>*));
+ MOCK_CONST_METHOD1(getColorModes, hal::Error(std::vector<hal::ColorMode>*));
MOCK_CONST_METHOD0(getSupportedPerFrameMetadata, int32_t());
MOCK_CONST_METHOD2(getRenderIntents,
- Error(android::ui::ColorMode, std::vector<android::ui::RenderIntent>*));
- MOCK_METHOD2(getDataspaceSaturationMatrix, Error(android::ui::Dataspace, android::mat4*));
+ hal::Error(hal::ColorMode, std::vector<hal::RenderIntent>*));
+ MOCK_METHOD2(getDataspaceSaturationMatrix, hal::Error(hal::Dataspace, android::mat4*));
MOCK_CONST_METHOD0(getConfigs, std::vector<std::shared_ptr<const Config>>());
- MOCK_CONST_METHOD1(getName, Error(std::string*));
+ MOCK_CONST_METHOD1(getName, hal::Error(std::string*));
MOCK_METHOD2(getRequests,
- Error(HWC2::DisplayRequest*, std::unordered_map<Layer*, HWC2::LayerRequest>*));
- MOCK_CONST_METHOD1(getType, Error(HWC2::DisplayType*));
- MOCK_CONST_METHOD1(supportsDoze, Error(bool*));
- MOCK_CONST_METHOD1(getHdrCapabilities, Error(android::HdrCapabilities*));
+ hal::Error(hal::DisplayRequest*, std::unordered_map<Layer*, hal::LayerRequest>*));
+ MOCK_CONST_METHOD1(getType, hal::Error(hal::DisplayType*));
+ MOCK_CONST_METHOD1(supportsDoze, hal::Error(bool*));
+ MOCK_CONST_METHOD1(getHdrCapabilities, hal::Error(android::HdrCapabilities*));
MOCK_CONST_METHOD3(getDisplayedContentSamplingAttributes,
- Error(android::ui::PixelFormat*, android::ui::Dataspace*, uint8_t*));
- MOCK_CONST_METHOD3(setDisplayContentSamplingEnabled, Error(bool, uint8_t, uint64_t));
+ hal::Error(hal::PixelFormat*, hal::Dataspace*, uint8_t*));
+ MOCK_CONST_METHOD3(setDisplayContentSamplingEnabled, hal::Error(bool, uint8_t, uint64_t));
MOCK_CONST_METHOD3(getDisplayedContentSample,
- Error(uint64_t, uint64_t, android::DisplayedFrameStats*));
- MOCK_CONST_METHOD1(getReleaseFences,
- Error(std::unordered_map<Layer*, android::sp<android::Fence>>* outFences));
- MOCK_METHOD1(present, Error(android::sp<android::Fence>*));
- MOCK_METHOD1(setActiveConfig, Error(const std::shared_ptr<const HWC2::Display::Config>&));
+ hal::Error(uint64_t, uint64_t, android::DisplayedFrameStats*));
+ MOCK_CONST_METHOD1(
+ getReleaseFences,
+ hal::Error(std::unordered_map<Layer*, android::sp<android::Fence>>* outFences));
+ MOCK_METHOD1(present, hal::Error(android::sp<android::Fence>*));
+ MOCK_METHOD1(setActiveConfig, hal::Error(const std::shared_ptr<const HWC2::Display::Config>&));
MOCK_METHOD4(setClientTarget,
- Error(uint32_t, const android::sp<android::GraphicBuffer>&,
- const android::sp<android::Fence>&, android::ui::Dataspace));
- MOCK_METHOD2(setColorMode, Error(android::ui::ColorMode, android::ui::RenderIntent));
- MOCK_METHOD2(setColorTransform, Error(const android::mat4&, android_color_transform_t));
+ hal::Error(uint32_t, const android::sp<android::GraphicBuffer>&,
+ const android::sp<android::Fence>&, hal::Dataspace));
+ MOCK_METHOD2(setColorMode, hal::Error(hal::ColorMode, hal::RenderIntent));
+ MOCK_METHOD2(setColorTransform, hal::Error(const android::mat4&, hal::ColorTransform));
MOCK_METHOD2(setOutputBuffer,
- Error(const android::sp<android::GraphicBuffer>&,
- const android::sp<android::Fence>&));
- MOCK_METHOD1(setPowerMode, Error(HWC2::PowerMode));
- MOCK_METHOD1(setVsyncEnabled, Error(HWC2::Vsync));
- MOCK_METHOD2(validate, Error(uint32_t*, uint32_t*));
+ hal::Error(const android::sp<android::GraphicBuffer>&,
+ const android::sp<android::Fence>&));
+ MOCK_METHOD1(setPowerMode, hal::Error(hal::PowerMode));
+ MOCK_METHOD1(setVsyncEnabled, hal::Error(hal::Vsync));
+ MOCK_METHOD2(validate, hal::Error(uint32_t*, uint32_t*));
MOCK_METHOD4(presentOrValidate,
- Error(uint32_t*, uint32_t*, android::sp<android::Fence>*, uint32_t*));
- MOCK_CONST_METHOD1(setDisplayBrightness, Error(float));
+ hal::Error(uint32_t*, uint32_t*, android::sp<android::Fence>*, uint32_t*));
+ MOCK_METHOD1(setDisplayBrightness, std::future<hal::Error>(float));
+ MOCK_CONST_METHOD1(getDisplayVsyncPeriod, hal::Error(nsecs_t*));
+ MOCK_METHOD3(setActiveConfigWithConstraints,
+ hal::Error(const std::shared_ptr<const HWC2::Display::Config>&,
+ const hal::VsyncPeriodChangeConstraints&,
+ hal::VsyncPeriodChangeTimeline*));
+ MOCK_METHOD1(setAutoLowLatencyMode, hal::Error(bool on));
+ MOCK_CONST_METHOD1(getSupportedContentTypes, hal::Error(std::vector<hal::ContentType>*));
+ MOCK_METHOD1(setContentType, hal::Error(hal::ContentType));
+ MOCK_CONST_METHOD1(getConnectionType, hal::Error(android::DisplayConnectionType*));
+ MOCK_CONST_METHOD0(isVsyncPeriodSwitchSupported, bool());
};
} // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp
index f6c4f62..1c8c44d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp
@@ -17,6 +17,7 @@
#include "mock/MockDispSync.h"
#include <thread>
+using namespace std::chrono_literals;
namespace android {
namespace mock {
@@ -54,8 +55,9 @@
void DispSync::triggerCallback() {
if (mCallback.callback == nullptr) return;
- mCallback.callback->onDispSyncEvent(
- std::chrono::steady_clock::now().time_since_epoch().count());
+ const std::chrono::nanoseconds now = std::chrono::steady_clock::now().time_since_epoch();
+ const auto expectedVSyncTime = now + 16ms;
+ mCallback.callback->onDispSyncEvent(now.count(), expectedVSyncTime.count());
}
} // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index a2ae6c9..b39487c 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -37,9 +37,9 @@
MOCK_METHOD0(getPeriod, nsecs_t());
MOCK_METHOD0(getIntendedPeriod, nsecs_t());
MOCK_METHOD1(setRefreshSkipCount, void(int));
- MOCK_CONST_METHOD1(computeNextRefresh, nsecs_t(int));
+ MOCK_CONST_METHOD2(computeNextRefresh, nsecs_t(int, nsecs_t));
MOCK_METHOD1(setIgnorePresentFences, void(bool));
- MOCK_METHOD0(expectedPresentTime, nsecs_t());
+ MOCK_METHOD1(expectedPresentTime, nsecs_t(nsecs_t));
MOCK_CONST_METHOD1(dump, void(std::string&));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 50eb390..054aaf8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -40,7 +40,7 @@
status_t(const sp<android::EventThreadConnection> &));
MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &));
MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &));
- MOCK_METHOD0(requestLatestConfig, void());
+ MOCK_METHOD1(requestLatestConfig, void(const sp<android::EventThreadConnection> &));
MOCK_METHOD1(pauseVsyncCallback, void(bool));
MOCK_METHOD0(getEventThreadConnectionCount, size_t());
};
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.cpp b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.cpp
index 97a13e4..5fb06fd 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.cpp
@@ -16,12 +16,15 @@
#include "mock/MockMessageQueue.h"
-namespace android {
-namespace mock {
+namespace android::mock {
-// Explicit default instantiation is recommended.
-MessageQueue::MessageQueue() = default;
+MessageQueue::MessageQueue() {
+ ON_CALL(*this, postMessage).WillByDefault([](sp<MessageHandler>&& handler) {
+ // Execute task to prevent broken promise exception on destruction.
+ handler->handleMessage(Message());
+ });
+}
+
MessageQueue::~MessageQueue() = default;
-} // namespace mock
-} // namespace android
\ No newline at end of file
+} // namespace android::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index e781c0a..a82b583 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -21,8 +21,7 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
-namespace android {
-namespace mock {
+namespace android::mock {
class MessageQueue : public android::MessageQueue {
public:
@@ -32,10 +31,9 @@
MOCK_METHOD1(init, void(const sp<SurfaceFlinger>&));
MOCK_METHOD1(setEventConnection, void(const sp<EventThreadConnection>& connection));
MOCK_METHOD0(waitMessage, void());
- MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
+ MOCK_METHOD1(postMessage, void(sp<MessageHandler>&&));
MOCK_METHOD0(invalidate, void());
MOCK_METHOD0(refresh, void());
};
-} // namespace mock
-} // namespace android
+} // namespace android::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 9ea4dd0..4186e2b 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -37,6 +37,7 @@
MOCK_METHOD0(incrementClientCompositionFrames, void());
MOCK_METHOD0(incrementClientCompositionReusedFrames, void());
MOCK_METHOD0(incrementRefreshRateSwitches, void());
+ MOCK_METHOD0(incrementCompositionStrategyChanges, void());
MOCK_METHOD1(recordDisplayEventConnectionCount, void(int32_t));
MOCK_METHOD2(recordFrameDuration, void(nsecs_t, nsecs_t));
MOCK_METHOD2(recordRenderEngineDuration, void(nsecs_t, nsecs_t));
@@ -52,7 +53,8 @@
MOCK_METHOD3(setPresentFence, void(int32_t, uint64_t, const std::shared_ptr<FenceTime>&));
MOCK_METHOD1(onDestroy, void(int32_t));
MOCK_METHOD2(removeTimeRecord, void(int32_t, uint64_t));
- MOCK_METHOD1(setPowerMode, void(int32_t));
+ MOCK_METHOD1(setPowerMode,
+ void(hardware::graphics::composer::V2_4::IComposerClient::PowerMode));
MOCK_METHOD2(recordRefreshRate, void(uint32_t, nsecs_t));
MOCK_METHOD1(setPresentFenceGlobal, void(const std::shared_ptr<FenceTime>&));
};
diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h
index 2c63da0..8e1f943 100644
--- a/services/surfaceflinger/tests/utils/TransactionUtils.h
+++ b/services/surfaceflinger/tests/utils/TransactionUtils.h
@@ -17,18 +17,13 @@
#pragma once
#include <chrono>
-#include <gtest/gtest.h>
#include <android/native_window.h>
-#include <hardware/hwcomposer_defs.h>
-
#include <binder/IPCThreadState.h>
-
+#include <gtest/gtest.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-
#include <private/gui/ComposerService.h>
-
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 018f200..f69de1f 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -79,6 +79,7 @@
"hwvulkan_headers",
"libnativeloader-headers",
"vulkan_headers",
+ "libsurfaceflinger_headers",
],
export_header_lib_headers: ["vulkan_headers"],
shared_libs: [
@@ -100,6 +101,7 @@
"libnativeloader_lazy",
"libnativewindow",
"android.hardware.graphics.common@1.0",
+ "libSurfaceFlingerProp",
],
static_libs: ["libgrallocusage"],
}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index a7ec4ae..7bcb2c1 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -23,9 +23,10 @@
#include <stdlib.h>
#include <string.h>
+#include <SurfaceFlingerProperties.h>
+#include <android-base/properties.h>
#include <android/dlext.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <android-base/properties.h>
#include <configstore/Utils.h>
#include <cutils/properties.h>
#include <graphicsenv/GraphicsEnv.h>
@@ -251,18 +252,6 @@
result = LoadUpdatedDriver(&module);
if (result == -ENOENT) {
result = LoadBuiltinDriver(&module);
- if (result != 0) {
- // -ENOENT means the sphal namespace doesn't exist, not that there
- // is a problem with the driver.
- ALOGW_IF(
- result != -ENOENT,
- "Failed to load Vulkan driver into sphal namespace. This "
- "usually means the driver has forbidden library dependencies."
- "Please fix, this will soon stop working.");
- result =
- hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
- reinterpret_cast<const hw_module_t**>(&module));
- }
}
if (result != 0) {
android::GraphicsEnv::getInstance().setDriverLoaded(
@@ -959,9 +948,7 @@
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
- bool hdrBoardConfig =
- getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(
- false);
+ bool hdrBoardConfig = android::sysprop::has_HDR_display(false);
if (hdrBoardConfig) {
loader_extensions.push_back({VK_EXT_HDR_METADATA_EXTENSION_NAME,
VK_EXT_HDR_METADATA_SPEC_VERSION});
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index a44b9e7..d3ed88d 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1478,7 +1478,7 @@
ANativeWindowBuffer* buffer;
int fence_fd;
err = window->dequeueBuffer(window, &buffer, &fence_fd);
- if (err == android::TIMED_OUT) {
+ if (err == android::TIMED_OUT || err == android::INVALID_OPERATION) {
ALOGW("dequeueBuffer timed out: %s (%d)", strerror(-err), err);
return timeout ? VK_TIMEOUT : VK_NOT_READY;
} else if (err != android::OK) {