Merge "composer: add API to control display idle timer"

This commit is contained in:
TreeHugger Robot
2022-01-26 03:04:51 +00:00
committed by Android (Google) Code Review
9 changed files with 144 additions and 1 deletions

View File

@@ -42,4 +42,5 @@ enum DisplayCapability {
AUTO_LOW_LATENCY_MODE = 5,
SUSPEND = 6,
DISPLAY_DECORATION = 7,
DISPLAY_IDLE_TIMER = 8,
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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,
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -1394,6 +1394,14 @@ class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
return layer;
}
bool hasDisplayCapability(int64_t display, DisplayCapability cap) {
std::vector<DisplayCapability> 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) {
@@ -2165,6 +2173,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,

View File

@@ -16,6 +16,7 @@
#include "include/GraphicsComposerCallback.h"
#include <log/log_main.h>
#include <utils/Timers.h>
#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<VsyncPeriodChangeTimeline>
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

View File

@@ -45,6 +45,10 @@ class GraphicsComposerCallback : public BnComposerCallback {
int32_t getInvalidSeamlessPossibleCount() const;
int32_t getVsyncIdleCount() const;
int64_t getVsyncIdleTime() const;
std::optional<VsyncPeriodChangeTimeline> 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<VsyncPeriodChangeTimeline> 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
} // namespace aidl::android::hardware::graphics::composer3::vts