Merge "Add a test case to ensure hover enter/exit synth is WAI when mirrored" into main
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index aa67869..9f091ef 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -29,7 +29,6 @@
#include <binder/Parcel.h>
#include <binder/RecordedTransaction.h>
#include <binder/RpcServer.h>
-#include <private/android_filesystem_config.h>
#include <pthread.h>
#include <utils/misc.h>
@@ -45,6 +44,8 @@
namespace android {
+constexpr uid_t kUidRoot = 0;
+
// Service implementations inherit from BBinder and IBinder, and this is frozen
// in prebuilts.
#ifdef __LP64__
@@ -300,7 +301,7 @@
return INVALID_OPERATION;
}
uid_t uid = IPCThreadState::self()->getCallingUid();
- if (uid != AID_ROOT) {
+ if (uid != kUidRoot) {
ALOGE("Binder recording not allowed because client %" PRIu32 " is not root", uid);
return PERMISSION_DENIED;
}
@@ -330,7 +331,7 @@
return INVALID_OPERATION;
}
uid_t uid = IPCThreadState::self()->getCallingUid();
- if (uid != AID_ROOT) {
+ if (uid != kUidRoot) {
ALOGE("Binder recording not allowed because client %" PRIu32 " is not root", uid);
return PERMISSION_DENIED;
}
@@ -634,7 +635,7 @@
return INVALID_OPERATION;
}
uid_t uid = IPCThreadState::self()->getCallingUid();
- if (uid != AID_ROOT) {
+ if (uid != kUidRoot) {
ALOGE("%s: not allowed because client %" PRIu32 " is not root", __PRETTY_FUNCTION__, uid);
return PERMISSION_DENIED;
}
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index f7dd9c9..47da296 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -21,7 +21,9 @@
#include <android/binder_status.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
+#if __has_include(<private/android_filesystem_config.h>)
#include <private/android_filesystem_config.h>
+#endif
#include "ibinder_internal.h"
#include "parcel_internal.h"
@@ -229,7 +231,11 @@
// Shell commands should only be callable by ADB.
uid_t uid = AIBinder_getCallingUid();
- if (uid != AID_ROOT && uid != AID_SHELL) {
+ if (uid != 0 /* root */
+#ifdef AID_SHELL
+ && uid != AID_SHELL
+#endif
+ ) {
if (resultReceiver != nullptr) {
resultReceiver->send(-1);
}
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index 76acff5..3ee36cd 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -156,7 +156,10 @@
}
sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
+#pragma clang diagnostic pop
if (binder == nullptr) {
return nullptr;
}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 15708ca..cab1a60 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -341,7 +341,10 @@
// libbinder across processes to the NDK service which doesn't implement
// shell
static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> testService = sm->getService(String16(IFoo::kSomeInstanceName));
+#pragma clang diagnostic pop
Vector<String16> argsVec;
EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
@@ -384,7 +387,10 @@
// checkService on it, since the other process serving it might not be started yet.
{
// getService, not waitForService, to take advantage of timeout
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
auto binder = ndk::SpAIBinder(AServiceManager_getService(IFoo::kSomeInstanceName));
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, binder.get());
}
@@ -574,7 +580,10 @@
}
TEST(NdkBinder, RetrieveNonNdkService) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, binder);
EXPECT_TRUE(AIBinder_isRemote(binder));
EXPECT_TRUE(AIBinder_isAlive(binder));
@@ -588,7 +597,10 @@
}
TEST(NdkBinder, LinkToDeath) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, binder);
AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
@@ -618,7 +630,10 @@
}
TEST(NdkBinder, SetInheritRtNonLocal) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+#pragma clang diagnostic pop
ASSERT_NE(binder, nullptr);
ASSERT_TRUE(AIBinder_isRemote(binder));
@@ -654,11 +669,14 @@
}
TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
ASSERT_NE(nullptr, binderA);
AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
ASSERT_NE(nullptr, binderB);
+#pragma clang diagnostic pop
EXPECT_EQ(binderA, binderB);
@@ -672,7 +690,10 @@
}
TEST(NdkBinder, ABpBinderRefCount) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+#pragma clang diagnostic pop
AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
ASSERT_NE(nullptr, binder);
@@ -695,7 +716,10 @@
}
TEST(NdkBinder, RequestedSidWorks) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
+#pragma clang diagnostic pop
std::shared_ptr<aidl::IBinderNdkUnitTest> service =
aidl::IBinderNdkUnitTest::fromBinder(binder);
@@ -718,7 +742,10 @@
std::shared_ptr<MyEmpty> empty = ndk::SharedRefBase::make<MyEmpty>();
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
+#pragma clang diagnostic pop
std::shared_ptr<aidl::IBinderNdkUnitTest> service =
aidl::IBinderNdkUnitTest::fromBinder(binder);
@@ -741,7 +768,10 @@
TEST(NdkBinder, ConvertToPlatformBinder) {
for (const ndk::SpAIBinder& binder :
{// remote
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+#pragma clang diagnostic pop
// local
ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
// convert to platform binder
@@ -774,7 +804,10 @@
TEST(NdkBinder, GetAndVerifyScopedAIBinder_Weak) {
for (const ndk::SpAIBinder& binder :
{// remote
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+#pragma clang diagnostic pop
// local
ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
// get a const ScopedAIBinder_Weak and verify promote
@@ -869,7 +902,10 @@
TEST(NdkBinder, UseHandleShellCommand) {
static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestService));
+#pragma clang diagnostic pop
EXPECT_EQ("", shellCmdToString(testService, {}));
EXPECT_EQ("", shellCmdToString(testService, {"", ""}));
@@ -879,7 +915,10 @@
TEST(NdkBinder, FlaggedServiceAccessible) {
static const sp<android::IServiceManager> sm(android::defaultServiceManager());
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestServiceFlagged));
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, testService);
}
diff --git a/libs/binder/rust/tests/serialization.hpp b/libs/binder/rust/tests/serialization.hpp
index 0041608..9edcd6d 100644
--- a/libs/binder/rust/tests/serialization.hpp
+++ b/libs/binder/rust/tests/serialization.hpp
@@ -14,7 +14,10 @@
* limitations under the License.
*/
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpragma-once-outside-header"
#pragma once
+#pragma clang diagnostic pop
#include <binder/IBinder.h>
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 8e95d69..5bf9680 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -279,7 +279,10 @@
while (-1 != (opt = getopt(argc, argv, "gi:"))) {
switch (opt) {
case 'g': {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
serviceRetriever = &android::IServiceManager::getService;
+#pragma clang diagnostic pop
} break;
case 'i': {
ip_address = optarg;
diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp
index 307151c..3ea5b55 100644
--- a/libs/binder/tests/binderClearBufTest.cpp
+++ b/libs/binder/tests/binderClearBufTest.cpp
@@ -74,7 +74,10 @@
};
TEST(BinderClearBuf, ClearKernelBuffer) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> binder = defaultServiceManager()->getService(kServerName);
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, binder);
std::string replyBuffer;
diff --git a/libs/binder/tests/binderHostDeviceTest.cpp b/libs/binder/tests/binderHostDeviceTest.cpp
index 77a5fa8..0075688 100644
--- a/libs/binder/tests/binderHostDeviceTest.cpp
+++ b/libs/binder/tests/binderHostDeviceTest.cpp
@@ -135,7 +135,10 @@
TEST_F(HostDeviceTest, GetService) {
auto sm = defaultServiceManager();
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
auto rpcBinder = sm->getService(String16(kServiceName));
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, rpcBinder);
EXPECT_THAT(rpcBinder->pingBinder(), StatusEq(OK));
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 0396869..341e9ce 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -213,7 +213,10 @@
sp<IServiceManager> sm = defaultServiceManager();
//printf("%s: pid %d, get service\n", __func__, m_pid);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
m_server = sm->getService(binderLibTestServiceName);
+#pragma clang diagnostic pop
ASSERT_TRUE(m_server != nullptr);
//printf("%s: pid %d, get service done\n", __func__, m_pid);
}
@@ -1107,6 +1110,7 @@
status_t ret;
data.writeInterfaceToken(binderLibTestServiceName);
ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
Parcel data2, reply2;
status_t ret2;
@@ -1595,9 +1599,8 @@
}
switch (code) {
case BINDER_LIB_TEST_REGISTER_SERVER: {
- int32_t id;
sp<IBinder> binder;
- id = data.readInt32();
+ /*id =*/data.readInt32();
binder = data.readStrongBinder();
if (binder == nullptr) {
return BAD_VALUE;
@@ -1993,7 +1996,10 @@
if (index == 0) {
ret = sm->addService(binderLibTestServiceName, testService);
} else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> server = sm->getService(binderLibTestServiceName);
+#pragma clang diagnostic pop
Parcel data, reply;
data.writeInt32(index);
data.writeStrongBinder(testService);
diff --git a/libs/binder/tests/binderRecordReplayTest.cpp b/libs/binder/tests/binderRecordReplayTest.cpp
index 6773c95..d08a9bb 100644
--- a/libs/binder/tests/binderRecordReplayTest.cpp
+++ b/libs/binder/tests/binderRecordReplayTest.cpp
@@ -133,7 +133,10 @@
public:
void SetUp() override {
// get the remote service
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
auto binder = defaultServiceManager()->getService(kServerName);
+#pragma clang diagnostic pop
ASSERT_NE(nullptr, binder);
mInterface = interface_cast<IBinderRecordReplayTest>(binder);
mBpBinder = binder->remoteBinder();
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 5e8a32a..1c13866 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -605,7 +605,10 @@
static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }
sp<ISafeInterfaceTest> getRemoteService() {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> binder = defaultServiceManager()->getService(kServiceName);
+#pragma clang diagnostic pop
sp<ISafeInterfaceTest> iface = interface_cast<ISafeInterfaceTest>(binder);
EXPECT_TRUE(iface != nullptr);
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 2398e1e..3d99358 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -155,7 +155,10 @@
}
TEST(BinderStability, ForceDowngradeToVendorStability) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
+#pragma clang diagnostic pop
auto server = interface_cast<IBinderStabilityTest>(serverBinder);
ASSERT_NE(nullptr, server.get());
@@ -206,7 +209,10 @@
EXPECT_EQ(connectionInfo, std::nullopt);
}
TEST(BinderStability, CantCallVendorBinderInSystemContext) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
+#pragma clang diagnostic pop
auto server = interface_cast<IBinderStabilityTest>(serverBinder);
ASSERT_NE(nullptr, server.get());
@@ -310,8 +316,11 @@
extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
SpAIBinder binder = SpAIBinder(AServiceManager_getService(
String8(kSystemStabilityServer).c_str()));
+#pragma clang diagnostic pop
std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
aidl::IBinderStabilityTest::fromBinder(binder);
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index cfaf2a9..0ea4a3f 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -204,7 +204,10 @@
for (int i = 0; i < server_count; i++) {
if (num == i)
continue;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
workers.push_back(serviceMgr->getService(generateServiceName(i)));
+#pragma clang diagnostic pop
}
// Run the benchmark if client
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 0035e4e..d3cd528 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -340,7 +340,10 @@
for (int i = 0; i < server_count; i++) {
// self service is in-process so just skip
if (num == i) continue;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
workers.push_back(serviceMgr->getService(generateServiceName(i)));
+#pragma clang diagnostic pop
}
// Client for each pair iterates here
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 613721e..fd8fc8d 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -85,6 +85,7 @@
changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS),
defaultFrameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
frameRateCategory(ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT),
+ frameRateCategorySmoothSwitchOnly(false),
frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF),
fixedTransformHint(ui::Transform::ROT_INVALID),
autoRefresh(false),
@@ -162,6 +163,7 @@
SAFE_PARCEL(output.writeByte, changeFrameRateStrategy);
SAFE_PARCEL(output.writeByte, defaultFrameRateCompatibility);
SAFE_PARCEL(output.writeByte, frameRateCategory);
+ SAFE_PARCEL(output.writeBool, frameRateCategorySmoothSwitchOnly);
SAFE_PARCEL(output.writeByte, frameRateSelectionStrategy);
SAFE_PARCEL(output.writeUint32, fixedTransformHint);
SAFE_PARCEL(output.writeBool, autoRefresh);
@@ -296,6 +298,7 @@
SAFE_PARCEL(input.readByte, &changeFrameRateStrategy);
SAFE_PARCEL(input.readByte, &defaultFrameRateCompatibility);
SAFE_PARCEL(input.readByte, &frameRateCategory);
+ SAFE_PARCEL(input.readBool, &frameRateCategorySmoothSwitchOnly);
SAFE_PARCEL(input.readByte, &frameRateSelectionStrategy);
SAFE_PARCEL(input.readUint32, &tmpUint32);
fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
@@ -669,6 +672,7 @@
if (other.what & eFrameRateCategoryChanged) {
what |= eFrameRateCategoryChanged;
frameRateCategory = other.frameRateCategory;
+ frameRateCategorySmoothSwitchOnly = other.frameRateCategorySmoothSwitchOnly;
}
if (other.what & eFrameRateSelectionStrategyChanged) {
what |= eFrameRateSelectionStrategyChanged;
@@ -784,7 +788,8 @@
CHECK_DIFF(diff, eFrameRateSelectionPriority, other, frameRateSelectionPriority);
CHECK_DIFF3(diff, eFrameRateChanged, other, frameRate, frameRateCompatibility,
changeFrameRateStrategy);
- CHECK_DIFF(diff, eFrameRateCategoryChanged, other, frameRateCategory);
+ CHECK_DIFF2(diff, eFrameRateCategoryChanged, other, frameRateCategory,
+ frameRateCategorySmoothSwitchOnly);
CHECK_DIFF(diff, eFrameRateSelectionStrategyChanged, other, frameRateSelectionStrategy);
CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint);
CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8a57f92..300ac2e 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2098,7 +2098,7 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameRateCategory(
- const sp<SurfaceControl>& sc, int8_t category) {
+ const sp<SurfaceControl>& sc, int8_t category, bool smoothSwitchOnly) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
@@ -2106,6 +2106,7 @@
}
s->what |= layer_state_t::eFrameRateCategoryChanged;
s->frameRateCategory = category;
+ s->frameRateCategorySmoothSwitchOnly = smoothSwitchOnly;
return *this;
}
@@ -2604,6 +2605,7 @@
outMode.xDpi = mode.xDpi;
outMode.yDpi = mode.yDpi;
outMode.refreshRate = mode.refreshRate;
+ outMode.vsyncRate = mode.vsyncRate;
outMode.appVsyncOffset = mode.appVsyncOffset;
outMode.sfVsyncOffset = mode.sfVsyncOffset;
outMode.presentationDeadline = mode.presentationDeadline;
diff --git a/libs/gui/aidl/android/gui/DisplayMode.aidl b/libs/gui/aidl/android/gui/DisplayMode.aidl
index ce30426..b057653 100644
--- a/libs/gui/aidl/android/gui/DisplayMode.aidl
+++ b/libs/gui/aidl/android/gui/DisplayMode.aidl
@@ -29,7 +29,9 @@
float yDpi = 0.0f;
int[] supportedHdrTypes;
+ // Some modes have peak refresh rate lower than the panel vsync rate.
float refreshRate = 0.0f;
+ float vsyncRate = 0.0f;
long appVsyncOffset = 0;
long sfVsyncOffset = 0;
long presentationDeadline = 0;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 4371007..d3cde74 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -361,6 +361,7 @@
// Frame rate category to suggest what frame rate range a surface should run.
int8_t frameRateCategory;
+ bool frameRateCategorySmoothSwitchOnly;
// Strategy of the layer for frame rate selection.
int8_t frameRateSelectionStrategy;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 26b1fbd..bc63c41 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -686,7 +686,8 @@
Transaction& setDefaultFrameRateCompatibility(const sp<SurfaceControl>& sc,
int8_t compatibility);
- Transaction& setFrameRateCategory(const sp<SurfaceControl>& sc, int8_t category);
+ Transaction& setFrameRateCategory(const sp<SurfaceControl>& sc, int8_t category,
+ bool smoothSwitchOnly);
Transaction& setFrameRateSelectionStrategy(const sp<SurfaceControl>& sc, int8_t strategy);
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index ab4af1a..69a4f0a 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -46,6 +46,14 @@
name: "aconfig_input_flags_c_lib",
aconfig_declarations: "aconfig_input_flags",
host_supported: true,
+ // Use the test version of the aconfig flag library by default to allow tests to set local
+ // overrides for flags, without having to link against a separate version of libinput or of this
+ // library. Bundling this library directly into libinput prevents us from having to add this
+ // library as a shared lib dependency everywhere where libinput is used.
+ test: true,
+ shared: {
+ enabled: false,
+ },
}
aidl_interface {
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 9d61d62..25296f0 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -49,6 +49,15 @@
// a color correction effect is added to the shader.
constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
constexpr auto kOtherDataSpace = ui::Dataspace::DISPLAY_P3;
+constexpr auto kBT2020DataSpace = ui::Dataspace::BT2020_ITU_PQ;
+constexpr auto kExtendedHdrDataSpce =
+ static_cast<ui::Dataspace>(ui::Dataspace::RANGE_EXTENDED | ui::Dataspace::TRANSFER_SRGB |
+ ui::Dataspace::STANDARD_DCI_P3);
+// Dimming is needed to trigger linear effects for some dataspace pairs
+const std::array<float, 3> kLayerWhitePoints = {
+ 1000.0f, 500.0f,
+ 100.0f, // trigger dithering by dimming below 20%
+};
} // namespace
static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
@@ -317,6 +326,298 @@
renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
}
+static void drawImageDimmedLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ // The position transform doesn't matter when the reduced shader mode
+ // in in effect. A matrix transform stage is always included.
+ .positionTransform = mat4(),
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ .roundedCornersRadius = {0.f, 0.f},
+ },
+ .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = true}},
+ .alpha = 1.f,
+ .sourceDataspace = kDestDataSpace,
+ };
+
+ std::vector<LayerSettings> layers;
+
+ for (auto layerWhitePoint : kLayerWhitePoints) {
+ layer.whitePointNits = layerWhitePoint;
+ layers.push_back(layer);
+ }
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+}
+
+static void drawTransparentImageDimmedLayers(SkiaRenderEngine* renderengine,
+ const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .positionTransform = mat4(),
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ },
+ .source = PixelSource{.buffer =
+ Buffer{
+ .buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = false,
+ }},
+ .sourceDataspace = kDestDataSpace,
+ };
+
+ for (auto roundedCornerRadius : {0.f, 50.f}) {
+ layer.geometry.roundedCornersRadius = {roundedCornerRadius, roundedCornerRadius};
+ for (auto alpha : {0.5f, 1.0f}) {
+ layer.alpha = alpha;
+ for (auto isOpaque : {true, false}) {
+ if (roundedCornerRadius == 0.f && isOpaque) {
+ // already covered in drawImageDimmedLayers
+ continue;
+ }
+
+ layer.source.buffer.isOpaque = isOpaque;
+ std::vector<LayerSettings> layers;
+
+ for (auto layerWhitePoint : kLayerWhitePoints) {
+ layer.whitePointNits = layerWhitePoint;
+ layers.push_back(layer);
+ }
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+ }
+ }
+ }
+}
+
+static void drawClippedDimmedImageLayers(SkiaRenderEngine* renderengine,
+ const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+
+ // If rect and boundary is too small compared to roundedCornersRadius, Skia will switch to
+ // blending instead of EllipticalRRect, so enlarge them a bit.
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ FloatRect boundary(0, 0, displayRect.width(),
+ displayRect.height() - 20); // boundary is smaller
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .positionTransform = mat4(),
+ .boundaries = boundary,
+ .roundedCornersCrop = rect,
+ .roundedCornersRadius = {27.f, 27.f},
+ },
+ .source = PixelSource{.buffer =
+ Buffer{
+ .buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = false,
+ }},
+ .alpha = 1.f,
+ .sourceDataspace = kDestDataSpace,
+ };
+
+ std::array<mat4, 2> transforms = {kScaleAndTranslate, kScaleAsymmetric};
+
+ constexpr float radius = 27.f;
+
+ for (size_t i = 0; i < transforms.size(); i++) {
+ layer.geometry.positionTransform = transforms[i];
+ layer.geometry.roundedCornersRadius = {radius, radius};
+
+ std::vector<LayerSettings> layers;
+
+ for (auto layerWhitePoint : kLayerWhitePoints) {
+ layer.whitePointNits = layerWhitePoint;
+ layers.push_back(layer);
+ }
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+ }
+}
+
+static void drawSolidDimmedLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ },
+ .source =
+ PixelSource{
+ .solidColor = half3(0.1f, 0.2f, 0.3f),
+ },
+ .alpha = 1.f,
+ };
+
+ std::vector<LayerSettings> layers;
+
+ for (auto layerWhitePoint : kLayerWhitePoints) {
+ layer.whitePointNits = layerWhitePoint;
+ layers.push_back(layer);
+ }
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+}
+
+static void drawBT2020ImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ // The position transform doesn't matter when the reduced shader mode
+ // in in effect. A matrix transform stage is always included.
+ .positionTransform = mat4(),
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ .roundedCornersRadius = {0.f, 0.f},
+ },
+ .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = true}},
+ .alpha = 1.f,
+ .sourceDataspace = kBT2020DataSpace,
+ };
+
+ for (auto alpha : {0.5f, 1.f}) {
+ layer.alpha = alpha;
+ std::vector<LayerSettings> layers;
+ layer.whitePointNits = -1.f;
+ layers.push_back(layer);
+
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+ }
+}
+static void drawBT2020ClippedImageLayers(SkiaRenderEngine* renderengine,
+ const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+
+ // If rect and boundary is too small compared to roundedCornersRadius, Skia will switch to
+ // blending instead of EllipticalRRect, so enlarge them a bit.
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ FloatRect boundary(0, 0, displayRect.width(),
+ displayRect.height() - 10); // boundary is smaller
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .positionTransform = kScaleAsymmetric,
+ .boundaries = boundary,
+ .roundedCornersCrop = rect,
+ .roundedCornersRadius = {64.1f, 64.1f},
+ },
+ .source = PixelSource{.buffer =
+ Buffer{
+ .buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = true,
+ }},
+ .alpha = 0.5f,
+ .sourceDataspace = kBT2020DataSpace,
+ };
+
+ std::vector<LayerSettings> layers = {layer};
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+}
+
+static void drawExtendedHDRImageLayers(SkiaRenderEngine* renderengine,
+ const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ // The position transform doesn't matter when the reduced shader mode
+ // in in effect. A matrix transform stage is always included.
+ .positionTransform = mat4(),
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ .roundedCornersRadius = {50.f, 50.f},
+ },
+ .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = true}},
+ .alpha = 0.5f,
+ .sourceDataspace = kExtendedHdrDataSpce,
+ };
+
+ for (auto roundedCornerRadius : {0.f, 50.f}) {
+ layer.geometry.roundedCornersRadius = {roundedCornerRadius, roundedCornerRadius};
+ for (auto alpha : {0.5f, 1.f}) {
+ layer.alpha = alpha;
+ std::vector<LayerSettings> layers;
+
+ for (auto layerWhitePoint : kLayerWhitePoints) {
+ layer.whitePointNits = layerWhitePoint;
+ layers.push_back(layer);
+ }
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+ }
+ }
+}
+
+static void drawP3ImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ // The position transform doesn't matter when the reduced shader mode
+ // in in effect. A matrix transform stage is always included.
+ .positionTransform = mat4(),
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ .roundedCornersRadius = {50.f, 50.f},
+ },
+ .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
+ .maxLuminanceNits = 1000.f,
+ .usePremultipliedAlpha = true,
+ .isOpaque = false}},
+ .alpha = 0.5f,
+ .sourceDataspace = kOtherDataSpace,
+ };
+
+ for (auto alpha : {0.5f, 1.f}) {
+ layer.alpha = alpha;
+ std::vector<LayerSettings> layers;
+
+ for (auto layerWhitePoint : kLayerWhitePoints) {
+ layer.whitePointNits = layerWhitePoint;
+ layers.push_back(layer);
+ }
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+ }
+}
+
//
// The collection of shaders cached here were found by using perfetto to record shader compiles
// during actions that involve RenderEngine, logging the layer settings, and the shader code
@@ -353,6 +654,23 @@
.maxLuminance = 500,
.outputDataspace = kOtherDataSpace,
};
+ DisplaySettings p3DisplayEnhance{.physicalDisplay = displayRect,
+ .clip = displayRect,
+ .maxLuminance = 500,
+ .outputDataspace = kOtherDataSpace,
+ .dimmingStage = aidl::android::hardware::graphics::
+ composer3::DimmingStage::GAMMA_OETF,
+ .renderIntent = aidl::android::hardware::graphics::
+ composer3::RenderIntent::ENHANCE};
+ DisplaySettings bt2020Display{.physicalDisplay = displayRect,
+ .clip = displayRect,
+ .maxLuminance = 500,
+ .outputDataspace = ui::Dataspace::BT2020,
+ .deviceHandlesColorTransform = true,
+ .dimmingStage = aidl::android::hardware::graphics::composer3::
+ DimmingStage::GAMMA_OETF,
+ .renderIntent = aidl::android::hardware::graphics::composer3::
+ RenderIntent::TONE_MAP_ENHANCE};
const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
@@ -377,6 +695,8 @@
impl::ExternalTexture::Usage::WRITEABLE);
drawHolePunchLayer(renderengine, display, dstTexture);
drawSolidLayers(renderengine, display, dstTexture);
+ drawSolidLayers(renderengine, p3Display, dstTexture);
+ drawSolidDimmedLayers(renderengine, display, dstTexture);
drawShadowLayers(renderengine, display, srcTexture);
drawShadowLayers(renderengine, p3Display, srcTexture);
@@ -417,12 +737,35 @@
for (auto texture : textures) {
drawImageLayers(renderengine, display, dstTexture, texture);
+
+ drawImageDimmedLayers(renderengine, display, dstTexture, texture);
+ drawImageDimmedLayers(renderengine, p3Display, dstTexture, texture);
+ drawImageDimmedLayers(renderengine, bt2020Display, dstTexture, texture);
+
// Draw layers for b/185569240.
drawClippedLayers(renderengine, display, dstTexture, texture);
}
drawPIPImageLayer(renderengine, display, dstTexture, externalTexture);
+ drawTransparentImageDimmedLayers(renderengine, bt2020Display, dstTexture, externalTexture);
+ drawTransparentImageDimmedLayers(renderengine, display, dstTexture, externalTexture);
+ drawTransparentImageDimmedLayers(renderengine, p3Display, dstTexture, externalTexture);
+ drawTransparentImageDimmedLayers(renderengine, p3DisplayEnhance, dstTexture,
+ externalTexture);
+
+ drawClippedDimmedImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
+ drawBT2020ClippedImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
+
+ drawBT2020ImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
+ drawBT2020ImageLayers(renderengine, p3Display, dstTexture, externalTexture);
+
+ drawExtendedHDRImageLayers(renderengine, display, dstTexture, externalTexture);
+ drawExtendedHDRImageLayers(renderengine, p3Display, dstTexture, externalTexture);
+ drawExtendedHDRImageLayers(renderengine, p3DisplayEnhance, dstTexture, externalTexture);
+
+ drawP3ImageLayers(renderengine, p3DisplayEnhance, dstTexture, externalTexture);
+
// draw one final layer synchronously to force GL submit
LayerSettings layer{
.source = PixelSource{.solidColor = half3(0.f, 0.f, 0.f)},
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 17f263d..8821c0e 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -25,6 +25,7 @@
#include <GrContextOptions.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
+#include <include/gpu/ganesh/vk/GrVkDirectContext.h>
#include <android-base/stringprintf.h>
#include <gui/TraceUtils.h>
@@ -603,11 +604,11 @@
sSetupVulkanInterface();
SkiaRenderEngine::Contexts contexts;
- contexts.first = GrDirectContext::MakeVulkan(sVulkanInterface.getBackendContext(), options);
+ contexts.first = GrDirectContexts::MakeVulkan(sVulkanInterface.getBackendContext(), options);
if (supportsProtectedContentImpl()) {
contexts.second =
- GrDirectContext::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
- options);
+ GrDirectContexts::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
+ options);
}
return contexts;
diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h
index 65a8769..a469c78 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -37,7 +37,9 @@
float yDpi = 0;
std::vector<ui::Hdr> supportedHdrTypes;
- float refreshRate = 0;
+ // Some modes have peak refresh rate lower than the panel vsync rate.
+ float refreshRate = 0.f;
+ float vsyncRate = 0.f;
nsecs_t appVsyncOffset = 0;
nsecs_t sfVsyncOffset = 0;
nsecs_t presentationDeadline = 0;
diff --git a/libs/vibrator/OWNERS b/libs/vibrator/OWNERS
index d073e2b..c4de58a 100644
--- a/libs/vibrator/OWNERS
+++ b/libs/vibrator/OWNERS
@@ -1 +1,2 @@
+# Bug component: 345036
include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index ee1f3cb..6f092a6 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -39,6 +39,9 @@
"options": [
{
"include-filter": "android.hardware.input.cts.tests"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
},
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 03c0993..4db2b66 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -731,6 +731,10 @@
: parentSnapshot.outputFilter.layerStack;
}
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
+ snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
+ }
+
if (snapshot.isHiddenByPolicyFromParent &&
!snapshot.changes.test(RequestedLayerState::Changes::Created)) {
if (forceUpdate ||
@@ -761,10 +765,6 @@
(requested.flags & layer_state_t::eLayerSkipScreenshot);
}
- if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
- snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
- }
-
if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
? requested.stretchEffect
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 168267b..087d7c8 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -124,6 +124,7 @@
dimmingEnabled = true;
defaultFrameRateCompatibility = static_cast<int8_t>(scheduler::FrameRateCompatibility::Default);
frameRateCategory = static_cast<int8_t>(FrameRateCategory::Default);
+ frameRateCategorySmoothSwitchOnly = false;
frameRateSelectionStrategy =
static_cast<int8_t>(scheduler::LayerInfo::FrameRateSelectionStrategy::Self);
dataspace = ui::Dataspace::V0_SRGB;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2dc8758..0c1c014 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1334,13 +1334,15 @@
return true;
}
-bool Layer::setFrameRateCategory(FrameRateCategory category) {
- if (mDrawingState.frameRate.category == category) {
+bool Layer::setFrameRateCategory(FrameRateCategory category, bool smoothSwitchOnly) {
+ if (mDrawingState.frameRate.category == category &&
+ mDrawingState.frameRate.categorySmoothSwitchOnly == smoothSwitchOnly) {
return false;
}
mDrawingState.sequence++;
mDrawingState.frameRate.category = category;
+ mDrawingState.frameRate.categorySmoothSwitchOnly = smoothSwitchOnly;
mDrawingState.modified = true;
updateTreeHasFrameRateVote();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0b66866..1b99255 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -783,7 +783,7 @@
Rect getCroppedBufferSize(const Layer::State& s) const;
bool setFrameRate(FrameRate::FrameRateVote);
- bool setFrameRateCategory(FrameRateCategory);
+ bool setFrameRateCategory(FrameRateCategory, bool smoothSwitchOnly);
bool setFrameRateSelectionStrategy(FrameRateSelectionStrategy);
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index 48a9190..f25619a 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -247,10 +247,13 @@
layerSettings.frameNumber = mSnapshot->frameNumber;
layerSettings.bufferId = mSnapshot->externalTexture->getId();
+ const bool useFiltering = targetSettings.needsFiltering ||
+ mSnapshot->geomLayerTransform.needsBilinearFiltering();
+
// Query the texture matrix given our current filtering mode.
float textureMatrix[16];
getDrawingTransformMatrix(layerSettings.source.buffer.buffer, mSnapshot->geomContentCrop,
- mSnapshot->geomBufferTransform, targetSettings.needsFiltering,
+ mSnapshot->geomBufferTransform, useFiltering,
textureMatrix);
if (mSnapshot->geomBufferUsesDisplayInverseTransform) {
@@ -301,7 +304,7 @@
mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));
- layerSettings.source.buffer.useTextureFiltering = targetSettings.needsFiltering;
+ layerSettings.source.buffer.useTextureFiltering = useFiltering;
layerSettings.source.buffer.textureTransform =
mat4(static_cast<const float*>(textureMatrix)) * tr;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 4e5659e..069d89b 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -194,7 +194,8 @@
to_string(vote.fps).c_str(), categoryString.c_str(),
weight * 100);
summary.push_back({info->getName(), info->getOwnerUid(), vote.type, vote.fps,
- vote.seamlessness, vote.category, weight, layerFocused});
+ vote.seamlessness, vote.category, vote.categorySmoothSwitchOnly,
+ weight, layerFocused});
if (CC_UNLIKELY(mTraceEnabled)) {
trace(*info, vote.type, vote.fps.getIntValue());
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index dd96930..36f2475 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -309,7 +309,8 @@
ALOGV("%s uses frame rate category: %d", mName.c_str(),
static_cast<int>(mLayerVote.category));
votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(),
- Seamlessness::Default, mLayerVote.category});
+ Seamlessness::Default, mLayerVote.category,
+ mLayerVote.categorySmoothSwitchOnly});
}
if (mLayerVote.fps.isValid() ||
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index d580b58..7d3cffa 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -71,8 +71,8 @@
LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic;
Fps fps;
Seamlessness seamlessness = Seamlessness::Default;
- // Category is in effect if fps is not specified.
FrameRateCategory category = FrameRateCategory::Default;
+ bool categorySmoothSwitchOnly = false;
// Returns true if the layer explicitly should contribute to frame rate scoring.
bool isNoVote() const { return RefreshRateSelector::isNoVote(type); }
@@ -111,6 +111,7 @@
} vote;
FrameRateCategory category = FrameRateCategory::Default;
+ bool categorySmoothSwitchOnly = false;
FrameRate() = default;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index b06723d..1d23fb5 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -494,6 +494,7 @@
int explicitExact = 0;
int explicitCategoryVoteLayers = 0;
int seamedFocusedLayers = 0;
+ int categorySmoothSwitchOnlyLayers = 0;
for (const auto& layer : layers) {
switch (layer.vote) {
@@ -531,6 +532,9 @@
if (layer.seamlessness == Seamlessness::SeamedAndSeamless && layer.focused) {
seamedFocusedLayers++;
}
+ if (layer.frameRateCategorySmoothSwitchOnly) {
+ categorySmoothSwitchOnlyLayers++;
+ }
}
const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 ||
@@ -578,10 +582,17 @@
return {ranking, kNoSignals};
}
+ const bool smoothSwitchOnly = categorySmoothSwitchOnlyLayers > 0;
+ const DisplayModeId activeModeId = activeMode.getId();
+
// Only if all layers want Min we should return Min
if (noVoteLayers + minVoteLayers == layers.size()) {
ALOGV("All layers Min");
- const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending);
+ const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending,
+ std::nullopt, [&](FrameRateMode mode) {
+ return !smoothSwitchOnly ||
+ mode.modePtr->getId() == activeModeId;
+ });
ATRACE_FORMAT_INSTANT("%s (All layers Min)",
to_string(ranking.front().frameRateMode.fps).c_str());
return {ranking, kNoSignals};
@@ -627,6 +638,14 @@
continue;
}
+ if (smoothSwitchOnly && modePtr->getId() != activeModeId) {
+ ALOGV("%s ignores %s because it's non-VRR and smooth switch only."
+ " Current mode = %s",
+ formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(),
+ to_string(activeMode).c_str());
+ continue;
+ }
+
// Layers with default seamlessness vote for the current mode group if
// there are layers with seamlessness=SeamedAndSeamless and for the default
// mode group otherwise. In second case, if the current mode group is different
@@ -770,6 +789,7 @@
to_string(descending.front().frameRateMode.fps).c_str());
return {descending, kNoSignals};
} else {
+ ALOGV("primaryRangeIsSingleRate");
ATRACE_FORMAT_INSTANT("%s (primaryRangeIsSingleRate)",
to_string(ranking.front().frameRateMode.fps).c_str());
return {ranking, kNoSignals};
@@ -805,6 +825,7 @@
// If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
// current config
if (noLayerScore && refreshRateOrder == RefreshRateOrder::Ascending) {
+ ALOGV("preferredDisplayMode");
const auto ascendingWithPreferred =
rankFrameRates(anchorGroup, RefreshRateOrder::Ascending, activeMode.getId());
ATRACE_FORMAT_INSTANT("%s (preferredDisplayMode)",
@@ -812,6 +833,7 @@
return {ascendingWithPreferred, kNoSignals};
}
+ ALOGV("%s (scored))", to_string(ranking.front().frameRateMode.fps).c_str());
ATRACE_FORMAT_INSTANT("%s (scored))", to_string(ranking.front().frameRateMode.fps).c_str());
return {ranking, kNoSignals};
}
@@ -1017,7 +1039,8 @@
auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt,
RefreshRateOrder refreshRateOrder,
- std::optional<DisplayModeId> preferredDisplayModeOpt) const
+ std::optional<DisplayModeId> preferredDisplayModeOpt,
+ const RankFrameRatesPredicate& predicate) const
-> FrameRateRanking {
using fps_approx_ops::operator<;
const char* const whence = __func__;
@@ -1044,7 +1067,8 @@
std::deque<ScoredFrameRate> ranking;
const auto rankFrameRate = [&](const FrameRateMode& frameRateMode) REQUIRES(mLock) {
const auto& modePtr = frameRateMode.modePtr;
- if (anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) {
+ if ((anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) ||
+ !predicate(frameRateMode)) {
return;
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index 5d32414..545b939 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -170,8 +170,11 @@
Fps desiredRefreshRate;
// If a seamless mode switch is required.
Seamlessness seamlessness = Seamlessness::Default;
- // Layer frame rate category. Superseded by desiredRefreshRate.
+ // Layer frame rate category.
FrameRateCategory frameRateCategory = FrameRateCategory::Default;
+ // Goes together with frame rate category vote. Allow refresh rate changes only
+ // if there would be no jank.
+ bool frameRateCategorySmoothSwitchOnly = false;
// Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer
// would have on choosing the refresh rate.
float weight = 0.0f;
@@ -446,10 +449,15 @@
ftl_last = Descending
};
- // Only uses the primary range, not the app request range.
+ typedef std::function<bool(const FrameRateMode)> RankFrameRatesPredicate;
+
+ // Rank the frame rates.
+ // Only modes in the primary range for which `predicate` is `true` will be scored.
+ // Does not use the app requested range.
FrameRateRanking rankFrameRates(
std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder,
- std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt) const
+ std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt,
+ const RankFrameRatesPredicate& predicate = [](FrameRateMode) { return true; }) const
REQUIRES(mLock);
const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Timer.h b/services/surfaceflinger/Scheduler/include/scheduler/Timer.h
index 58ad6cb..67f7abe 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/Timer.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Timer.h
@@ -60,6 +60,7 @@
void reset() EXCLUDES(mMutex);
void cleanup() REQUIRES(mMutex);
void setDebugState(DebugState) EXCLUDES(mMutex);
+ void setCallback(std::function<void()>&&) REQUIRES(mMutex);
int mTimerFd = -1;
@@ -71,6 +72,7 @@
void endDispatch();
mutable std::mutex mMutex;
+
std::function<void()> mCallback GUARDED_BY(mMutex);
bool mExpectingCallback GUARDED_BY(mMutex) = false;
DebugState mDebugState GUARDED_BY(mMutex);
diff --git a/services/surfaceflinger/Scheduler/src/Timer.cpp b/services/surfaceflinger/Scheduler/src/Timer.cpp
index a4cf57f..09e8a1e 100644
--- a/services/surfaceflinger/Scheduler/src/Timer.cpp
+++ b/services/surfaceflinger/Scheduler/src/Timer.cpp
@@ -93,8 +93,8 @@
close(mPipes[kWritePipe]);
mPipes[kWritePipe] = -1;
}
- mExpectingCallback = false;
- mCallback = {};
+
+ setCallback({});
}
void Timer::endDispatch() {
@@ -112,8 +112,7 @@
static constexpr int ns_per_s =
std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
- mCallback = std::move(callback);
- mExpectingCallback = true;
+ setCallback(std::move(callback));
struct itimerspec old_timer;
struct itimerspec new_timer {
@@ -142,6 +141,8 @@
if (timerfd_settime(mTimerFd, 0, &new_timer, &old_timer)) {
ALOGW("Failed to disarm timerfd");
}
+
+ setCallback({});
}
void Timer::threadMain() {
@@ -231,6 +232,11 @@
mDebugState = state;
}
+void Timer::setCallback(std::function<void()>&& callback) {
+ mExpectingCallback = bool(callback);
+ mCallback = std::move(callback);
+}
+
void Timer::dump(std::string& result) const {
std::lock_guard lock(mMutex);
result.append("\t\tDebugState: ");
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7e799bb..533c276 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1047,6 +1047,7 @@
const auto peakFps = mode->getPeakFps();
outMode.refreshRate = peakFps.getValue();
+ outMode.vsyncRate = mode->getVsyncRate().getValue();
const auto vsyncConfigSet =
mVsyncConfiguration->getConfigsForRefreshRate(Fps::fromValue(outMode.refreshRate));
@@ -5228,7 +5229,7 @@
}
if (what & layer_state_t::eFrameRateCategoryChanged) {
const FrameRateCategory category = Layer::FrameRate::convertCategory(s.frameRateCategory);
- if (layer->setFrameRateCategory(category)) {
+ if (layer->setFrameRateCategory(category, s.frameRateCategorySmoothSwitchOnly)) {
flags |= eTraversalNeeded;
}
}
@@ -9189,6 +9190,7 @@
outMode.xDpi = mode.xDpi;
outMode.yDpi = mode.yDpi;
outMode.refreshRate = mode.refreshRate;
+ outMode.vsyncRate = mode.vsyncRate;
outMode.appVsyncOffset = mode.appVsyncOffset;
outMode.sfVsyncOffset = mode.sfVsyncOffset;
outMode.presentationDeadline = mode.presentationDeadline;
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
index 922fd07..f339d22 100644
--- a/services/surfaceflinger/TEST_MAPPING
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -40,5 +40,10 @@
{
"name": "libsurfaceflinger_unittest"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsSurfaceControlTestsStaging"
+ }
]
}
diff --git a/services/surfaceflinger/tests/BootDisplayMode_test.cpp b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
index f2874ae..4f41a81 100644
--- a/services/surfaceflinger/tests/BootDisplayMode_test.cpp
+++ b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
@@ -28,33 +28,95 @@
using gui::aidl_utils::statusTFromBinderStatus;
-TEST(BootDisplayModeTest, setBootDisplayMode) {
- sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+struct BootDisplayModeTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mSf = ComposerServiceAIDL::getComposerService();
- const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
- ASSERT_FALSE(ids.empty());
- auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
- bool bootModeSupport = false;
- binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport);
- ASSERT_NO_FATAL_FAILURE(statusTFromBinderStatus(status));
- if (bootModeSupport) {
- status = sf->setBootDisplayMode(displayToken, 0);
+ const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
+ ASSERT_FALSE(ids.empty());
+ mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
+ bool bootModeSupport = false;
+ binder::Status status = mSf->getBootDisplayModeSupport(&bootModeSupport);
+ ASSERT_NO_FATAL_FAILURE(statusTFromBinderStatus(status));
+
+ if (!bootModeSupport) {
+ GTEST_SKIP() << "Boot mode not supported";
+ }
+
+ gui::DynamicDisplayInfo info;
+ status = mSf->getDynamicDisplayInfoFromToken(mDisplayToken, &info);
ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+ mOldMode = info.preferredBootDisplayMode;
+ const auto newMode = [&]() -> std::optional<ui::DisplayModeId> {
+ for (const auto& mode : info.supportedDisplayModes) {
+ if (mode.id != mOldMode) {
+ return std::optional(mode.id);
+ }
+ }
+ return std::nullopt;
+ }();
+
+ if (!newMode) {
+ GTEST_SKIP() << "Only a single mode is supported";
+ }
+
+ mNewMode = *newMode;
}
+
+ void TearDown() override {
+ binder::Status status = mSf->setBootDisplayMode(mDisplayToken, mOldMode);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+
+ gui::DynamicDisplayInfo info;
+ status = mSf->getDynamicDisplayInfoFromToken(mDisplayToken, &info);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+ EXPECT_EQ(mOldMode, info.preferredBootDisplayMode);
+ }
+
+ ui::DisplayModeId mOldMode;
+ ui::DisplayModeId mNewMode;
+ sp<gui::ISurfaceComposer> mSf;
+ sp<IBinder> mDisplayToken;
+};
+
+TEST_F(BootDisplayModeTest, setBootDisplayMode) {
+ // Set a new mode and check that it got applied
+ binder::Status status = mSf->setBootDisplayMode(mDisplayToken, mNewMode);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+
+ gui::DynamicDisplayInfo info;
+ status = mSf->getDynamicDisplayInfoFromToken(mDisplayToken, &info);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+ EXPECT_EQ(mNewMode, info.preferredBootDisplayMode);
}
-TEST(BootDisplayModeTest, clearBootDisplayMode) {
- sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
- const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
- ASSERT_FALSE(ids.empty());
- auto displayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
- bool bootModeSupport = false;
- binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport);
- ASSERT_NO_FATAL_FAILURE(statusTFromBinderStatus(status));
- if (bootModeSupport) {
- status = sf->clearBootDisplayMode(displayToken);
- ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
- }
+TEST_F(BootDisplayModeTest, clearBootDisplayMode) {
+ // Clear once to figure out what the system default is
+ binder::Status status = mSf->clearBootDisplayMode(mDisplayToken);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+
+ gui::DynamicDisplayInfo info;
+ status = mSf->getDynamicDisplayInfoFromToken(mDisplayToken, &info);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+
+ const ui::DisplayModeId systemMode = info.preferredBootDisplayMode;
+ const ui::DisplayModeId newMode = systemMode == mOldMode ? mNewMode : mOldMode;
+
+ // Now set a new mode and clear the boot mode again to figure out if the api worked.
+ status = mSf->setBootDisplayMode(mDisplayToken, newMode);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+
+ status = mSf->getDynamicDisplayInfoFromToken(mDisplayToken, &info);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+ EXPECT_EQ(newMode, info.preferredBootDisplayMode);
+
+ status = mSf->clearBootDisplayMode(mDisplayToken);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+
+ status = mSf->getDynamicDisplayInfoFromToken(mDisplayToken, &info);
+ EXPECT_EQ(NO_ERROR, statusTFromBinderStatus(status));
+ EXPECT_EQ(systemMode, info.preferredBootDisplayMode);
}
} // namespace android
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index 69e9a16..822ac4d 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -275,18 +275,6 @@
ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
}
-TEST_F(CredentialsTest, CaptureTest) {
- const auto display = getFirstDisplayToken();
- std::function<status_t()> condition = [=]() {
- sp<GraphicBuffer> outBuffer;
- DisplayCaptureArgs captureArgs;
- captureArgs.displayToken = display;
- ScreenCaptureResults captureResults;
- return ScreenCapture::captureDisplay(captureArgs, captureResults);
- };
- ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
-}
-
TEST_F(CredentialsTest, CaptureLayersTest) {
setupBackgroundSurface();
sp<GraphicBuffer> outBuffer;
diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
index 34c9182..f9b4bba 100644
--- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
@@ -167,18 +167,18 @@
.setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
.apply(true);
- DisplayCaptureArgs args;
- args.displayToken = mDisplay;
+ LayerCaptureArgs args;
+ args.layerHandle = layer->getHandle();
ScreenCaptureResults captureResults;
{
// Ensure the UID is not root because root has all permissions
UIDFaker f(AID_APP_START);
- ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(args, captureResults));
+ ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults));
}
Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
- ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, captureResults));
+ ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(args, captureResults));
}
TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 91910c7..ec21eaf 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -45,8 +45,7 @@
cc_aconfig_library {
name: "libsurfaceflingerflags_test",
aconfig_declarations: "surfaceflinger_flags",
- // TODO(b/304338314): uncomment the below line once the bug is fixed
- // test: true,
+ test: true,
}
cc_test {
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index d319dcc..7f3171f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -443,6 +443,17 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setTrustedOverlay(uint32_t id, bool isTrustedOverlay) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eTrustedOverlayChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.isTrustedOverlay = isTrustedOverlay;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
LayerLifecycleManager mLifecycleManager;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 50dfcaa..fc4bb22 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -861,4 +861,15 @@
EXPECT_EQ(getSnapshot(1)->shadowSettings.length, SHADOW_RADIUS);
}
+TEST_F(LayerSnapshotTest, setTrustedOverlayForNonVisibleInput) {
+ hideLayer(1);
+ setTrustedOverlay(1, true);
+ Region touch{Rect{0, 0, 1000, 1000}};
+ setTouchableRegion(1, touch);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {2});
+ EXPECT_TRUE(getSnapshot(1)->inputInfo.inputConfig.test(
+ gui::WindowInfo::InputConfig::TRUSTED_OVERLAY));
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index 0b67137..faa12a1 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -117,9 +117,9 @@
return std::make_pair(ranking, consideredSignals);
}
- ftl::NonNull<DisplayModePtr> getBestFrameRateMode(
- const std::vector<LayerRequirement>& layers = {}, GlobalSignals signals = {}) const {
- return getRankedFrameRates(layers, signals).ranking.front().frameRateMode.modePtr;
+ FrameRateMode getBestFrameRateMode(const std::vector<LayerRequirement>& layers = {},
+ GlobalSignals signals = {}) const {
+ return getRankedFrameRates(layers, signals).ranking.front().frameRateMode;
}
ScoredFrameRate getBestScoredFrameRate(const std::vector<LayerRequirement>& layers = {},
@@ -429,11 +429,11 @@
// If there are no layers we select the default frame rate, which is the max of the primary
// range.
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode());
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode().modePtr);
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}}));
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode());
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode().modePtr);
}
{
// We select max even when this will cause a non-seamless switch.
@@ -442,7 +442,7 @@
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy(
{kModeId90, {0_Hz, 90_Hz}, kAllowGroupSwitching}));
- EXPECT_EQ(kMode90_G1, selector.getBestFrameRateMode());
+ EXPECT_EQ(kMode90_G1, selector.getBestFrameRateMode().modePtr);
}
}
@@ -455,7 +455,7 @@
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy({kModeId72, {0_Hz, 90_Hz}}));
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_90) {
@@ -466,107 +466,107 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.name = "";
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}}));
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}}));
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 120_Hz}}));
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_multipleThreshold_60_90) {
@@ -577,32 +577,32 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_72_90) {
@@ -612,26 +612,26 @@
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90_120) {
@@ -645,19 +645,19 @@
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48_Hz;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 48_Hz;
lr2.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes) {
@@ -673,7 +673,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -681,7 +681,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -689,7 +689,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -697,7 +697,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -705,7 +705,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -713,7 +713,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
@@ -721,7 +721,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -729,7 +729,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -737,7 +737,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest,
@@ -756,7 +756,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -764,7 +764,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "60Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -772,7 +772,7 @@
lr2.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "60Hz ExplicitDefault";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -780,7 +780,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -788,7 +788,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -796,7 +796,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::Heuristic;
@@ -804,7 +804,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -812,7 +812,7 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitDefault;
@@ -820,14 +820,14 @@
lr2.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.name = "90Hz ExplicitExactOrMultiple";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.name = "24Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -835,7 +835,7 @@
lr2.desiredRefreshRate = 120_Hz;
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.name = "120Hz ExplicitDefault";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 24_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -843,7 +843,7 @@
lr2.desiredRefreshRate = 120_Hz;
lr2.vote = LayerVoteType::ExplicitExact;
lr2.name = "120Hz ExplicitExact";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 10_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -851,7 +851,7 @@
lr2.desiredRefreshRate = 120_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.name = "120Hz ExplicitExact";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
lr1.desiredRefreshRate = 30_Hz;
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -862,7 +862,7 @@
lr3.vote = LayerVoteType::Heuristic;
lr3.desiredRefreshRate = 120_Hz;
lr3.name = "120Hz Heuristic";
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60) {
@@ -872,26 +872,26 @@
auto& lr = layers[0];
lr.vote = LayerVoteType::Min;
- EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90) {
@@ -902,42 +902,42 @@
lr.vote = LayerVoteType::Min;
lr.name = "Min";
- EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
lr.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 90_Hz;
lr.vote = LayerVoteType::Heuristic;
lr.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
lr.desiredRefreshRate = 45_Hz;
lr.name = "45Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
lr.desiredRefreshRate = 30_Hz;
lr.name = "30Hz Heuristic";
- EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers));
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr);
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
lr.desiredRefreshRate = 24_Hz;
lr.name = "24Hz Heuristic";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
lr.desiredRefreshRate = 24_Hz;
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.name = "24Hz ExplicitExactOrMultiple";
- EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers));
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr);
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_PriorityTest) {
@@ -949,39 +949,39 @@
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Max;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Min;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 24_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Max;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 15_Hz;
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 30_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 45_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo) {
@@ -993,7 +993,7 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = Fps::fromValue(fps);
- const auto mode = selector.getBestFrameRateMode(layers);
+ const auto mode = selector.getBestFrameRateMode(layers).modePtr;
EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses "
<< to_string(mode->getPeakFps()) << "("
<< to_string(mode->getVsyncRate()) << ")";
@@ -1009,7 +1009,7 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) {
lr.desiredRefreshRate = Fps::fromValue(fps);
- const auto mode = selector.getBestFrameRateMode(layers);
+ const auto mode = selector.getBestFrameRateMode(layers).modePtr;
EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses "
<< to_string(mode->getPeakFps()) << "("
<< to_string(mode->getVsyncRate()) << ")";
@@ -1027,19 +1027,19 @@
lr1.desiredRefreshRate = 60_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 90_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::Heuristic;
lr1.desiredRefreshRate = 90_Hz;
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 60_Hz;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_75HzContent) {
@@ -1051,7 +1051,7 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
lr.desiredRefreshRate = Fps::fromValue(fps);
- const auto mode = selector.getBestFrameRateMode(layers, {});
+ const auto mode = selector.getBestFrameRateMode(layers, {}).modePtr;
EXPECT_EQ(kMode90, mode) << lr.desiredRefreshRate << " chooses "
<< to_string(mode->getPeakFps()) << "("
<< to_string(mode->getVsyncRate()) << ")";
@@ -1071,7 +1071,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
@@ -1079,14 +1079,14 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz ExplicitDefault";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30_Hz;
@@ -1094,14 +1094,14 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 30_Hz;
lr1.name = "30Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) {
@@ -1116,28 +1116,28 @@
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
lr2.vote = LayerVoteType::Max;
lr2.name = "Max";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
// The other layer starts to provide buffers
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1146,7 +1146,7 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 90_Hz;
lr2.name = "90Hz Heuristic";
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicy) {
@@ -1464,7 +1464,8 @@
layers.push_back(layer);
}
- EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps())
+ EXPECT_EQ(testCase.expectedFrameRate,
+ selector.getBestFrameRateMode(layers).modePtr->getPeakFps())
<< "Did not get expected frame rate for frameRate="
<< to_string(testCase.desiredFrameRate)
<< " category=" << ftl::enum_string(testCase.frameRateCategory);
@@ -1528,13 +1529,147 @@
layers.push_back(layer);
}
- EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps())
+ EXPECT_EQ(testCase.expectedFrameRate,
+ selector.getBestFrameRateMode(layers).modePtr->getPeakFps())
<< "Did not get expected frame rate for frameRate="
<< to_string(testCase.desiredFrameRate)
<< " category=" << ftl::enum_string(testCase.frameRateCategory);
}
}
+TEST_P(RefreshRateSelectorTest,
+ getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_nonVrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ // VRR compatibility is determined by the presence of a vrr config in the DisplayMode.
+ auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120);
+
+ struct Case {
+ // Params
+ FrameRateCategory frameRateCategory = FrameRateCategory::Default;
+ bool smoothSwitchOnly = false;
+
+ // Expected result
+ Fps expectedFrameRate = 0_Hz;
+ DisplayModeId expectedModeId = kModeId60;
+ };
+
+ const std::initializer_list<Case> testCases = {
+ // These layers may switch modes because smoothSwitchOnly=false.
+ {FrameRateCategory::Default, false, 120_Hz, kModeId120},
+ // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
+ {FrameRateCategory::NoPreference, false, 60_Hz, kModeId60},
+ {FrameRateCategory::Low, false, 30_Hz, kModeId60},
+ {FrameRateCategory::Normal, false, 60_Hz, kModeId60},
+ {FrameRateCategory::High, false, 120_Hz, kModeId120},
+
+ // These layers cannot change mode due to smoothSwitchOnly, and will definitely use
+ // active mode (120Hz).
+ {FrameRateCategory::NoPreference, true, 120_Hz, kModeId120},
+ {FrameRateCategory::Low, true, 40_Hz, kModeId120},
+ {FrameRateCategory::Normal, true, 40_Hz, kModeId120},
+ {FrameRateCategory::High, true, 120_Hz, kModeId120},
+ };
+
+ for (auto testCase : testCases) {
+ std::vector<LayerRequirement> layers;
+ ALOGI("**** %s: Testing frameRateCategory=%s (smooth=%d)", __func__,
+ ftl::enum_string(testCase.frameRateCategory).c_str(), testCase.smoothSwitchOnly);
+
+ if (testCase.frameRateCategory != FrameRateCategory::Default) {
+ std::stringstream ss;
+ ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory)
+ << " smooth:" << testCase.smoothSwitchOnly << ")";
+ LayerRequirement layer = {.name = ss.str(),
+ .vote = LayerVoteType::ExplicitCategory,
+ .frameRateCategory = testCase.frameRateCategory,
+ .frameRateCategorySmoothSwitchOnly =
+ testCase.smoothSwitchOnly,
+ .weight = 1.f};
+ layers.push_back(layer);
+ }
+
+ auto actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ EXPECT_EQ(testCase.expectedFrameRate, actualFrameRateMode.fps)
+ << "Did not get expected frame rate for category="
+ << ftl::enum_string(testCase.frameRateCategory)
+ << " (smooth=" << testCase.smoothSwitchOnly << ")";
+
+ EXPECT_EQ(testCase.expectedModeId, actualFrameRateMode.modePtr->getId())
+ << "Did not get expected mode for category="
+ << ftl::enum_string(testCase.frameRateCategory)
+ << " (smooth=" << testCase.smoothSwitchOnly << ")";
+ }
+}
+
+TEST_P(RefreshRateSelectorTest,
+ getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_vrr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ // VRR compatibility is determined by the presence of a vrr config in the DisplayMode.
+ auto selector = createSelector(kVrrModes_60_120, kModeId120);
+
+ struct Case {
+ // Params
+ FrameRateCategory frameRateCategory = FrameRateCategory::Default;
+ bool smoothSwitchOnly = false;
+
+ // Expected result
+ Fps expectedFrameRate = 0_Hz;
+ };
+
+ // Note that `smoothSwitchOnly` should not have an effect.
+ const std::initializer_list<Case> testCases = {
+ {FrameRateCategory::Default, false, 240_Hz},
+ // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
+ {FrameRateCategory::NoPreference, false, 240_Hz},
+ {FrameRateCategory::Low, false, 30_Hz},
+ {FrameRateCategory::Normal, false, 60_Hz},
+ {FrameRateCategory::High, false, 120_Hz},
+ {FrameRateCategory::Default, true, 240_Hz},
+ // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
+ {FrameRateCategory::NoPreference, true, 240_Hz},
+ {FrameRateCategory::Low, true, 30_Hz},
+ {FrameRateCategory::Normal, true, 60_Hz},
+ {FrameRateCategory::High, true, 120_Hz},
+ };
+
+ for (auto testCase : testCases) {
+ std::vector<LayerRequirement> layers;
+ ALOGI("**** %s: Testing frameRateCategory=%s (smooth=%d)", __func__,
+ ftl::enum_string(testCase.frameRateCategory).c_str(), testCase.smoothSwitchOnly);
+
+ if (testCase.frameRateCategory != FrameRateCategory::Default) {
+ std::stringstream ss;
+ ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory)
+ << " smooth:" << testCase.smoothSwitchOnly << ")";
+ LayerRequirement layer = {.name = ss.str(),
+ .vote = LayerVoteType::ExplicitCategory,
+ .frameRateCategory = testCase.frameRateCategory,
+ .frameRateCategorySmoothSwitchOnly =
+ testCase.smoothSwitchOnly,
+ .weight = 1.f};
+ layers.push_back(layer);
+ }
+
+ auto actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ EXPECT_EQ(testCase.expectedFrameRate, actualFrameRateMode.fps)
+ << "Did not get expected frame rate for category="
+ << ftl::enum_string(testCase.frameRateCategory)
+ << " (smooth=" << testCase.smoothSwitchOnly << ")";
+
+ // Expect all cases to be able to stay at the mode with TE 240 due to VRR compatibility.
+ EXPECT_EQ(kVrrMode120TE240->getId(), actualFrameRateMode.modePtr->getId())
+ << "Did not get expected mode for category="
+ << ftl::enum_string(testCase.frameRateCategory)
+ << " (smooth=" << testCase.smoothSwitchOnly << ")";
+ }
+}
+
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitDefault) {
auto selector = createSelector(kModes_60_90_72_120, kModeId60);
@@ -1568,7 +1703,7 @@
ss << "ExplicitDefault " << desired;
lr.name = ss.str();
- const auto bestMode = selector.getBestFrameRateMode(layers);
+ const auto bestMode = selector.getBestFrameRateMode(layers).modePtr;
EXPECT_EQ(expected, bestMode->getPeakFps())
<< "expected " << expected << " for " << desired << " but got "
<< bestMode->getPeakFps() << "(" << bestMode->getVsyncRate() << ")";
@@ -1589,7 +1724,7 @@
lr.vote = LayerVoteType::ExplicitExactOrMultiple;
lr.desiredRefreshRate = 23.976_Hz;
lr.name = "ExplicitExactOrMultiple 23.976 Hz";
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
// Test that 24 will choose 23.976 if 24 is not supported
@@ -1600,7 +1735,7 @@
lr.desiredRefreshRate = 24_Hz;
lr.name = "ExplicitExactOrMultiple 24 Hz";
- EXPECT_EQ(kModeId24Frac, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId24Frac, selector.getBestFrameRateMode(layers).modePtr->getId());
}
// Test that 29.97 will prefer 59.94 over 60 and 30
@@ -1611,7 +1746,7 @@
lr.desiredRefreshRate = 29.97_Hz;
lr.name = "ExplicitExactOrMultiple 29.97 Hz";
- EXPECT_EQ(kModeId60Frac, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60Frac, selector.getBestFrameRateMode(layers).modePtr->getId());
}
// Test that 29.97 will choose 60 if 59.94 is not supported
@@ -1620,7 +1755,7 @@
lr.desiredRefreshRate = 29.97_Hz;
lr.name = "ExplicitExactOrMultiple 29.97 Hz";
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
// Test that 59.94 will choose 60 if 59.94 is not supported
@@ -1629,7 +1764,7 @@
lr.desiredRefreshRate = 59.94_Hz;
lr.name = "ExplicitExactOrMultiple 59.94 Hz";
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
}
@@ -1648,7 +1783,8 @@
ss << "ExplicitExact " << desired;
lr.name = ss.str();
- EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getPeakFps());
+ EXPECT_EQ(lr.desiredRefreshRate,
+ selector.getBestFrameRateMode(layers).modePtr->getPeakFps());
}
}
}
@@ -1694,7 +1830,7 @@
lr.desiredRefreshRate = 90_Hz;
lr.name = "90Hz ExplicitDefault";
lr.focused = true;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.idle = true}));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.idle = true}).modePtr);
}
TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) {
@@ -1905,46 +2041,46 @@
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz ExplicitExactOrMultiple";
lr.focused = false;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.focused = true;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::ExplicitDefault;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz ExplicitDefault";
lr.focused = false;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.focused = true;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Heuristic;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Heuristic";
lr.focused = false;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.focused = true;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Max;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Max";
lr.focused = false;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.focused = true;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.vote = LayerVoteType::Min;
lr.desiredRefreshRate = 60_Hz;
lr.name = "60Hz Min";
lr.focused = false;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
lr.focused = true;
- EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr);
}
TEST_P(RefreshRateSelectorTest, groupSwitchingNotAllowed) {
@@ -1960,7 +2096,7 @@
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayer) {
@@ -1978,7 +2114,7 @@
layer.seamlessness = Seamlessness::SeamedAndSeamless;
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamless) {
@@ -1997,7 +2133,7 @@
layer.seamlessness = Seamlessness::OnlySeamless;
layer.name = "90Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) {
@@ -2018,7 +2154,7 @@
layer.seamlessness = Seamlessness::OnlySeamless;
layer.name = "60Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerDefaultSeamlessness) {
@@ -2042,7 +2178,7 @@
layer.name = "60Hz ExplicitDefault";
layer.focused = true;
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) {
@@ -2071,7 +2207,7 @@
layers[1].name = "90Hz ExplicitDefault";
layers[1].focused = false;
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeamed) {
@@ -2104,7 +2240,7 @@
layers[1].vote = LayerVoteType::ExplicitDefault;
layers[1].name = "90Hz ExplicitDefault";
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSeamed) {
@@ -2134,7 +2270,7 @@
layers[1].vote = LayerVoteType::ExplicitDefault;
layers[1].name = "90Hz ExplicitDefault";
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, nonSeamlessVotePrefersSeamlessSwitches) {
@@ -2154,10 +2290,10 @@
layer.name = "60Hz ExplicitExactOrMultiple";
layer.focused = true;
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId());
selector.setActiveMode(kModeId120, 120_Hz);
- EXPECT_EQ(kModeId120, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId120, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, nonSeamlessExactAndSeamlessMultipleLayers) {
@@ -2182,14 +2318,14 @@
.weight = 1.f,
.focused = true}};
- EXPECT_EQ(kModeId50, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId50, selector.getBestFrameRateMode(layers).modePtr->getId());
auto& seamedLayer = layers[0];
seamedLayer.desiredRefreshRate = 30_Hz;
seamedLayer.name = "30Hz ExplicitDefault";
selector.setActiveMode(kModeId30, 30_Hz);
- EXPECT_EQ(kModeId25, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId25, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, minLayersDontTrigerSeamedSwitch) {
@@ -2204,7 +2340,7 @@
std::vector<LayerRequirement> layers = {
{.name = "Min", .vote = LayerVoteType::Min, .weight = 1.f, .focused = true}};
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId());
+ EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, primaryVsAppRequestPolicy) {
@@ -2225,7 +2361,7 @@
layers[0].vote = voteType;
layers[0].desiredRefreshRate = fps;
layers[0].focused = args.focused;
- return selector.getBestFrameRateMode(layers, {.touch = args.touch})->getId();
+ return selector.getBestFrameRateMode(layers, {.touch = args.touch}).modePtr->getId();
};
constexpr FpsRange k30_60 = {30_Hz, 60_Hz};
@@ -2234,7 +2370,7 @@
EXPECT_EQ(SetPolicyResult::Changed,
selector.setDisplayManagerPolicy({kModeId60, {k30_60, k30_60}, {k30_90, k30_90}}));
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode()->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode().modePtr->getId());
EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::NoVote, 90_Hz));
EXPECT_EQ(kModeId30, getFrameRate(LayerVoteType::Min, 90_Hz));
EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::Max, 90_Hz));
@@ -2302,7 +2438,8 @@
}
// With no layers, idle should still be lower priority than touch boost.
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode({}, {.touch = true, .idle = true})->getId());
+ EXPECT_EQ(kModeId90,
+ selector.getBestFrameRateMode({}, {.touch = true, .idle = true}).modePtr->getId());
// Idle should be higher precedence than other layer frame rate considerations.
selector.setActiveMode(kModeId90, 90_Hz);
@@ -2319,7 +2456,7 @@
}
// Idle should be applied rather than the active mode when there are no layers.
- EXPECT_EQ(kModeId60, selector.getBestFrameRateMode({}, {.idle = true})->getId());
+ EXPECT_EQ(kModeId60, selector.getBestFrameRateMode({}, {.idle = true}).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, findClosestKnownFrameRate) {
@@ -2368,7 +2505,7 @@
for (const auto& [fps, mode] : knownFrameRatesExpectations) {
layer.desiredRefreshRate = fps;
- EXPECT_EQ(mode, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(mode, selector.getBestFrameRateMode(layers).modePtr);
}
}
@@ -2471,17 +2608,17 @@
explicitExactLayer.name = "ExplicitExact";
explicitExactLayer.desiredRefreshRate = 30_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
if (GetParam() == Config::FrameRateOverride::Disabled) {
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
} else {
- EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
}
explicitExactOrMultipleLayer.vote = LayerVoteType::NoVote;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true}));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr);
}
TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_FractionalRefreshRates_ExactAndDefault) {
@@ -2499,7 +2636,7 @@
explicitDefaultLayer.name = "ExplicitDefault";
explicitDefaultLayer.desiredRefreshRate = 59.94_Hz;
- EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers));
+ EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr);
}
// b/190578904
@@ -2526,7 +2663,7 @@
layers[0].desiredRefreshRate = fps;
layers[0].vote = vote;
EXPECT_EQ(fps.getIntValue(),
- selector.getBestFrameRateMode(layers)->getPeakFps().getIntValue())
+ selector.getBestFrameRateMode(layers).modePtr->getPeakFps().getIntValue())
<< "Failed for " << ftl::enum_string(vote);
};
@@ -2565,7 +2702,7 @@
},
};
- EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getPeakFps());
+ EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals).modePtr->getPeakFps());
}
TEST_P(RefreshRateSelectorTest, modeComparison) {
@@ -3176,7 +3313,8 @@
selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 90_Hz}}));
// With no layers, idle should still be lower priority than touch boost.
- EXPECT_EQ(kModeId90, selector.getBestFrameRateMode({}, {.touch = true, .idle = true})->getId());
+ EXPECT_EQ(kModeId90,
+ selector.getBestFrameRateMode({}, {.touch = true, .idle = true}).modePtr->getId());
// Idle should be higher precedence than other layer frame rate considerations.
selector.setActiveMode(kModeId90, 90_Hz);
@@ -3192,7 +3330,7 @@
}
// Idle should be applied rather than the active mode when there are no layers.
- EXPECT_EQ(kModeId35, selector.getBestFrameRateMode({}, {.idle = true})->getId());
+ EXPECT_EQ(kModeId35, selector.getBestFrameRateMode({}, {.idle = true}).modePtr->getId());
}
TEST_P(RefreshRateSelectorTest, policyCanBeInfinity) {
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index a1eda94..b8fdce1 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -1065,10 +1065,8 @@
EXPECT_THAT(cb.mReadyTime[0], Eq(2000));
}
-// TODO(b/304338314): Set the flag value instead of skipping the test
TEST_F(VSyncDispatchTimerQueueTest, skipAVsyc) {
- // SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false);
- if (flags::dont_skip_on_early()) GTEST_SKIP();
+ SET_FLAG_FOR_TEST(flags::dont_skip_on_early, false);
EXPECT_CALL(mMockClock, alarmAt(_, 500));
CountingCallback cb(mDispatch);
@@ -1088,10 +1086,8 @@
ASSERT_THAT(cb.mCalls.size(), Eq(1));
}
-// TODO(b/304338314): Set the flag value instead of skipping the test
TEST_F(VSyncDispatchTimerQueueTest, dontskipAVsyc) {
- // SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true);
- if (!flags::dont_skip_on_early()) GTEST_SKIP();
+ SET_FLAG_FOR_TEST(flags::dont_skip_on_early, true);
EXPECT_CALL(mMockClock, alarmAt(_, 500));
CountingCallback cb(mDispatch);