VTS for the Refresh rate callback debug enabled
BUG: 202734676
Test: atest VtsHalGraphicsComposer3_TargetTest
with the patch of
Ibc80d66eae6b21c3cf84d35fa819e97ccc509ede
Change-Id: I02bdf061420fe12ef4548008d66bb73e8cd416e8
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 4974e71..37576b9 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1217,6 +1217,14 @@
}
}
+ bool checkIfCallbackRefreshRateChangedDebugEnabledReceived(
+ std::function<bool(RefreshRateChangedDebugData)> filter) {
+ const auto list = mComposerClient->takeListOfRefreshRateChangedDebugData();
+ return std::any_of(list.begin(), list.end(), [&](auto refreshRateChangedDebugData) {
+ return filter(refreshRateChangedDebugData);
+ });
+ }
+
sp<GraphicBuffer> allocate(::android::PixelFormat pixelFormat) {
return sp<GraphicBuffer>::make(
static_cast<uint32_t>(getPrimaryDisplay().getDisplayWidth()),
@@ -1316,7 +1324,7 @@
return vsyncPeriod;
}
- int64_t createOnScreenLayer() {
+ int64_t createOnScreenLayer(Composition composition = Composition::DEVICE) {
const auto& [status, layer] =
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(status.isOk());
@@ -1324,12 +1332,25 @@
getPrimaryDisplay().getDisplayHeight()};
FRect cropRect{0, 0, (float)getPrimaryDisplay().getDisplayWidth(),
(float)getPrimaryDisplay().getDisplayHeight()};
- configureLayer(getPrimaryDisplay(), layer, Composition::DEVICE, displayFrame, cropRect);
+ configureLayer(getPrimaryDisplay(), layer, composition, displayFrame, cropRect);
auto& writer = getWriter(getPrimaryDisplayId());
writer.setLayerDataspace(getPrimaryDisplayId(), layer, common::Dataspace::UNKNOWN);
return layer;
}
+ void sendBufferUpdate(int64_t layer) {
+ const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+ ASSERT_NE(nullptr, buffer->handle);
+
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer->handle,
+ /*acquireFence*/ -1);
+
+ const sp<::android::Fence> presentFence =
+ presentAndGetFence(ComposerClientWriter::kNoTimestamp);
+ presentFence->waitForever(LOG_TAG);
+ }
+
bool hasDisplayCapability(int64_t display, DisplayCapability cap) {
const auto& [status, capabilities] = mComposerClient->getDisplayCapabilities(display);
EXPECT_TRUE(status.isOk());
@@ -2268,6 +2289,179 @@
EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk());
}
+TEST_P(GraphicsComposerAidlCommandTest, SetRefreshRateChangedCallbackDebug_Unsupported) {
+ if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
+ auto status = mComposerClient->setRefreshRateChangedCallbackDebugEnabled(
+ getPrimaryDisplayId(), /*enabled*/ true);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_NO_FATAL_FAILURE(
+ assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED));
+
+ status = mComposerClient->setRefreshRateChangedCallbackDebugEnabled(getPrimaryDisplayId(),
+ /*enabled*/ false);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_NO_FATAL_FAILURE(
+ assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED));
+ }
+}
+
+TEST_P(GraphicsComposerAidlCommandTest, SetRefreshRateChangedCallbackDebug_Enabled) {
+ if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
+ GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is not supported";
+ return;
+ }
+
+ const auto displayId = getPrimaryDisplayId();
+ EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
+ // Enable the callback
+ ASSERT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId,
+ /*enabled*/ true)
+ .isOk());
+ std::this_thread::sleep_for(100ms);
+
+ const bool isCallbackReceived = checkIfCallbackRefreshRateChangedDebugEnabledReceived(
+ [&](auto refreshRateChangedDebugData) {
+ return displayId == refreshRateChangedDebugData.display;
+ });
+
+ // Check that we immediately got a callback
+ EXPECT_TRUE(isCallbackReceived);
+
+ ASSERT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId,
+ /*enabled*/ false)
+ .isOk());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest,
+ SetRefreshRateChangedCallbackDebugEnabled_noCallbackWhenIdle) {
+ if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
+ GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is not supported";
+ return;
+ }
+
+ auto display = getEditablePrimaryDisplay();
+ const auto displayId = display.getDisplayId();
+
+ if (!hasDisplayCapability(displayId, DisplayCapability::DISPLAY_IDLE_TIMER)) {
+ GTEST_SUCCEED() << "DisplayCapability::DISPLAY_IDLE_TIMER is not supported";
+ return;
+ }
+
+ EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
+ EXPECT_TRUE(mComposerClient->setPeakRefreshRateConfig(&display).isOk());
+
+ ASSERT_TRUE(mComposerClient->setIdleTimerEnabled(displayId, /*timeoutMs*/ 500).isOk());
+ // Enable the callback
+ ASSERT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId,
+ /*enabled*/ true)
+ .isOk());
+
+ const bool isCallbackReceived = checkIfCallbackRefreshRateChangedDebugEnabledReceived(
+ [&](auto refreshRateChangedDebugData) {
+ return displayId == refreshRateChangedDebugData.display;
+ });
+
+ int retryCount = 3;
+ do {
+ // Wait for 1s so that we enter the idle state
+ std::this_thread::sleep_for(1s);
+ if (!isCallbackReceived) {
+ // DID NOT receive a callback, we are in the idle state.
+ break;
+ }
+ } while (--retryCount > 0);
+
+ if (retryCount == 0) {
+ GTEST_SUCCEED() << "Unable to enter the idle mode";
+ return;
+ }
+
+ // Send the REFRESH_RATE_INDICATOR update
+ ASSERT_NO_FATAL_FAILURE(
+ sendBufferUpdate(createOnScreenLayer(Composition::REFRESH_RATE_INDICATOR)));
+ std::this_thread::sleep_for(1s);
+ EXPECT_FALSE(isCallbackReceived)
+ << "A callback should not be received for REFRESH_RATE_INDICATOR";
+
+ EXPECT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId,
+ /*enabled*/ false)
+ .isOk());
+}
+
+TEST_P(GraphicsComposerAidlCommandTest,
+ SetRefreshRateChangedCallbackDebugEnabled_SetActiveConfigWithConstraints) {
+ if (!hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG)) {
+ GTEST_SUCCEED() << "Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG is not supported";
+ return;
+ }
+
+ VsyncPeriodChangeConstraints constraints;
+ constraints.seamlessRequired = false;
+ constraints.desiredTimeNanos = systemTime();
+
+ for (VtsDisplay& display : mDisplays) {
+ const auto displayId = display.getDisplayId();
+ EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk());
+
+ // Enable the callback
+ ASSERT_TRUE(mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId, /*enabled*/ true)
+ .isOk());
+
+ forEachTwoConfigs(displayId, [&](int32_t config1, int32_t config2) {
+ const int32_t vsyncPeriod1 = display.getDisplayConfig(config1).vsyncPeriod;
+ const int32_t vsyncPeriod2 = display.getDisplayConfig(config2).vsyncPeriod;
+
+ if (vsyncPeriod1 == vsyncPeriod2) {
+ return; // continue
+ }
+
+ EXPECT_TRUE(mComposerClient->setActiveConfig(&display, config1).isOk());
+ sendRefreshFrame(display, nullptr);
+
+ const auto& [status, timeline] =
+ mComposerClient->setActiveConfigWithConstraints(&display, config2, constraints);
+ EXPECT_TRUE(status.isOk());
+
+ if (timeline.refreshRequired) {
+ sendRefreshFrame(display, &timeline);
+ }
+
+ const auto isCallbackReceived = checkIfCallbackRefreshRateChangedDebugEnabledReceived(
+ [&](auto refreshRateChangedDebugData) {
+ constexpr int kVsyncThreshold = 1000;
+ return displayId == refreshRateChangedDebugData.display &&
+ std::abs(vsyncPeriod2 -
+ refreshRateChangedDebugData.vsyncPeriodNanos) <=
+ kVsyncThreshold;
+ });
+
+ int retryCount = 3;
+ do {
+ std::this_thread::sleep_for(100ms);
+ if (isCallbackReceived) {
+ GTEST_SUCCEED() << "Received a callback successfully";
+ break;
+ }
+ } while (--retryCount > 0);
+
+ if (retryCount == 0) {
+ GTEST_FAIL() << "failed to get a callback for the display " << displayId
+ << " with config " << config2;
+ }
+ });
+
+ EXPECT_TRUE(
+ mComposerClient
+ ->setRefreshRateChangedCallbackDebugEnabled(displayId, /*enabled*/ false)
+ .isOk());
+ }
+}
+
/*
* Test that no two display configs are exactly the same.
*/