Merge "Adds support for restore dexopt flag" into rvc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 544e26c..8637a31 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -233,6 +233,7 @@
{ REQ, "events/filemap/enable" },
} },
{ "memory", "Memory", 0, {
+ { OPT, "events/mm_event/mm_event_record/enable" },
{ OPT, "events/kmem/rss_stat/enable" },
{ OPT, "events/kmem/ion_heap_grow/enable" },
{ OPT, "events/kmem/ion_heap_shrink/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 6e460a0..040ddde 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/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
chmod 0666 /sys/kernel/tracing/events/signal/signal_generate/enable
chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_deliver/enable
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 1824943..bfcc058 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -137,6 +137,8 @@
ds_info->calling_package = calling_package;
pthread_t thread;
+ // Initialize dumpstate
+ ds_->Initialize();
status_t err = pthread_create(&thread, nullptr, dumpstate_thread_main, ds_info);
if (err != 0) {
delete ds_info;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index e17f18e..8ff4ca6 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -32,7 +32,7 @@
*
* @param progress the progress in [0, 100]
*/
- void onProgress(int progress);
+ oneway void onProgress(int progress);
// NOTE: If you add to or change these error codes, please also change the corresponding enums
// in system server, in BugreportManager.java.
@@ -54,16 +54,18 @@
/**
* Called on an error condition with one of the error codes listed above.
+ * This is not an asynchronous method since it can race with dumpstate exiting, thus triggering
+ * death recipient.
*/
void onError(int errorCode);
/**
* Called when taking bugreport finishes successfully.
*/
- void onFinished();
+ oneway void onFinished();
/**
* Called when screenshot is taken.
*/
- void onScreenshotTaken(boolean success);
+ oneway void onScreenshotTaken(boolean success);
}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 772b9fe..c85c7cf 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2395,6 +2395,13 @@
options_ = std::move(options);
}
+void Dumpstate::Initialize() {
+ /* gets the sequential id */
+ uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
+ id_ = ++last_id;
+ android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
+}
+
Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
if (listener_ != nullptr) {
@@ -2505,11 +2512,6 @@
: "";
progress_.reset(new Progress(stats_path));
- /* gets the sequential id */
- uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
- id_ = ++last_id;
- android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
-
if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
} else {
@@ -2675,15 +2677,6 @@
MYLOGI("User denied consent. Returning\n");
return status;
}
- if (options_->do_screenshot &&
- options_->screenshot_fd.get() != -1 &&
- !options_->is_screenshot_copied) {
- bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
- options_->screenshot_fd.get());
- if (copy_succeeded) {
- android::os::UnlinkAndLogOnError(screenshot_path_);
- }
- }
if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
MYLOGI(
"Did not receive user consent yet."
@@ -2813,6 +2806,16 @@
bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
if (copy_succeeded) {
android::os::UnlinkAndLogOnError(path_);
+ if (options_->do_screenshot &&
+ options_->screenshot_fd.get() != -1 &&
+ !options_->is_screenshot_copied) {
+ copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
+ options_->screenshot_fd.get());
+ options_->is_screenshot_copied = copy_succeeded;
+ if (copy_succeeded) {
+ android::os::UnlinkAndLogOnError(screenshot_path_);
+ }
+ }
}
return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
} else if (consent_result == UserConsentResult::UNAVAILABLE) {
@@ -2837,8 +2840,9 @@
assert(options_->bugreport_fd.get() == -1);
// calling_uid and calling_package are for user consent to share the bugreport with
- // an app; they are irrelvant here because bugreport is only written to a local
- // directory, and not shared.
+ // an app; they are irrelevant here because bugreport is triggered via command line.
+ // Update Last ID before calling Run().
+ Initialize();
status = Run(-1 /* calling_uid */, "" /* calling_package */);
}
return status;
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 9ce662b..498f338 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -216,6 +216,9 @@
/* Checkes whether dumpstate is generating a zipped bugreport. */
bool IsZipping() const;
+ /* Initialize dumpstate fields before starting bugreport generation */
+ void Initialize();
+
/*
* Forks a command, waits for it to finish, and returns its status.
*
@@ -329,7 +332,12 @@
struct DumpOptions;
- /* Main entry point for running a complete bugreport. */
+ /*
+ * Main entry point for running a complete bugreport.
+ *
+ * Initialize() dumpstate before calling this method.
+ *
+ */
RunStatus Run(int32_t calling_uid, const std::string& calling_package);
RunStatus ParseCommandlineAndRun(int argc, char* argv[]);
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index c9b51b5..ae44d38 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -42,6 +42,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
@@ -75,6 +76,7 @@
#define LOG_TAG "installd"
#endif
+using android::base::ParseUint;
using android::base::StringPrintf;
using std::endl;
@@ -1101,6 +1103,43 @@
return ok();
}
+binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified(
+ const std::unique_ptr<std::string> &volumeUuid, const int32_t userId,
+ const std::vector<int32_t>& retainSnapshotIds) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr;
+
+ auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, userId);
+
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(base_path.c_str()), closedir);
+ if (!dir) {
+ return error(-1, "Failed to open rollback base dir " + base_path);
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir.get()))) {
+ if (ent->d_type != DT_DIR) {
+ continue;
+ }
+
+ uint snapshot_id;
+ bool parse_ok = ParseUint(ent->d_name, &snapshot_id);
+ if (parse_ok &&
+ std::find(retainSnapshotIds.begin(), retainSnapshotIds.end(),
+ snapshot_id) == retainSnapshotIds.end()) {
+ auto rollback_path = create_data_misc_ce_rollback_path(
+ volume_uuid, userId, snapshot_id);
+ int res = delete_dir_contents_and_dir(rollback_path, true /* ignore_if_missing */);
+ if (res != 0) {
+ return error(res, "Failed clearing snapshot " + rollback_path);
+ }
+ }
+ }
+ return ok();
+}
binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index df01c3c..eb151ca 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -69,6 +69,8 @@
binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid,
const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode,
const int32_t snapshotId, int32_t storageFlags);
+ binder::Status destroyCeSnapshotsNotSpecified(const std::unique_ptr<std::string> &volumeUuid,
+ const int32_t userId, const std::vector<int32_t>& retainSnapshotIds);
binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index ca95cb3..5e5af73 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -116,6 +116,9 @@
int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags);
void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
int userId, long ceSnapshotInode, int snapshotId, int storageFlags);
+ void destroyCeSnapshotsNotSpecified(@nullable @utf8InCpp String uuid, int userId,
+ in int[] retainSnapshotIds);
+
void tryMountDataMirror(@nullable @utf8InCpp String volumeUuid);
void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 07f8ff0..2944ac5 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -396,6 +396,14 @@
bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
vold_decrypt == "1";
+ std::string updatable_bcp_packages =
+ MapPropertyToArg("dalvik.vm.dex2oat-updatable-bcp-packages-file",
+ "--updatable-bcp-packages-file=%s");
+ if (updatable_bcp_packages.empty()) {
+ // Make dex2oat fail by providing non-existent file name.
+ updatable_bcp_packages = "--updatable-bcp-packages-file=/nonx/updatable-bcp-packages.txt";
+ }
+
std::string resolve_startup_string_arg =
MapPropertyToArg("persist.device_config.runtime.dex2oat_resolve_startup_strings",
"--resolve-startup-const-strings=%s");
@@ -542,6 +550,7 @@
AddRuntimeArg(dex2oat_Xms_arg);
AddRuntimeArg(dex2oat_Xmx_arg);
+ AddArg(updatable_bcp_packages);
AddArg(resolve_startup_string_arg);
AddArg(image_block_size_arg);
AddArg(dex2oat_compiler_filter_arg);
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index a31d510..0fb62ae 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -641,6 +641,46 @@
"com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk());
}
+TEST_F(AppDataSnapshotTest, DestroyCeSnapshotsNotSpecified) {
+ auto rollback_ce_dir_in_1 = create_data_misc_ce_rollback_path("TEST", 0, 1543);
+ auto rollback_ce_dir_in_2 = create_data_misc_ce_rollback_path("TEST", 0, 77);
+ auto rollback_ce_dir_out_1 = create_data_misc_ce_rollback_path("TEST", 0, 1500);
+ auto rollback_ce_dir_out_2 = create_data_misc_ce_rollback_path("TEST", 0, 2);
+
+ // Create snapshots
+ ASSERT_TRUE(mkdirs(rollback_ce_dir_in_1 + "/com.foo/", 0700));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "CE_RESTORE_CONTENT", rollback_ce_dir_in_1 + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir_in_2 + "/com.foo/", 0700));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "CE_RESTORE_CONTENT", rollback_ce_dir_in_2 + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir_out_1 + "/com.foo/", 0700));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "CE_RESTORE_CONTENT", rollback_ce_dir_out_1 + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_TRUE(mkdirs(rollback_ce_dir_out_2 + "/com.foo/", 0700));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "CE_RESTORE_CONTENT", rollback_ce_dir_out_2 + "/com.foo/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ ASSERT_TRUE(service->destroyCeSnapshotsNotSpecified(
+ std::make_unique<std::string>("TEST"), 0, { 1543, 77 }).isOk());
+
+ // Check only snapshots not specified are deleted.
+ struct stat sb;
+ ASSERT_EQ(0, stat((rollback_ce_dir_in_1 + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(0, stat((rollback_ce_dir_in_2 + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_ce_dir_out_1 + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(ENOENT, errno);
+ ASSERT_EQ(-1, stat((rollback_ce_dir_out_2 + "/com.foo").c_str(), &sb));
+ ASSERT_EQ(ENOENT, errno);
+}
+
TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
// Setup rollback data to make sure that fails due to wrong volumeUuid being
// passed, not because of some other reason.
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 0ce1dd5..b9eb281 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -39,7 +39,7 @@
data.writeInterfaceToken(IAppOpsCallback::getInterfaceDescriptor());
data.writeInt32(op);
data.writeString16(packageName);
- remote()->transact(OP_CHANGED_TRANSACTION, data, &reply);
+ remote()->transact(OP_CHANGED_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -58,7 +58,6 @@
String16 packageName;
(void)data.readString16(&packageName);
opChanged(op, packageName);
- reply->writeNoException();
return NO_ERROR;
} break;
default:
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/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 2ee5930..6afcd77 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -122,7 +122,16 @@
OP_LEGACY_STORAGE = 87,
OP_ACCESS_ACCESSIBILITY = 88,
OP_READ_DEVICE_IDENTIFIERS = 89,
- _NUM_OP = 90
+ OP_ACCESS_MEDIA_LOCATION = 90,
+ OP_QUERY_ALL_PACKAGES = 91,
+ OP_MANAGE_EXTERNAL_STORAGE = 92,
+ OP_INTERACT_ACROSS_PROFILES = 93,
+ OP_ACTIVATE_PLATFORM_VPN = 94,
+ OP_LOADER_USAGE_STATS = 95,
+ OP_DEPRECATED_1 = 96,
+ OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97,
+ OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98,
+ _NUM_OP = 99
};
AppOpsManager();
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 3ee8187..c7b7551 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -40,7 +40,7 @@
},
srcs: ["binderDriverInterfaceTest.cpp"],
- test_suites: ["device-tests", "vts-core"],
+ test_suites: ["device-tests", "vts"],
}
cc_test {
@@ -69,7 +69,7 @@
"libbinder",
"libutils",
],
- test_suites: ["device-tests", "vts-core"],
+ test_suites: ["device-tests", "vts"],
require_root: true,
}
@@ -131,7 +131,7 @@
"liblog",
"libutils",
],
- test_suites: ["device-tests", "vts-core"],
+ test_suites: ["device-tests", "vts"],
require_root: true,
}
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index b2b74dc..fd557b7 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -73,6 +73,7 @@
"android.hardware.thermal@2.0::IThermal",
"android.hardware.vr@1.0::IVr",
"android.hardware.automotive.audiocontrol@1.0::IAudioControl",
+ "android.hardware.automotive.audiocontrol@2.0::IAudioControl",
"android.hardware.automotive.vehicle@2.0::IVehicle",
"android.hardware.automotive.evs@1.0::IEvsCamera",
"android.hardware.neuralnetworks@1.0::IDevice",
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/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 30e1351..a8384ac 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -110,7 +110,7 @@
mProducer->setMaxDequeuedBufferCount(2);
}
mBufferItemConsumer =
- new BLASTBufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
+ new BLASTBufferItemConsumer(mConsumer, GraphicBuffer::USAGE_HW_COMPOSER, 1, true);
static int32_t id = 0;
auto name = std::string("BLAST Consumer") + std::to_string(id);
id++;
@@ -119,7 +119,9 @@
mBufferItemConsumer->setBufferFreedListener(this);
mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
+
mTransformHint = mSurfaceControl->getTransformHint();
+ mBufferItemConsumer->setTransformHint(mTransformHint);
mNumAcquired = 0;
mNumFrameAvailable = 0;
@@ -130,9 +132,12 @@
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
std::unique_lock _lock{mMutex};
mSurfaceControl = surface;
- mWidth = width;
- mHeight = height;
- mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
+
+ if (mWidth != width || mHeight != height) {
+ mWidth = width;
+ mHeight = height;
+ mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
+ }
}
static void transactionCallbackThunk(void* context, nsecs_t latchTime,
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/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8d79cf8..6fd53cf 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);
@@ -1038,7 +1037,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) {
@@ -1145,6 +1144,42 @@
ALOGE("setFrameRate: failed to transact: %s (%d)", strerror(-err), err);
return err;
}
+
+ return reply.readInt32();
+ }
+
+ virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) {
+ if (!outToken) return BAD_VALUE;
+
+ Parcel data, reply;
+ status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (err != NO_ERROR) {
+ ALOGE("acquireFrameRateFlexibilityToken: failed writing interface token: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ err = remote()->transact(BnSurfaceComposer::ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, data,
+ &reply);
+ if (err != NO_ERROR) {
+ ALOGE("acquireFrameRateFlexibilityToken: failed to transact: %s (%d)", strerror(-err),
+ err);
+ return err;
+ }
+
+ err = reply.readInt32();
+ if (err != NO_ERROR) {
+ ALOGE("acquireFrameRateFlexibilityToken: call failed: %s (%d)", strerror(-err), err);
+ return err;
+ }
+
+ err = reply.readStrongBinder(outToken);
+ if (err != NO_ERROR) {
+ ALOGE("acquireFrameRateFlexibilityToken: failed reading binder token: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
+
return NO_ERROR;
}
};
@@ -1945,6 +1980,16 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> token;
+ status_t result = acquireFrameRateFlexibilityToken(&token);
+ reply->writeInt32(result);
+ if (result == NO_ERROR) {
+ reply->writeStrongBinder(token);
+ }
+ return NO_ERROR;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 2307fbf..d9cbeb7 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);
}
@@ -430,6 +453,19 @@
}
status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const {
+ // If we write the Transaction to a parcel, we want to ensure the Buffers are cached
+ // before crossing the IPC boundary. Otherwise the receiving party will cache the buffers
+ // but is unlikely to use them again as they are owned by the other process.
+ // You may be asking yourself, is this const cast safe? Const cast is safe up
+ // until the point where you try and write to an object that was originally const at which
+ // point we enter undefined behavior. In this case we are safe though, because there are
+ // two possibilities:
+ // 1. The SurfaceComposerClient::Transaction was originally non-const. Safe.
+ // 2. It was originall const! In this case not only was it useless, but it by definition
+ // contains no composer states and so cacheBuffers will not perform any writes.
+
+ const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers();
+
parcel->writeUint32(mForceSynchronous);
parcel->writeUint32(mTransactionNestCount);
parcel->writeBool(mAnimation);
@@ -507,7 +543,7 @@
mInputWindowCommands.merge(other.mInputWindowCommands);
- mContainsBuffer = other.mContainsBuffer;
+ mContainsBuffer |= other.mContainsBuffer;
mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup;
other.clear();
return *this;
@@ -547,6 +583,11 @@
layer_state_t* s = getLayerState(handle);
if (!(s->what & layer_state_t::eBufferChanged)) {
continue;
+ } else if (s->what & layer_state_t::eCachedBufferChanged) {
+ // If eBufferChanged and eCachedBufferChanged are both trued then that means
+ // we already cached the buffer in a previous call to cacheBuffers, perhaps
+ // from writeToParcel on a Transaction that was merged in to this one.
+ continue;
}
// Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste
@@ -558,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;
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 09487ea..b4a3fbe 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
*
@@ -468,8 +468,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.
@@ -508,6 +507,14 @@
*/
virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
int8_t compatibility) = 0;
+
+ /*
+ * Acquire a frame rate flexibility token from SurfaceFlinger. While this token is acquired,
+ * surface flinger will freely switch between frame rates in any way it sees fit, regardless of
+ * the current restrictions applied by DisplayManager. This is useful to get consistent behavior
+ * for tests. Release the token by releasing the returned IBinder reference.
+ */
+ virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) = 0;
};
// ----------------------------------------------------------------------------
@@ -566,6 +573,7 @@
GET_GAME_CONTENT_TYPE_SUPPORT,
SET_GAME_CONTENT_TYPE,
SET_FRAME_RATE,
+ ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
// Always append new enum to the end.
};
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/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 8c0f8f8..2de6b69 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -804,7 +804,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 +822,7 @@
return NO_ERROR;
}
status_t setDisplayBrightness(const sp<IBinder>& /*displayToken*/,
- float /*brightness*/) const override {
+ float /*brightness*/) override {
return NO_ERROR;
}
@@ -859,6 +859,8 @@
return NO_ERROR;
}
+ status_t acquireFrameRateFlexibilityToken(sp<IBinder>* /*outToken*/) { return NO_ERROR; }
+
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index e73f245..36a54a7 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -793,34 +793,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.
- 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);
@@ -1015,8 +1047,8 @@
setOutputDataSpace(display.outputDataspace);
setDisplayMaxLuminance(display.maxLuminance);
- mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
- mState.projectionMatrix = projectionMatrix;
+ const mat4 projectionMatrix =
+ ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
if (!display.clearRegion.isEmpty()) {
glDisable(GL_BLEND);
fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
diff --git a/libs/renderengine/gl/filters/BlurFilter.cpp b/libs/renderengine/gl/filters/BlurFilter.cpp
index 6ba78dc..724877b 100644
--- a/libs/renderengine/gl/filters/BlurFilter.cpp
+++ b/libs/renderengine/gl/filters/BlurFilter.cpp
@@ -54,13 +54,13 @@
static constexpr auto translation = 1.0f;
const GLfloat vboData[] = {
// Vertex data
- translation-size, -translation-size,
- translation-size, -translation+size,
- translation+size, -translation+size,
+ translation - size, -translation - size,
+ translation - size, -translation + size,
+ translation + size, -translation + size,
// UV data
- 0.0f, 0.0f-translation,
- 0.0f, size-translation,
- size, size-translation
+ 0.0f, 0.0f - translation,
+ 0.0f, size - translation,
+ size, size - translation
};
mMeshBuffer.allocateBuffers(vboData, 12 /* size */);
}
@@ -69,7 +69,10 @@
ATRACE_NAME("BlurFilter::setAsDrawTarget");
mRadius = radius;
- if (!mTexturesAllocated) {
+ if (mDisplayWidth < display.physicalDisplay.width() ||
+ mDisplayHeight < display.physicalDisplay.height()) {
+ ATRACE_NAME("BlurFilter::allocatingTextures");
+
mDisplayWidth = display.physicalDisplay.width();
mDisplayHeight = display.physicalDisplay.height();
mCompositionFbo.allocateBuffers(mDisplayWidth, mDisplayHeight);
@@ -78,7 +81,6 @@
const uint32_t fboHeight = floorf(mDisplayHeight * kFboScale);
mPingFbo.allocateBuffers(fboWidth, fboHeight);
mPongFbo.allocateBuffers(fboWidth, fboHeight);
- mTexturesAllocated = true;
if (mPingFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) {
ALOGE("Invalid ping buffer");
@@ -120,27 +122,35 @@
status_t BlurFilter::prepare() {
ATRACE_NAME("BlurFilter::prepare");
- blit(mCompositionFbo, mPingFbo);
// Kawase is an approximation of Gaussian, but it behaves differently from it.
// A radius transformation is required for approximating them, and also to introduce
// non-integer steps, necessary to smoothly interpolate large radii.
- auto radius = mRadius / 6.0f;
+ const auto radius = mRadius / 6.0f;
// Calculate how many passes we'll do, based on the radius.
// Too many passes will make the operation expensive.
- auto passes = min(kMaxPasses, (uint32_t)ceil(radius));
+ const auto passes = min(kMaxPasses, (uint32_t)ceil(radius));
- // We'll ping pong between our textures, to accumulate the result of various offsets.
+ const float radiusByPasses = radius / (float)passes;
+ const float stepX = radiusByPasses / (float)mCompositionFbo.getBufferWidth();
+ const float stepY = radiusByPasses / (float)mCompositionFbo.getBufferHeight();
+
+ // Let's start by downsampling and blurring the composited frame simultaneously.
mBlurProgram.useProgram();
- GLFramebuffer* read = &mPingFbo;
- GLFramebuffer* draw = &mPongFbo;
- float stepX = radius / (float)mCompositionFbo.getBufferWidth() / (float)passes;
- float stepY = radius / (float)mCompositionFbo.getBufferHeight() / (float)passes;
- glViewport(0, 0, draw->getBufferWidth(), draw->getBufferHeight());
glActiveTexture(GL_TEXTURE0);
glUniform1i(mBTextureLoc, 0);
- for (auto i = 0; i < passes; i++) {
+ glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
+ glUniform2f(mBOffsetLoc, stepX, stepY);
+ glViewport(0, 0, mPingFbo.getBufferWidth(), mPingFbo.getBufferHeight());
+ mPingFbo.bind();
+ drawMesh(mBUvLoc, mBPosLoc);
+
+ // And now we'll ping pong between our textures, to accumulate the result of various offsets.
+ GLFramebuffer* read = &mPingFbo;
+ GLFramebuffer* draw = &mPongFbo;
+ glViewport(0, 0, draw->getBufferWidth(), draw->getBufferHeight());
+ for (auto i = 1; i < passes; i++) {
ATRACE_NAME("BlurFilter::renderPass");
draw->bind();
@@ -156,9 +166,6 @@
}
mLastDrawTarget = read;
- // Cleanup
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
return NO_ERROR;
}
@@ -177,7 +184,6 @@
glBlitFramebuffer(0, 0, mLastDrawTarget->getBufferWidth(),
mLastDrawTarget->getBufferHeight(), 0, 0, mDisplayWidth, mDisplayHeight,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
return NO_ERROR;
}
@@ -256,12 +262,12 @@
}
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);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
} // namespace gl
diff --git a/libs/renderengine/gl/filters/BlurFilter.h b/libs/renderengine/gl/filters/BlurFilter.h
index 3eb5c96..7e0819f 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;
@@ -67,11 +67,10 @@
// Frame buffers holding the blur passes.
GLFramebuffer mPingFbo;
GLFramebuffer mPongFbo;
- uint32_t mDisplayWidth;
- uint32_t mDisplayHeight;
+ uint32_t mDisplayWidth = 0;
+ uint32_t mDisplayHeight = 0;
// Buffer holding the final blur pass.
GLFramebuffer* mLastDrawTarget;
- bool mTexturesAllocated = false;
// VBO containing vertex and uv data of a fullscreen triangle.
GLVertexBuffer mMeshBuffer;
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index c4a29a9..ca16d2c 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -40,9 +40,6 @@
// z=1.
Rect clip = Rect::INVALID_RECT;
- // Global transform to apply to all layers.
- mat4 globalTransform = mat4();
-
// Maximum luminance pulled from the display's HDR capabilities.
float maxLuminance = 1.0f;
@@ -55,19 +52,19 @@
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;
- // The orientation of the physical display.
+ // An additional orientation flag to be applied after clipping the output.
+ // By way of example, this may be used for supporting fullscreen screenshot
+ // capture of a device in landscape while the buffer is in portrait
+ // orientation.
uint32_t orientation = ui::Transform::ROT_0;
};
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;
}
@@ -79,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/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index afcbc50..f5bf014 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -298,7 +298,7 @@
void fillBufferPhysicalOffset();
template <typename SourceVariant>
- void fillBufferCheckers(mat4 transform);
+ void fillBufferCheckers(uint32_t rotation);
template <typename SourceVariant>
void fillBufferCheckersRotate0();
@@ -509,12 +509,12 @@
}
template <typename SourceVariant>
-void RenderEngineTest::fillBufferCheckers(mat4 transform) {
+void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
// Here logical space is 2x2
settings.clip = Rect(2, 2);
- settings.globalTransform = transform;
+ settings.orientation = orientationFlag;
std::vector<const renderengine::LayerSettings*> layers;
@@ -545,7 +545,7 @@
template <typename SourceVariant>
void RenderEngineTest::fillBufferCheckersRotate0() {
- fillBufferCheckers<SourceVariant>(mat4());
+ fillBufferCheckers<SourceVariant>(ui::Transform::ROT_0);
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 255, 0, 0,
255);
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -561,8 +561,7 @@
template <typename SourceVariant>
void RenderEngineTest::fillBufferCheckersRotate90() {
- mat4 matrix = mat4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1);
- fillBufferCheckers<SourceVariant>(matrix);
+ fillBufferCheckers<SourceVariant>(ui::Transform::ROT_90);
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 255, 0,
255);
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -578,8 +577,7 @@
template <typename SourceVariant>
void RenderEngineTest::fillBufferCheckersRotate180() {
- mat4 matrix = mat4(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 2, 2, 0, 1);
- fillBufferCheckers<SourceVariant>(matrix);
+ fillBufferCheckers<SourceVariant>(ui::Transform::ROT_180);
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0,
0);
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -595,8 +593,7 @@
template <typename SourceVariant>
void RenderEngineTest::fillBufferCheckersRotate270() {
- mat4 matrix = mat4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1);
- fillBufferCheckers<SourceVariant>(matrix);
+ fillBufferCheckers<SourceVariant>(ui::Transform::ROT_270);
expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 255,
255);
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -927,8 +924,7 @@
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(1, 1));
+ settings.clearRegion = Region(Rect(2, 4));
std::vector<const renderengine::LayerSettings*> layers;
// dummy layer, without bounds should not render anything
renderengine::LayerSettings layer;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index ba6255d..458ee67 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: [
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/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/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/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/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/InputManager.cpp b/services/inputflinger/InputManager.cpp
index fc771a2..e68946d 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -111,8 +111,10 @@
handlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>());
handlesPerDisplay[info.displayId].push_back(new BinderWindowHandle(info));
}
- for (auto const& i : handlesPerDisplay) {
- mDispatcher->setInputWindows(i.second, i.first, setInputWindowsListener);
+ mDispatcher->setInputWindows(handlesPerDisplay);
+
+ if (setInputWindowsListener) {
+ setInputWindowsListener->onSetInputWindowsFinished();
}
}
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 3b18813..7c5c9c5 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -252,7 +252,7 @@
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> window = new FakeWindowHandle(application, dispatcher, "Fake Window");
- dispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ dispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
NotifyMotionArgs motionArgs = generateMotionArgs();
@@ -288,7 +288,7 @@
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> window = new FakeWindowHandle(application, dispatcher, "Fake Window");
- dispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ dispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
for (auto _ : state) {
MotionEvent event = generateMotionEvent();
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 308d19b..4ec61b0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3621,6 +3621,18 @@
mWindowHandlesByDisplay[displayId] = newHandles;
}
+void InputDispatcher::setInputWindows(
+ const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>& handlesPerDisplay) {
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ for (auto const& i : handlesPerDisplay) {
+ setInputWindowsLocked(i.second, i.first);
+ }
+ }
+ // Wake up poll loop since it may need to make new input dispatching choices.
+ mLooper->wake();
+}
+
/**
* Called from InputManagerService, update window handle list by displayId that can receive input.
* A window handle contains information about InputChannel, Touch Region, Types, Focused,...
@@ -3628,9 +3640,8 @@
* For focused handle, check if need to change and send a cancel event to previous one.
* For removed handle, check if need to send a cancel event if already in touch.
*/
-void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>& inputWindowHandles,
- int32_t displayId,
- const sp<ISetInputWindowsListener>& setInputWindowsListener) {
+void InputDispatcher::setInputWindowsLocked(
+ const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
if (DEBUG_FOCUS) {
std::string windowList;
for (const sp<InputWindowHandle>& iwh : inputWindowHandles) {
@@ -3638,109 +3649,97 @@
}
ALOGD("setInputWindows displayId=%" PRId32 " %s", displayId, windowList.c_str());
}
- { // acquire lock
- std::scoped_lock _l(mLock);
- // Copy old handles for release if they are no longer present.
- const std::vector<sp<InputWindowHandle>> oldWindowHandles =
- getWindowHandlesLocked(displayId);
+ // Copy old handles for release if they are no longer present.
+ const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
- updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
+ updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
- sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
- bool foundHoveredWindow = false;
- for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
- // Set newFocusedWindowHandle to the top most focused window instead of the last one
- if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
- windowHandle->getInfo()->visible) {
- newFocusedWindowHandle = windowHandle;
+ sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
+ bool foundHoveredWindow = false;
+ for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
+ // Set newFocusedWindowHandle to the top most focused window instead of the last one
+ if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
+ windowHandle->getInfo()->visible) {
+ newFocusedWindowHandle = windowHandle;
+ }
+ if (windowHandle == mLastHoverWindowHandle) {
+ foundHoveredWindow = true;
+ }
+ }
+
+ if (!foundHoveredWindow) {
+ mLastHoverWindowHandle = nullptr;
+ }
+
+ sp<InputWindowHandle> oldFocusedWindowHandle =
+ getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+
+ if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) {
+ if (oldFocusedWindowHandle != nullptr) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Focus left window: %s in display %" PRId32,
+ oldFocusedWindowHandle->getName().c_str(), displayId);
}
- if (windowHandle == mLastHoverWindowHandle) {
- foundHoveredWindow = true;
+ sp<InputChannel> focusedInputChannel =
+ getInputChannelLocked(oldFocusedWindowHandle->getToken());
+ if (focusedInputChannel != nullptr) {
+ CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
+ "focus left window");
+ synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
+ enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/);
}
+ mFocusedWindowHandlesByDisplay.erase(displayId);
+ }
+ if (newFocusedWindowHandle != nullptr) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Focus entered window: %s in display %" PRId32,
+ newFocusedWindowHandle->getName().c_str(), displayId);
+ }
+ mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
+ enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/);
}
- if (!foundHoveredWindow) {
- mLastHoverWindowHandle = nullptr;
+ if (mFocusedDisplayId == displayId) {
+ onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
}
+ }
- sp<InputWindowHandle> oldFocusedWindowHandle =
- getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
-
- if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) {
- if (oldFocusedWindowHandle != nullptr) {
+ ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
+ if (stateIndex >= 0) {
+ TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
+ for (size_t i = 0; i < state.windows.size();) {
+ TouchedWindow& touchedWindow = state.windows[i];
+ if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
if (DEBUG_FOCUS) {
- ALOGD("Focus left window: %s in display %" PRId32,
- oldFocusedWindowHandle->getName().c_str(), displayId);
+ ALOGD("Touched window was removed: %s in display %" PRId32,
+ touchedWindow.windowHandle->getName().c_str(), displayId);
}
- sp<InputChannel> focusedInputChannel =
- getInputChannelLocked(oldFocusedWindowHandle->getToken());
- if (focusedInputChannel != nullptr) {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "focus left window");
- synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
- enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/);
+ sp<InputChannel> touchedInputChannel =
+ getInputChannelLocked(touchedWindow.windowHandle->getToken());
+ if (touchedInputChannel != nullptr) {
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+ "touched window was removed");
+ synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel, options);
}
- mFocusedWindowHandlesByDisplay.erase(displayId);
- }
- if (newFocusedWindowHandle != nullptr) {
- if (DEBUG_FOCUS) {
- ALOGD("Focus entered window: %s in display %" PRId32,
- newFocusedWindowHandle->getName().c_str(), displayId);
- }
- mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
- enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/);
- }
-
- if (mFocusedDisplayId == displayId) {
- onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
+ state.windows.erase(state.windows.begin() + i);
+ } else {
+ ++i;
}
}
+ }
- ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
- if (stateIndex >= 0) {
- TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
- for (size_t i = 0; i < state.windows.size();) {
- TouchedWindow& touchedWindow = state.windows[i];
- if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
- if (DEBUG_FOCUS) {
- ALOGD("Touched window was removed: %s in display %" PRId32,
- touchedWindow.windowHandle->getName().c_str(), displayId);
- }
- sp<InputChannel> touchedInputChannel =
- getInputChannelLocked(touchedWindow.windowHandle->getToken());
- if (touchedInputChannel != nullptr) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "touched window was removed");
- synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel,
- options);
- }
- state.windows.erase(state.windows.begin() + i);
- } else {
- ++i;
- }
+ // Release information for windows that are no longer present.
+ // This ensures that unused input channels are released promptly.
+ // Otherwise, they might stick around until the window handle is destroyed
+ // which might not happen until the next GC.
+ for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) {
+ if (!hasWindowHandleLocked(oldWindowHandle)) {
+ if (DEBUG_FOCUS) {
+ ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
}
+ oldWindowHandle->releaseChannel();
}
-
- // Release information for windows that are no longer present.
- // This ensures that unused input channels are released promptly.
- // Otherwise, they might stick around until the window handle is destroyed
- // which might not happen until the next GC.
- for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) {
- if (!hasWindowHandleLocked(oldWindowHandle)) {
- if (DEBUG_FOCUS) {
- ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
- }
- oldWindowHandle->releaseChannel();
- }
- }
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-
- if (setInputWindowsListener) {
- setInputWindowsListener->onSetInputWindowsFinished();
}
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 4aa47f8..cbba7e1 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -109,8 +109,8 @@
virtual std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override;
virtual void setInputWindows(
- const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId,
- const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) override;
+ const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>&
+ handlesPerDisplay) override;
virtual void setFocusedApplication(
int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) override;
virtual void setFocusedDisplay(int32_t displayId) override;
@@ -278,6 +278,8 @@
std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay
GUARDED_BY(mLock);
+ void setInputWindowsLocked(const std::vector<sp<InputWindowHandle>>& inputWindowHandles,
+ int32_t displayId) REQUIRES(mLock);
// Get window handles by display, return an empty vector if not found.
std::vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const
REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 6e98676..09dc92c 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -19,6 +19,7 @@
#include <InputListener.h>
#include <input/ISetInputWindowsListener.h>
+#include <unordered_map>
namespace android {
@@ -99,13 +100,13 @@
*/
virtual std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) = 0;
- /* Sets the list of input windows.
+ /* Sets the list of input windows per display.
*
* This method may be called on any thread (usually by the input manager).
*/
virtual void setInputWindows(
- const std::vector<sp<InputWindowHandle> >& inputWindowHandles, int32_t displayId,
- const sp<ISetInputWindowsListener>& setInputWindowsListener = nullptr) = 0;
+ const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>&
+ handlesPerDisplay) = 0;
/* Sets the focused application on the given display.
*
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index bbc8e53..99a572a 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -160,8 +160,8 @@
: InputMapper(deviceContext),
mSource(0),
mDeviceMode(DEVICE_MODE_DISABLED),
- mSurfaceWidth(-1),
- mSurfaceHeight(-1),
+ mRawSurfaceWidth(-1),
+ mRawSurfaceHeight(-1),
mSurfaceLeft(0),
mSurfaceTop(0),
mPhysicalWidth(-1),
@@ -680,7 +680,7 @@
naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.deviceHeight - naturalPhysicalWidth;
+ naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
naturalPhysicalTop = mViewport.physicalLeft;
naturalDeviceWidth = mViewport.deviceHeight;
naturalDeviceHeight = mViewport.deviceWidth;
@@ -701,7 +701,7 @@
naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
naturalPhysicalLeft = mViewport.physicalTop;
- naturalPhysicalTop = mViewport.deviceWidth - naturalPhysicalHeight;
+ naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
naturalDeviceWidth = mViewport.deviceHeight;
naturalDeviceHeight = mViewport.deviceWidth;
break;
@@ -729,10 +729,12 @@
mPhysicalLeft = naturalPhysicalLeft;
mPhysicalTop = naturalPhysicalTop;
- mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
- mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
+ mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
+ mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
+ mSurfaceRight = mSurfaceLeft + naturalLogicalWidth;
+ mSurfaceBottom = mSurfaceTop + naturalLogicalHeight;
mSurfaceOrientation =
mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0;
@@ -742,8 +744,8 @@
mPhysicalLeft = 0;
mPhysicalTop = 0;
- mSurfaceWidth = rawWidth;
- mSurfaceHeight = rawHeight;
+ mRawSurfaceWidth = rawWidth;
+ mRawSurfaceHeight = rawHeight;
mSurfaceLeft = 0;
mSurfaceTop = 0;
mSurfaceOrientation = DISPLAY_ORIENTATION_0;
@@ -769,12 +771,12 @@
if (viewportChanged || deviceModeChanged) {
ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
"display id %d",
- getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
+ getDeviceId(), getDeviceName().c_str(), mRawSurfaceWidth, mRawSurfaceHeight,
mSurfaceOrientation, mDeviceMode, mViewport.displayId);
// Configure X and Y factors.
- mXScale = float(mSurfaceWidth) / rawWidth;
- mYScale = float(mSurfaceHeight) / rawHeight;
+ mXScale = float(mRawSurfaceWidth) / rawWidth;
+ mYScale = float(mRawSurfaceHeight) / rawHeight;
mXTranslate = -mSurfaceLeft;
mYTranslate = -mSurfaceTop;
mXPrecision = 1.0f / mXScale;
@@ -793,7 +795,7 @@
mGeometricScale = avg(mXScale, mYScale);
// Size of diagonal axis.
- float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
+ float diagonalSize = hypotf(mRawSurfaceWidth, mRawSurfaceHeight);
// Size factors.
if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
@@ -956,13 +958,13 @@
mOrientedYPrecision = mXPrecision;
mOrientedRanges.x.min = mYTranslate;
- mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
+ mOrientedRanges.x.max = mRawSurfaceHeight + mYTranslate - 1;
mOrientedRanges.x.flat = 0;
mOrientedRanges.x.fuzz = 0;
mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
mOrientedRanges.y.min = mXTranslate;
- mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
+ mOrientedRanges.y.max = mRawSurfaceWidth + mXTranslate - 1;
mOrientedRanges.y.flat = 0;
mOrientedRanges.y.fuzz = 0;
mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
@@ -973,13 +975,13 @@
mOrientedYPrecision = mYPrecision;
mOrientedRanges.x.min = mXTranslate;
- mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
+ mOrientedRanges.x.max = mRawSurfaceWidth + mXTranslate - 1;
mOrientedRanges.x.flat = 0;
mOrientedRanges.x.fuzz = 0;
mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
mOrientedRanges.y.min = mYTranslate;
- mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
+ mOrientedRanges.y.max = mRawSurfaceHeight + mYTranslate - 1;
mOrientedRanges.y.flat = 0;
mOrientedRanges.y.fuzz = 0;
mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
@@ -992,7 +994,7 @@
if (mDeviceMode == DEVICE_MODE_POINTER) {
// Compute pointer gesture detection parameters.
float rawDiagonal = hypotf(rawWidth, rawHeight);
- float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
+ float displayDiagonal = hypotf(mRawSurfaceWidth, mRawSurfaceHeight);
// Scale movements such that one whole swipe of the touch pad covers a
// given area relative to the diagonal size of the display when no acceleration
@@ -1027,10 +1029,12 @@
void TouchInputMapper::dumpSurface(std::string& dump) {
dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
- dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
- dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
+ dump += StringPrintf(INDENT3 "RawSurfaceWidth: %dpx\n", mRawSurfaceWidth);
+ dump += StringPrintf(INDENT3 "RawSurfaceHeight: %dpx\n", mRawSurfaceHeight);
dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+ dump += StringPrintf(INDENT3 "SurfaceRight: %d\n", mSurfaceRight);
+ dump += StringPrintf(INDENT3 "SurfaceBottom: %d\n", mSurfaceBottom);
dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
@@ -1074,16 +1078,16 @@
int32_t halfHeight = virtualKeyDefinition.height / 2;
virtualKey.hitLeft =
- (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mSurfaceWidth +
+ (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mRawSurfaceWidth +
touchScreenLeft;
virtualKey.hitRight =
- (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mSurfaceWidth +
+ (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mRawSurfaceWidth +
touchScreenLeft;
- virtualKey.hitTop =
- (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight / mSurfaceHeight +
+ virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight /
+ mRawSurfaceHeight +
touchScreenTop;
- virtualKey.hitBottom =
- (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mSurfaceHeight +
+ virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight /
+ mRawSurfaceHeight +
touchScreenTop;
mVirtualKeys.push_back(virtualKey);
}
@@ -2188,13 +2192,10 @@
rotateAndScale(xTransformed, yTransformed);
// Adjust X, Y, and coverage coords for surface orientation.
- float x, y;
float left, top, right, bottom;
switch (mSurfaceOrientation) {
case DISPLAY_ORIENTATION_90:
- x = yTransformed + mYTranslate;
- y = xTransformed + mXTranslate;
left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
@@ -2207,8 +2208,6 @@
}
break;
case DISPLAY_ORIENTATION_180:
- x = xTransformed + mXTranslate;
- y = yTransformed + mYTranslate;
left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
@@ -2221,8 +2220,6 @@
}
break;
case DISPLAY_ORIENTATION_270:
- x = yTransformed + mYTranslate;
- y = xTransformed + mXTranslate;
left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
@@ -2235,8 +2232,6 @@
}
break;
default:
- x = xTransformed + mXTranslate;
- y = yTransformed + mYTranslate;
left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
@@ -2247,8 +2242,8 @@
// Write output coords.
PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
out.clear();
- out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ out.setAxisValue(AMOTION_EVENT_AXIS_X, xTransformed);
+ out.setAxisValue(AMOTION_EVENT_AXIS_Y, yTransformed);
out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
@@ -3624,34 +3619,47 @@
abortTouches(when, 0 /* policyFlags*/);
}
+// Transform raw coordinate to surface coordinate
void TouchInputMapper::rotateAndScale(float& x, float& y) {
+ // Scale to surface coordinate.
+ const float xScaled = float(x - mRawPointerAxes.x.minValue) * mXScale;
+ const float yScaled = float(y - mRawPointerAxes.y.minValue) * mYScale;
+
+ // Rotate to surface coordinate.
+ // 0 - no swap and reverse.
+ // 90 - swap x/y and reverse y.
+ // 180 - reverse x, y.
+ // 270 - swap x/y and reverse x.
switch (mSurfaceOrientation) {
+ case DISPLAY_ORIENTATION_0:
+ x = xScaled + mXTranslate;
+ y = yScaled + mYTranslate;
+ break;
case DISPLAY_ORIENTATION_90:
- x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
- y = float(y - mRawPointerAxes.y.minValue) * mYScale;
+ y = mSurfaceRight - xScaled;
+ x = yScaled + mYTranslate;
break;
case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
- y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+ x = mSurfaceRight - xScaled;
+ y = mSurfaceBottom - yScaled;
break;
case DISPLAY_ORIENTATION_270:
- x = float(x - mRawPointerAxes.x.minValue) * mXScale;
- y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+ y = xScaled + mXTranslate;
+ x = mSurfaceBottom - yScaled;
break;
default:
- x = float(x - mRawPointerAxes.x.minValue) * mXScale;
- y = float(y - mRawPointerAxes.y.minValue) * mYScale;
- break;
+ assert(false);
}
}
bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
- float xTransformed = x, yTransformed = y;
- rotateAndScale(xTransformed, yTransformed);
+ const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale;
+ const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale;
+
return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
- xTransformed >= mSurfaceLeft && xTransformed <= mSurfaceLeft + mSurfaceWidth &&
+ xScaled >= mSurfaceLeft && xScaled <= mSurfaceRight &&
y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
- yTransformed >= mSurfaceTop && yTransformed <= mSurfaceTop + mSurfaceHeight;
+ yScaled >= mSurfaceTop && yScaled <= mSurfaceBottom;
}
const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index e21a33a..58bfc5c 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -407,12 +407,16 @@
// The surface orientation, width and height set by configureSurface().
// The width and height are derived from the viewport but are specified
// in the natural orientation.
+ // They could be used for calculating diagonal, scaling factors, and virtual keys.
+ int32_t mRawSurfaceWidth;
+ int32_t mRawSurfaceHeight;
+
// The surface origin specifies how the surface coordinates should be translated
// to align with the logical display coordinate space.
- int32_t mSurfaceWidth;
- int32_t mSurfaceHeight;
int32_t mSurfaceLeft;
int32_t mSurfaceTop;
+ int32_t mSurfaceRight;
+ int32_t mSurfaceBottom;
// Similar to the surface coordinates, but in the raw display coordinate space rather than in
// the logical coordinate space.
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index be2e19e..71731b0 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -34,6 +34,7 @@
using android::sp;
using android::UinputHomeKey;
using std::chrono_literals::operator""ms;
+using std::chrono_literals::operator""s;
static constexpr bool DEBUG = false;
@@ -70,11 +71,12 @@
mEventHub = std::make_unique<EventHub>();
consumeInitialDeviceAddedEvents();
mKeyboard = createUinputDevice<UinputHomeKey>();
- mDeviceId = waitForDeviceCreation();
+ ASSERT_NO_FATAL_FAILURE(mDeviceId = waitForDeviceCreation());
}
virtual void TearDown() override {
mKeyboard.reset();
waitForDeviceClose(mDeviceId);
+ assertNoMoreEvents();
}
/**
@@ -83,21 +85,38 @@
int32_t waitForDeviceCreation();
void waitForDeviceClose(int32_t deviceId);
void consumeInitialDeviceAddedEvents();
- std::vector<RawEvent> getEvents(std::chrono::milliseconds timeout = 5ms);
+ void assertNoMoreEvents();
+ /**
+ * Read events from the EventHub.
+ *
+ * If expectedEvents is set, wait for a significant period of time to try and ensure that
+ * the expected number of events has been read. The number of returned events
+ * may be smaller (if timeout has been reached) or larger than expectedEvents.
+ *
+ * If expectedEvents is not set, return all of the immediately available events.
+ */
+ std::vector<RawEvent> getEvents(std::optional<size_t> expectedEvents = std::nullopt);
};
-std::vector<RawEvent> EventHubTest::getEvents(std::chrono::milliseconds timeout) {
+std::vector<RawEvent> EventHubTest::getEvents(std::optional<size_t> expectedEvents) {
static constexpr size_t EVENT_BUFFER_SIZE = 256;
std::array<RawEvent, EVENT_BUFFER_SIZE> eventBuffer;
std::vector<RawEvent> events;
while (true) {
- size_t count =
+ std::chrono::milliseconds timeout = 0s;
+ if (expectedEvents) {
+ timeout = 2s;
+ }
+ const size_t count =
mEventHub->getEvents(timeout.count(), eventBuffer.data(), eventBuffer.size());
if (count == 0) {
break;
}
events.insert(events.end(), eventBuffer.begin(), eventBuffer.begin() + count);
+ if (expectedEvents && events.size() >= *expectedEvents) {
+ break;
+ }
}
if (DEBUG) {
dumpEvents(events);
@@ -111,7 +130,7 @@
* it will return a lot of "device added" type of events.
*/
void EventHubTest::consumeInitialDeviceAddedEvents() {
- std::vector<RawEvent> events = getEvents(0ms);
+ std::vector<RawEvent> events = getEvents();
std::set<int32_t /*deviceId*/> existingDevices;
// All of the events should be DEVICE_ADDED type, except the last one.
for (size_t i = 0; i < events.size() - 1; i++) {
@@ -128,8 +147,11 @@
int32_t EventHubTest::waitForDeviceCreation() {
// Wait a little longer than usual, to ensure input device has time to be created
- std::vector<RawEvent> events = getEvents(20ms);
- EXPECT_EQ(2U, events.size()); // Using "expect" because the function is non-void.
+ std::vector<RawEvent> events = getEvents(2);
+ if (events.size() != 2) {
+ ADD_FAILURE() << "Instead of 2 events, received " << events.size();
+ return 0; // this value is unused
+ }
const RawEvent& deviceAddedEvent = events[0];
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_ADDED), deviceAddedEvent.type);
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceAddedEvent.deviceId);
@@ -142,7 +164,7 @@
}
void EventHubTest::waitForDeviceClose(int32_t deviceId) {
- std::vector<RawEvent> events = getEvents(20ms);
+ std::vector<RawEvent> events = getEvents(2);
ASSERT_EQ(2U, events.size());
const RawEvent& deviceRemovedEvent = events[0];
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_REMOVED), deviceRemovedEvent.type);
@@ -152,6 +174,11 @@
finishedDeviceScanEvent.type);
}
+void EventHubTest::assertNoMoreEvents() {
+ std::vector<RawEvent> events = getEvents();
+ ASSERT_TRUE(events.empty());
+}
+
/**
* Ensure that input_events are generated with monotonic clock.
* That means input_event should receive a timestamp that is in the future of the time
@@ -162,7 +189,7 @@
nsecs_t lastEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
ASSERT_NO_FATAL_FAILURE(mKeyboard->pressAndReleaseHomeKey());
- std::vector<RawEvent> events = getEvents();
+ std::vector<RawEvent> events = getEvents(4);
ASSERT_EQ(4U, events.size()) << "Expected to receive 2 keys and 2 syncs, total of 4 events";
for (const RawEvent& event : events) {
// Cannot use strict comparison because the events may happen too quickly
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 1f283b1..e0d32a0 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -491,7 +491,7 @@
// --- InputDispatcherTest SetInputWindowTest ---
static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
-static constexpr int32_t DISPATCHING_TIMEOUT = 100;
+static constexpr nsecs_t DISPATCHING_TIMEOUT = seconds_to_nanoseconds(5);
class FakeApplicationHandle : public InputApplicationHandle {
public:
@@ -871,7 +871,7 @@
sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
<< "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
@@ -888,7 +888,7 @@
sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
<< "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
@@ -910,7 +910,7 @@
// Display should have only one focused window
windowSecond->setFocus(true);
- mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
windowSecond->consumeFocusEvent(true);
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
@@ -935,7 +935,7 @@
windowTop->setFocus(true);
windowSecond->setFocus(true);
- mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
windowTop->consumeFocusEvent(true);
ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
<< "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
@@ -960,7 +960,7 @@
windowSecond->setFocus(true);
// Release channel for window is no longer valid.
windowTop->releaseChannel();
- mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
windowSecond->consumeFocusEvent(true);
// Test inject a key down, should dispatch to a valid window.
@@ -986,7 +986,7 @@
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
- mDispatcher->setInputWindows({windowLeft, windowRight}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
// Inject an event with coordinate in the area of right window, with mouse cursor in the area of
// left window. This event should be dispatched to the left window.
@@ -1003,7 +1003,7 @@
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFocus(true);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true);
NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
@@ -1025,7 +1025,7 @@
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
NotifyMotionArgs motionArgs =
generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
@@ -1053,7 +1053,7 @@
"Second Window", ADISPLAY_ID_DEFAULT);
// Add the windows to the dispatcher
- mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
// Send down to the first window
NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
@@ -1090,7 +1090,7 @@
"Second Window", ADISPLAY_ID_DEFAULT);
// Add the windows to the dispatcher
- mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
// Send down to the first window
NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
@@ -1152,7 +1152,7 @@
| InputWindowInfo::FLAG_SPLIT_TOUCH);
// Add the windows to the dispatcher
- mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
PointF pointInFirst = {300, 200};
PointF pointInSecond = {300, 600};
@@ -1204,7 +1204,7 @@
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
window->setFocus(true);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true);
@@ -1220,7 +1220,7 @@
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
mDispatcher->notifyKey(&keyArgs);
@@ -1235,7 +1235,7 @@
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
// Send key
NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
@@ -1289,7 +1289,7 @@
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
true /*isGestureMonitor*/);
@@ -1309,7 +1309,7 @@
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
window->setFocus(true);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true);
FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
@@ -1325,7 +1325,7 @@
sp<FakeApplicationHandle> application = new FakeApplicationHandle();
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
true /*isGestureMonitor*/);
@@ -1351,7 +1351,7 @@
sp<FakeWindowHandle> window =
new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
NotifyMotionArgs motionArgs =
generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
@@ -1387,29 +1387,29 @@
window->setFocus(true);
SCOPED_TRACE("Check default value of touch mode");
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
SCOPED_TRACE("Remove the window to trigger focus loss");
window->setFocus(false);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
SCOPED_TRACE("Disable touch mode");
mDispatcher->setInTouchMode(false);
window->setFocus(true);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
SCOPED_TRACE("Remove the window to trigger focus loss");
window->setFocus(false);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
SCOPED_TRACE("Enable touch mode again");
mDispatcher->setInTouchMode(true);
window->setFocus(true);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
window->assertNoEvents();
@@ -1423,7 +1423,7 @@
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
window->setFocus(true);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
@@ -1459,7 +1459,7 @@
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
- mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
NotifyMotionArgs motionArgs =
generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
@@ -1512,7 +1512,7 @@
mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
mWindow->setFocus(true);
- mDispatcher->setInputWindows({mWindow}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
mWindow->consumeFocusEvent(true);
}
@@ -1602,7 +1602,7 @@
// Set focus window for primary display, but focused display would be second one.
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
windowInPrimary->setFocus(true);
- mDispatcher->setInputWindows({windowInPrimary}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
windowInPrimary->consumeFocusEvent(true);
application2 = new FakeApplicationHandle();
@@ -1614,7 +1614,7 @@
// Set focus window for second display.
mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
windowInSecondary->setFocus(true);
- mDispatcher->setInputWindows({windowInSecondary}, SECOND_DISPLAY_ID);
+ mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
windowInSecondary->consumeFocusEvent(true);
}
@@ -1664,7 +1664,7 @@
windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
// Remove all windows in secondary display.
- mDispatcher->setInputWindows({}, SECOND_DISPLAY_ID);
+ mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
// Expect old focus should receive a cancel event.
windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
@@ -1828,7 +1828,7 @@
mFocusedWindow->setFocus(true);
// Expect one focus window exist in display.
- mDispatcher->setInputWindows({mUnfocusedWindow, mFocusedWindow}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
mFocusedWindow->consumeFocusEvent(true);
}
@@ -1852,6 +1852,7 @@
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());
@@ -1864,6 +1865,7 @@
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 +1876,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();
@@ -1888,6 +1891,7 @@
injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
<< "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+ mFocusedWindow->consumeMotionDown();
ASSERT_TRUE(mDispatcher->waitForIdle());
mFakePolicy->assertOnPointerDownWasNotCalled();
@@ -1916,7 +1920,7 @@
mWindow2->setId(1);
mWindow2->setFrame(Rect(100, 100, 200, 200));
- mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
}
protected:
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 618aefc..96d86b6 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -6990,51 +6990,7 @@
ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
}
-/**
- * Test touch should not work if outside of surface.
- */
-TEST_F(MultiTouchInputMapperTest, Viewports_SurfaceRange) {
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
- // Touch on left-top area should work.
- int32_t rawX = DISPLAY_WIDTH / 2 - 1;
- int32_t rawY = DISPLAY_HEIGHT / 2 - 1;
- processPosition(mapper, rawX, rawY);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-
- // Reset.
- mapper.reset(ARBITRARY_TIME);
-
- // Let logical display be different to physical display and rotate 90-degrees.
- std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- internalViewport->orientation = DISPLAY_ORIENTATION_90;
- internalViewport->logicalLeft = 0;
- internalViewport->logicalTop = 0;
- internalViewport->logicalRight = DISPLAY_HEIGHT;
- internalViewport->logicalBottom = DISPLAY_WIDTH / 2;
-
- internalViewport->physicalLeft = DISPLAY_HEIGHT;
- internalViewport->physicalTop = DISPLAY_WIDTH / 2;
- internalViewport->physicalRight = DISPLAY_HEIGHT;
- internalViewport->physicalBottom = DISPLAY_WIDTH;
-
- internalViewport->deviceWidth = DISPLAY_HEIGHT;
- internalViewport->deviceHeight = DISPLAY_WIDTH;
- mFakePolicy->updateViewport(internalViewport.value());
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- // Display align to right-top after rotate 90-degrees, touch on left-top area should not work.
- processPosition(mapper, rawX, rawY);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
addConfigurationProperty("touch.deviceType", "touchScreen");
@@ -7161,4 +7117,130 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
}
+
+/**
+ * Test touch should not work if outside of surface.
+ */
+class MultiTouchInputMapperTest_SurfaceRange : public MultiTouchInputMapperTest {
+protected:
+ void halfDisplayToCenterHorizontal(int32_t orientation) {
+ std::optional<DisplayViewport> internalViewport =
+ mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+
+ // Half display to (width/4, 0, width * 3/4, height) to make display has offset.
+ internalViewport->orientation = orientation;
+ if (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270) {
+ internalViewport->logicalLeft = 0;
+ internalViewport->logicalTop = 0;
+ internalViewport->logicalRight = DISPLAY_HEIGHT;
+ internalViewport->logicalBottom = DISPLAY_WIDTH / 2;
+
+ internalViewport->physicalLeft = 0;
+ internalViewport->physicalTop = DISPLAY_WIDTH / 4;
+ internalViewport->physicalRight = DISPLAY_HEIGHT;
+ internalViewport->physicalBottom = DISPLAY_WIDTH * 3 / 4;
+
+ internalViewport->deviceWidth = DISPLAY_HEIGHT;
+ internalViewport->deviceHeight = DISPLAY_WIDTH;
+ } else {
+ internalViewport->logicalLeft = 0;
+ internalViewport->logicalTop = 0;
+ internalViewport->logicalRight = DISPLAY_WIDTH / 2;
+ internalViewport->logicalBottom = DISPLAY_HEIGHT;
+
+ internalViewport->physicalLeft = DISPLAY_WIDTH / 4;
+ internalViewport->physicalTop = 0;
+ internalViewport->physicalRight = DISPLAY_WIDTH * 3 / 4;
+ internalViewport->physicalBottom = DISPLAY_HEIGHT;
+
+ internalViewport->deviceWidth = DISPLAY_WIDTH;
+ internalViewport->deviceHeight = DISPLAY_HEIGHT;
+ }
+
+ mFakePolicy->updateViewport(internalViewport.value());
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ }
+
+ void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xInside, int32_t yInside,
+ int32_t xOutside, int32_t yOutside, int32_t xExpected,
+ int32_t yExpected) {
+ // touch on outside area should not work.
+ processPosition(mapper, toRawX(xOutside), toRawY(yOutside));
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // touch on inside area should receive the event.
+ NotifyMotionArgs args;
+ processPosition(mapper, toRawX(xInside), toRawY(yInside));
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_NEAR(xExpected, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
+ ASSERT_NEAR(yExpected, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
+
+ // Reset.
+ mapper.reset(ARBITRARY_TIME);
+ }
+};
+
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Touch on center of normal display should work.
+ const int32_t x = DISPLAY_WIDTH / 4;
+ const int32_t y = DISPLAY_HEIGHT / 2;
+ processPosition(mapper, toRawX(x), toRawY(y));
+ processSync(mapper);
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], x, y, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f));
+ // Reset.
+ mapper.reset(ARBITRARY_TIME);
+
+ // Let physical display be different to device, and make surface and physical could be 1:1.
+ halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_0);
+
+ const int32_t xExpected = (x + 1) - (DISPLAY_WIDTH / 4);
+ const int32_t yExpected = y;
+ processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
+}
+
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Half display to (width/4, 0, width * 3/4, height) and rotate 90-degrees.
+ halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_90);
+
+ const int32_t x = DISPLAY_WIDTH / 4;
+ const int32_t y = DISPLAY_HEIGHT / 2;
+
+ // expect x/y = swap x/y then reverse y.
+ const int32_t xExpected = y;
+ const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1);
+ processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
+}
+
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Half display to (width/4, 0, width * 3/4, height) and rotate 270-degrees.
+ halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_270);
+
+ const int32_t x = DISPLAY_WIDTH / 4;
+ const int32_t y = DISPLAY_HEIGHT / 2;
+
+ // expect x/y = swap x/y then reverse x.
+ constexpr int32_t xExpected = DISPLAY_HEIGHT - y;
+ constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4;
+ processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
+}
} // namespace android
diff --git a/services/inputflinger/tests/UinputDevice.cpp b/services/inputflinger/tests/UinputDevice.cpp
index 99480b7..10e7293 100644
--- a/services/inputflinger/tests/UinputDevice.cpp
+++ b/services/inputflinger/tests/UinputDevice.cpp
@@ -44,9 +44,7 @@
device.id.product = 0x01;
device.id.version = 1;
- // Using EXPECT instead of ASSERT to allow the device creation to continue even when
- // some failures are reported when configuring the device.
- EXPECT_NO_FATAL_FAILURE(configureDevice(mDeviceFd, &device));
+ ASSERT_NO_FATAL_FAILURE(configureDevice(mDeviceFd, &device));
if (write(mDeviceFd, &device, sizeof(device)) < 0) {
FAIL() << "Could not write uinput_user_dev struct into uinput file descriptor: "
@@ -70,7 +68,7 @@
" with value %" PRId32 " : %s",
type, code, value, strerror(errno));
ALOGE("%s", msg.c_str());
- ADD_FAILURE() << msg.c_str();
+ FAIL() << msg.c_str();
}
}
@@ -82,41 +80,41 @@
void UinputKeyboard::configureDevice(int fd, uinput_user_dev* device) {
// enable key press/release event
if (ioctl(fd, UI_SET_EVBIT, EV_KEY)) {
- ADD_FAILURE() << "Error in ioctl : UI_SET_EVBIT : EV_KEY: " << strerror(errno);
+ FAIL() << "Error in ioctl : UI_SET_EVBIT : EV_KEY: " << strerror(errno);
}
// enable set of KEY events
std::for_each(mKeys.begin(), mKeys.end(), [fd](int key) {
if (ioctl(fd, UI_SET_KEYBIT, key)) {
- ADD_FAILURE() << "Error in ioctl : UI_SET_KEYBIT : " << key << " : " << strerror(errno);
+ FAIL() << "Error in ioctl : UI_SET_KEYBIT : " << key << " : " << strerror(errno);
}
});
// enable synchronization event
if (ioctl(fd, UI_SET_EVBIT, EV_SYN)) {
- ADD_FAILURE() << "Error in ioctl : UI_SET_EVBIT : EV_SYN: " << strerror(errno);
+ FAIL() << "Error in ioctl : UI_SET_EVBIT : EV_SYN: " << strerror(errno);
}
}
void UinputKeyboard::pressKey(int key) {
if (mKeys.find(key) == mKeys.end()) {
- ADD_FAILURE() << mName << ": Cannot inject key press: Key not found: " << key;
+ FAIL() << mName << ": Cannot inject key press: Key not found: " << key;
}
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, key, 1));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, key, 1);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputKeyboard::releaseKey(int key) {
if (mKeys.find(key) == mKeys.end()) {
- ADD_FAILURE() << mName << ": Cannot inject key release: Key not found: " << key;
+ FAIL() << mName << ": Cannot inject key release: Key not found: " << key;
}
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, key, 0));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, key, 0);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputKeyboard::pressAndReleaseKey(int key) {
- EXPECT_NO_FATAL_FAILURE(pressKey(key));
- EXPECT_NO_FATAL_FAILURE(releaseKey(key));
+ pressKey(key);
+ releaseKey(key);
}
// --- UinputHomeKey ---
@@ -124,7 +122,7 @@
UinputHomeKey::UinputHomeKey() : UinputKeyboard({KEY_HOME}) {}
void UinputHomeKey::pressAndReleaseHomeKey() {
- EXPECT_NO_FATAL_FAILURE(pressAndReleaseKey(KEY_HOME));
+ pressAndReleaseKey(KEY_HOME);
}
// --- UinputTouchScreen ---
@@ -158,35 +156,35 @@
}
void UinputTouchScreen::sendSlot(int32_t slot) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_SLOT, slot));
+ injectEvent(EV_ABS, ABS_MT_SLOT, slot);
}
void UinputTouchScreen::sendTrackingId(int32_t trackingId) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_TRACKING_ID, trackingId));
+ injectEvent(EV_ABS, ABS_MT_TRACKING_ID, trackingId);
}
void UinputTouchScreen::sendDown(const Point& point) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, BTN_TOUCH, 1));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, BTN_TOUCH, 1);
+ injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x);
+ injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputTouchScreen::sendMove(const Point& point) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x);
+ injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputTouchScreen::sendUp() {
sendTrackingId(0xffffffff);
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, BTN_TOUCH, 0));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_KEY, BTN_TOUCH, 0);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
void UinputTouchScreen::sendToolType(int32_t toolType) {
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_TOOL_TYPE, toolType));
- EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
+ injectEvent(EV_ABS, ABS_MT_TOOL_TYPE, toolType);
+ injectEvent(EV_SYN, SYN_REPORT, 0);
}
// Get the center x, y base on the range definition.
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 9a13c00..e799372 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -91,11 +91,11 @@
result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
"max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
mMaxCacheSize);
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
+ for (auto& it : mSensorInfo) {
+ const FlushInfo& flushInfo = it.second;
result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
- mService->getSensorName(mSensorInfo.keyAt(i)).string(),
- mSensorInfo.keyAt(i),
+ mService->getSensorName(it.first).string(),
+ it.first,
flushInfo.mFirstFlushPending ? "First flush pending" :
"active",
flushInfo.mPendingFlushEventsToSend);
@@ -135,12 +135,12 @@
proto->write(UID, int32_t(mUid));
proto->write(CACHE_SIZE, int32_t(mCacheSize));
proto->write(MAX_CACHE_SIZE, int32_t(mMaxCacheSize));
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
+ for (auto& it : mSensorInfo) {
+ const FlushInfo& flushInfo = it.second;
const uint64_t token = proto->start(FLUSH_INFOS);
proto->write(FlushInfoProto::SENSOR_NAME,
- std::string(mService->getSensorName(mSensorInfo.keyAt(i))));
- proto->write(FlushInfoProto::SENSOR_HANDLE, mSensorInfo.keyAt(i));
+ std::string(mService->getSensorName(it.first)));
+ proto->write(FlushInfoProto::SENSOR_HANDLE, it.first);
proto->write(FlushInfoProto::FIRST_FLUSH_PENDING, flushInfo.mFirstFlushPending);
proto->write(FlushInfoProto::PENDING_FLUSH_EVENTS_TO_SEND,
flushInfo.mPendingFlushEventsToSend);
@@ -162,24 +162,33 @@
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
if (si == nullptr ||
!canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
- mSensorInfo.indexOfKey(handle) >= 0) {
+ mSensorInfo.count(handle) > 0) {
return false;
}
- mSensorInfo.add(handle, FlushInfo());
+ mSensorInfo[handle] = FlushInfo();
return true;
}
bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
- if (mSensorInfo.removeItem(handle) >= 0) {
+ if (mSensorInfo.erase(handle) >= 0) {
return true;
}
return false;
}
+std::vector<int32_t> SensorService::SensorEventConnection::getActiveSensorHandles() const {
+ Mutex::Autolock _l(mConnectionLock);
+ std::vector<int32_t> list;
+ for (auto& it : mSensorInfo) {
+ list.push_back(it.first);
+ }
+ return list;
+}
+
bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
Mutex::Autolock _l(mConnectionLock);
- return mSensorInfo.indexOfKey(handle) >= 0;
+ return mSensorInfo.count(handle) > 0;
}
bool SensorService::SensorEventConnection::hasAnySensor() const {
@@ -189,8 +198,8 @@
bool SensorService::SensorEventConnection::hasOneShotSensors() const {
Mutex::Autolock _l(mConnectionLock);
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- const int handle = mSensorInfo.keyAt(i);
+ for (auto &it : mSensorInfo) {
+ const int handle = it.first;
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
if (si != nullptr && si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
return true;
@@ -206,9 +215,8 @@
void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
bool value) {
Mutex::Autolock _l(mConnectionLock);
- ssize_t index = mSensorInfo.indexOfKey(handle);
- if (index >= 0) {
- FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+ if (mSensorInfo.count(handle) > 0) {
+ FlushInfo& flushInfo = mSensorInfo[handle];
flushInfo.mFirstFlushPending = value;
}
}
@@ -233,8 +241,8 @@
int looper_flags = 0;
if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- const int handle = mSensorInfo.keyAt(i);
+ for (auto& it : mSensorInfo) {
+ const int handle = it.first;
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
if (si != nullptr && si->getSensor().isWakeUpSensor()) {
looper_flags |= ALOOPER_EVENT_INPUT;
@@ -266,9 +274,8 @@
void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
- ssize_t index = mSensorInfo.indexOfKey(handle);
- if (index >= 0) {
- FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+ if (mSensorInfo.count(handle) > 0) {
+ FlushInfo& flushInfo = mSensorInfo[handle];
flushInfo.mPendingFlushEventsToSend++;
}
}
@@ -296,15 +303,14 @@
sensor_handle = buffer[i].meta_data.sensor;
}
- ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
// Check if this connection has registered for this sensor. If not continue to the
// next sensor_event.
- if (index < 0) {
+ if (mSensorInfo.count(sensor_handle) == 0) {
++i;
continue;
}
- FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+ 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) {
@@ -522,14 +528,14 @@
flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
// Loop through all the sensors for this connection and check if there are any pending
// flush complete events to be sent.
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- const int handle = mSensorInfo.keyAt(i);
+ for (auto& it : mSensorInfo) {
+ const int handle = it.first;
sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
if (si == nullptr) {
continue;
}
- FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
+ FlushInfo& flushInfo = it.second;
while (flushInfo.mPendingFlushEventsToSend > 0) {
flushCompleteEvent.meta_data.sensor = handle;
bool wakeUpSensor = si->getSensor().isWakeUpSensor();
@@ -615,14 +621,13 @@
// separately before the next batch of events.
for (int j = 0; j < numEventsDropped; ++j) {
if (scratch[j].type == SENSOR_TYPE_META_DATA) {
- ssize_t index = mSensorInfo.indexOfKey(scratch[j].meta_data.sensor);
- if (index < 0) {
+ if (mSensorInfo.count(scratch[j].meta_data.sensor) == 0) {
ALOGW("%s: sensor 0x%x is not found in connection",
__func__, scratch[j].meta_data.sensor);
continue;
}
- FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+ FlushInfo& flushInfo = mSensorInfo[scratch[j].meta_data.sensor];
flushInfo.mPendingFlushEventsToSend++;
ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
flushInfo.mPendingFlushEventsToSend);
@@ -764,8 +769,8 @@
int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const {
size_t fifoWakeUpSensors = 0;
size_t fifoNonWakeUpSensors = 0;
- for (size_t i = 0; i < mSensorInfo.size(); ++i) {
- sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(mSensorInfo.keyAt(i));
+ for (auto& it : mSensorInfo) {
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(it.first);
if (si == nullptr) {
continue;
}
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index caf5d7c..1ca35c0 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -23,7 +23,6 @@
#include <utils/Vector.h>
#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/AndroidThreads.h>
#include <utils/RefBase.h>
@@ -60,6 +59,7 @@
bool hasOneShotSensors() const;
bool addSensor(int32_t handle);
bool removeSensor(int32_t handle);
+ std::vector<int32_t> getActiveSensorHandles() const;
void setFirstFlushPending(int32_t handle, bool value);
void dump(String8& result);
void dump(util::ProtoOutputStream* proto) const;
@@ -169,8 +169,8 @@
FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
};
- // protected by SensorService::mLock. Key for this vector is the sensor handle.
- KeyedVector<int, FlushInfo> mSensorInfo;
+ // protected by SensorService::mLock. Key for this map is the sensor handle.
+ std::unordered_map<int32_t, FlushInfo> mSensorInfo;
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 22a15c6..5fdc74f 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1740,8 +1740,7 @@
status_t err(NO_ERROR);
Mutex::Autolock _l(mLock);
// Loop through all sensors for this connection and call flush on each of them.
- for (size_t i = 0; i < connection->mSensorInfo.size(); ++i) {
- const int handle = connection->mSensorInfo.keyAt(i);
+ for (int handle : connection->getActiveSensorHandles()) {
sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
if (sensor == nullptr) {
continue;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index e4d754c..54cd04f 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -272,7 +272,7 @@
// pixel format is HDR Y410 masquerading as RGBA_1010102
return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ &&
mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA &&
- mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
+ mBufferInfo.mPixelFormat == HAL_PIXEL_FORMAT_RGBA_1010102);
}
sp<compositionengine::LayerFE> BufferLayer::getCompositionEngineLayerFE() const {
@@ -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) {
@@ -374,6 +381,12 @@
return true;
}
+void BufferLayer::gatherBufferInfo() {
+ mBufferInfo.mPixelFormat =
+ !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format;
+ mBufferInfo.mFrameLatencyNeeded = true;
+}
+
bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
nsecs_t expectedPresentTime) {
ATRACE_CALL();
@@ -434,7 +447,6 @@
gatherBufferInfo();
mRefreshPending = true;
- mBufferInfo.mFrameLatencyNeeded = true;
if (oldBufferInfo.mBuffer == nullptr) {
// the first time we receive a buffer, we need to trigger a
// geometry invalidation.
@@ -613,6 +625,39 @@
sourceCrop.getWidth() != displayFrame.getWidth();
}
+bool BufferLayer::needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+ 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);
+ if (outputLayer == nullptr) {
+ return false;
+ }
+
+ // 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 inverseTransform = inverseParentTransform * displayTransform.inverse();
+ // Undo the transformation of the displayFrame so that we're back into
+ // layer-stack space.
+ const Rect frame = inverseTransform.transform(compositionState.displayFrame);
+ const FloatRect sourceCrop = compositionState.sourceCrop;
+
+ int32_t frameHeight = frame.getHeight();
+ int32_t frameWidth = frame.getWidth();
+ // If the display transform had a rotational component then undo the
+ // rotation so that the orientation matches the source crop.
+ if (displayTransform.getOrientation() & ui::Transform::ROT_90) {
+ std::swap(frameHeight, frameWidth);
+ }
+ return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth;
+}
+
uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const {
if (hasFrameUpdate()) {
return getFrameNumber(expectedPresentTime);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index f678910..56bab1b 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -161,7 +161,7 @@
Region mSurfaceDamage;
HdrMetadata mHdrMetadata;
int mApi;
- PixelFormat mPixelFormat;
+ PixelFormat mPixelFormat{PIXEL_FORMAT_NONE};
bool mTransformToDisplayInverse{false};
sp<GraphicBuffer> mBuffer;
@@ -208,6 +208,8 @@
private:
// Returns true if this layer requires filtering
bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const override;
+ bool needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+ const ui::Transform& inverseParentTransform) const override;
// BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
// and its parent layer is not bounded
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 4e5c593..f4e630e 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -365,21 +365,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
// -----------------------------------------------------------------------
@@ -525,8 +510,6 @@
return BAD_VALUE;
}
- mFormat = format;
-
setDefaultBufferSize(w, h);
mConsumer->setDefaultBufferFormat(format);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
@@ -550,6 +533,8 @@
}
void BufferQueueLayer::gatherBufferInfo() {
+ BufferLayer::gatherBufferInfo();
+
mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp();
mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime();
mBufferInfo.mFence = mConsumer->getCurrentFence();
@@ -560,7 +545,6 @@
mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage();
mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata();
mBufferInfo.mApi = mConsumer->getCurrentApi();
- mBufferInfo.mPixelFormat = mFormat;
mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
}
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 5f7587c..16b4b6e 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -82,7 +82,6 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void preparePerFrameCompositionState() override;
sp<Layer> createClone() override;
void onFrameAvailable(const BufferItem& item);
@@ -132,8 +131,6 @@
sp<BufferLayerConsumer> mConsumer;
sp<IGraphicBufferProducer> mProducer;
- PixelFormat mFormat{PIXEL_FORMAT_NONE};
-
bool mUpdateTexImageFailed{false};
uint64_t mPreviousBufferId = 0;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 3ed6889..a121ce0 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -631,19 +631,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()) {
@@ -718,8 +705,9 @@
}
void BufferStateLayer::gatherBufferInfo() {
- const State& s(getDrawingState());
+ BufferLayer::gatherBufferInfo();
+ const State& s(getDrawingState());
mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;
mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);
mBufferInfo.mFence = s.acquireFence;
@@ -730,8 +718,6 @@
mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion;
mBufferInfo.mHdrMetadata = s.hdrMetadata;
mBufferInfo.mApi = s.api;
- mBufferInfo.mPixelFormat =
- !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format;
mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse;
mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);
}
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 753a742..5873a73 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -138,7 +138,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
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index c345405..308ec5a 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, HWC2::DisplayCapability::SkipClientColorTransform)
+ : hwc.hasCapability(HWC2::Capability::SkipClientColorTransform);
}
bool Display::anyLayersRequireClientComposition() const {
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 248933e..34d0cb2 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -829,7 +829,6 @@
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
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 88f2686..f73a6f7 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -681,15 +681,17 @@
using DisplayGetSkipColorTransformTest = DisplayWithLayersTestCommon;
-TEST_F(DisplayGetSkipColorTransformTest, doesNothingIfNonHwcDisplay) {
+TEST_F(DisplayGetSkipColorTransformTest, checksCapabilityIfNonHwcDisplay) {
+ EXPECT_CALL(mHwComposer, hasCapability(HWC2::Capability::SkipClientColorTransform))
+ .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),
+ hasDisplayCapability(DEFAULT_DISPLAY_ID,
HWC2::DisplayCapability::SkipClientColorTransform))
.WillOnce(Return(true));
EXPECT_TRUE(mDisplay->getSkipColorTransform());
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 02226ab..52bd6a1 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -40,11 +40,11 @@
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));
+ MOCK_CONST_METHOD2(hasDisplayCapability, bool(DisplayId, HWC2::DisplayCapability));
MOCK_METHOD3(allocateVirtualDisplay,
std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
+ MOCK_METHOD2(allocatePhysicalDisplay, void(hwc2_display_t, DisplayId));
MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
MOCK_METHOD3(getDeviceCompositionChanges,
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 63bb459..1c9cd9c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3100,9 +3100,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 +3111,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 +3122,7 @@
.andIfUsesHdr(true)
.andIfSkipColorTransform(false)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
+ kDefaultMaxLuminance, kDefaultOutputDataspace,
kDefaultColorTransformMat, Region::INVALID_REGION,
kDefaultOutputOrientation})
.execute()
@@ -3136,7 +3134,7 @@
.andIfUsesHdr(false)
.andIfSkipColorTransform(false)
.thenExpectDisplaySettingsUsed({kDefaultOutputDestinationClip, kDefaultOutputSourceClip,
- mat4(), kDefaultMaxLuminance, kDefaultOutputDataspace,
+ kDefaultMaxLuminance, kDefaultOutputDataspace,
kDefaultColorTransformMat, Region::INVALID_REGION,
kDefaultOutputOrientation})
.execute()
@@ -3149,9 +3147,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();
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b72214d..b81eb18 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -220,13 +220,11 @@
const bool needsFiltering =
(!globalTransform.preserveRects() || (type >= ui::Transform::SCALE));
- Rect sourceClip = globalTransform.transform(viewport);
- if (sourceClip.isEmpty()) {
- sourceClip = displayBounds;
+ const Rect& sourceClip = viewport;
+ Rect destinationClip = globalTransform.transform(viewport);
+ if (destinationClip.isEmpty()) {
+ destinationClip = displayBounds;
}
- // For normal display use we always set the source and destination clip
- // rectangles to the same values.
- const Rect& destinationClip = sourceClip;
uint32_t transformOrientation;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index fb6c817..e670d78 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -183,9 +183,10 @@
struct Physical {
DisplayId id;
DisplayConnectionType type;
+ hwc2_display_t hwcDisplayId;
bool operator==(const Physical& other) const {
- return id == other.id && type == other.type;
+ return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId;
}
};
@@ -243,14 +244,12 @@
uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation,
bool allowSecureLayers = true)
: RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace,
- display->getViewport(),
- applyInversePhysicalOrientation(rotation,
- display->getPhysicalOrientation())),
+ display->getViewport(), applyDeviceOrientation(rotation, display)),
mDisplay(std::move(display)),
mSourceCrop(sourceCrop),
mAllowSecureLayers(allowSecureLayers) {}
- const ui::Transform& getTransform() const override { return mDisplay->getTransform(); }
+ const ui::Transform& getTransform() const override { return mTransform; }
Rect getBounds() const override { return mDisplay->getBounds(); }
int getHeight() const override { return mDisplay->getHeight(); }
int getWidth() const override { return mDisplay->getWidth(); }
@@ -258,15 +257,9 @@
sp<const DisplayDevice> getDisplayDevice() const override { return mDisplay; }
bool needsFiltering() const override {
- // check if the projection from the logical display to the physical
- // display needs filtering
- if (mDisplay->needsFiltering()) {
- return true;
- }
-
- // check if the projection from the logical render area (i.e., the
- // physical display) to the physical render area requires filtering
- const Rect sourceCrop = getSourceCrop();
+ // check if the projection from the logical render area
+ // to the physical render area requires filtering
+ const Rect& sourceCrop = getSourceCrop();
int width = sourceCrop.width();
int height = sourceCrop.height();
if (getRotationFlags() & ui::Transform::ROT_90) {
@@ -281,36 +274,44 @@
return mDisplay->getSourceClip();
}
- // Recompute the device transformation for the source crop.
+ // If there is a source crop provided then it is assumed that the device
+ // was in portrait orientation. This may not logically be true, so
+ // correct for the orientation error by undoing the rotation
+
+ ui::Rotation logicalOrientation = mDisplay->getOrientation();
+ if (logicalOrientation == ui::Rotation::Rotation90) {
+ logicalOrientation = ui::Rotation::Rotation270;
+ } else if (logicalOrientation == ui::Rotation::Rotation270) {
+ logicalOrientation = ui::Rotation::Rotation90;
+ }
+
+ const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
+ int width = mDisplay->getSourceClip().getWidth();
+ int height = mDisplay->getSourceClip().getHeight();
ui::Transform rotation;
- ui::Transform translatePhysical;
- ui::Transform translateLogical;
- ui::Transform scale;
- const Rect& viewport = mDisplay->getViewport();
- const Rect& sourceClip = mDisplay->getSourceClip();
- const Rect& frame = mDisplay->getFrame();
-
- const auto flags = ui::Transform::toRotationFlags(mDisplay->getPhysicalOrientation());
- rotation.set(flags, getWidth(), getHeight());
-
- translateLogical.set(-viewport.left, -viewport.top);
- translatePhysical.set(sourceClip.left, sourceClip.top);
- scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0,
- frame.getHeight() / float(viewport.getHeight()));
- const ui::Transform finalTransform =
- rotation * translatePhysical * scale * translateLogical;
- return finalTransform.transform(mSourceCrop);
+ rotation.set(flags, width, height);
+ return rotation.transform(mSourceCrop);
}
private:
- static RotationFlags applyInversePhysicalOrientation(RotationFlags orientation,
- ui::Rotation physicalOrientation) {
+ static RotationFlags applyDeviceOrientation(RotationFlags orientationFlag,
+ const sp<const DisplayDevice>& device) {
uint32_t inverseRotate90 = 0;
uint32_t inverseReflect = 0;
- switch (physicalOrientation) {
+ // Reverse the logical orientation.
+ ui::Rotation logicalOrientation = device->getOrientation();
+ if (logicalOrientation == ui::Rotation::Rotation90) {
+ logicalOrientation = ui::Rotation::Rotation270;
+ } else if (logicalOrientation == ui::Rotation::Rotation270) {
+ logicalOrientation = ui::Rotation::Rotation90;
+ }
+
+ const ui::Rotation orientation = device->getPhysicalOrientation() + logicalOrientation;
+
+ switch (orientation) {
case ui::ROTATION_0:
- return orientation;
+ return orientationFlag;
case ui::ROTATION_90:
inverseRotate90 = ui::Transform::ROT_90;
@@ -326,8 +327,8 @@
break;
}
- const uint32_t rotate90 = orientation & ui::Transform::ROT_90;
- uint32_t reflect = orientation & ui::Transform::ROT_180;
+ const uint32_t rotate90 = orientationFlag & ui::Transform::ROT_90;
+ uint32_t reflect = orientationFlag & ui::Transform::ROT_180;
// Apply reflection for double rotation.
if (rotate90 & inverseRotate90) {
@@ -341,6 +342,7 @@
const sp<const DisplayDevice> mDisplay;
const Rect mSourceCrop;
const bool mAllowSecureLayers;
+ const ui::Transform mTransform = ui::Transform();
};
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index f24f314..4dfc743 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -35,6 +35,7 @@
using byte_view = std::basic_string_view<uint8_t>;
+constexpr size_t kEdidBlockSize = 128;
constexpr size_t kEdidHeaderLength = 5;
constexpr uint16_t kFallbackEdidManufacturerId = 0;
@@ -95,9 +96,66 @@
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;
}
+Cea861ExtensionBlock parseCea861Block(const byte_view& block) {
+ Cea861ExtensionBlock cea861Block;
+
+ constexpr size_t kRevisionNumberOffset = 1;
+ cea861Block.revisionNumber = block[kRevisionNumberOffset];
+
+ constexpr size_t kDetailedTimingDescriptorsOffset = 2;
+ const size_t dtdStart =
+ std::min(kEdidBlockSize, static_cast<size_t>(block[kDetailedTimingDescriptorsOffset]));
+
+ // Parse data blocks.
+ for (size_t dataBlockOffset = 4; dataBlockOffset < dtdStart;) {
+ const uint8_t header = block[dataBlockOffset];
+ const uint8_t tag = header >> 5;
+ const size_t bodyLength = header & 0b11111;
+ constexpr size_t kDataBlockHeaderSize = 1;
+ const size_t dataBlockSize = bodyLength + kDataBlockHeaderSize;
+
+ if (block.size() < dataBlockOffset + dataBlockSize) {
+ ALOGW("Invalid EDID: CEA 861 data block is truncated.");
+ break;
+ }
+
+ const byte_view dataBlock(block.data() + dataBlockOffset, dataBlockSize);
+ constexpr uint8_t kVendorSpecificDataBlockTag = 0x3;
+
+ if (tag == kVendorSpecificDataBlockTag) {
+ const uint32_t ieeeRegistrationId =
+ dataBlock[1] | (dataBlock[2] << 8) | (dataBlock[3] << 16);
+ constexpr uint32_t kHdmiIeeeRegistrationId = 0xc03;
+
+ if (ieeeRegistrationId == kHdmiIeeeRegistrationId) {
+ const uint8_t a = dataBlock[4] >> 4;
+ const uint8_t b = dataBlock[4] & 0b1111;
+ const uint8_t c = dataBlock[5] >> 4;
+ const uint8_t d = dataBlock[5] & 0b1111;
+ cea861Block.hdmiVendorDataBlock =
+ HdmiVendorDataBlock{.physicalAddress = HdmiPhysicalAddress{a, b, c, d}};
+ } else {
+ ALOGV("Ignoring vendor specific data block for vendor with IEEE OUI %x",
+ ieeeRegistrationId);
+ }
+ } else {
+ ALOGV("Ignoring CEA-861 data block with tag %x", tag);
+ }
+ dataBlockOffset += bodyLength + kDataBlockHeaderSize;
+ }
+
+ return cea861Block;
+}
+
} // namespace
uint16_t DisplayId::manufacturerId() const {
@@ -115,13 +173,12 @@
}
std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
- constexpr size_t kMinLength = 128;
- if (edid.size() < kMinLength) {
+ if (edid.size() < kEdidBlockSize) {
ALOGW("Invalid EDID: structure is truncated.");
// Attempt parsing even if EDID is malformed.
} else {
- ALOGW_IF(edid[126] != 0, "EDID extensions are currently unsupported.");
- ALOGW_IF(std::accumulate(edid.begin(), edid.begin() + kMinLength, static_cast<uint8_t>(0)),
+ ALOGW_IF(std::accumulate(edid.begin(), edid.begin() + kEdidBlockSize,
+ static_cast<uint8_t>(0)),
"Invalid EDID: structure does not checksum.");
}
@@ -227,13 +284,43 @@
// have been observed to change on some displays with multiple inputs.
const auto modelHash = static_cast<uint32_t>(std::hash<std::string_view>()(modelString));
+ // Parse extension blocks.
+ std::optional<Cea861ExtensionBlock> cea861Block;
+ if (edid.size() < kEdidBlockSize) {
+ ALOGW("Invalid EDID: block 0 is truncated.");
+ } else {
+ constexpr size_t kNumExtensionsOffset = 126;
+ const size_t numExtensions = edid[kNumExtensionsOffset];
+ view = byte_view(edid.data(), edid.size());
+ for (size_t blockNumber = 1; blockNumber <= numExtensions; blockNumber++) {
+ view.remove_prefix(kEdidBlockSize);
+ if (view.size() < kEdidBlockSize) {
+ ALOGW("Invalid EDID: block %zu is truncated.", blockNumber);
+ break;
+ }
+
+ const byte_view block(view.data(), kEdidBlockSize);
+ ALOGW_IF(std::accumulate(block.begin(), block.end(), static_cast<uint8_t>(0)),
+ "Invalid EDID: block %zu does not checksum.", blockNumber);
+ const uint8_t tag = block[0];
+
+ constexpr uint8_t kCea861BlockTag = 0x2;
+ if (tag == kCea861BlockTag) {
+ cea861Block = parseCea861Block(block);
+ } else {
+ ALOGV("Ignoring block number %zu with tag %x.", blockNumber, tag);
+ }
+ }
+ }
+
return Edid{.manufacturerId = manufacturerId,
.productId = productId,
.pnpId = *pnpId,
.modelHash = modelHash,
.displayName = displayName,
+ .manufactureOrModelYear = manufactureOrModelYear,
.manufactureWeek = manufactureWeek,
- .manufactureOrModelYear = manufactureOrModelYear};
+ .cea861Block = cea861Block};
}
std::optional<PnpId> getPnpId(uint16_t manufacturerId) {
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index d91b957..9e6c549 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -57,6 +57,26 @@
std::optional<DeviceProductInfo> deviceProductInfo;
};
+struct ExtensionBlock {
+ uint8_t tag;
+ uint8_t revisionNumber;
+};
+
+struct HdmiPhysicalAddress {
+ // The address describes the path from the display sink in the network of connected HDMI
+ // devices. The format of the address is "a.b.c.d". For example, address 2.1.0.0 means we are
+ // connected to port 1 of a device which is connected to port 2 of the sink.
+ uint8_t a, b, c, d;
+};
+
+struct HdmiVendorDataBlock {
+ HdmiPhysicalAddress physicalAddress;
+};
+
+struct Cea861ExtensionBlock : ExtensionBlock {
+ std::optional<HdmiVendorDataBlock> hdmiVendorDataBlock;
+};
+
struct Edid {
uint16_t manufacturerId;
uint16_t productId;
@@ -65,6 +85,7 @@
std::string_view displayName;
uint8_t manufactureOrModelYear;
uint8_t manufactureWeek;
+ std::optional<Cea861ExtensionBlock> cea861Block;
};
bool isEdid(const DisplayIdentificationData&);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1c1e113..f30d662 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -190,71 +190,22 @@
return mCapabilities.count(capability) > 0;
}
-bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
+bool HWComposer::hasDisplayCapability(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;
+ 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> info;
-
- if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
- info = DisplayIdentificationInfo{.id = *displayId,
- .name = std::string(),
- .deviceProductInfo = std::nullopt};
- } else {
- if (connection == HWC2::Connection::Disconnected) {
- ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
+ switch (connection) {
+ case HWC2::Connection::Connected:
+ return onHotplugConnect(hwcDisplayId);
+ case HWC2::Connection::Disconnected:
+ return onHotplugDisconnect(hwcDisplayId);
+ case HWC2::Connection::Invalid:
return {};
- }
-
- info = onHotplugConnect(hwcDisplayId);
- if (!info) return {};
}
-
- ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(),
- hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external",
- to_string(info->id).c_str(), hwcDisplayId);
-
- if (connection == HWC2::Connection::Connected) {
- auto& displayData = mDisplayData[info->id];
- // If we get a hotplug connected event for a display we already have,
- // destroy the display and recreate it. This will force us to requery
- // the display params and recreate all layers on that display.
- if (displayData.hwcDisplay != nullptr && displayData.hwcDisplay->isConnected()) {
- ALOGI("Hotplug connecting an already connected display."
- " Clearing old display state.");
- }
- displayData.hwcDisplay.reset();
- auto newDisplay =
- std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
- HWC2::DisplayType::Physical);
- newDisplay->setConnected(true);
- displayData.hwcDisplay = std::move(newDisplay);
- mPhysicalDisplayIdMap[hwcDisplayId] = info->id;
- } else if (connection == HWC2::Connection::Disconnected) {
- // The display will later be destroyed by a call to
- // destroyDisplay(). For now we just mark it disconnected.
- auto& displayData = mDisplayData[info->id];
- if (displayData.hwcDisplay) {
- displayData.hwcDisplay->setConnected(false);
- } else {
- ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
- }
- // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
- // via SurfaceFlinger's onHotplugReceived callback handling
- }
-
- return info;
}
bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
@@ -337,6 +288,22 @@
return displayId;
}
+void HWComposer::allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) {
+ if (!mInternalHwcDisplayId) {
+ mInternalHwcDisplayId = hwcDisplayId;
+ } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
+ mExternalHwcDisplayId = hwcDisplayId;
+ }
+
+ auto& displayData = mDisplayData[displayId];
+ auto newDisplay =
+ std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
+ HWC2::DisplayType::Physical);
+ newDisplay->setConnected(true);
+ displayData.hwcDisplay = std::move(newDisplay);
+ mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
+}
+
HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
@@ -911,52 +878,93 @@
return {};
}
-std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
+bool HWComposer::shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
+ bool hasDisplayIdentificationData) const {
if (isUsingVrComposer() && mInternalHwcDisplayId) {
ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
- return {};
+ return true;
}
- uint8_t port;
- DisplayIdentificationData data;
- const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data);
-
- if (mPhysicalDisplayIdMap.empty()) {
- mHasMultiDisplaySupport = hasMultiDisplaySupport;
- ALOGI("Switching to %s multi-display mode",
- hasMultiDisplaySupport ? "generalized" : "legacy");
- } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) {
+ if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
hwcDisplayId);
- return {};
+ return true;
}
- std::optional<DisplayIdentificationInfo> info;
-
- if (mHasMultiDisplaySupport) {
- info = parseDisplayIdentificationData(port, data);
- ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId);
- } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) {
+ if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) {
ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
- return {};
+ return true;
+ }
+
+ return false;
+}
+
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
+ std::optional<DisplayIdentificationInfo> info;
+ if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
+ info = DisplayIdentificationInfo{.id = *displayId,
+ .name = std::string(),
+ .deviceProductInfo = std::nullopt};
} else {
- ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64,
- hwcDisplayId);
- port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY;
+ uint8_t port;
+ DisplayIdentificationData data;
+ const bool hasDisplayIdentificationData =
+ getDisplayIdentificationData(hwcDisplayId, &port, &data);
+ if (mPhysicalDisplayIdMap.empty()) {
+ mHasMultiDisplaySupport = hasDisplayIdentificationData;
+ ALOGI("Switching to %s multi-display mode",
+ mHasMultiDisplaySupport ? "generalized" : "legacy");
+ }
+
+ if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
+ return {};
+ }
+
+ info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
+ const bool isPrimary = !mInternalHwcDisplayId;
+ if (mHasMultiDisplaySupport) {
+ if (const auto info = parseDisplayIdentificationData(port, data)) {
+ return *info;
+ }
+ ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
+ } else {
+ ALOGW_IF(hasDisplayIdentificationData,
+ "Ignoring identification data for display %" PRIu64, hwcDisplayId);
+ port = isPrimary ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL;
+ }
+
+ return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
+ .name = isPrimary ? "Internal display"
+ : "External display",
+ .deviceProductInfo = std::nullopt};
+ }();
}
- if (!mInternalHwcDisplayId) {
- mInternalHwcDisplayId = hwcDisplayId;
- } else if (!mExternalHwcDisplayId) {
- mExternalHwcDisplayId = hwcDisplayId;
+ if (!isConnected(info->id)) {
+ allocatePhysicalDisplay(hwcDisplayId, info->id);
+ }
+ return info;
+}
+
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
+ hwc2_display_t hwcDisplayId) {
+ const auto displayId = toPhysicalDisplayId(hwcDisplayId);
+ if (!displayId) {
+ ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
+ return {};
}
- if (info) return info;
-
- return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
- .name = hwcDisplayId == mInternalHwcDisplayId
- ? "Internal display"
- : "External display",
+ // The display will later be destroyed by a call to
+ // destroyDisplay(). For now we just mark it disconnected.
+ if (isConnected(*displayId)) {
+ mDisplayData[*displayId].hwcDisplay->setConnected(false);
+ } else {
+ ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
+ }
+ // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
+ // via SurfaceFlinger's onHotplugReceived callback handling
+ return DisplayIdentificationInfo{.id = *displayId,
+ .name = std::string(),
.deviceProductInfo = std::nullopt};
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 41db501..e18419a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -70,13 +70,15 @@
DisplayIdentificationData* outData) const = 0;
virtual bool hasCapability(HWC2::Capability capability) const = 0;
- virtual bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
+ virtual bool hasDisplayCapability(DisplayId displayId,
HWC2::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;
+
// Attempts to create a new layer on this display
virtual HWC2::Layer* createLayer(DisplayId displayId) = 0;
// Destroy a previously created layer
@@ -164,6 +166,7 @@
// 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;
@@ -231,13 +234,16 @@
DisplayIdentificationData* outData) const override;
bool hasCapability(HWC2::Capability capability) const override;
- bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
+ bool hasDisplayCapability(DisplayId displayId,
HWC2::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;
+
// Attempts to create a new layer on this display
HWC2::Layer* createLayer(DisplayId displayId) override;
// Destroy a previously created layer
@@ -361,6 +367,10 @@
friend TestableSurfaceFlinger;
std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
+ std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hwc2_display_t hwcDisplayId);
+ bool shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
+ bool hasDisplayIdentificationData) const;
+
void loadCapabilities();
void loadLayerMetadataSupport();
uint32_t getMaxVirtualDisplayCount() const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3d67a6b..5039761 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2134,10 +2134,12 @@
writeToProtoDrawingState(layerProto, traceFlags);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
- // Only populate for the primary display.
- if (device) {
- const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device);
- layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
+ // Only populate for the primary display.
+ if (device) {
+ const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device);
+ layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ }
}
for (const sp<Layer>& layer : mDrawingChildren) {
@@ -2180,8 +2182,10 @@
LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
[&]() { return layerInfo->mutable_position(); });
LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
- LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
- [&]() { return layerInfo->mutable_visible_region(); });
+ if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
+ LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(),
+ [&]() { return layerInfo->mutable_visible_region(); });
+ }
LayerProtoHelper::writeToProto(surfaceDamageRegion,
[&]() { return layerInfo->mutable_damage_region(); });
@@ -2191,15 +2195,13 @@
}
}
- if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
- LayerProtoHelper::writeToProto(mSourceBounds,
- [&]() { return layerInfo->mutable_source_bounds(); });
- LayerProtoHelper::writeToProto(mScreenBounds,
- [&]() { return layerInfo->mutable_screen_bounds(); });
- LayerProtoHelper::writeToProto(getRoundedCornerState().cropRect,
- [&]() { return layerInfo->mutable_corner_radius_crop(); });
- layerInfo->set_shadow_radius(mEffectiveShadowRadius);
- }
+ LayerProtoHelper::writeToProto(mSourceBounds,
+ [&]() { return layerInfo->mutable_source_bounds(); });
+ LayerProtoHelper::writeToProto(mScreenBounds,
+ [&]() { return layerInfo->mutable_screen_bounds(); });
+ LayerProtoHelper::writeToProto(getRoundedCornerState().cropRect,
+ [&]() { return layerInfo->mutable_corner_radius_crop(); });
+ layerInfo->set_shadow_radius(mEffectiveShadowRadius);
}
void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index be80f78..92ac015 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -535,6 +535,19 @@
}
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
virtual bool needsFiltering(const sp<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,
+ // where as this method transforms the displayFrame to layer-stack space
+ // first. This method should be used if there is no physical display to
+ // project onto when taking screenshots, as the filtering requirements are
+ // 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 {
+ return false;
+ }
// This layer is not a clone, but it's the parent to the cloned hierarchy. The
// variable mClonedChild represents the top layer that will be cloned so this
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index c675971..0a0f2f1 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -170,7 +170,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 +179,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());
@@ -207,7 +207,7 @@
const int32_t right = left + display->getWidth() / 8;
const int32_t buttom = top + display->getHeight() / 32;
- auto buffer = mBufferCache[refreshRate.fps];
+ auto buffer = mBufferCache[refreshRate.getFps()];
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});
mLayer->setFrame(Rect(left, top, right, buttom));
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 9b3a9f4..6b0455a 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -61,10 +61,9 @@
// render area. It can be larger than the logical render area. It can
// also be optionally rotated.
//
- // Layers are first clipped to the source crop (in addition to being
- // clipped to the logical render area already). The source crop and the
- // layers are then rotated around the center of the source crop, and
- // scaled to the physical render area linearly.
+ // The source crop is specified in layer space (when rendering a layer and
+ // its children), or in layer-stack space (when rendering all layers visible
+ // on the display).
virtual Rect getSourceCrop() const = 0;
// Returns the rotation of the source crop and the layers.
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 0d6a92e..8347650 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -429,7 +429,13 @@
ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
std::string debugInfo = "VsyncSource debug info:\n";
mVSyncSource->dump(debugInfo);
- ALOGW("%s", debugInfo.c_str());
+ // Log the debug info line-by-line to avoid logcat overflow
+ auto pos = debugInfo.find('\n');
+ while (pos != std::string::npos) {
+ ALOGW("%s", debugInfo.substr(0, pos).c_str());
+ debugInfo = debugInfo.substr(pos + 1);
+ pos = debugInfo.find('\n');
+ }
}
LOG_FATAL_IF(!mVSyncState);
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/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 43883fb..d9aaa05 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,7 @@
PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs)
: PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs),
- refreshRateConfigs.getCurrentRefreshRate().fps,
+ refreshRateConfigs.getCurrentRefreshRate().getFps(),
// 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
@@ -275,7 +275,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/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 02d0b53..5634adb 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -53,7 +53,7 @@
if (explicitContentFramerate != 0) {
contentFramerate = explicitContentFramerate;
} else if (contentFramerate == 0) {
- contentFramerate = round<int>(mMaxSupportedRefreshRate->fps);
+ contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps());
}
ATRACE_INT("ContentFPS", contentFramerate);
@@ -177,7 +177,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 = [&]() {
@@ -301,7 +301,7 @@
mCurrentRefreshRate) != mAvailableRefreshRates.end()) {
return *mCurrentRefreshRate;
}
- return *mRefreshRates.at(mDefaultConfig);
+ return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig);
}
void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
@@ -309,55 +309,85 @@
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("%2.ffps", 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();
}
-status_t RefreshRateConfigs::setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate,
- float maxRefreshRate, bool* outPolicyChanged) {
+bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
+ // defaultConfig must be a valid config, and within the given refresh rate range.
+ auto iter = mRefreshRates.find(policy.defaultConfig);
+ if (iter == mRefreshRates.end()) {
+ return false;
+ }
+ const RefreshRate& refreshRate = *iter->second;
+ if (!refreshRate.inPolicy(policy.minRefreshRate, policy.maxRefreshRate)) {
+ return false;
+ }
+ return true;
+}
+
+status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
std::lock_guard lock(mLock);
- bool policyChanged = defaultConfigId != mDefaultConfig ||
- minRefreshRate != mMinRefreshRateFps || maxRefreshRate != mMaxRefreshRateFps;
- if (outPolicyChanged) {
- *outPolicyChanged = policyChanged;
- }
- if (!policyChanged) {
- return NO_ERROR;
- }
- // defaultConfigId must be a valid config ID, and within the given refresh rate range.
- if (mRefreshRates.count(defaultConfigId) == 0) {
+ if (!isPolicyValid(policy)) {
return BAD_VALUE;
}
- const RefreshRate& refreshRate = *mRefreshRates.at(defaultConfigId);
- if (!refreshRate.inPolicy(minRefreshRate, maxRefreshRate)) {
- return BAD_VALUE;
+ Policy previousPolicy = *getCurrentPolicyLocked();
+ mDisplayManagerPolicy = policy;
+ if (*getCurrentPolicyLocked() == previousPolicy) {
+ return CURRENT_POLICY_UNCHANGED;
}
- mDefaultConfig = defaultConfigId;
- mMinRefreshRateFps = minRefreshRate;
- mMaxRefreshRateFps = maxRefreshRate;
constructAvailableRefreshRates();
return NO_ERROR;
}
-void RefreshRateConfigs::getPolicy(HwcConfigIndexType* defaultConfigId, float* minRefreshRate,
- float* maxRefreshRate) const {
+status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) {
std::lock_guard lock(mLock);
- *defaultConfigId = mDefaultConfig;
- *minRefreshRate = mMinRefreshRateFps;
- *maxRefreshRate = mMaxRefreshRateFps;
+ if (policy && !isPolicyValid(*policy)) {
+ return BAD_VALUE;
+ }
+ Policy previousPolicy = *getCurrentPolicyLocked();
+ mOverridePolicy = policy;
+ if (*getCurrentPolicyLocked() == previousPolicy) {
+ return CURRENT_POLICY_UNCHANGED;
+ }
+ constructAvailableRefreshRates();
+ return NO_ERROR;
+}
+
+const RefreshRateConfigs::Policy* RefreshRateConfigs::getCurrentPolicyLocked() const {
+ return mOverridePolicy ? &mOverridePolicy.value() : &mDisplayManagerPolicy;
+}
+
+RefreshRateConfigs::Policy RefreshRateConfigs::getCurrentPolicy() const {
+ std::lock_guard lock(mLock);
+ return *getCurrentPolicyLocked();
+}
+
+RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const {
+ std::lock_guard lock(mLock);
+ return mDisplayManagerPolicy;
}
bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
@@ -385,19 +415,35 @@
std::sort(outRefreshRates->begin(), outRefreshRates->end(),
[](const auto refreshRate1, const auto refreshRate2) {
- return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
+ if (refreshRate1->hwcConfig->getVsyncPeriod() !=
+ refreshRate2->hwcConfig->getVsyncPeriod()) {
+ return refreshRate1->hwcConfig->getVsyncPeriod() >
+ refreshRate2->hwcConfig->getVsyncPeriod();
+ } else {
+ return refreshRate1->hwcConfig->getConfigGroup() >
+ refreshRate2->hwcConfig->getConfigGroup();
+ }
});
}
void RefreshRateConfigs::constructAvailableRefreshRates() {
// Filter configs based on current policy and sort based on vsync period
- HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig)->configGroup;
+ const Policy* policy = getCurrentPolicyLocked();
+ const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig;
ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
- mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps);
+ policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->minRefreshRate,
+ policy->maxRefreshRate);
getSortedRefreshRateList(
[&](const RefreshRate& refreshRate) REQUIRES(mLock) {
- return refreshRate.configGroup == group &&
- refreshRate.inPolicy(mMinRefreshRateFps, mMaxRefreshRateFps);
+ const auto& hwcConfig = refreshRate.hwcConfig;
+
+ 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(policy->minRefreshRate, policy->maxRefreshRate);
},
&mAvailableRefreshRates);
@@ -409,33 +455,8 @@
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",
- mDefaultConfig.value(), mMinRefreshRateFps, mMaxRefreshRateFps);
-}
-
-// 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());
-
- 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);
- mDefaultConfig = currentHwcConfig;
- mMinSupportedRefreshRate = sortedConfigs.front();
- mMaxSupportedRefreshRate = sortedConfigs.back();
- constructAvailableRefreshRates();
+ policy->defaultConfig.value(), policy->minRefreshRate,
+ policy->maxRefreshRate);
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 87d4389..dea7e90 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -20,6 +20,7 @@
#include <algorithm>
#include <numeric>
+#include <optional>
#include <type_traits>
#include "DisplayHardware/HWComposer.h"
@@ -28,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 };
@@ -48,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.
@@ -80,24 +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>>;
- // Sets the current policy to choose refresh rates. Returns NO_ERROR if the requested policy is
- // valid, or a negative error value otherwise. policyChanged, if non-null, will be set to true
- // if the new policy is different from the old policy.
- status_t setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate,
- float maxRefreshRate, bool* policyChanged) EXCLUDES(mLock);
- // Gets the current policy.
- void getPolicy(HwcConfigIndexType* defaultConfigId, float* minRefreshRate,
- float* maxRefreshRate) const EXCLUDES(mLock);
+ struct Policy {
+ // 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();
+ // Whether or not we switch config groups to get the best frame rate. Only used by tests.
+ bool allowGroupSwitching = false;
+
+ bool operator==(const Policy& other) const {
+ return defaultConfig == other.defaultConfig && minRefreshRate == other.minRefreshRate &&
+ maxRefreshRate == other.maxRefreshRate &&
+ allowGroupSwitching == other.allowGroupSwitching;
+ }
+
+ bool operator!=(const Policy& other) const { return !(*this == other); }
+ };
+
+ // Return code set*Policy() to indicate the current policy is unchanged.
+ static constexpr int CURRENT_POLICY_UNCHANGED = 1;
+
+ // We maintain the display manager policy and the override policy separately. The override
+ // policy is used by CTS tests to get a consistent device state for testing. While the override
+ // policy is set, it takes precedence over the display manager policy. Once the override policy
+ // is cleared, we revert to using the display manager policy.
+
+ // Sets the display manager policy to choose refresh rates. The return value will be:
+ // - A negative value if the policy is invalid or another error occurred.
+ // - NO_ERROR if the policy was successfully updated, and the current policy is different from
+ // what it was before the call.
+ // - CURRENT_POLICY_UNCHANGED if the policy was successfully updated, but the current policy
+ // is the same as it was before the call.
+ status_t setDisplayManagerPolicy(const Policy& policy) EXCLUDES(mLock);
+ // Sets the override policy. See setDisplayManagerPolicy() for the meaning of the return value.
+ status_t setOverridePolicy(const std::optional<Policy>& policy) EXCLUDES(mLock);
+ // Gets the current policy, which will be the override policy if active, and the display manager
+ // policy otherwise.
+ Policy getCurrentPolicy() const EXCLUDES(mLock);
+ // Gets the display manager policy, regardless of whether an override policy is active.
+ Policy getDisplayManagerPolicy() const EXCLUDES(mLock);
// Returns true if config is allowed by the current policy.
bool isConfigAllowed(HwcConfigIndexType config) const EXCLUDES(mLock);
@@ -174,20 +223,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(
@@ -208,6 +247,9 @@
// the policy.
const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock);
+ const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
+ bool isPolicyValid(const Policy& policy);
+
// The list of refresh rates, indexed by display config ID. This must not change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates;
@@ -220,14 +262,10 @@
// the main thread, and read by the Scheduler (and other objects) on other threads.
const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock);
- // The default 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.
- HwcConfigIndexType mDefaultConfig GUARDED_BY(mLock);
-
- // The min and max FPS allowed by the policy. This will change at runtime and set by
- // SurfaceFlinger on the main thread.
- float mMinRefreshRateFps GUARDED_BY(mLock) = 0;
- float mMaxRefreshRateFps GUARDED_BY(mLock) = std::numeric_limits<float>::max();
+ // The policy values will change at runtime. They're set by SurfaceFlinger on the main thread,
+ // and read by the Scheduler (and other objects) on other threads.
+ Policy mDisplayManagerPolicy GUARDED_BY(mLock);
+ std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);
// The min and max refresh rates supported by the device.
// This will not change at runtime.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index e44cd52..66d4a03 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -78,10 +78,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;
@@ -115,7 +115,7 @@
}
mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs;
fps = static_cast<uint32_t>(std::round(
- mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps));
+ mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).getFps()));
} else {
mScreenOffTime += timeElapsedMs;
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index cd6075f..9a9523f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -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());
}
}
@@ -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);
}
}
@@ -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.
@@ -580,30 +581,31 @@
if (mDisplayPowerTimer &&
(!mFeatures.isDisplayPowerStateNormal ||
mFeatures.displayPowerTimer == TimerState::Reset)) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
}
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;
+ 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;
+ 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;
@@ -613,7 +615,7 @@
mTouchTimer &&
mFeatures.touch == TouchState::Active,
&touchConsidered)
- .configId;
+ .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.
diff --git a/services/surfaceflinger/Scheduler/TimeKeeper.h b/services/surfaceflinger/Scheduler/TimeKeeper.h
index 38f0708..da2195c 100644
--- a/services/surfaceflinger/Scheduler/TimeKeeper.h
+++ b/services/surfaceflinger/Scheduler/TimeKeeper.h
@@ -53,6 +53,8 @@
*/
virtual void alarmCancel() = 0;
+ virtual void dump(std::string& result) const = 0;
+
protected:
TimeKeeper(TimeKeeper const&) = delete;
TimeKeeper& operator=(TimeKeeper const&) = delete;
diff --git a/services/surfaceflinger/Scheduler/Timer.cpp b/services/surfaceflinger/Scheduler/Timer.cpp
index 8f81c2c..7c5058e 100644
--- a/services/surfaceflinger/Scheduler/Timer.cpp
+++ b/services/surfaceflinger/Scheduler/Timer.cpp
@@ -17,6 +17,7 @@
#undef LOG_TAG
#define LOG_TAG "SchedulerTimer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <android-base/stringprintf.h>
#include <log/log.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
@@ -29,28 +30,53 @@
#include "Timer.h"
namespace android::scheduler {
+using base::StringAppendF;
static constexpr size_t kReadPipe = 0;
static constexpr size_t kWritePipe = 1;
-Timer::Timer()
- : mTimerFd(timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)),
- mEpollFd(epoll_create1(EPOLL_CLOEXEC)) {
- if (pipe2(mPipes.data(), O_CLOEXEC | O_NONBLOCK)) {
- ALOGE("could not create TimerDispatch mPipes");
- };
-
- mDispatchThread = std::thread(std::bind(&Timer::dispatch, this));
+Timer::Timer() {
+ reset();
+ mDispatchThread = std::thread([this]() { threadMain(); });
}
Timer::~Timer() {
endDispatch();
mDispatchThread.join();
+ cleanup();
+}
- close(mPipes[kWritePipe]);
- close(mPipes[kReadPipe]);
- close(mEpollFd);
- close(mTimerFd);
+void Timer::reset() {
+ cleanup();
+ mTimerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
+ mEpollFd = epoll_create1(EPOLL_CLOEXEC);
+ if (pipe2(mPipes.data(), O_CLOEXEC | O_NONBLOCK)) {
+ ALOGE("could not create TimerDispatch mPipes");
+ return;
+ };
+ setDebugState(DebugState::Reset);
+}
+
+void Timer::cleanup() {
+ if (mTimerFd != -1) {
+ close(mTimerFd);
+ mTimerFd = -1;
+ }
+
+ if (mEpollFd != -1) {
+ close(mEpollFd);
+ mEpollFd = -1;
+ }
+
+ if (mPipes[kReadPipe] != -1) {
+ close(mPipes[kReadPipe]);
+ mPipes[kReadPipe] = -1;
+ }
+
+ if (mPipes[kWritePipe] != -1) {
+ close(mPipes[kWritePipe]);
+ mPipes[kWritePipe] = -1;
+ }
}
void Timer::endDispatch() {
@@ -99,7 +125,14 @@
}
}
-void Timer::dispatch() {
+void Timer::threadMain() {
+ while (dispatch()) {
+ reset();
+ }
+}
+
+bool Timer::dispatch() {
+ setDebugState(DebugState::Running);
struct sched_param param = {0};
param.sched_priority = 2;
if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0) {
@@ -116,7 +149,7 @@
timerEvent.data.u32 = DispatchType::TIMER;
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mTimerFd, &timerEvent) == -1) {
ALOGE("Error adding timer fd to epoll dispatch loop");
- return;
+ return true;
}
epoll_event terminateEvent;
@@ -124,18 +157,20 @@
terminateEvent.data.u32 = DispatchType::TERMINATE;
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mPipes[kReadPipe], &terminateEvent) == -1) {
ALOGE("Error adding control fd to dispatch loop");
- return;
+ return true;
}
uint64_t iteration = 0;
char const traceNamePrefix[] = "TimerIteration #";
static constexpr size_t maxlen = arrayLen(traceNamePrefix) + max64print;
std::array<char, maxlen> str_buffer;
- auto timing = true;
- while (timing) {
+
+ while (true) {
+ setDebugState(DebugState::Waiting);
epoll_event events[DispatchType::MAX_DISPATCH_TYPE];
int nfds = epoll_wait(mEpollFd, events, DispatchType::MAX_DISPATCH_TYPE, -1);
+ setDebugState(DebugState::Running);
if (ATRACE_ENABLED()) {
snprintf(str_buffer.data(), str_buffer.size(), "%s%" PRIu64, traceNamePrefix,
iteration++);
@@ -144,29 +179,62 @@
if (nfds == -1) {
if (errno != EINTR) {
- timing = false;
- continue;
+ ALOGE("Error waiting on epoll: %s", strerror(errno));
+ return true;
}
}
for (auto i = 0; i < nfds; i++) {
if (events[i].data.u32 == DispatchType::TIMER) {
static uint64_t mIgnored = 0;
+ setDebugState(DebugState::Reading);
read(mTimerFd, &mIgnored, sizeof(mIgnored));
+ setDebugState(DebugState::Running);
std::function<void()> cb;
{
std::lock_guard<decltype(mMutex)> lk(mMutex);
cb = mCallback;
}
if (cb) {
+ setDebugState(DebugState::InCallback);
cb();
+ setDebugState(DebugState::Running);
}
}
if (events[i].data.u32 == DispatchType::TERMINATE) {
- timing = false;
+ ALOGE("Terminated");
+ setDebugState(DebugState::Running);
+ return false;
}
}
}
}
+void Timer::setDebugState(DebugState state) {
+ std::lock_guard lk(mMutex);
+ mDebugState = state;
+}
+
+const char* Timer::strDebugState(DebugState state) const {
+ switch (state) {
+ case DebugState::Reset:
+ return "Reset";
+ case DebugState::Running:
+ return "Running";
+ case DebugState::Waiting:
+ return "Waiting";
+ case DebugState::Reading:
+ return "Reading";
+ case DebugState::InCallback:
+ return "InCallback";
+ case DebugState::Terminated:
+ return "Terminated";
+ }
+}
+
+void Timer::dump(std::string& result) const {
+ std::lock_guard lk(mMutex);
+ StringAppendF(&result, "\t\tDebugState: %s\n", strDebugState(mDebugState));
+}
+
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Timer.h b/services/surfaceflinger/Scheduler/Timer.h
index 0ae82c8..a8e2d5a 100644
--- a/services/surfaceflinger/Scheduler/Timer.h
+++ b/services/surfaceflinger/Scheduler/Timer.h
@@ -34,18 +34,27 @@
// Most users will want to serialize thes calls so as to be aware of the timer state.
void alarmIn(std::function<void()> const& cb, nsecs_t fireIn) final;
void alarmCancel() final;
+ void dump(std::string& result) const final;
private:
- int const mTimerFd;
- int const mEpollFd;
- std::array<int, 2> mPipes;
+ enum class DebugState { Reset, Running, Waiting, Reading, InCallback, Terminated };
+ void reset();
+ void cleanup();
+ void setDebugState(DebugState state) EXCLUDES(mMutex);
+ const char* strDebugState(DebugState state) const;
+
+ int mTimerFd = -1;
+ int mEpollFd = -1;
+ std::array<int, 2> mPipes = {-1, -1};
std::thread mDispatchThread;
- void dispatch();
+ void threadMain();
+ bool dispatch();
void endDispatch();
- std::mutex mMutex;
+ mutable std::mutex mMutex;
std::function<void()> mCallback GUARDED_BY(mMutex);
+ DebugState mDebugState GUARDED_BY(mMutex);
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index 460d4a5..cd15617 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -168,6 +168,7 @@
mIntendedWakeupTime = targetTime;
mTimeKeeper->alarmIn(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
targetTime - now);
+ mLastTimerSchedule = mTimeKeeper->now();
}
void VSyncDispatchTimerQueue::rearmTimer(nsecs_t now) {
@@ -226,6 +227,7 @@
std::vector<Invocation> invocations;
{
std::lock_guard<decltype(mMutex)> lk(mMutex);
+ mLastTimerCallback = mTimeKeeper->now();
for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
auto& callback = it->second;
auto const wakeupTime = callback->wakeupTime();
@@ -322,10 +324,15 @@
void VSyncDispatchTimerQueue::dump(std::string& result) const {
std::lock_guard<decltype(mMutex)> lk(mMutex);
+ StringAppendF(&result, "\tTimer:\n");
+ mTimeKeeper->dump(result);
StringAppendF(&result, "\tmTimerSlack: %.2fms mMinVsyncDistance: %.2fms\n", mTimerSlack / 1e6f,
mMinVsyncDistance / 1e6f);
StringAppendF(&result, "\tmIntendedWakeupTime: %.2fms from now\n",
- (mIntendedWakeupTime - systemTime()) / 1e6f);
+ (mIntendedWakeupTime - mTimeKeeper->now()) / 1e6f);
+ StringAppendF(&result, "\tmLastTimerCallback: %.2fms ago mLastTimerSchedule: %.2fms ago\n",
+ (mTimeKeeper->now() - mLastTimerCallback) / 1e6f,
+ (mTimeKeeper->now() - mLastTimerSchedule) / 1e6f);
StringAppendF(&result, "\tCallbacks:\n");
for (const auto& [token, entry] : mCallbacks) {
entry->dump(result);
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
index 390e0c4..26a8ec0 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
@@ -152,6 +152,10 @@
std::array<char, maxlen> str_buffer;
void note(std::string_view name, nsecs_t in, nsecs_t vs);
} mTraceBuffer GUARDED_BY(mMutex);
+
+ // For debugging purposes
+ nsecs_t mLastTimerCallback GUARDED_BY(mMutex) = kInvalidTime;
+ nsecs_t mLastTimerSchedule GUARDED_BY(mMutex) = kInvalidTime;
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2da92b3..d721f8d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -169,19 +169,22 @@
#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;
@@ -200,6 +203,15 @@
return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3;
}
+class FrameRateFlexibilityToken : public BBinder {
+public:
+ FrameRateFlexibilityToken(std::function<void()> callback) : mCallback(callback) {}
+ virtual ~FrameRateFlexibilityToken() { mCallback(); }
+
+private:
+ std::function<void()> mCallback;
+};
+
} // namespace anonymous
// ---------------------------------------------------------------------------
@@ -457,17 +469,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);
@@ -899,26 +911,35 @@
}
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;
+
+ {
+ 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;
+ }
}
- if (display->isPrimary()) {
+ if (isPrimary) {
std::lock_guard<std::mutex> lock(mActiveConfigLock);
if (mDesiredActiveConfigChanged) {
return mDesiredActiveConfig.configId.value();
}
}
- return display->getActiveConfig().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) {
@@ -930,7 +951,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;
}
@@ -942,12 +963,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());
}
@@ -963,22 +984,25 @@
return BAD_VALUE;
}
- status_t result = NO_ERROR;
+ status_t result = NAME_NOT_FOUND;
postMessageSync(new LambdaMessage([&]() {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set allowed display configs for invalid display token %p",
displayToken.get());
- result = BAD_VALUE;
} else if (display->isVirtual()) {
ALOGW("Attempt to set allowed display configs for virtual display");
- result = BAD_VALUE;
+ result = INVALID_OPERATION;
} else {
HwcConfigIndexType config(mode);
const auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(config);
- result = setDesiredDisplayConfigSpecsInternal(display, config, refreshRate.fps,
- refreshRate.fps);
+ result = setDesiredDisplayConfigSpecsInternal(display,
+ scheduler::RefreshRateConfigs::
+ Policy{config,
+ refreshRate.getFps(),
+ refreshRate.getFps()},
+ /*overridePolicy=*/false);
}
}));
@@ -993,6 +1017,9 @@
return;
}
+ auto& oldRefreshRate =
+ mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig());
+
std::lock_guard<std::mutex> lock(mActiveConfigLock);
mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId);
mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
@@ -1000,14 +1027,17 @@
auto& refreshRate =
mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId);
- mPhaseConfiguration->setRefreshRateFps(refreshRate.fps);
+ if (refreshRate.getVsyncPeriod() != oldRefreshRate.getVsyncPeriod()) {
+ mTimeStats->incrementRefreshRateSwitches();
+ }
+ 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);
}
@@ -1020,62 +1050,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;
- {
+ const auto desiredActiveConfig = [&]() -> std::optional<ActiveConfigInfo> {
std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (!mDesiredActiveConfigChanged) {
- return false;
+ if (mDesiredActiveConfigChanged) {
+ return mDesiredActiveConfig;
}
- desiredActiveConfig = mDesiredActiveConfig;
+ return std::nullopt;
+ }();
+
+ 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;
@@ -1091,13 +1112,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,
@@ -1143,7 +1163,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));
@@ -1151,7 +1171,9 @@
}
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);
@@ -1167,7 +1189,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());
@@ -1187,82 +1209,61 @@
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,
+ *outSupport = getHwComposer().hasDisplayCapability(*displayId,
HWC2::DisplayCapability::AutoLowLatencyMode);
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);
+ postMessageAsync(new LambdaMessage([=] {
+ 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<HWC2::ContentType> types;
+ getHwComposer().getSupportedContentTypes(*displayId, &types);
+
+ *outSupport = std::any_of(types.begin(), types.end(),
+ [](auto type) { return type == HWC2::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);
+ postMessageAsync(new LambdaMessage([=] {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ const auto type = on ? HWC2::ContentType::Game : HWC2::ContentType::None;
+ getHwComposer().setContentType(*displayId, type);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
}
status_t SurfaceFlinger::clearAnimationFrameStats() {
@@ -1279,15 +1280,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();
@@ -1330,39 +1331,46 @@
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;
- }
+ uint64_t maxFrames) {
+ status_t result = NAME_NOT_FOUND;
- return getHwComposer().setDisplayContentSamplingEnabled(*display->getId(), enable,
- componentMask, maxFrames);
+ postMessageSync(new LambdaMessage([&] {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ result = getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable,
+ componentMask, maxFrames);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
+
+ return result;
}
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 {
@@ -1378,19 +1386,15 @@
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;
}
@@ -1465,25 +1469,34 @@
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, HWC2::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);
+
+ status_t result = NAME_NOT_FOUND;
+
+ postMessageSync(new LambdaMessage([&] {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ result = getHwComposer().setDisplayBrightness(*displayId, brightness);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ }
+ }));
+
+ return result;
}
status_t SurfaceFlinger::notifyPowerHint(int32_t hintId) {
@@ -1603,13 +1616,13 @@
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,
@@ -1882,6 +1895,20 @@
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();
+ break;
+ }
+
+ // 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) {
@@ -1929,8 +1956,25 @@
// potentially trigger a display handoff.
updateVrFlinger();
- bool refreshNeeded = handleMessageTransaction();
- refreshNeeded |= handleMessageInvalidate();
+ 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.
@@ -1941,9 +1985,7 @@
mScheduler->chooseRefreshRateForContent();
}
- if (performSetActiveConfig()) {
- break;
- }
+ performSetActiveConfig();
updateCursorAsync();
updateInputFlinger();
@@ -2074,7 +2116,7 @@
mLayersWithQueuedFrames.clear();
if (mVisibleRegionsDirty) {
mVisibleRegionsDirty = false;
- if (mTracingEnabled) {
+ if (mTracingEnabled && mAddCompositionStateToTrace) {
mTracing.notify("visibleRegionsDirty");
}
}
@@ -2213,6 +2255,9 @@
}
});
+ mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
+ mTransactionCompletedThread.sendCallbacks();
+
if (displayDevice && displayDevice->isPrimary() &&
displayDevice->getPowerMode() == HWC_POWER_MODE_NORMAL && presentFenceTime->isValid()) {
mScheduler->addPresentFence(presentFenceTime);
@@ -2293,9 +2338,6 @@
}
}
- mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
- mTransactionCompletedThread.sendCallbacks();
-
if (mLumaSampling && mRegionSamplingThread) {
mRegionSamplingThread->notifyNewContent();
}
@@ -2385,7 +2427,8 @@
}
DisplayDeviceState state;
- state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId)};
+ state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId),
+ event.hwcDisplayId};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = info->name;
@@ -2394,6 +2437,12 @@
mPhysicalDisplayTokens.emplace(displayId, std::move(token));
mInterceptor->saveDisplayCreation(state);
+ } else {
+ ALOGV("Recreating display %s", to_string(displayId).c_str());
+
+ const auto token = it->second;
+ auto& state = mCurrentState.displays.editValueFor(token);
+ state.sequenceId = DisplayDeviceState{}.sequenceId;
}
} else {
ALOGV("Removing display %s", to_string(displayId).c_str());
@@ -2571,20 +2620,17 @@
producer = bqProducer;
}
- if (displaySurface != nullptr) {
- mDisplays.emplace(displayToken,
- setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
- displaySurface, producer));
- if (!state.isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, true);
- }
+ LOG_FATAL_IF(!displaySurface);
+ const auto display = setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
+ displaySurface, producer);
+ mDisplays.emplace(displayToken, display);
+ if (!state.isVirtual()) {
+ LOG_FATAL_IF(!displayId);
+ dispatchDisplayHotplugEvent(displayId->value, true);
+ }
- const auto displayDevice = mDisplays[displayToken];
- if (displayDevice->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() *
- displayDevice->getHeight());
- }
+ if (display->isPrimary()) {
+ mScheduler->onPrimaryDisplayAreaChanged(display->getWidth() * display->getHeight());
}
}
@@ -2595,7 +2641,7 @@
display->disconnect();
if (!display->isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
+ LOG_FATAL_IF(!displayId);
dispatchDisplayHotplugEvent(displayId->value, false);
}
}
@@ -2608,13 +2654,19 @@
const DisplayDeviceState& drawingState) {
const sp<IBinder> currentBinder = IInterface::asBinder(currentState.surface);
const sp<IBinder> drawingBinder = IInterface::asBinder(drawingState.surface);
- if (currentBinder != drawingBinder) {
+ if (currentBinder != drawingBinder || currentState.sequenceId != drawingState.sequenceId) {
// changing the surface is like destroying and recreating the DisplayDevice
if (const auto display = getDisplayDeviceLocked(displayToken)) {
display->disconnect();
}
mDisplays.erase(displayToken);
+ if (const auto& physical = currentState.physical) {
+ getHwComposer().allocatePhysicalDisplay(physical->hwcDisplayId, physical->id);
+ }
processDisplayAdded(displayToken, currentState);
+ if (currentState.physical) {
+ initializeDisplays();
+ }
return;
}
@@ -2939,15 +2991,14 @@
// 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);
}
void SurfaceFlinger::commitTransaction()
{
- withTracingLock([this]() { commitTransactionLocked(); });
-
+ commitTransactionLocked();
mTransactionPending = false;
mAnimTransactionPending = false;
mTransactionCV.broadcast();
@@ -2996,26 +3047,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) {
@@ -3480,12 +3511,13 @@
return flags;
}
-bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess() {
+bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermissionCache) {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
- !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
+ (usePermissionCache ? !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)
+ : !checkPermission(sAccessSurfaceFlinger, pid, uid))) {
return false;
}
return true;
@@ -4132,6 +4164,9 @@
}
if (currentMode == HWC_POWER_MODE_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) {
setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
@@ -4142,19 +4177,11 @@
mVisibleRegionsDirty = true;
mHasPoweredOff = true;
repaintEverything();
-
- struct sched_param param = {0};
- param.sched_priority = 1;
- if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
- ALOGW("Couldn't set SCHED_FIFO on display on");
- }
} else if (mode == HWC_POWER_MODE_OFF) {
// Turn off the display
- struct sched_param param = {0};
- if (sched_setscheduler(0, SCHED_OTHER, ¶m) != 0) {
- ALOGW("Couldn't set SCHED_OTHER on display off");
+ 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) {
mScheduler->disableHardwareVsync(true);
mScheduler->onScreenReleased(mAppConnectionHandle);
@@ -4197,7 +4224,7 @@
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
- const auto display = getDisplayDevice(displayToken);
+ const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
displayToken.get());
@@ -4362,17 +4389,16 @@
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
dispSyncPresentTimeOffset, getVsyncPeriod());
- HwcConfigIndexType defaultConfig;
- float minFps, maxFps;
- mRefreshRateConfigs->getPolicy(&defaultConfig, &minFps, &maxFps);
+ scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy();
StringAppendF(&result,
"DesiredDisplayConfigSpecs: default config ID: %d"
", min: %.2f Hz, max: %.2f Hz",
- defaultConfig.value(), minFps, maxFps);
+ policy.defaultConfig.value(), policy.minRefreshRate, policy.maxRefreshRate);
StringAppendF(&result, "(config override by backdoor: %s)\n\n",
mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
mScheduler->dump(mAppConnectionHandle, result);
+ mScheduler->getPrimaryDispSync().dump(result);
}
void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const {
@@ -4527,11 +4553,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);
}
return layersProto;
@@ -4563,10 +4591,7 @@
LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
LayersProto layersProto;
- postMessageSync(new LambdaMessage([&]() {
- const auto& displayDevice = getDefaultDisplayDeviceLocked();
- layersProto = dumpDrawingStateProto(traceFlags, displayDevice);
- }));
+ postMessageSync(new LambdaMessage([&] { layersProto = dumpDrawingStateProto(traceFlags); }));
return layersProto;
}
@@ -4807,8 +4832,12 @@
case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
case GET_DISPLAYED_CONTENT_SAMPLE:
case NOTIFY_POWER_HINT:
- case SET_GLOBAL_SHADOW_SETTINGS: {
- if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
+ case SET_GLOBAL_SHADOW_SETTINGS:
+ case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: {
+ // ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN is used by CTS tests, which acquire the
+ // necessary permission dynamically. Don't use the permission cache for this check.
+ bool usePermissionCache = code != ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN;
+ if (!callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) {
IPCThreadState* ipc = IPCThreadState::self();
ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
ipc->getCallingPid(), ipc->getCallingUid());
@@ -5089,20 +5118,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);
@@ -5307,10 +5328,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
@@ -5322,7 +5343,6 @@
DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace,
renderAreaRotation, captureSecureLayers);
-
auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
std::placeholders::_1);
return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat,
@@ -5341,6 +5361,26 @@
}
}
+status_t SurfaceFlinger::setSchedFifo(bool enabled) {
+ static constexpr int kFifoPriority = 2;
+ static constexpr int kOtherPriority = 0;
+
+ struct sched_param param = {0};
+ int sched_policy;
+ if (enabled) {
+ sched_policy = SCHED_FIFO;
+ param.sched_priority = kFifoPriority;
+ } else {
+ sched_policy = SCHED_OTHER;
+ param.sched_priority = kOtherPriority;
+ }
+
+ if (sched_setscheduler(0, sched_policy, ¶m) != 0) {
+ return -errno;
+ }
+ return NO_ERROR;
+}
+
const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
if (displayToken) {
@@ -5367,10 +5407,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());
@@ -5430,10 +5470,7 @@
mFlinger(flinger),
mChildrenOnly(childrenOnly) {}
const ui::Transform& getTransform() const override { return mTransform; }
- Rect getBounds() const override {
- const Layer::State& layerState(mLayer->getDrawingState());
- return mLayer->getBufferSize(layerState);
- }
+ Rect getBounds() const override { return mLayer->getBufferSize(mLayer->getDrawingState()); }
int getHeight() const override {
return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
}
@@ -5476,9 +5513,8 @@
mTransform = mLayer->getTransform().inverse();
drawLayers();
} else {
- Rect bounds = getBounds();
- uint32_t w = static_cast<uint32_t>(bounds.getWidth());
- uint32_t h = static_cast<uint32_t>(bounds.getHeight());
+ uint32_t w = static_cast<uint32_t>(getWidth());
+ uint32_t h = static_cast<uint32_t>(getHeight());
// In the "childrenOnly" case we reparent the children to a screenshot
// layer which has no properties set and which does not draw.
sp<ContainerLayer> screenshotParentLayer =
@@ -5509,7 +5545,7 @@
std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
Rect displayViewport;
{
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
parent = fromHandle(layerHandleBinder);
if (parent == nullptr || parent->isRemovedFromCurrentState()) {
@@ -5553,9 +5589,9 @@
}
}
- auto display = getDisplayByLayerStack(parent->getLayerStack());
+ const auto display = getDisplayByLayerStack(parent->getLayerStack());
if (!display) {
- return BAD_VALUE;
+ return NAME_NOT_FOUND;
}
displayViewport = display->getViewport();
@@ -5693,9 +5729,9 @@
const auto reqWidth = renderArea.getReqWidth();
const auto reqHeight = renderArea.getReqHeight();
- const auto rotation = renderArea.getRotationFlags();
- const auto transform = renderArea.getTransform();
const auto sourceCrop = renderArea.getSourceCrop();
+ const auto transform = renderArea.getTransform();
+ const auto rotation = renderArea.getRotationFlags();
const auto& displayViewport = renderArea.getDisplayViewport();
renderengine::DisplaySettings clientCompositionDisplay;
@@ -5705,55 +5741,7 @@
// buffer bounds.
clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
clientCompositionDisplay.clip = sourceCrop;
- clientCompositionDisplay.globalTransform = transform.asMatrix4();
-
- // Now take into account the rotation flag. We append a transform that
- // rotates the layer stack about the origin, then translate by buffer
- // boundaries to be in the right quadrant.
- mat4 rotMatrix;
- int displacementX = 0;
- int displacementY = 0;
- float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
- switch (rotation) {
- case ui::Transform::ROT_90:
- rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
- displacementX = renderArea.getBounds().getHeight();
- break;
- case ui::Transform::ROT_180:
- rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
- displacementY = renderArea.getBounds().getWidth();
- displacementX = renderArea.getBounds().getHeight();
- break;
- case ui::Transform::ROT_270:
- rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
- displacementY = renderArea.getBounds().getWidth();
- break;
- default:
- break;
- }
-
- // We need to transform the clipping window into the right spot.
- // First, rotate the clipping rectangle by the rotation hint to get the
- // right orientation
- const vec4 clipTL = vec4(sourceCrop.left, sourceCrop.top, 0, 1);
- const vec4 clipBR = vec4(sourceCrop.right, sourceCrop.bottom, 0, 1);
- const vec4 rotClipTL = rotMatrix * clipTL;
- const vec4 rotClipBR = rotMatrix * clipBR;
- const int newClipLeft = std::min(rotClipTL[0], rotClipBR[0]);
- const int newClipTop = std::min(rotClipTL[1], rotClipBR[1]);
- const int newClipRight = std::max(rotClipTL[0], rotClipBR[0]);
- const int newClipBottom = std::max(rotClipTL[1], rotClipBR[1]);
-
- // Now reposition the clipping rectangle with the displacement vector
- // computed above.
- const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
- clientCompositionDisplay.clip =
- Rect(newClipLeft + displacementX, newClipTop + displacementY,
- newClipRight + displacementX, newClipBottom + displacementY);
-
- mat4 clipTransform = displacementMat * rotMatrix;
- clientCompositionDisplay.globalTransform =
- clipTransform * clientCompositionDisplay.globalTransform;
+ clientCompositionDisplay.orientation = rotation;
clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
@@ -5763,10 +5751,12 @@
compositionengine::LayerFE::LayerSettings fillLayer;
fillLayer.source.buffer.buffer = nullptr;
fillLayer.source.solidColor = half3(0.0, 0.0, 0.0);
- fillLayer.geometry.boundaries = FloatRect(0.0, 0.0, 1.0, 1.0);
+ fillLayer.geometry.boundaries =
+ FloatRect(sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom);
fillLayer.alpha = half(alpha);
clientCompositionLayers.push_back(fillLayer);
+ std::vector<Layer*> renderedLayers;
Region clearRegion = Region::INVALID_REGION;
traverseLayers([&](Layer* layer) {
const bool supportProtectedContent = false;
@@ -5774,7 +5764,8 @@
compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
clip,
useIdentityTransform,
- layer->needsFiltering(renderArea.getDisplayDevice()) || renderArea.needsFiltering(),
+ layer->needsFilteringForScreenshots(renderArea.getDisplayDevice(), transform) ||
+ renderArea.needsFiltering(),
renderArea.isSecure(),
supportProtectedContent,
clearRegion,
@@ -5785,19 +5776,23 @@
};
std::vector<compositionengine::LayerFE::LayerSettings> results =
layer->prepareClientCompositionList(targetSettings);
- clientCompositionLayers.insert(clientCompositionLayers.end(),
- std::make_move_iterator(results.begin()),
- std::make_move_iterator(results.end()));
- results.clear();
-
+ if (results.size() > 0) {
+ for (auto& settings : results) {
+ settings.geometry.positionTransform =
+ transform.asMatrix4() * settings.geometry.positionTransform;
+ }
+ clientCompositionLayers.insert(clientCompositionLayers.end(),
+ std::make_move_iterator(results.begin()),
+ std::make_move_iterator(results.end()));
+ renderedLayers.push_back(layer);
+ }
});
- std::vector<const renderengine::LayerSettings*> clientCompositionLayerPointers;
- clientCompositionLayers.reserve(clientCompositionLayers.size());
+ std::vector<const renderengine::LayerSettings*> clientCompositionLayerPointers(
+ clientCompositionLayers.size());
std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
- std::back_inserter(clientCompositionLayerPointers),
- [](compositionengine::LayerFE::LayerSettings& settings)
- -> renderengine::LayerSettings* { return &settings; });
+ clientCompositionLayerPointers.begin(),
+ std::pointer_traits<renderengine::LayerSettings*>::pointer_to);
clientCompositionDisplay.clearRegion = clearRegion;
// Use an empty fence for the buffer fence, since we just created the buffer so
@@ -5809,6 +5804,13 @@
/*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
*outSyncFd = drawFence.release();
+
+ if (*outSyncFd >= 0) {
+ sp<Fence> releaseFence = new Fence(dup(*outSyncFd));
+ for (auto* layer : renderedLayers) {
+ layer->onLayerDisplayed(releaseFence);
+ }
+ }
}
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
@@ -5877,12 +5879,15 @@
}
}
-status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const sp<DisplayDevice>& display,
- HwcConfigIndexType defaultConfig,
- float minRefreshRate,
- float maxRefreshRate) {
+status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(
+ const sp<DisplayDevice>& display,
+ const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {
Mutex::Autolock lock(mStateLock);
+ LOG_ALWAYS_FATAL_IF(!display->isPrimary() && overridePolicy,
+ "Can only set override policy on the primary display");
+ LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy");
+
if (!display->isPrimary()) {
// TODO(b/144711714): For non-primary displays we should be able to set an active config
// as well. For now, just call directly to setActiveConfigWithConstraints but ideally
@@ -5896,7 +5901,8 @@
constraints.seamlessRequired = false;
HWC2::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
- if (getHwComposer().setActiveConfigWithConstraints(*displayId, defaultConfig.value(),
+ if (getHwComposer().setActiveConfigWithConstraints(*displayId,
+ policy->defaultConfig.value(),
constraints, &timeline) < 0) {
return BAD_VALUE;
}
@@ -5904,11 +5910,12 @@
repaintEverythingForHWC();
}
- display->setActiveConfig(defaultConfig);
- const nsecs_t vsyncPeriod =
- getHwComposer().getConfigs(*displayId)[defaultConfig.value()]->getVsyncPeriod();
- mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, defaultConfig,
- vsyncPeriod);
+ display->setActiveConfig(policy->defaultConfig);
+ const nsecs_t vsyncPeriod = getHwComposer()
+ .getConfigs(*displayId)[policy->defaultConfig.value()]
+ ->getVsyncPeriod();
+ mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
+ policy->defaultConfig, vsyncPeriod);
return NO_ERROR;
}
@@ -5917,23 +5924,27 @@
return NO_ERROR;
}
- bool policyChanged;
- if (mRefreshRateConfigs->setPolicy(defaultConfig, minRefreshRate, maxRefreshRate,
- &policyChanged) < 0) {
+ status_t setPolicyResult = overridePolicy
+ ? mRefreshRateConfigs->setOverridePolicy(policy)
+ : mRefreshRateConfigs->setDisplayManagerPolicy(*policy);
+ if (setPolicyResult < 0) {
return BAD_VALUE;
}
- if (!policyChanged) {
+ if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {
return NO_ERROR;
}
+ scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy();
ALOGV("Setting desired display config specs: defaultConfig: %d min: %.f max: %.f",
- defaultConfig.value(), minRefreshRate, maxRefreshRate);
+ currentPolicy.defaultConfig.value(), currentPolicy.minRefreshRate,
+ currentPolicy.maxRefreshRate);
// 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);
@@ -5941,15 +5952,18 @@
auto& preferredRefreshRate = configId
? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId)
// NOTE: Choose the default config ID, if Scheduler doesn't have one in mind.
- : mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig);
+ : 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;
@@ -5964,21 +5978,24 @@
return BAD_VALUE;
}
- status_t result = NO_ERROR;
+ status_t result = NAME_NOT_FOUND;
postMessageSync(new LambdaMessage([&]() {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
- result = BAD_VALUE;
ALOGE("Attempt to set desired display configs for invalid display token %p",
displayToken.get());
} else if (display->isVirtual()) {
- result = BAD_VALUE;
ALOGW("Attempt to set desired display configs for virtual display");
+ result = INVALID_OPERATION;
} else {
- result =
- setDesiredDisplayConfigSpecsInternal(display, HwcConfigIndexType(defaultConfig),
- minRefreshRate, maxRefreshRate);
+ result = setDesiredDisplayConfigSpecsInternal(display,
+ scheduler::RefreshRateConfigs::
+ Policy{HwcConfigIndexType(
+ defaultConfig),
+ minRefreshRate,
+ maxRefreshRate},
+ /*overridePolicy=*/false);
}
}));
@@ -6002,17 +6019,18 @@
}
if (display->isPrimary()) {
- HwcConfigIndexType defaultConfig;
- mRefreshRateConfigs->getPolicy(&defaultConfig, outMinRefreshRate, outMaxRefreshRate);
- *outDefaultConfig = defaultConfig.value();
+ scheduler::RefreshRateConfigs::Policy policy =
+ mRefreshRateConfigs->getDisplayManagerPolicy();
+ *outDefaultConfig = policy.defaultConfig.value();
+ *outMinRefreshRate = policy.minRefreshRate;
+ *outMaxRefreshRate = policy.maxRefreshRate;
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;
@@ -6124,6 +6142,68 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) {
+ if (!outToken) {
+ return BAD_VALUE;
+ }
+ status_t result = NO_ERROR;
+ postMessageSync(new LambdaMessage([&]() {
+ if (mFrameRateFlexibilityTokenCount == 0) {
+ // |mStateLock| not needed as we are on the main thread
+ const auto display = getDefaultDisplayDeviceLocked();
+
+ // This is a little racy, but not in a way that hurts anything. As we grab the
+ // defaultConfig from the display manager policy, we could be setting a new display
+ // manager policy, leaving us using a stale defaultConfig. The defaultConfig doesn't
+ // matter for the override policy though, since we set allowGroupSwitching to true, so
+ // it's not a problem.
+ scheduler::RefreshRateConfigs::Policy overridePolicy;
+ overridePolicy.defaultConfig =
+ mRefreshRateConfigs->getDisplayManagerPolicy().defaultConfig;
+ overridePolicy.allowGroupSwitching = true;
+ result = setDesiredDisplayConfigSpecsInternal(display, overridePolicy,
+ /*overridePolicy=*/true);
+ }
+
+ if (result == NO_ERROR) {
+ mFrameRateFlexibilityTokenCount++;
+ // Handing out a reference to the SurfaceFlinger object, as we're doing in the line
+ // below, is something to consider carefully. The lifetime of the
+ // FrameRateFlexibilityToken isn't tied to SurfaceFlinger object lifetime, so if this
+ // SurfaceFlinger object were to be destroyed while the token still exists, the token
+ // destructor would be accessing a stale SurfaceFlinger reference, and crash. This is ok
+ // in this case, for two reasons:
+ // 1. Once SurfaceFlinger::run() is called by main_surfaceflinger.cpp, the only way
+ // the program exits is via a crash. So we won't have a situation where the
+ // SurfaceFlinger object is dead but the process is still up.
+ // 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(
+ [this]() { onFrameRateFlexibilityTokenReleased(); });
+ ALOGD("Frame rate flexibility token acquired. count=%d",
+ mFrameRateFlexibilityTokenCount);
+ }
+ }));
+ return result;
+}
+
+void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() {
+ postMessageAsync(new LambdaMessage([&]() {
+ LOG_ALWAYS_FATAL_IF(mFrameRateFlexibilityTokenCount == 0,
+ "Failed tracking frame rate flexibility tokens");
+ mFrameRateFlexibilityTokenCount--;
+ ALOGD("Frame rate flexibility token released. count=%d", mFrameRateFlexibilityTokenCount);
+ if (mFrameRateFlexibilityTokenCount == 0) {
+ // |mStateLock| not needed as we are on the main thread
+ const auto display = getDefaultDisplayDeviceLocked();
+ status_t result =
+ setDesiredDisplayConfigSpecsInternal(display, {}, /*overridePolicy=*/true);
+ LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token");
+ }
+ }));
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6ab1fcf..eb0afc8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -259,6 +259,9 @@
// overhead that is caused by reading from sysprop.
static bool useFrameRateApi;
+ // set main thread scheduling policy
+ static status_t setSchedFifo(bool enabled) ANDROID_API;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
@@ -404,7 +407,8 @@
*/
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
- bool callingThreadHasUnscopedSurfaceFlingerAccess() EXCLUDES(mStateLock);
+ bool callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermissionCache = true)
+ EXCLUDES(mStateLock);
/* ------------------------------------------------------------------------
* ISurfaceComposer interface
@@ -471,14 +475,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;
@@ -494,12 +497,13 @@
float* outMaxRefreshRate) 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;
status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
int8_t compatibility) override;
+ status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
@@ -560,27 +564,20 @@
// 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);
// Sets the desired display configs.
- status_t setDesiredDisplayConfigSpecsInternal(const sp<DisplayDevice>& display,
- HwcConfigIndexType defaultConfig,
- float minRefreshRate, float maxRefreshRate)
+ status_t setDesiredDisplayConfigSpecsInternal(
+ const sp<DisplayDevice>& display,
+ 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);
-
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -735,16 +732,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);
@@ -942,8 +929,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
@@ -951,7 +937,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;
@@ -965,6 +950,8 @@
return doDump(fd, args, asProto);
}
+ void onFrameRateFlexibilityTokenReleased();
+
/* ------------------------------------------------------------------------
* VrFlinger
*/
@@ -991,9 +978,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;
@@ -1068,9 +1052,13 @@
bool mPropagateBackpressure = true;
bool mPropagateBackpressureClientComposition = false;
std::unique_ptr<SurfaceInterceptor> mInterceptor;
+
SurfaceTracing mTracing{*this};
+ std::mutex mTracingLock;
bool mTracingEnabled = false;
- bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
+ bool mAddCompositionStateToTrace = false;
+ std::atomic<bool> mTracingEnabledChanged = false;
+
const std::shared_ptr<TimeStats> mTimeStats;
const std::unique_ptr<FrameTracer> mFrameTracer;
bool mUseHwcVirtualDisplays = false;
@@ -1217,7 +1205,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;
@@ -1272,6 +1260,8 @@
std::atomic<bool> mInputDirty = true;
void dirtyInput() { mInputDirty = true; }
bool inputDirty() { return mInputDirty; }
+
+ int mFrameRateFlexibilityTokenCount = 0;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index a9c3332..d84ce69 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -33,33 +33,32 @@
namespace android {
SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger)
- : mFlinger(flinger), mSfLock(flinger.mDrawingStateLock) {}
+ : mFlinger(flinger), mSfLock(flinger.mTracingLock) {}
void SurfaceTracing::mainLoop() {
- addFirstEntry();
- bool enabled = true;
+ bool enabled = addFirstEntry();
while (enabled) {
LayersTraceProto entry = traceWhenNotified();
enabled = addTraceToBuffer(entry);
}
}
-void SurfaceTracing::addFirstEntry() {
- const auto displayDevice = mFlinger.getDefaultDisplayDevice();
+bool SurfaceTracing::addFirstEntry() {
LayersTraceProto entry;
{
std::scoped_lock lock(mSfLock);
- entry = traceLayersLocked("tracing.enable", displayDevice);
+ entry = traceLayersLocked("tracing.enable");
}
- addTraceToBuffer(entry);
+ 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();
return entry;
}
@@ -76,7 +75,15 @@
void SurfaceTracing::notify(const char* where) {
std::scoped_lock lock(mSfLock);
+ notifyLocked(where);
+}
+
+void SurfaceTracing::notifyLocked(const char* where) {
mWhere = where;
+ if (mTracingInProgress) {
+ mMissedTraceEntries++;
+ }
+ mTracingInProgress = true;
mCanStartTrace.notify_one();
}
@@ -117,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() {
@@ -167,15 +176,17 @@
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));
- mFlinger.dumpOffscreenLayersProto(layers);
+ LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
+
+ if (flagIsSetLocked(SurfaceTracing::TRACE_EXTRA)) {
+ mFlinger.dumpOffscreenLayersProto(layers);
+ }
entry.mutable_layers()->Swap(&layers);
if (mTraceFlags & SurfaceTracing::TRACE_HWC) {
@@ -183,6 +194,10 @@
mFlinger.dumpHwc(hwcDump);
entry.set_hwc_blob(hwcDump);
}
+ if (!flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION)) {
+ entry.set_excludes_composition_state(true);
+ }
+ entry.set_missed_entries(mMissedTraceEntries);
return entry;
}
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 83872ed..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,11 +42,12 @@
class SurfaceTracing {
public:
explicit SurfaceTracing(SurfaceFlinger& flinger);
- void enable();
+ bool enable();
bool disable();
status_t writeToFile();
bool isEnabled() const;
void notify(const char* where);
+ void notifyLocked(const char* where) NO_THREAD_SAFETY_ANALYSIS /* REQUIRES(mSfLock) */;
void setBufferSize(size_t bufferSizeInByte);
void writeToFileAsync();
@@ -57,11 +56,15 @@
enum : uint32_t {
TRACE_CRITICAL = 1 << 0,
TRACE_INPUT = 1 << 1,
- TRACE_EXTRA = 1 << 2,
- TRACE_HWC = 1 << 3,
+ TRACE_COMPOSITION = 1 << 2,
+ TRACE_EXTRA = 1 << 3,
+ TRACE_HWC = 1 << 4,
TRACE_ALL = 0xffffffff
};
void setTraceFlags(uint32_t flags);
+ bool flagIsSetLocked(uint32_t flags) NO_THREAD_SAFETY_ANALYSIS /* REQUIRES(mSfLock) */ {
+ return (mTraceFlags & flags) == flags;
+ }
private:
static constexpr auto kDefaultBufferCapInByte = 5_MB;
@@ -85,11 +88,9 @@
};
void mainLoop();
- void addFirstEntry();
+ 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);
@@ -103,6 +104,8 @@
std::mutex& mSfLock;
uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_CRITICAL | TRACE_INPUT;
const char* mWhere GUARDED_BY(mSfLock) = "";
+ uint32_t mMissedTraceEntries GUARDED_BY(mSfLock) = 0;
+ bool mTracingInProgress GUARDED_BY(mSfLock) = false;
mutable std::mutex mTraceLock;
LayersTraceBuffer mBuffer GUARDED_BY(mTraceLock);
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 4f59bf2..606e137 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -281,6 +281,15 @@
mTimeStats.clientCompositionReusedFrames++;
}
+void TimeStats::incrementRefreshRateSwitches() {
+ if (!mEnabled.load()) return;
+
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ mTimeStats.refreshRateSwitches++;
+}
+
void TimeStats::recordDisplayEventConnectionCount(int32_t count) {
if (!mEnabled.load()) return;
@@ -834,6 +843,7 @@
mTimeStats.missedFrames = 0;
mTimeStats.clientCompositionFrames = 0;
mTimeStats.clientCompositionReusedFrames = 0;
+ mTimeStats.refreshRateSwitches = 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 f9bd90b..806b47e 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -52,6 +52,8 @@
virtual void incrementMissedFrames() = 0;
virtual void incrementClientCompositionFrames() = 0;
virtual void incrementClientCompositionReusedFrames() = 0;
+ // Increments the number of times the display refresh rate changed.
+ virtual void incrementRefreshRateSwitches() = 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;
@@ -215,6 +217,7 @@
void incrementMissedFrames() override;
void incrementClientCompositionFrames() override;
void incrementClientCompositionReusedFrames() override;
+ void incrementRefreshRateSwitches() override;
void recordDisplayEventConnectionCount(int32_t count) override;
void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) override;
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index e2f85cc..5305de9 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -105,6 +105,7 @@
StringAppendF(&result, "missedFrames = %d\n", missedFrames);
StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
StringAppendF(&result, "clientCompositionReusedFrames = %d\n", clientCompositionReusedFrames);
+ StringAppendF(&result, "refreshRateSwitches = %d\n", refreshRateSwitches);
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 5e7c449..afb98e0 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -62,6 +62,7 @@
int32_t missedFrames = 0;
int32_t clientCompositionFrames = 0;
int32_t clientCompositionReusedFrames = 0;
+ int32_t refreshRateSwitches = 0;
int32_t displayEventConnectionsCount = 0;
int64_t displayOnTime = 0;
Histogram presentToPresent;
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
index ac33a0e..acf621e 100644
--- a/services/surfaceflinger/layerproto/layerstrace.proto
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -51,4 +51,10 @@
// Blob for the current HWC information for all layers, reported by dumpsys.
optional string hwc_blob = 4;
+
+ /* Includes state sent during composition like visible region and composition type. */
+ optional bool excludes_composition_state = 5;
+
+ /* Number of missed entries since the last entry was recorded. */
+ optional int32 missed_entries = 6;
}
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index d7ad9de..2b8424c 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -31,6 +31,7 @@
#include <binder/ProcessState.h>
#include <configstore/Utils.h>
#include <displayservice/DisplayService.h>
+#include <errno.h>
#include <hidl/LegacySupport.h>
#include <processgroup/sched_policy.h>
#include "SurfaceFlinger.h"
@@ -114,10 +115,8 @@
startDisplayService(); // dependency on SF getting registered above
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO");
+ if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
}
// run surface flinger in this thread
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 932c7c8..40ec502 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -52,9 +52,10 @@
virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client,
const char* name, uint32_t width, uint32_t height,
uint32_t flags = 0, SurfaceControl* parent = nullptr,
- uint32_t* outTransformHint = nullptr) {
- auto layer = createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags,
- parent, outTransformHint);
+ uint32_t* outTransformHint = nullptr,
+ PixelFormat format = PIXEL_FORMAT_RGBA_8888) {
+ auto layer =
+ createSurface(client, name, width, height, format, flags, parent, outTransformHint);
Transaction t;
t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase);
@@ -81,8 +82,9 @@
virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
uint32_t flags = 0, SurfaceControl* parent = nullptr,
- uint32_t* outTransformHint = nullptr) {
- return createLayer(mClient, name, width, height, flags, parent, outTransformHint);
+ uint32_t* outTransformHint = nullptr,
+ PixelFormat format = PIXEL_FORMAT_RGBA_8888) {
+ return createLayer(mClient, name, width, height, flags, parent, outTransformHint, format);
}
sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index 2fd2579..d666d7e 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -365,6 +365,67 @@
getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBufferFormat) {
+ int32_t width = 100;
+ int32_t height = 100;
+ Rect crop = Rect(0, 0, width, height);
+
+ sp<SurfaceControl> behindLayer = createColorLayer("Behind layer", Color::RED);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, 0, nullptr, nullptr,
+ PIXEL_FORMAT_RGBX_8888));
+
+ Transaction()
+ .setLayer(layer, INT32_MAX - 1)
+ .show(layer)
+ .setLayerStack(behindLayer, mDisplayLayerStack)
+ .setCrop_legacy(behindLayer, crop)
+ .setLayer(behindLayer, INT32_MAX - 2)
+ .show(behindLayer)
+ .apply();
+
+ sp<Surface> surface = layer->getSurface();
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(width, height, PIXEL_FORMAT_RGBX_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillGraphicBufferColor(buffer, crop, Color::TRANSPARENT));
+
+ if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
+ Surface::attachAndQueueBufferWithDataspace(surface.get(), buffer, ui::Dataspace::V0_SRGB);
+ } else {
+ Transaction().setBuffer(layer, buffer).apply();
+ }
+
+ {
+ SCOPED_TRACE("Buffer Opaque Format");
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::BLACK);
+ }
+
+ buffer = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillGraphicBufferColor(buffer, crop, Color::TRANSPARENT));
+
+ if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
+ Surface::attachAndQueueBufferWithDataspace(surface.get(), buffer, ui::Dataspace::V0_SRGB);
+ } else {
+ Transaction().setBuffer(layer, buffer).apply();
+ }
+
+ {
+ SCOPED_TRACE("Buffer Transparent Format");
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::RED);
+ }
+}
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
index f8a5b40..06e8761 100644
--- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
+++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
@@ -104,7 +104,7 @@
// Verify color layer renders correctly on virtual display.
ScreenCapture::captureScreen(&sc, mVirtualDisplay);
sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
- sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 0});
+ sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 255});
}
TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) {
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index 040852f..f0af363 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -88,13 +88,14 @@
sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
uint32_t flags = 0, SurfaceControl* parent = nullptr,
- uint32_t* outTransformHint = nullptr) {
+ uint32_t* outTransformHint = nullptr,
+ PixelFormat format = PIXEL_FORMAT_RGBA_8888) {
// if the flags already have a layer type specified, return an error
if (flags & ISurfaceComposerClient::eFXSurfaceMask) {
return nullptr;
}
return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType, parent,
- outTransformHint);
+ outTransformHint, format);
}
void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth,
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/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 680b0a0..2dcaf63 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -305,14 +305,14 @@
compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
ceDisplayArgs);
- test->mDisplay =
- FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
- DisplayConnectionType::Internal, true /* isPrimary */)
- .setDisplaySurface(test->mDisplaySurface)
- .setNativeWindow(test->mNativeWindow)
- .setSecure(Derived::IS_SECURE)
- .setPowerMode(Derived::INIT_POWER_MODE)
- .inject();
+ test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
+ DisplayConnectionType::Internal, HWC_DISPLAY,
+ true /* isPrimary */)
+ .setDisplaySurface(test->mDisplaySurface)
+ .setNativeWindow(test->mNativeWindow)
+ .setSecure(Derived::IS_SECURE)
+ .setPowerMode(Derived::INIT_POWER_MODE)
+ .inject();
Mock::VerifyAndClear(test->mNativeWindow);
test->mDisplay->setLayerStack(DEFAULT_LAYER_STACK);
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index c2ddfce..2a0e913 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -96,7 +96,7 @@
"\x0a\x20\x20\x20\x20\x20\x01\x47\x02\x03\x2d\x71\x50\x90\x05"
"\x04\x03\x07\x02\x06\x01\x1f\x14\x13\x12\x16\x11\x15\x20\x2c"
"\x09\x07\x03\x15\x07\x50\x57\x07\x00\x39\x07\xbb\x66\x03\x0c"
- "\x00\x20\x00\x00\x83\x01\x00\x00\x01\x1d\x00\x72\x51\xd0\x1e"
+ "\x00\x12\x34\x00\x83\x01\x00\x00\x01\x1d\x00\x72\x51\xd0\x1e"
"\x20\x6e\x28\x55\x00\xc4\x8e\x21\x00\x00\x1e\x01\x1d\x80\x18"
"\x71\x1c\x16\x20\x58\x2c\x25\x00\xc4\x8e\x21\x00\x00\x9e\x8c"
"\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\x13\x8e\x21\x00"
@@ -185,6 +185,7 @@
EXPECT_EQ(12610, edid->productId);
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
+ EXPECT_FALSE(edid->cea861Block);
edid = parseEdid(getExternalEdid());
ASSERT_TRUE(edid);
@@ -195,6 +196,7 @@
EXPECT_EQ(10348, edid->productId);
EXPECT_EQ(22, edid->manufactureOrModelYear);
EXPECT_EQ(2, edid->manufactureWeek);
+ EXPECT_FALSE(edid->cea861Block);
edid = parseEdid(getExternalEedid());
ASSERT_TRUE(edid);
@@ -205,6 +207,13 @@
EXPECT_EQ(2302, edid->productId);
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(41, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
+ 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);
edid = parseEdid(getPanasonicTvEdid());
ASSERT_TRUE(edid);
@@ -215,6 +224,13 @@
EXPECT_EQ(41622, edid->productId);
EXPECT_EQ(29, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
+ 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);
edid = parseEdid(getHisenseTvEdid());
ASSERT_TRUE(edid);
@@ -225,6 +241,13 @@
EXPECT_EQ(0, edid->productId);
EXPECT_EQ(29, edid->manufactureOrModelYear);
EXPECT_EQ(18, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
+ 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);
edid = parseEdid(getCtlDisplayEdid());
ASSERT_TRUE(edid);
@@ -235,6 +258,8 @@
EXPECT_EQ(9373, edid->productId);
EXPECT_EQ(23, edid->manufactureOrModelYear);
EXPECT_EQ(0xff, edid->manufactureWeek);
+ ASSERT_TRUE(edid->cea861Block);
+ EXPECT_FALSE(edid->cea861Block->hdmiVendorDataBlock);
}
TEST(DisplayIdentificationTest, parseInvalidEdid) {
@@ -287,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());
@@ -298,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());
@@ -311,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());
@@ -324,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());
@@ -336,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());
@@ -349,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());
@@ -360,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 6d00ccc..cd11409 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -246,6 +246,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;
// The DisplayDevice is required to have a framebuffer (behind the
// ANativeWindow interface) which uses the actual hardware display
@@ -270,7 +271,7 @@
auto injector =
FakeDisplayDeviceInjector(mFlinger, compositionDisplay, DisplayConnectionType::Internal,
- true /* isPrimary */);
+ DEFAULT_DISPLAY_HWC_DISPLAY_ID, true /* isPrimary */);
injector.setNativeWindow(mNativeWindow);
if (injectExtra) {
@@ -373,6 +374,23 @@
static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
};
+template <typename>
+struct HwcDisplayIdGetter {
+ static constexpr std::optional<hwc2_display_t> value;
+};
+
+constexpr hwc2_display_t 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;
+};
+
+template <typename PhysicalDisplay>
+struct HwcDisplayIdGetter<PhysicalDisplayId<PhysicalDisplay>> {
+ static constexpr std::optional<hwc2_display_t> value = PhysicalDisplay::HWC_DISPLAY_ID;
+};
+
// DisplayIdType can be:
// 1) PhysicalDisplayId<...> for generated ID of physical display backed by HWC.
// 2) VirtualDisplayId<...> for hard-coded ID of virtual display backed by HWC.
@@ -382,6 +400,7 @@
struct DisplayVariant {
using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
+ using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
// The display width and height
static constexpr int WIDTH = width;
@@ -418,9 +437,9 @@
compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
ceDisplayArgs.build());
- auto injector =
- FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
- CONNECTION_TYPE::value, static_cast<bool>(PRIMARY));
+ auto injector = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
+ CONNECTION_TYPE::value, HWC_DISPLAY_ID_OPT::value,
+ static_cast<bool>(PRIMARY));
injector.setSecure(static_cast<bool>(SECURE));
injector.setNativeWindow(test->mNativeWindow);
@@ -603,12 +622,11 @@
constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
-template <hwc2_display_t hwcDisplayId, typename PhysicalDisplay, int width, int height,
- Critical critical>
+template <typename PhysicalDisplay, int width, int height, Critical critical>
struct PhysicalDisplayVariant
: DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height, critical, Async::FALSE,
Secure::TRUE, PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
- HwcDisplayVariant<hwcDisplayId, HWC2::DisplayType::Physical,
+ HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, HWC2::DisplayType::Physical,
DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height,
critical, Async::FALSE, Secure::TRUE,
PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
@@ -619,6 +637,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 bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
};
@@ -628,6 +647,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 bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
};
@@ -635,19 +655,19 @@
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 auto GET_IDENTIFICATION_DATA = getExternalEdid;
};
// A primary display is a physical display that is critical
using PrimaryDisplayVariant =
- PhysicalDisplayVariant<1001, PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
+ PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
// An external display is physical display that is not critical.
using ExternalDisplayVariant =
- PhysicalDisplayVariant<1002, ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
+ PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
-using TertiaryDisplayVariant =
- PhysicalDisplayVariant<1003, TertiaryDisplay, 1600, 1200, Critical::FALSE>;
+using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
// A virtual display not supported by the HWC.
constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
@@ -696,7 +716,7 @@
: DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, secure,
Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
HwcDisplayVariant<
- 1010, HWC2::DisplayType::Virtual,
+ HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, HWC2::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,
@@ -1484,7 +1504,7 @@
mHardwareDisplaySize.height),
compositionState.transform);
EXPECT_EQ(TRANSFORM_FLAGS_ROT_90, compositionState.orientation);
- EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.sourceClip);
+ EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.sourceClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
// For 90, the frame and viewport have the hardware display size width and height swapped
EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.frame);
@@ -1511,7 +1531,7 @@
mHardwareDisplaySize.height),
compositionState.transform);
EXPECT_EQ(TRANSFORM_FLAGS_ROT_270, compositionState.orientation);
- EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.sourceClip);
+ EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.sourceClip);
EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
// For 270, the frame and viewport have the hardware display size width and height swapped
EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.frame);
@@ -1711,7 +1731,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);
@@ -1767,7 +1788,9 @@
if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(displayId);
- state.physical = {*displayId, *connectionType};
+ const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
+ ASSERT_TRUE(hwcDisplayId);
+ state.physical = {*displayId, *connectionType, *hwcDisplayId};
}
state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -1941,7 +1964,9 @@
if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(displayId);
- expectedPhysical = {*displayId, *connectionType};
+ const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
+ ASSERT_TRUE(hwcDisplayId);
+ expectedPhysical = {*displayId, *connectionType, *hwcDisplayId};
}
// The display should have been set up in the current display state
@@ -2124,11 +2149,11 @@
ignoresHotplugConnectCommon<SimpleExternalDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processHotplugDisconnectPrimaryDisplay) {
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) {
processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processHotplugDisconnectExternalDisplay) {
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectExternalDisplay) {
processesHotplugDisconnectCommon<SimpleExternalDisplayCase>();
}
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..71e37a8 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;
diff --git a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp
index 8d49201..ce5993a 100644
--- a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp
@@ -45,8 +45,8 @@
class PhaseDurationTest : public testing::Test {
protected:
PhaseDurationTest()
- : mPhaseDurations(60.0f, 10'500'000, 20'500'000, 16'000'000, 33'500'000, 13'500'000,
- 38'000'000) {}
+ : mPhaseDurations(60.0f, 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000,
+ 21'000'000) {}
~PhaseDurationTest() = default;
@@ -69,11 +69,11 @@
EXPECT_EQ(offsets.early.sf, 666'667);
- EXPECT_EQ(offsets.early.app, 500'001);
+ EXPECT_EQ(offsets.early.app, 833'334);
EXPECT_EQ(offsets.earlyGl.sf, 3'166'667);
- EXPECT_EQ(offsets.earlyGl.app, 15'166'668);
+ EXPECT_EQ(offsets.earlyGl.app, 15'500'001);
}
TEST_F(PhaseDurationTest, getOffsetsForRefreshRate_90Hz) {
@@ -88,11 +88,11 @@
EXPECT_EQ(offsets.early.sf, -4'888'889);
- EXPECT_EQ(offsets.early.app, 6'055'555);
+ EXPECT_EQ(offsets.early.app, 833'333);
EXPECT_EQ(offsets.earlyGl.sf, -2'388'889);
- EXPECT_EQ(offsets.earlyGl.app, 4'055'555);
+ EXPECT_EQ(offsets.earlyGl.app, 9'944'444);
}
TEST_F(PhaseDurationTest, getOffsetsForRefreshRate_DefaultOffsets) {
@@ -134,11 +134,11 @@
EXPECT_EQ(offsets.early.sf, 52'027'208);
- EXPECT_EQ(offsets.early.app, 18'527'208);
+ EXPECT_EQ(offsets.early.app, 35'527'208);
EXPECT_EQ(offsets.earlyGl.sf, 54'527'208);
- EXPECT_EQ(offsets.earlyGl.app, 16'527'208);
+ EXPECT_EQ(offsets.earlyGl.app, 33'527'208);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index dd04076..1b8f11b 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::_;
@@ -37,24 +38,95 @@
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 +139,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, hwc2_config_t(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->setPolicy(HwcConfigIndexType(10), 60, 60, nullptr), 0);
- ASSERT_LT(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 20, 40, nullptr), 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 +186,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->setPolicy(HWC_CONFIG_ID_90, 60, 90, nullptr), 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->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 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->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 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->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 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->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 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->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 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) {
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,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
false, &ignored));
// Current refresh rate can always be changed.
refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60);
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/
false, &ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.name = "";
- ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 60, 60}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, 90, 90}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0);
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, 0, 120}), 0);
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,7 +580,7 @@
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected120Config,
+ EXPECT_EQ(mExpected120Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -533,7 +588,7 @@
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -541,27 +596,16 @@
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48.0f;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,7 +618,7 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(expected120Config,
+ EXPECT_EQ(mExpected120Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -584,7 +628,7 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(expected120Config,
+ EXPECT_EQ(mExpected120Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -594,7 +638,7 @@
lr2.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
- EXPECT_EQ(expected120Config,
+ EXPECT_EQ(mExpected120Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -604,7 +648,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -614,7 +658,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -624,7 +668,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -634,7 +678,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -644,7 +688,7 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -654,158 +698,137 @@
lr2.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,
+ EXPECT_EQ(mExpected30Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 30.0f;
- EXPECT_EQ(expected30Config,
+ EXPECT_EQ(mExpected30Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,
+ EXPECT_EQ(mExpected30Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 90.0f;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr.desiredRefreshRate = 60.0f;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
&ignored));
lr.desiredRefreshRate = 45.0f;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
&ignored));
lr.desiredRefreshRate = 30.0f;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(expected30Config,
+ EXPECT_EQ(mExpected30Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
&ignored));
lr.desiredRefreshRate = 24.0f;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
&ignored));
lr.desiredRefreshRate = 24.0f;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
- EXPECT_EQ(expected72Config,
+ EXPECT_EQ(mExpected72Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ true,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,35 +837,35 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -850,7 +873,7 @@
lr1.desiredRefreshRate = 15.0f;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -858,22 +881,16 @@
lr1.desiredRefreshRate = 30.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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];
@@ -884,20 +901,15 @@
const auto& refreshRate =
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored);
- printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
- EXPECT_EQ(expected60Config, refreshRate);
+ 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 +920,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) {
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,7 +944,7 @@
lr1.desiredRefreshRate = 60.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -945,7 +952,7 @@
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -953,32 +960,24 @@
lr1.desiredRefreshRate = 90.0f;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60.0f;
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ 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) {
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];
@@ -989,21 +988,16 @@
const auto& refreshRate =
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored);
- printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
- EXPECT_EQ(expected90Config, refreshRate);
+ printf("%.2fHz chooses %s\n", fps, refreshRate.getName().c_str());
+ EXPECT_EQ(mExpected90Config, refreshRate);
}
}
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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,7 +1010,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -1026,7 +1020,7 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -1035,7 +1029,7 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -1045,7 +1039,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ false,
&ignored));
@@ -1054,21 +1048,16 @@
lr1.name = "30Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ 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,7 +1069,7 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected60Config,
+ EXPECT_EQ(mExpected60Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1088,7 +1077,7 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1096,7 +1085,7 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, true, &ignored));
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1104,7 +1093,7 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored));
// The other layer starts to provide buffers
@@ -1114,17 +1103,15 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90.0f;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(expected90Config,
+ EXPECT_EQ(mExpected90Config,
refreshRateConfigs->getRefreshRateForContentV2(layers, 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);
EXPECT_EQ(false, touchConsidered);
@@ -1172,14 +1159,9 @@
TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_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];
@@ -1213,11 +1195,36 @@
const auto& refreshRate =
refreshRateConfigs->getRefreshRateForContentV2(layers, false, &ignored);
- EXPECT_FLOAT_EQ(refreshRate.fps, test.second)
+ EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second)
<< "Expecting " << test.first << "fps => " << test.second << "Hz";
}
}
+TEST_F(RefreshRateConfigsTest, groupSwitching) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentGroups,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& layer = layers[0];
+ layer.vote = LayerVoteType::ExplicitDefault;
+ layer.desiredRefreshRate = 90.0f;
+ layer.name = "90Hz ExplicitDefault";
+
+ bool touchConsidered;
+ ASSERT_EQ(HWC_CONFIG_ID_60,
+ refreshRateConfigs->getRefreshRateForContentV2(layers, 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)
+ .getConfigId());
+}
+
} // namespace
} // namespace scheduler
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 18d6bd2..038e6e6 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -26,6 +26,7 @@
#include <thread>
#include "Scheduler/RefreshRateStats.h"
+#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockTimeStats.h"
using namespace std::chrono_literals;
@@ -39,14 +40,14 @@
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 =
@@ -55,9 +56,14 @@
/*currentPowerMode=*/HWC_POWER_MODE_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, hwc2_config_t(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));
@@ -123,7 +137,8 @@
}
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));
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/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 414085c..6995ee0 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 {
@@ -198,8 +199,12 @@
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<
@@ -549,9 +554,10 @@
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
std::shared_ptr<compositionengine::Display> compositionDisplay,
std::optional<DisplayConnectionType> connectionType,
- bool isPrimary)
+ std::optional<hwc2_display_t> hwcDisplayId, bool isPrimary)
: mFlinger(flinger),
- mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay) {
+ mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay),
+ mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
}
@@ -619,7 +625,8 @@
DisplayDeviceState state;
if (const auto type = mCreationArgs.connectionType) {
LOG_ALWAYS_FATAL_IF(!displayId);
- state.physical = {*displayId, *type};
+ LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
+ state.physical = {*displayId, *type, *mHwcDisplayId};
}
state.isSecure = mCreationArgs.isSecure;
@@ -640,11 +647,13 @@
TestableSurfaceFlinger& mFlinger;
sp<BBinder> mDisplayToken = new BBinder();
DisplayDeviceCreationArgs mCreationArgs;
+ const std::optional<hwc2_display_t> 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 4f65aee..1f04673 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -362,6 +362,21 @@
EXPECT_THAT(result, HasSubstr(expectedResult));
}
+TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) {
+ // this stat is not in the proto so verify by checking the string dump
+ constexpr size_t REFRESH_RATE_SWITCHES = 2;
+
+ EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
+ for (size_t i = 0; i < REFRESH_RATE_SWITCHES; i++) {
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
+ }
+
+ const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
+ const std::string expectedResult =
+ "refreshRateSwitches = " + std::to_string(REFRESH_RATE_SWITCHES);
+ EXPECT_THAT(result, HasSubstr(expectedResult));
+}
+
TEST_F(TimeStatsTest, canAverageFrameDuration) {
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL);
@@ -744,6 +759,7 @@
// These stats are not in the proto so verify by checking the string dump.
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);
mTimeStats
->recordFrameDuration(std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count(),
@@ -759,6 +775,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("averageFrameDuration = 0.000 ms"));
EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
}
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index 3543361..1899bed 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -71,6 +71,7 @@
MOCK_CONST_METHOD0(now, nsecs_t());
MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
MOCK_METHOD0(alarmCancel, void());
+ MOCK_CONST_METHOD1(dump, void(std::string&));
void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
mCallback = callback;
@@ -188,6 +189,7 @@
}
void alarmCancel() final { mControllableClock.alarmCancel(); }
nsecs_t now() const final { return mControllableClock.now(); }
+ void dump(std::string&) const final {}
private:
TimeKeeper& mControllableClock;
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..3968035 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
@@ -29,6 +29,9 @@
class Display : public HWC2::Display {
public:
+ using Error = ::Error;
+ using Layer = ::Layer;
+
Display();
~Display();
@@ -80,6 +83,16 @@
MOCK_METHOD4(presentOrValidate,
Error(uint32_t*, uint32_t*, android::sp<android::Fence>*, uint32_t*));
MOCK_CONST_METHOD1(setDisplayBrightness, Error(float));
+ MOCK_CONST_METHOD1(getDisplayVsyncPeriod, Error(nsecs_t*));
+ MOCK_METHOD3(setActiveConfigWithConstraints,
+ Error(const std::shared_ptr<const HWC2::Display::Config>&,
+ const HWC2::VsyncPeriodChangeConstraints&,
+ HWC2::VsyncPeriodChangeTimeline*));
+ MOCK_CONST_METHOD1(setAutoLowLatencyMode, Error(bool on));
+ MOCK_CONST_METHOD1(getSupportedContentTypes, Error(std::vector<HWC2::ContentType>*));
+ MOCK_CONST_METHOD1(setContentType, Error(HWC2::ContentType));
+ MOCK_CONST_METHOD1(getConnectionType, Error(android::DisplayConnectionType*));
+ MOCK_CONST_METHOD0(isVsyncPeriodSwitchSupported, bool());
};
} // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index c45d584..9ea4dd0 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -36,6 +36,7 @@
MOCK_METHOD0(incrementMissedFrames, void());
MOCK_METHOD0(incrementClientCompositionFrames, void());
MOCK_METHOD0(incrementClientCompositionReusedFrames, void());
+ MOCK_METHOD0(incrementRefreshRateSwitches, void());
MOCK_METHOD1(recordDisplayEventConnectionCount, void(int32_t));
MOCK_METHOD2(recordFrameDuration, void(nsecs_t, nsecs_t));
MOCK_METHOD2(recordRenderEngineDuration, void(nsecs_t, nsecs_t));