diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp index 5e45fd902b..f72cf55300 100644 --- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp +++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp @@ -1291,6 +1291,9 @@ TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigurations) { frameIntervalPowerHints.cend()); EXPECT_LE(minFrameInterval->frameIntervalNs, VtsComposerClient::kMaxFrameIntervalNs); + const auto maxFrameInterval = *max_element(frameIntervalPowerHints.cbegin(), + frameIntervalPowerHints.cend()); + EXPECT_GE(maxFrameInterval->frameIntervalNs, vrrConfig.minFrameIntervalNs); EXPECT_TRUE(std::all_of(frameIntervalPowerHints.cbegin(), frameIntervalPowerHints.cend(), @@ -1385,17 +1388,6 @@ TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigsIsSubsetOfGetDisplayConfigur } } -// TODO(b/291792736) Add detailed VTS test cases for NotifyExpectedPresent -TEST_P(GraphicsComposerAidlV3Test, NotifyExpectedPresent) { - for (const auto& display : mDisplays) { - EXPECT_TRUE(mComposerClient - ->notifyExpectedPresent(display.getDisplayId(), - ClockMonotonicTimestamp{0}, - std::chrono::nanoseconds{8ms}.count()) - .isOk()); - } -} - // Tests for Command. class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { protected: @@ -1539,18 +1531,20 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { } sp<::android::Fence> presentAndGetFence( - std::optional expectedPresentTime) { - auto& writer = getWriter(getPrimaryDisplayId()); - writer.validateDisplay(getPrimaryDisplayId(), expectedPresentTime, - VtsComposerClient::kNoFrameIntervalNs); + std::optional expectedPresentTime, + std::optional displayIdOpt = {}, + int32_t frameIntervalNs = VtsComposerClient::kNoFrameIntervalNs) { + const auto displayId = displayIdOpt.value_or(getPrimaryDisplayId()); + auto& writer = getWriter(displayId); + writer.validateDisplay(displayId, expectedPresentTime, frameIntervalNs); execute(); EXPECT_TRUE(mReader.takeErrors().empty()); - writer.presentDisplay(getPrimaryDisplayId()); + writer.presentDisplay(displayId); execute(); EXPECT_TRUE(mReader.takeErrors().empty()); - auto presentFence = mReader.takePresentFence(getPrimaryDisplayId()); + auto presentFence = mReader.takePresentFence(displayId); // take ownership const int fenceOwner = presentFence.get(); *presentFence.getR() = -1; @@ -1569,18 +1563,17 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { return vsyncPeriod; } - int64_t createOnScreenLayer(Composition composition = Composition::DEVICE) { - auto& writer = getWriter(getPrimaryDisplayId()); + int64_t createOnScreenLayer(const VtsDisplay& display, + Composition composition = Composition::DEVICE) { + auto& writer = getWriter(display.getDisplayId()); const auto& [status, layer] = - mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount, &writer); + mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount, &writer); EXPECT_TRUE(status.isOk()); - Rect displayFrame{0, 0, getPrimaryDisplay().getDisplayWidth(), - getPrimaryDisplay().getDisplayHeight()}; - FRect cropRect{0, 0, (float)getPrimaryDisplay().getDisplayWidth(), - (float)getPrimaryDisplay().getDisplayHeight()}; - configureLayer(getPrimaryDisplay(), layer, composition, displayFrame, cropRect); + Rect displayFrame{0, 0, display.getDisplayWidth(), display.getDisplayHeight()}; + FRect cropRect{0, 0, (float)display.getDisplayWidth(), (float)display.getDisplayHeight()}; + configureLayer(display, layer, composition, displayFrame, cropRect); - writer.setLayerDataspace(getPrimaryDisplayId(), layer, common::Dataspace::UNKNOWN); + writer.setLayerDataspace(display.getDisplayId(), layer, common::Dataspace::UNKNOWN); return layer; } @@ -1692,7 +1685,7 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { ASSERT_NE(nullptr, buffer1); ASSERT_NE(nullptr, buffer2); - const auto layer = createOnScreenLayer(); + const auto layer = createOnScreenLayer(getPrimaryDisplay()); auto& writer = getWriter(getPrimaryDisplayId()); writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer1->handle, /*acquireFence*/ -1); @@ -1725,6 +1718,38 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { ASSERT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk()); } + void forEachNotifyExpectedPresentConfig( + std::function func) { + for (VtsDisplay& display : mDisplays) { + const auto displayId = display.getDisplayId(); + EXPECT_TRUE(mComposerClient->setPowerMode(displayId, PowerMode::ON).isOk()); + const auto& [status, displayConfigurations] = + mComposerClient->getDisplayConfigurations(displayId); + EXPECT_TRUE(status.isOk()); + EXPECT_FALSE(displayConfigurations.empty()); + for (const auto& config : displayConfigurations) { + if (config.vrrConfig && config.vrrConfig->notifyExpectedPresentConfig) { + const auto [vsyncPeriodStatus, oldVsyncPeriod] = + mComposerClient->getDisplayVsyncPeriod(displayId); + ASSERT_TRUE(vsyncPeriodStatus.isOk()); + const auto& [timelineStatus, timeline] = + mComposerClient->setActiveConfigWithConstraints( + &display, config.configId, + VsyncPeriodChangeConstraints{.seamlessRequired = false}); + ASSERT_TRUE(timelineStatus.isOk()); + if (timeline.refreshRequired) { + sendRefreshFrame(display, &timeline); + } + waitForVsyncPeriodChange(displayId, timeline, systemTime(), oldVsyncPeriod, + config.vsyncPeriod); + func(display, config); + } + } + EXPECT_TRUE( + mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::OFF).isOk()); + } + } + void configureLayer(const VtsDisplay& display, int64_t layer, Composition composition, const Rect& displayFrame, const FRect& cropRect) { auto& writer = getWriter(display.getDisplayId()); @@ -2592,7 +2617,7 @@ TEST_P(GraphicsComposerAidlCommandTest, SetIdleTimerEnabled_Timeout_2) { const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); ASSERT_NE(nullptr, buffer->handle); - const auto layer = createOnScreenLayer(); + const auto layer = createOnScreenLayer(getPrimaryDisplay()); auto& writer = getWriter(getPrimaryDisplayId()); writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer->handle, /*acquireFence*/ -1); @@ -2778,8 +2803,8 @@ TEST_P(GraphicsComposerAidlCommandV2Test, } // Send the REFRESH_RATE_INDICATOR update - ASSERT_NO_FATAL_FAILURE( - sendBufferUpdate(createOnScreenLayer(Composition::REFRESH_RATE_INDICATOR))); + ASSERT_NO_FATAL_FAILURE(sendBufferUpdate( + createOnScreenLayer(getPrimaryDisplay(), Composition::REFRESH_RATE_INDICATOR))); std::this_thread::sleep_for(1s); EXPECT_FALSE(checkIfCallbackRefreshRateChangedDebugEnabledReceived(displayFilter)) << "A callback should not be received for REFRESH_RATE_INDICATOR"; @@ -3075,6 +3100,141 @@ TEST_P(GraphicsComposerAidlCommandV3Test, NoCreateDestroyBatchedCommandIncorrect ASSERT_TRUE(errors.size() == 1 && errors[0].errorCode == IComposerClient::EX_BAD_LAYER); } +TEST_P(GraphicsComposerAidlCommandV3Test, notifyExpectedPresentTimeout) { + if (hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + GTEST_SUCCEED() << "Device has unreliable present fences capability, skipping"; + return; + } + forEachNotifyExpectedPresentConfig([&](VtsDisplay& display, + const DisplayConfiguration& config) { + const auto displayId = display.getDisplayId(); + auto minFrameIntervalNs = config.vrrConfig->minFrameIntervalNs; + const auto timeoutNs = config.vrrConfig->notifyExpectedPresentConfig->timeoutNs; + + const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); + ASSERT_NE(nullptr, buffer); + const auto layer = createOnScreenLayer(display); + auto& writer = getWriter(displayId); + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle, + /*acquireFence*/ -1); + sp<::android::Fence> presentFence = presentAndGetFence(ComposerClientWriter::kNoTimestamp, + displayId, minFrameIntervalNs); + presentFence->waitForever(LOG_TAG); + auto lastPresentTimeNs = presentFence->getSignalTime(); + + // Frame presents 30ms after timeout + const auto timeout = static_cast(timeoutNs); + const auto vsyncPeriod = config.vsyncPeriod; + int32_t frameAfterTimeoutNs = + vsyncPeriod * static_cast((timeout + 30ms).count() / vsyncPeriod); + auto expectedPresentTimestamp = + ClockMonotonicTimestamp{lastPresentTimeNs + frameAfterTimeoutNs}; + std::this_thread::sleep_for(timeout); + mComposerClient->notifyExpectedPresent(displayId, expectedPresentTimestamp, + minFrameIntervalNs); + presentFence = presentAndGetFence(expectedPresentTimestamp, displayId, minFrameIntervalNs); + presentFence->waitForever(LOG_TAG); + lastPresentTimeNs = presentFence->getSignalTime(); + ASSERT_GE(lastPresentTimeNs, expectedPresentTimestamp.timestampNanos - vsyncPeriod / 2); + mComposerClient->destroyLayer(displayId, layer, &writer); + }); +} + +TEST_P(GraphicsComposerAidlCommandV3Test, notifyExpectedPresentFrameIntervalChange) { + if (hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + GTEST_SUCCEED() << "Device has unreliable present fences capability, skipping"; + return; + } + forEachNotifyExpectedPresentConfig([&](VtsDisplay& display, + const DisplayConfiguration& config) { + const auto displayId = display.getDisplayId(); + const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); + ASSERT_NE(nullptr, buffer); + const auto layer = createOnScreenLayer(display); + auto& writer = getWriter(displayId); + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle, + /*acquireFence*/ -1); + auto minFrameIntervalNs = config.vrrConfig->minFrameIntervalNs; + sp<::android::Fence> presentFence = presentAndGetFence(ComposerClientWriter::kNoTimestamp, + displayId, minFrameIntervalNs); + presentFence->waitForever(LOG_TAG); + auto lastPresentTimeNs = presentFence->getSignalTime(); + + auto vsyncPeriod = config.vsyncPeriod; + int32_t highestDivisor = VtsComposerClient::kMaxFrameIntervalNs / vsyncPeriod; + int32_t lowestDivisor = minFrameIntervalNs / vsyncPeriod; + const auto headsUpNs = config.vrrConfig->notifyExpectedPresentConfig->headsUpNs; + float totalDivisorsPassed = 0.f; + for (int divisor = lowestDivisor; divisor <= highestDivisor; divisor++) { + const auto frameIntervalNs = vsyncPeriod * divisor; + const auto frameAfterHeadsUp = frameIntervalNs * (headsUpNs / frameIntervalNs); + auto presentTime = lastPresentTimeNs + frameIntervalNs + frameAfterHeadsUp; + const auto expectedPresentTimestamp = ClockMonotonicTimestamp{presentTime}; + ASSERT_TRUE(mComposerClient + ->notifyExpectedPresent(displayId, expectedPresentTimestamp, + frameIntervalNs) + .isOk()); + presentFence = presentAndGetFence(expectedPresentTimestamp, displayId, frameIntervalNs); + presentFence->waitForever(LOG_TAG); + lastPresentTimeNs = presentFence->getSignalTime(); + if (lastPresentTimeNs >= expectedPresentTimestamp.timestampNanos - vsyncPeriod / 2) { + ++totalDivisorsPassed; + } + } + EXPECT_TRUE(totalDivisorsPassed > + (static_cast(highestDivisor - lowestDivisor)) * 0.75f); + mComposerClient->destroyLayer(displayId, layer, &writer); + }); +} + +TEST_P(GraphicsComposerAidlCommandV3Test, frameIntervalChangeAtPresentFrame) { + if (hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + GTEST_SUCCEED() << "Device has unreliable present fences capability, skipping"; + return; + } + forEachNotifyExpectedPresentConfig([&](VtsDisplay& display, + const DisplayConfiguration& config) { + const auto displayId = display.getDisplayId(); + const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888); + ASSERT_NE(nullptr, buffer); + const auto layer = createOnScreenLayer(display); + auto& writer = getWriter(displayId); + writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle, + /*acquireFence*/ -1); + auto minFrameIntervalNs = config.vrrConfig->minFrameIntervalNs; + + auto vsyncPeriod = config.vsyncPeriod; + int32_t highestDivisor = VtsComposerClient::kMaxFrameIntervalNs / vsyncPeriod; + int32_t lowestDivisor = minFrameIntervalNs / vsyncPeriod; + const auto headsUpNs = config.vrrConfig->notifyExpectedPresentConfig->headsUpNs; + float totalDivisorsPassed = 0.f; + int divisor = lowestDivisor; + auto frameIntervalNs = vsyncPeriod * divisor; + sp<::android::Fence> presentFence = + presentAndGetFence(ComposerClientWriter::kNoTimestamp, displayId, frameIntervalNs); + presentFence->waitForever(LOG_TAG); + auto lastPresentTimeNs = presentFence->getSignalTime(); + do { + frameIntervalNs = vsyncPeriod * divisor; + ++divisor; + const auto nextFrameIntervalNs = vsyncPeriod * divisor; + const auto frameAfterHeadsUp = frameIntervalNs * (headsUpNs / frameIntervalNs); + auto presentTime = lastPresentTimeNs + frameIntervalNs + frameAfterHeadsUp; + const auto expectedPresentTimestamp = ClockMonotonicTimestamp{presentTime}; + presentFence = + presentAndGetFence(expectedPresentTimestamp, displayId, nextFrameIntervalNs); + presentFence->waitForever(LOG_TAG); + lastPresentTimeNs = presentFence->getSignalTime(); + if (lastPresentTimeNs >= expectedPresentTimestamp.timestampNanos - vsyncPeriod / 2) { + ++totalDivisorsPassed; + } + } while (divisor < highestDivisor); + EXPECT_TRUE(totalDivisorsPassed > + (static_cast(highestDivisor - lowestDivisor)) * 0.75f); + mComposerClient->destroyLayer(displayId, layer, &writer); + }); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerAidlCommandTest,