Merge changes from topic "HWC3-V3" into main

* changes:
  [Composer VTS] Adds VTS for getDisplayConfigurations
  Upgrade Composer interface version
  [Composer-HAL-AIDL] Interface changes with getDisplayConfigurations
This commit is contained in:
Ram Indani
2023-07-15 03:51:04 +00:00
committed by Android (Google) Code Review
10 changed files with 337 additions and 52 deletions

View File

@@ -248,7 +248,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.graphics.composer3</name>
<version>2</version>
<version>3</version>
<interface>
<name>IComposer</name>
<instance>default</instance>

View File

@@ -53,13 +53,13 @@ cc_defaults {
cc_defaults {
name: "android.hardware.graphics.composer3-ndk_static",
static_libs: [
"android.hardware.graphics.composer3-V2-ndk",
"android.hardware.graphics.composer3-V3-ndk",
],
}
cc_defaults {
name: "android.hardware.graphics.composer3-ndk_shared",
shared_libs: [
"android.hardware.graphics.composer3-V2-ndk",
"android.hardware.graphics.composer3-V3-ndk",
],
}

View File

@@ -31,7 +31,7 @@ aidl_interface {
enabled: true,
support_system_process: true,
},
frozen: true,
frozen: false,
vndk_use_version: "1",
srcs: [
"android/hardware/graphics/composer3/*.aidl",

View File

@@ -0,0 +1,47 @@
/**
* Copyright 2023, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
// two cases:
// 1). this is a frozen version file - do not edit this in any case.
// 2). this is a 'current' file. If you make a backwards compatible change to
// the interface (from the latest frozen version), the build system will
// prompt you to update this file with `m <name>-update-api`.
//
// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.graphics.composer3;
@VintfStability
parcelable DisplayConfiguration {
int configId;
int width;
int height;
@nullable android.hardware.graphics.composer3.DisplayConfiguration.Dpi dpi;
int configGroup;
int vsyncPeriod;
parcelable Dpi {
float x;
float y;
}
}

View File

@@ -44,6 +44,9 @@ interface IComposerClient {
float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
android.hardware.graphics.composer3.DisplayCapability[] getDisplayCapabilities(long display);
/**
* @deprecated use getDisplayConfigurations instead. For legacy support getDisplayConfigs should return at least one valid config. All the configs returned from the getDisplayConfigs should also be returned from getDisplayConfigurations.
*/
int[] getDisplayConfigs(long display);
android.hardware.graphics.composer3.DisplayConnectionType getDisplayConnectionType(long display);
android.hardware.graphics.composer3.DisplayIdentification getDisplayIdentificationData(long display);
@@ -79,6 +82,7 @@ interface IComposerClient {
android.hardware.graphics.common.HdrConversionCapability[] getHdrConversionCapabilities();
android.hardware.graphics.common.Hdr setHdrConversionStrategy(in android.hardware.graphics.common.HdrConversionStrategy conversionStrategy);
void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled);
android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display);
const int EX_BAD_CONFIG = 1;
const int EX_BAD_DISPLAY = 2;
const int EX_BAD_LAYER = 3;

View File

@@ -0,0 +1,63 @@
/**
* Copyright 2023, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.graphics.composer3;
@VintfStability
parcelable DisplayConfiguration {
/**
* The config id, to be used with IComposerClient.setActiveConfig.
*/
int configId;
/**
* Dimensions in pixels
*/
int width;
int height;
/**
* Dots per thousand inches.
* If the DPI for a configuration is unavailable or is
* considered unreliable, the device may set null instead.
*/
parcelable Dpi {
float x;
float y;
}
@nullable Dpi dpi;
/**
* The configuration group ID this config is associated to.
* Switching between configurations within the same group may be
* done seamlessly in some conditions via
* setActiveConfigWithConstraints. Configurations which share the
* same config group are similar in all attributes except for the
* vsync period.
*/
int configGroup;
/**
* Vsync period in nanoseconds. This period represents the internal
* frequency of the display. IComposerCallback.onVsync is expected
* to be called on each vsync event. For non-VRR configurations, a
* frame can be presented on each vsync event.
*
* A present fence, retrieved from CommandResultPayload.presentFence
* must be signaled on a vsync boundary.
*/
int vsyncPeriod;
}

View File

@@ -28,6 +28,7 @@ import android.hardware.graphics.composer3.ContentType;
import android.hardware.graphics.composer3.DisplayAttribute;
import android.hardware.graphics.composer3.DisplayCapability;
import android.hardware.graphics.composer3.DisplayCommand;
import android.hardware.graphics.composer3.DisplayConfiguration;
import android.hardware.graphics.composer3.DisplayConnectionType;
import android.hardware.graphics.composer3.DisplayContentSample;
import android.hardware.graphics.composer3.DisplayContentSamplingAttributes;
@@ -263,15 +264,12 @@ interface IComposerClient {
DisplayCapability[] getDisplayCapabilities(long display);
/**
* Returns handles for all of the valid display configurations on this
* display.
* This should never return INVALID_CONFIGURATION as a valid value.
* @deprecated use getDisplayConfigurations instead.
* For legacy support getDisplayConfigs should return at least one valid config.
* All the configs returned from the getDisplayConfigs should also be returned
* from getDisplayConfigurations.
*
* @param display is the display to query.
*
* @return is an array of configuration handles.
*
* @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
* @see getDisplayConfigurations
*/
int[] getDisplayConfigs(long display);
@@ -864,4 +862,15 @@ interface IComposerClient {
* false when refresh rate callback is disabled.
*/
void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled);
/**
* Returns all of the valid display configurations.
* getDisplayConfigurations is the superset of getDisplayConfigs and
* getDisplayConfigs should return at least one config.
*
* @param display is the display for which the configurations are requested.
*
* @see getDisplayConfigs
*/
DisplayConfiguration[] getDisplayConfigurations(long display);
}

View File

@@ -58,7 +58,7 @@ bool VtsComposerClient::tearDown() {
return verifyComposerCallbackParams() && destroyAllLayers();
}
std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() {
std::pair<ScopedAStatus, int32_t> VtsComposerClient::getInterfaceVersion() const {
int32_t version = 1;
auto status = mComposerClient->getInterfaceVersion(&version);
return {std::move(status), version};
@@ -295,7 +295,24 @@ std::pair<ScopedAStatus, DisplayConnectionType> VtsComposerClient::getDisplayCon
std::pair<ScopedAStatus, std::vector<int32_t>> VtsComposerClient::getDisplayConfigs(
int64_t display) {
std::vector<int32_t> outConfigs;
return {mComposerClient->getDisplayConfigs(display, &outConfigs), outConfigs};
if (!getDisplayConfigurationSupported()) {
return {mComposerClient->getDisplayConfigs(display, &outConfigs), outConfigs};
}
auto [status, configs] = getDisplayConfigurations(display);
if (!status.isOk()) {
return {std::move(status), outConfigs};
}
for (const auto& config : configs) {
outConfigs.emplace_back(config.configId);
}
return {std::move(status), outConfigs};
}
std::pair<ScopedAStatus, std::vector<DisplayConfiguration>>
VtsComposerClient::getDisplayConfigurations(int64_t display) {
std::vector<DisplayConfiguration> outConfigs;
return {mComposerClient->getDisplayConfigurations(display, &outConfigs), outConfigs};
}
std::pair<ScopedAStatus, int32_t> VtsComposerClient::getDisplayVsyncPeriod(int64_t display) {
@@ -439,31 +456,41 @@ std::pair<ScopedAStatus, std::vector<VtsDisplay>> VtsComposerClient::getDisplays
vtsDisplays.reserve(displays.size());
for (int64_t display : displays) {
auto vtsDisplay = VtsDisplay{display};
auto configs = getDisplayConfigs(display);
if (!configs.first.isOk()) {
ALOGE("Unable to get the displays for test, failed to get the configs "
"for display %" PRId64,
display);
return {std::move(configs.first), vtsDisplays};
}
for (int config : configs.second) {
auto status = addDisplayConfig(&vtsDisplay, config);
if (getDisplayConfigurationSupported()) {
auto [status, configs] = getDisplayConfigurations(display);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, failed to add config "
ALOGE("Unable to get the displays for test, failed to get the DisplayConfigs "
"for display %" PRId64,
display);
return {std::move(status), vtsDisplays};
}
addDisplayConfigs(&vtsDisplay, configs);
} else {
auto [status, configs] = getDisplayConfigs(display);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, failed to get the configs "
"for display %" PRId64,
display);
return {std::move(status), vtsDisplays};
}
for (int config : configs) {
status = addDisplayConfigLegacy(&vtsDisplay, config);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, failed to add config "
"for display %" PRId64,
display);
return {std::move(status), vtsDisplays};
}
}
}
auto config = getActiveConfig(display);
if (!config.first.isOk()) {
auto activeConfig = getActiveConfig(display);
if (!activeConfig.first.isOk()) {
ALOGE("Unable to get the displays for test, failed to get active config "
"for display %" PRId64, display);
return {std::move(config.first), vtsDisplays};
"for display %" PRId64,
display);
return {std::move(activeConfig.first), vtsDisplays};
}
auto status = updateDisplayProperties(&vtsDisplay, config.second);
auto status = updateDisplayProperties(&vtsDisplay, activeConfig.second);
if (!status.isOk()) {
ALOGE("Unable to get the displays for test, "
"failed to update the properties "
@@ -480,39 +507,53 @@ std::pair<ScopedAStatus, std::vector<VtsDisplay>> VtsComposerClient::getDisplays
}
}
ScopedAStatus VtsComposerClient::addDisplayConfig(VtsDisplay* vtsDisplay, int32_t config) {
const auto width =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
const auto height =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
void VtsComposerClient::addDisplayConfigs(VtsDisplay* vtsDisplay,
const std::vector<DisplayConfiguration>& configs) {
for (const auto& config : configs) {
vtsDisplay->addDisplayConfig(config.configId, {config.vsyncPeriod, config.configGroup});
}
}
ScopedAStatus VtsComposerClient::addDisplayConfigLegacy(VtsDisplay* vtsDisplay, int32_t config) {
const auto vsyncPeriod =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::VSYNC_PERIOD);
const auto configGroup =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::CONFIG_GROUP);
if (width.first.isOk() && height.first.isOk() && vsyncPeriod.first.isOk() &&
configGroup.first.isOk()) {
if (vsyncPeriod.first.isOk() && configGroup.first.isOk()) {
vtsDisplay->addDisplayConfig(config, {vsyncPeriod.second, configGroup.second});
return ScopedAStatus::ok();
}
LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
<< ", height: " << height.first.isOk() << ", vsync: " << vsyncPeriod.first.isOk()
LOG(ERROR) << "Failed to update display property vsync: " << vsyncPeriod.first.isOk()
<< ", config: " << configGroup.first.isOk();
return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
}
ScopedAStatus VtsComposerClient::updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config) {
const auto width =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
const auto height =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
if (width.first.isOk() && height.first.isOk()) {
vtsDisplay->setDimensions(width.second, height.second);
return ScopedAStatus::ok();
}
if (getDisplayConfigurationSupported()) {
auto [status, configs] = getDisplayConfigurations(vtsDisplay->getDisplayId());
if (status.isOk()) {
for (const auto& displayConfig : configs) {
if (displayConfig.configId == config) {
vtsDisplay->setDimensions(displayConfig.width, displayConfig.height);
return ScopedAStatus::ok();
}
}
}
LOG(ERROR) << "Failed to update display property with DisplayConfig";
} else {
const auto width =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::WIDTH);
const auto height =
getDisplayAttribute(vtsDisplay->getDisplayId(), config, DisplayAttribute::HEIGHT);
if (width.first.isOk() && height.first.isOk()) {
vtsDisplay->setDimensions(width.second, height.second);
return ScopedAStatus::ok();
}
LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
<< ", height: " << height.first.isOk();
LOG(ERROR) << "Failed to update display property for width: " << width.first.isOk()
<< ", height: " << height.first.isOk();
}
return ScopedAStatus::fromServiceSpecificError(IComposerClient::EX_BAD_CONFIG);
}
@@ -576,6 +617,13 @@ bool VtsComposerClient::verifyComposerCallbackParams() {
return isValid;
}
bool VtsComposerClient::getDisplayConfigurationSupported() const {
auto [status, interfaceVersion] = getInterfaceVersion();
EXPECT_TRUE(status.isOk());
// getDisplayConfigurations api is supported starting interface version 3
return interfaceVersion >= 3;
}
bool VtsComposerClient::destroyAllLayers() {
std::unordered_map<int64_t, DisplayResource> physicalDisplays;
while (!mDisplayResources.empty()) {

View File

@@ -61,7 +61,7 @@ class VtsComposerClient {
bool tearDown();
std::pair<ScopedAStatus, int32_t> getInterfaceVersion();
std::pair<ScopedAStatus, int32_t> getInterfaceVersion() const;
std::pair<ScopedAStatus, VirtualDisplay> createVirtualDisplay(int32_t width, int32_t height,
PixelFormat pixelFormat,
@@ -142,6 +142,9 @@ class VtsComposerClient {
std::pair<ScopedAStatus, std::vector<int32_t>> getDisplayConfigs(int64_t display);
std::pair<ScopedAStatus, std::vector<DisplayConfiguration>> getDisplayConfigurations(
int64_t display);
std::pair<ScopedAStatus, int32_t> getDisplayVsyncPeriod(int64_t display);
ScopedAStatus setAutoLowLatencyMode(int64_t display, bool isEnabled);
@@ -190,7 +193,9 @@ class VtsComposerClient {
std::vector<RefreshRateChangedDebugData> takeListOfRefreshRateChangedDebugData();
private:
ScopedAStatus addDisplayConfig(VtsDisplay* vtsDisplay, int32_t config);
void addDisplayConfigs(VtsDisplay*, const std::vector<DisplayConfiguration>&);
ScopedAStatus addDisplayConfigLegacy(VtsDisplay*, int32_t config);
bool getDisplayConfigurationSupported() const;
ScopedAStatus updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config);
ScopedAStatus addDisplayToDisplayResources(int64_t display, bool isVirtual);

View File

@@ -1208,6 +1208,110 @@ TEST_P(GraphicsComposerAidlV2Test, GetOverlaySupport) {
}
}
class GraphicsComposerAidlV3Test : public GraphicsComposerAidlTest {
protected:
void SetUp() override {
GraphicsComposerAidlTest::SetUp();
if (getInterfaceVersion() <= 2) {
GTEST_SKIP() << "Device interface version is expected to be >= 3";
}
}
};
TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigurations) {
for (const auto& display : mDisplays) {
const auto& [status, displayConfigurations] =
mComposerClient->getDisplayConfigurations(display.getDisplayId());
EXPECT_TRUE(status.isOk());
EXPECT_FALSE(displayConfigurations.empty());
for (const auto& displayConfig : displayConfigurations) {
EXPECT_NE(-1, displayConfig.width);
EXPECT_NE(-1, displayConfig.height);
EXPECT_NE(-1, displayConfig.vsyncPeriod);
EXPECT_NE(-1, displayConfig.configGroup);
if (displayConfig.dpi) {
EXPECT_NE(-1, displayConfig.dpi->x);
EXPECT_NE(-1, displayConfig.dpi->y);
}
}
}
}
TEST_P(GraphicsComposerAidlV3Test, GetDisplayConfigsIsSubsetOfGetDisplayConfigurations) {
for (const auto& display : mDisplays) {
const auto& [status, displayConfigurations] =
mComposerClient->getDisplayConfigurations(display.getDisplayId());
EXPECT_TRUE(status.isOk());
const auto& [legacyConfigStatus, legacyConfigs] =
mComposerClient->getDisplayConfigs(display.getDisplayId());
EXPECT_TRUE(legacyConfigStatus.isOk());
EXPECT_FALSE(legacyConfigs.empty());
EXPECT_TRUE(legacyConfigs.size() <= displayConfigurations.size());
for (const auto legacyConfigId : legacyConfigs) {
const auto& legacyWidth = mComposerClient->getDisplayAttribute(
display.getDisplayId(), legacyConfigId, DisplayAttribute::WIDTH);
const auto& legacyHeight = mComposerClient->getDisplayAttribute(
display.getDisplayId(), legacyConfigId, DisplayAttribute::HEIGHT);
const auto& legacyVsyncPeriod = mComposerClient->getDisplayAttribute(
display.getDisplayId(), legacyConfigId, DisplayAttribute::VSYNC_PERIOD);
const auto& legacyConfigGroup = mComposerClient->getDisplayAttribute(
display.getDisplayId(), legacyConfigId, DisplayAttribute::CONFIG_GROUP);
const auto& legacyDpiX = mComposerClient->getDisplayAttribute(
display.getDisplayId(), legacyConfigId, DisplayAttribute::DPI_X);
const auto& legacyDpiY = mComposerClient->getDisplayAttribute(
display.getDisplayId(), legacyConfigId, DisplayAttribute::DPI_Y);
EXPECT_TRUE(legacyWidth.first.isOk() && legacyHeight.first.isOk() &&
legacyVsyncPeriod.first.isOk() && legacyConfigGroup.first.isOk());
EXPECT_TRUE(std::any_of(
displayConfigurations.begin(), displayConfigurations.end(),
[&](const auto& displayConfiguration) {
const bool requiredAttributesPredicate =
displayConfiguration.configId == legacyConfigId &&
displayConfiguration.width == legacyWidth.second &&
displayConfiguration.height == legacyHeight.second &&
displayConfiguration.vsyncPeriod == legacyVsyncPeriod.second &&
displayConfiguration.configGroup == legacyConfigGroup.second;
if (!requiredAttributesPredicate) {
// Required attributes did not match
return false;
}
// Check optional attributes
const auto& [legacyDpiXStatus, legacyDpiXValue] = legacyDpiX;
const auto& [legacyDpiYStatus, legacyDpiYValue] = legacyDpiY;
if (displayConfiguration.dpi) {
if (!legacyDpiXStatus.isOk() || !legacyDpiYStatus.isOk()) {
// getDisplayAttribute failed for optional attributes
return false;
}
// DPI values in DisplayConfigurations are not scaled (* 1000.f)
// the way they are in the legacy DisplayConfigs.
constexpr float kEpsilon = 0.001f;
return std::abs(displayConfiguration.dpi->x -
legacyDpiXValue / 1000.f) < kEpsilon &&
std::abs(displayConfiguration.dpi->y -
legacyDpiYValue / 1000.f) < kEpsilon;
} else {
return !legacyDpiXStatus.isOk() && !legacyDpiYStatus.isOk() &&
EX_SERVICE_SPECIFIC == legacyDpiXStatus.getExceptionCode() &&
EX_SERVICE_SPECIFIC == legacyDpiYStatus.getExceptionCode() &&
IComposerClient::EX_UNSUPPORTED ==
legacyDpiXStatus.getServiceSpecificError() &&
IComposerClient::EX_UNSUPPORTED ==
legacyDpiYStatus.getServiceSpecificError();
}
}));
}
}
}
// Tests for Command.
class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
protected:
@@ -2641,6 +2745,11 @@ INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerAidlV2Test,
testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
::android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlV3Test);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerAidlV3Test,
testing::ValuesIn(::android::getAidlHalInstanceNames(IComposer::descriptor)),
::android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandV2Test);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerAidlCommandV2Test,