From a0b56bde1100acfe383a3ea11c449516e36087ff Mon Sep 17 00:00:00 2001 From: Midas Chien Date: Thu, 13 Jan 2022 23:27:33 +0800 Subject: [PATCH] composer: add API to control display idle timer Add new functions to control display idle timer - Adding an API to r configure display idle timer. - Extend DisplayCapability to query display support idle timer. - Adding an callback for notify client the display is idle, the refresh rate changed to a lower setting to preserve power and vsync cadence changed. The client can enable vsync callback to learn the new vsync cadence before sending a new frame. Bug: 194068871 Bug: 198808492 Test: build, vts Change-Id: I47649d222022922926a05f2d700ca798f8f48b35 --- .../graphics/composer3/DisplayCapability.aidl | 1 + .../graphics/composer3/IComposerCallback.aidl | 1 + .../graphics/composer3/IComposerClient.aidl | 1 + .../graphics/composer3/DisplayCapability.aidl | 5 ++ .../graphics/composer3/IComposerCallback.aidl | 10 +++ .../graphics/composer3/IComposerClient.aidl | 21 +++++ .../VtsHalGraphicsComposer3_TargetTest.cpp | 76 +++++++++++++++++++ .../composer-vts/GraphicsComposerCallback.cpp | 20 +++++ .../include/GraphicsComposerCallback.h | 10 ++- 9 files changed, 144 insertions(+), 1 deletion(-) diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl index fdf110032d..b41ac8a78a 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl @@ -42,4 +42,5 @@ enum DisplayCapability { AUTO_LOW_LATENCY_MODE = 5, SUSPEND = 6, DISPLAY_DECORATION = 7, + DISPLAY_IDLE_TIMER = 8, } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl index f82d02eeed..21620e7f31 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl @@ -39,4 +39,5 @@ interface IComposerCallback { oneway void onSeamlessPossible(long display); oneway void onVsync(long display, long timestamp, int vsyncPeriodNanos); oneway void onVsyncPeriodTimingChanged(long display, in android.hardware.graphics.composer3.VsyncPeriodChangeTimeline updatedTimeline); + oneway void onVsyncIdle(long display); } diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl index 5593c57069..2de699b94a 100644 --- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl +++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl @@ -73,6 +73,7 @@ interface IComposerClient { void setPowerMode(long display, android.hardware.graphics.composer3.PowerMode mode); void setReadbackBuffer(long display, in android.hardware.common.NativeHandle buffer, in @nullable ParcelFileDescriptor releaseFence); void setVsyncEnabled(long display, boolean enabled); + void setIdleTimerEnabled(long display, int timeoutMs); const int EX_BAD_CONFIG = 1; const int EX_BAD_DISPLAY = 2; const int EX_BAD_LAYER = 3; diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl index 249fed03a0..85136c44d9 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl @@ -79,4 +79,9 @@ enum DisplayCapability { * Indicates that the display supports Composition.DISPLAY_DECORATION. */ DISPLAY_DECORATION = 7, + /** + * Indicates that the display supports IComposerClient.setIdleTimerEnabled and + * IComposerCallback.onVsyncIdle. + */ + DISPLAY_IDLE_TIMER = 8, } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl index ac95b41a38..67954d4cc5 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerCallback.aidl @@ -86,4 +86,14 @@ interface IComposerCallback { */ oneway void onVsyncPeriodTimingChanged( long display, in VsyncPeriodChangeTimeline updatedTimeline); + + /** + * Notifies the client that the display is idle, the refresh rate changed to a lower setting to + * preserve power and vsync cadence changed. When a new frame is queued for presentation, the + * client is expected to enable vsync callbacks to learn the new vsync cadence before sending + * a new frame. + * + * @param display is the display whose vsync cadence changed due to panel idle mode. + */ + oneway void onVsyncIdle(long display); } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl index c86b9bdaec..2fe6656cb5 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl @@ -779,4 +779,25 @@ interface IComposerClient { * @exception EX_BAD_PARAMETER when enabled was an invalid value. */ void setVsyncEnabled(long display, boolean enabled); + + /** + * Enables or disables the idle timer on this display. + * + * Idle timer is used to allow the display to go into a panel idle mode after some + * idle period. + * + * This function should only be called if the display reports support for + * DisplayCapability.DISPLAY_IDLE from getDisplayCapabilities. + * + * @param display is the display to which the idle timer is set. + * @param timeoutMs is the minimum requirements of idle period in milliseconds. Panel + * should not go into the idle state within the minimum requirement after + * idle for a while. 0 means disabled, panel should not go into idle state. + * + * @exception EX_BAD_DISPLAY when an invalid display handle was passed in. + * @exception EX_BAD_PARAMETER when timeout is a negative number. + * @exception EX_UNSUPPORTED when idle is not supported on this display. + * + */ + void setIdleTimerEnabled(long display, int timeoutMs); } diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp index 1cfd3f95bb..1c84674d97 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp @@ -1383,6 +1383,14 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest { return layer; } + bool hasDisplayCapability(int64_t display, DisplayCapability cap) { + std::vector capabilities; + const auto error = mComposerClient->getDisplayCapabilities(display, &capabilities); + EXPECT_TRUE(error.isOk()); + + return std::find(capabilities.begin(), capabilities.end(), cap) != capabilities.end(); + } + void Test_setActiveConfigWithConstraints(const TestParameters& params) { for (VtsDisplay& display : mDisplays) { forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) { @@ -2134,6 +2142,74 @@ TEST_P(GraphicsComposerAidlCommandTest, expectedPresentTime_5) { ASSERT_NO_FATAL_FAILURE(Test_expectedPresentTime(5)); } +TEST_P(GraphicsComposerAidlCommandTest, setIdleTimerEnabled_Unsupported) { + const bool hasDisplayIdleTimerSupport = hasDisplayCapability(mPrimaryDisplay, + DisplayCapability::DISPLAY_IDLE_TIMER); + if (!hasDisplayIdleTimerSupport) { + const auto error = mComposerClient->setIdleTimerEnabled(mPrimaryDisplay, 0); + EXPECT_FALSE(error.isOk()); + EXPECT_EQ(IComposerClient::EX_UNSUPPORTED, error.getServiceSpecificError()); + } +} + +TEST_P(GraphicsComposerAidlCommandTest, setIdleTimerEnabled_BadParameter) { + const bool hasDisplayIdleTimerSupport = hasDisplayCapability(mPrimaryDisplay, + DisplayCapability::DISPLAY_IDLE_TIMER); + if (!hasDisplayIdleTimerSupport) { + GTEST_SUCCEED() << "DisplayCapability::DISPLAY_IDLE_TIMER is not supported"; + return; + } + + const auto error = mComposerClient->setIdleTimerEnabled(mPrimaryDisplay, -1); + EXPECT_FALSE(error.isOk()); + EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, error.getServiceSpecificError()); +} + +TEST_P(GraphicsComposerAidlCommandTest, setIdleTimerEnabled_Disable) { + const bool hasDisplayIdleTimerSupport = hasDisplayCapability(mPrimaryDisplay, + DisplayCapability::DISPLAY_IDLE_TIMER); + if (!hasDisplayIdleTimerSupport) { + GTEST_SUCCEED() << "DisplayCapability::DISPLAY_IDLE_TIMER is not supported"; + return; + } + + EXPECT_TRUE(mComposerClient->setIdleTimerEnabled(mPrimaryDisplay, 0).isOk()); + std::this_thread::sleep_for(1s); + EXPECT_EQ(0, mComposerCallback->getVsyncIdleCount()); +} + +TEST_P(GraphicsComposerAidlCommandTest, setIdleTimerEnabled_Timeout_2) { + const bool hasDisplayIdleTimerSupport = hasDisplayCapability(mPrimaryDisplay, + DisplayCapability::DISPLAY_IDLE_TIMER); + if (!hasDisplayIdleTimerSupport) { + GTEST_SUCCEED() << "DisplayCapability::DISPLAY_IDLE_TIMER is not supported"; + return; + } + + EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON).isOk()); + EXPECT_TRUE(mComposerClient->setIdleTimerEnabled(mPrimaryDisplay, 0).isOk()); + + const auto buffer = allocate(); + ASSERT_NE(nullptr, buffer->handle); + + const auto layer = createOnScreenLayer(); + mWriter.setLayerBuffer(mPrimaryDisplay, layer, 0, buffer->handle, -1); + int32_t vsyncIdleCount = mComposerCallback->getVsyncIdleCount(); + auto earlyVsyncIdleTime = systemTime() + std::chrono::nanoseconds(2s).count(); + EXPECT_TRUE(mComposerClient->setIdleTimerEnabled(mPrimaryDisplay, 2000).isOk()); + + const sp<::android::Fence> presentFence = + presentAndGetFence(ComposerClientWriter::kNoTimestamp); + presentFence->waitForever(LOG_TAG); + + std::this_thread::sleep_for(3s); + if (vsyncIdleCount < mComposerCallback->getVsyncIdleCount()) { + EXPECT_GE(mComposerCallback->getVsyncIdleTime(), earlyVsyncIdleTime); + } + + EXPECT_TRUE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF).isOk()); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest); INSTANTIATE_TEST_SUITE_P( PerInstance, GraphicsComposerAidlCommandTest, diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp index 307fe158d1..22b5d796fc 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/GraphicsComposerCallback.cpp @@ -16,6 +16,7 @@ #include "include/GraphicsComposerCallback.h" #include +#include #pragma push_macro("LOG_TAG") #undef LOG_TAG @@ -58,6 +59,16 @@ int32_t GraphicsComposerCallback::getInvalidSeamlessPossibleCount() const { return mInvalidSeamlessPossibleCount; } +int32_t GraphicsComposerCallback::getVsyncIdleCount() const { + std::scoped_lock lock(mMutex); + return mVsyncIdleCount; +} + +int64_t GraphicsComposerCallback::getVsyncIdleTime() const { + std::scoped_lock lock(mMutex); + return mVsyncIdleTime; +} + std::optional GraphicsComposerCallback::takeLastVsyncPeriodChangeTimeline() { std::scoped_lock lock(mMutex); @@ -125,4 +136,13 @@ GraphicsComposerCallback::takeLastVsyncPeriodChangeTimeline() { return ::ndk::ScopedAStatus::ok(); } +::ndk::ScopedAStatus GraphicsComposerCallback::onVsyncIdle(int64_t in_display) { + std::scoped_lock lock(mMutex); + if (mDisplays.count(in_display)) { + mVsyncIdleCount++; + mVsyncIdleTime = systemTime(); + } + return ::ndk::ScopedAStatus::ok(); +} + } // namespace aidl::android::hardware::graphics::composer3::vts diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h index c359d5eaa2..f25f36d4a4 100644 --- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h +++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/include/GraphicsComposerCallback.h @@ -45,6 +45,10 @@ class GraphicsComposerCallback : public BnComposerCallback { int32_t getInvalidSeamlessPossibleCount() const; + int32_t getVsyncIdleCount() const; + + int64_t getVsyncIdleTime() const; + std::optional takeLastVsyncPeriodChangeTimeline(); private: @@ -57,6 +61,7 @@ class GraphicsComposerCallback : public BnComposerCallback { int64_t in_display, const ::aidl::android::hardware::graphics::composer3::VsyncPeriodChangeTimeline& in_updatedTimeline) override; + virtual ::ndk::ScopedAStatus onVsyncIdle(int64_t in_display) override; mutable std::mutex mMutex; // the set of all currently connected displays @@ -66,6 +71,9 @@ class GraphicsComposerCallback : public BnComposerCallback { std::optional mTimeline GUARDED_BY(mMutex); + int32_t mVsyncIdleCount GUARDED_BY(mMutex) = 0; + int64_t mVsyncIdleTime GUARDED_BY(mMutex) = 0; + // track invalid callbacks int32_t mInvalidHotplugCount GUARDED_BY(mMutex) = 0; int32_t mInvalidRefreshCount GUARDED_BY(mMutex) = 0; @@ -74,4 +82,4 @@ class GraphicsComposerCallback : public BnComposerCallback { int32_t mInvalidSeamlessPossibleCount GUARDED_BY(mMutex) = 0; }; -} // namespace aidl::android::hardware::graphics::composer3::vts \ No newline at end of file +} // namespace aidl::android::hardware::graphics::composer3::vts