Add controls for ALLM and Content Types to composer hal

Also extending the passthrough interface with setLowLatencyMode
and setContentType.

Bug:132731049

Test: make -j$(nproc)
Test: vts-tradefed run vts-hal --skip-device-info -m
VtsHalGraphicsComposerV2_4Target

Change-Id: I0ec5a5be796700074bdd8cac75cd67f96cd5df58
This commit is contained in:
Galia Peycheva 2019-11-01 11:04:42 +01:00
parent 977c50bc91
commit 2bd7d43325
7 changed files with 301 additions and 0 deletions

View file

@ -48,6 +48,12 @@ interface IComposerClient extends @2.3::IComposerClient {
* with protected buffers.
*/
PROTECTED_CONTENTS = 4,
/**
* Indicates that both the composer HAL implementation and the given display
* support a low latency mode, such as HDMI 2.1 Auto Low Latency Mode.
*/
AUTO_LOW_LATENCY_MODE = 5,
};
/**
@ -64,6 +70,18 @@ interface IComposerClient extends @2.3::IComposerClient {
EXTERNAL = 1,
};
enum ContentType : uint32_t {
NONE = 0,
/**
* These modes correspond to those found in the HDMI 1.4 specification.
*/
GRAPHICS = 1,
PHOTO = 2,
CINEMA = 3,
GAME = 4,
};
/**
* Constraints for changing vsync period.
*/
@ -172,4 +190,60 @@ interface IComposerClient extends @2.3::IComposerClient {
setActiveConfigWithConstraints(Display display, Config config,
VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints)
generates (Error error, VsyncPeriodChangeTimeline timeline);
/**
* Requests the display to enable/disable its low latency mode.
*
* If the display is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If
* the display is internally connected and a custom low latency mode is available, that should
* be triggered.
*
* This function should only be called if the display reports support for
* DisplayCapability::AUTO_LOW_LATENCY_MODE from getDisplayCapabilities_2_4.
*
* @return error is NONE upon success. Otherwise,
* BAD_DISPLAY when an invalid display handle was passed in.
* UNSUPPORTED when AUTO_LOW_LATENCY_MODE is not supported by the composer
* implementation or the given display
*/
setAutoLowLatencyMode(Display display, bool on)
generates (Error error);
/**
* Provides a list of all the content types supported by this display (any of
* ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after
* initialization.
*
* Content types are introduced in HDMI 1.4 and supporting them is optional. The
* ContentType::NONE is always supported and will not be returned by this method..
*
* @return error is NONE upon success. Otherwise,
* BAD_DISPLAY when an invalid display handle was passed in.
* @return supportedContentTypes is a list of supported content types.
*/
getSupportedContentTypes(Display display)
generates(Error error, vec<ContentType> supportedContentTypes);
/**
* Instructs the connected display that the content being shown is of the given type - one of
* GRAPHICS, PHOTO, CINEMA, GAME.
*
* Content types are introduced in HDMI 1.4 and supporting them is optional. If they are
* supported, this signal should switch the display to a mode that is optimal for the given
* type of content. See HDMI 1.4 specification for more information.
*
* If the display is internally connected (not through HDMI), and such modes are available,
* this method should trigger them.
*
* This function should only be called if the display reports support for the corresponding
* content type (ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}) from getSupportedContentTypes.
* ContentType::NONE is supported by default and can always be set.
*
* @return error is NONE upon success. Otherwise,
* BAD_DISPLAY when an invalid display handle was passed in.
* UNSUPPORTED when the given content type is not supported by the composer
* implementation or the given display
*/
setContentType(Display display, ContentType type)
generates (Error error);
};

View file

@ -139,6 +139,24 @@ class ComposerClientImpl : public V2_3::hal::detail::ComposerClientImpl<Interfac
return Void();
}
Return<Error> setAutoLowLatencyMode(Display display, bool on) override {
return mHal->setAutoLowLatencyMode(display, on);
}
Return<void> getSupportedContentTypes(
Display display, IComposerClient::getSupportedContentTypes_cb hidl_cb) override {
std::vector<IComposerClient::ContentType> supportedContentTypes;
Error error = mHal->getSupportedContentTypes(display, &supportedContentTypes);
hidl_cb(error, supportedContentTypes);
return Void();
}
Return<Error> setContentType(Display display,
IComposerClient::ContentType contentType) override {
return mHal->setContentType(display, contentType);
}
static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
auto client = std::make_unique<ComposerClientImpl>(hal);
return client->init() ? std::move(client) : nullptr;

View file

@ -67,6 +67,11 @@ class ComposerHal : public V2_3::hal::ComposerHal {
Display display, Config config,
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* timeline) = 0;
virtual Error setAutoLowLatencyMode(Display display, bool on) = 0;
virtual Error getSupportedContentTypes(
Display display,
std::vector<IComposerClient::ContentType>* outSupportedContentTypes) = 0;
virtual Error setContentType(Display display, IComposerClient::ContentType contentType) = 0;
};
} // namespace hal

View file

@ -167,6 +167,57 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
return Error::NONE;
}
Error setAutoLowLatencyMode(Display display, bool on) override {
if (!mDispatch.setAutoLowLatencyMode) {
return Error::UNSUPPORTED;
}
int32_t error = mDispatch.setAutoLowLatencyMode(mDevice, display, on);
if (error != HWC2_ERROR_NONE) {
return static_cast<Error>(error);
}
return Error::NONE;
}
Error getSupportedContentTypes(
Display display,
std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override {
if (!mDispatch.getSupportedContentTypes) {
return Error::UNSUPPORTED;
}
uint32_t count = 0;
int32_t error = mDispatch.getSupportedContentTypes(mDevice, display, &count, nullptr);
if (error != HWC2_ERROR_NONE) {
return static_cast<Error>(error);
}
outSupportedContentTypes->resize(count);
error = mDispatch.getSupportedContentTypes(
mDevice, display, &count,
reinterpret_cast<std::underlying_type<IComposerClient::ContentType>::type*>(
outSupportedContentTypes->data()));
if (error != HWC2_ERROR_NONE) {
*outSupportedContentTypes = std::vector<IComposerClient::ContentType>();
return static_cast<Error>(error);
}
return Error::NONE;
}
Error setContentType(Display display, IComposerClient::ContentType contentType) override {
if (!mDispatch.setContentType) {
return Error::UNSUPPORTED;
}
int32_t error =
mDispatch.setContentType(mDevice, display, static_cast<int32_t>(contentType));
if (error != HWC2_ERROR_NONE) {
return static_cast<Error>(error);
}
return Error::NONE;
}
protected:
bool initDispatch() override {
if (!BaseType2_3::initDispatch()) {
@ -179,6 +230,11 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
&mDispatch.getDisplayVsyncPeriod);
this->initOptionalDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
&mDispatch.setActiveConfigWithConstraints);
this->initOptionalDispatch(HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE,
&mDispatch.setAutoLowLatencyMode);
this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
&mDispatch.getSupportedContentTypes);
this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType);
return true;
}
@ -222,6 +278,9 @@ class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType;
HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod;
HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints;
HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE setAutoLowLatencyMode;
HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes;
HWC2_PFN_SET_CONTENT_TYPE setContentType;
} mDispatch = {};
hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr;

View file

@ -106,6 +106,25 @@ Error ComposerClient::setActiveConfigWithConstraints(
return error;
}
Error ComposerClient::setAutoLowLatencyMode(Display display, bool on) {
return mClient->setAutoLowLatencyMode(display, on);
}
Error ComposerClient::getSupportedContentTypes(
Display display, std::vector<IComposerClient::ContentType>* outSupportedContentTypes) {
Error error = Error::NONE;
mClient->getSupportedContentTypes(
display, [&](const auto& tmpError, const auto& tmpSupportedContentTypes) {
error = tmpError;
*outSupportedContentTypes = tmpSupportedContentTypes;
});
return error;
}
Error ComposerClient::setContentType(Display display, IComposerClient::ContentType contentType) {
return mClient->setContentType(display, contentType);
}
} // namespace vts
} // namespace V2_4
} // namespace composer

View file

@ -84,6 +84,13 @@ class ComposerClient : public V2_3::vts::ComposerClient {
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* timeline);
Error setAutoLowLatencyMode(Display display, bool on);
Error getSupportedContentTypes(
Display display, std::vector<IComposerClient::ContentType>* outSupportedContentTypes);
Error setContentType(Display display, IComposerClient::ContentType contentType);
private:
const sp<IComposerClient> mClient;
};

View file

@ -47,6 +47,9 @@ using common::V1_2::PixelFormat;
using mapper::V2_0::IMapper;
using mapper::V2_0::vts::Gralloc;
using ContentType = IComposerClient::ContentType;
using DisplayCapability = IComposerClient::DisplayCapability;
class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
protected:
void SetUp() override {
@ -117,6 +120,11 @@ class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
void Test_setActiveConfigWithConstraints(
const IComposerClient::VsyncPeriodChangeConstraints& constraints);
void Test_setContentType(const ContentType& contentType, const char* contentTypeStr);
void Test_setContentTypeForDisplay(const Display& display,
const std::vector<ContentType>& capabilities,
const ContentType& contentType, const char* contentTypeStr);
std::unique_ptr<Composer> mComposer;
std::unique_ptr<ComposerClient> mComposerClient;
sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
@ -377,6 +385,117 @@ TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_delayed) {
Test_setActiveConfigWithConstraints(constraints);
}
TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) {
EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true));
EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, false));
}
TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyMode) {
for (Display display : mComposerCallback->getDisplays()) {
std::vector<DisplayCapability> capabilities;
const auto error = mComposerClient->getDisplayCapabilities(display, &capabilities);
EXPECT_EQ(Error::NONE, error);
const bool allmSupport =
std::find(capabilities.begin(), capabilities.end(),
DisplayCapability::AUTO_LOW_LATENCY_MODE) != capabilities.end();
if (!allmSupport) {
EXPECT_EQ(Error::UNSUPPORTED,
mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true));
EXPECT_EQ(Error::UNSUPPORTED,
mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false));
GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display "
<< to_string(display) << ", skipping test";
return;
}
EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true));
EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false));
}
}
TEST_P(GraphicsComposerHidlTest, getSupportedContentTypesBadDisplay) {
std::vector<ContentType> supportedContentTypes;
const auto error =
mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes);
EXPECT_EQ(Error::BAD_DISPLAY, error);
}
TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) {
std::vector<ContentType> supportedContentTypes;
for (Display display : mComposerCallback->getDisplays()) {
supportedContentTypes.clear();
const auto error =
mComposerClient->getSupportedContentTypes(display, &supportedContentTypes);
const bool noneSupported =
std::find(supportedContentTypes.begin(), supportedContentTypes.end(),
ContentType::NONE) != supportedContentTypes.end();
EXPECT_EQ(Error::NONE, error);
EXPECT_FALSE(noneSupported);
}
}
TEST_P(GraphicsComposerHidlTest, setContentTypeNoneAlwaysAccepted) {
for (Display display : mComposerCallback->getDisplays()) {
const auto error = mComposerClient->setContentType(display, ContentType::NONE);
EXPECT_NE(Error::UNSUPPORTED, error);
}
}
TEST_P(GraphicsComposerHidlTest, setContentTypeBadDisplay) {
const auto types = {ContentType::NONE, ContentType::GRAPHICS, ContentType::PHOTO,
ContentType::CINEMA, ContentType::GAME};
for (auto type : types) {
EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setContentType(mInvalidDisplayId, type));
}
}
void GraphicsComposerHidlTest::Test_setContentTypeForDisplay(
const Display& display, const std::vector<ContentType>& capabilities,
const ContentType& contentType, const char* contentTypeStr) {
const bool contentTypeSupport =
std::find(capabilities.begin(), capabilities.end(), contentType) != capabilities.end();
if (!contentTypeSupport) {
EXPECT_EQ(Error::UNSUPPORTED, mComposerClient->setContentType(display, contentType));
GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
<< to_string(display) << ", skipping test";
return;
}
EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, contentType));
EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, ContentType::NONE));
}
void GraphicsComposerHidlTest::Test_setContentType(const ContentType& contentType,
const char* contentTypeStr) {
for (Display display : mComposerCallback->getDisplays()) {
std::vector<ContentType> supportedContentTypes;
const auto error =
mComposerClient->getSupportedContentTypes(display, &supportedContentTypes);
EXPECT_EQ(Error::NONE, error);
Test_setContentTypeForDisplay(display, supportedContentTypes, contentType, contentTypeStr);
}
}
TEST_P(GraphicsComposerHidlTest, setGraphicsContentType) {
Test_setContentType(ContentType::GRAPHICS, "GRAPHICS");
}
TEST_P(GraphicsComposerHidlTest, setPhotoContentType) {
Test_setContentType(ContentType::PHOTO, "PHOTO");
}
TEST_P(GraphicsComposerHidlTest, setCinemaContentType) {
Test_setContentType(ContentType::CINEMA, "CINEMA");
}
TEST_P(GraphicsComposerHidlTest, setGameContentType) {
Test_setContentType(ContentType::GAME, "GAME");
}
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),