Merge "Migrate reader writer based tests for HAL 2.4"

This commit is contained in:
Ram Indani 2021-11-16 16:30:14 +00:00 committed by Android (Google) Code Review
commit 628d6f9335
6 changed files with 612 additions and 20 deletions

View file

@ -32,11 +32,27 @@ cc_test {
srcs: [ srcs: [
"VtsHalGraphicsComposer3_TargetTest.cpp", "VtsHalGraphicsComposer3_TargetTest.cpp",
"composer-vts/GraphicsComposerCallback.cpp", "composer-vts/GraphicsComposerCallback.cpp",
"composer-vts/TestCommandReader.cpp",
], ],
shared_libs: [ shared_libs: [
"libbinder_ndk", "libbinder_ndk",
"libbinder", "libbinder",
"libfmq",
"libbase",
"libsync",
"libui",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
"libvndksupport",
],
header_libs: [
"android.hardware.graphics.composer3-command-buffer",
], ],
static_libs: [ static_libs: [
"android.hardware.graphics.composer3-V1-ndk", "android.hardware.graphics.composer3-V1-ndk",
@ -44,9 +60,19 @@ cc_test {
"android.hardware.graphics.common@1.2", "android.hardware.graphics.common@1.2",
"android.hardware.common-V2-ndk", "android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk", "android.hardware.common.fmq-V1-ndk",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.composer@3-vts", "android.hardware.graphics.composer@3-vts",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1-vts",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0-vts",
"libaidlcommonsupport",
],
cflags: [
"-Wconversion",
], ],
test_suites: [ test_suites: [
"general-tests", "general-tests",
"vts", "vts",

View file

@ -1,13 +1,23 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#include <aidl/Gtest.h> #include <aidl/Gtest.h>
#include <aidl/Vintf.h> #include <aidl/Vintf.h>
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
#include <aidl/android/hardware/graphics/common/FRect.h>
#include <aidl/android/hardware/graphics/common/Rect.h>
#include <aidl/android/hardware/graphics/composer3/BlendMode.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/IComposer.h> #include <aidl/android/hardware/graphics/composer3/IComposer.h>
#include <android-base/properties.h> #include <android-base/properties.h>
#include <android/binder_manager.h> #include <android/binder_manager.h>
#include <android/binder_process.h> #include <android/binder_process.h>
#include <android/hardware/graphics/composer3/command-buffer.h>
#include <binder/ProcessState.h> #include <binder/ProcessState.h>
#include <composer-vts/include/GraphicsComposerCallback.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
#include <regex> #include <regex>
@ -16,8 +26,12 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <utility> #include <utility>
#include "composer-vts/include/GraphicsComposerCallback.h"
#include "composer-vts/include/TestCommandReader.h"
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion
#pragma push_macro("LOG_TAG")
#undef LOG_TAG #undef LOG_TAG
#define LOG_TAG "VtsHalGraphicsComposer3_TargetTest" #define LOG_TAG "VtsHalGraphicsComposer3_TargetTest"
@ -33,6 +47,12 @@ class VtsDisplay {
int64_t get() const { return mDisplayId; } int64_t get() const { return mDisplayId; }
FRect getCrop() const {
return {0, 0, static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)};
}
Rect getFrameRect() const { return {0, 0, mDisplayWidth, mDisplayHeight}; }
void setDimensions(int32_t displayWidth, int32_t displayHeight) { void setDimensions(int32_t displayWidth, int32_t displayHeight) {
mDisplayWidth = displayWidth; mDisplayWidth = displayWidth;
mDisplayHeight = displayHeight; mDisplayHeight = displayHeight;
@ -60,10 +80,30 @@ class GraphicsComposerAidlTest : public ::testing::TestWithParam<std::string> {
// assume the first displays are built-in and are never removed // assume the first displays are built-in and are never removed
mDisplays = waitForDisplays(); mDisplays = waitForDisplays();
// explicitly disable vsync
for (const auto& display : mDisplays) {
EXPECT_TRUE(mComposerClient->setVsyncEnabled(display.get(), false).isOk());
}
mComposerCallback->setVsyncAllowed(false);
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<TestCommandReader>();
} }
// use the slot count usually set by SF void TearDown() override {
static constexpr uint32_t kBufferSlotCount = 64; ASSERT_EQ(0, mReader->mErrors.size());
ASSERT_EQ(0, mReader->mCompositionChanges.size());
if (mComposerCallback != nullptr) {
EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncPeriodChangeCount());
EXPECT_EQ(0, mComposerCallback->getInvalidSeamlessPossibleCount());
}
}
// returns an invalid display id (one that has not been registered to a // returns an invalid display id (one that has not been registered to a
// display. Currently assuming that a device will never have close to // display. Currently assuming that a device will never have close to
@ -168,6 +208,282 @@ class GraphicsComposerAidlTest : public ::testing::TestWithParam<std::string> {
} }
} }
void execute() {
TestCommandReader* reader = mReader.get();
CommandWriterBase* writer = mWriter.get();
bool queueChanged = false;
int32_t commandLength = 0;
std::vector<NativeHandle> commandHandles;
ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
if (queueChanged) {
auto ret = mComposerClient->setInputCommandQueue(writer->getMQDescriptor());
ASSERT_TRUE(ret.isOk());
}
ExecuteCommandsStatus commandStatus;
EXPECT_TRUE(mComposerClient->executeCommands(commandLength, commandHandles, &commandStatus)
.isOk());
if (commandStatus.queueChanged) {
MQDescriptor<int32_t, SynchronizedReadWrite> outputCommandQueue;
ASSERT_TRUE(mComposerClient->getOutputCommandQueue(&outputCommandQueue).isOk());
reader->setMQDescriptor(outputCommandQueue);
}
ASSERT_TRUE(reader->readQueue(commandStatus.length, std::move(commandStatus.handles)));
reader->parse();
reader->reset();
writer->reset();
}
::android::sp<::android::GraphicBuffer> allocate(uint32_t width, uint32_t height) {
::android::sp<::android::GraphicBuffer> buffer =
::android::sp<::android::GraphicBuffer>::make(
width, height, ::android::PIXEL_FORMAT_RGBA_8888,
/*layerCount*/ 1,
static_cast<uint64_t>(
static_cast<int>(common::BufferUsage::CPU_WRITE_OFTEN) |
static_cast<int>(common::BufferUsage::CPU_READ_OFTEN)),
"VtsHalGraphicsComposer3_TargetTest");
return buffer;
}
struct TestParameters {
nsecs_t delayForChange;
bool refreshMiss;
};
static inline auto toTimePoint(nsecs_t time) {
return std::chrono::time_point<std::chrono::steady_clock>(std::chrono::nanoseconds(time));
}
int64_t createLayer(const VtsDisplay& display) {
int64_t layer;
EXPECT_TRUE(mComposerClient->createLayer(display.get(), kBufferSlotCount, &layer).isOk());
auto resourceIt = mDisplayResources.find(display.get());
if (resourceIt == mDisplayResources.end()) {
resourceIt = mDisplayResources.insert({display.get(), DisplayResource(false)}).first;
}
EXPECT_TRUE(resourceIt->second.layers.insert(layer).second)
<< "duplicated layer id " << layer;
return layer;
}
void destroyLayer(const VtsDisplay& display, int64_t layer) {
auto const error = mComposerClient->destroyLayer(display.get(), layer);
ASSERT_TRUE(error.isOk()) << "failed to destroy layer " << layer;
auto resourceIt = mDisplayResources.find(display.get());
ASSERT_NE(mDisplayResources.end(), resourceIt);
resourceIt->second.layers.erase(layer);
}
void forEachTwoConfigs(int64_t display, std::function<void(int32_t, int32_t)> func) {
std::vector<int32_t> displayConfigs;
EXPECT_TRUE(mComposerClient->getDisplayConfigs(display, &displayConfigs).isOk());
for (const int32_t config1 : displayConfigs) {
for (const int32_t config2 : displayConfigs) {
if (config1 != config2) {
func(config1, config2);
}
}
}
}
void setActiveConfig(VtsDisplay& display, int32_t config) {
EXPECT_TRUE(mComposerClient->setActiveConfig(display.get(), config).isOk());
int32_t displayWidth;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config, DisplayAttribute::WIDTH,
&displayWidth)
.isOk());
int32_t displayHeight;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config, DisplayAttribute::HEIGHT,
&displayHeight)
.isOk());
display.setDimensions(displayWidth, displayHeight);
}
void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
if (timeline != nullptr) {
// Refresh time should be before newVsyncAppliedTimeNanos
EXPECT_LT(timeline->refreshTimeNanos, timeline->newVsyncAppliedTimeNanos);
std::this_thread::sleep_until(toTimePoint(timeline->refreshTimeNanos));
}
mWriter->selectDisplay(display.get());
setPowerMode(display.get(), PowerMode::ON);
EXPECT_TRUE(
mComposerClient
->setColorMode(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC)
.isOk());
FRect displayCrop = display.getCrop();
auto displayWidth = static_cast<uint32_t>(std::ceilf(displayCrop.right - displayCrop.left));
auto displayHeight =
static_cast<uint32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
int64_t layer = 0;
ASSERT_NO_FATAL_FAILURE(layer = createLayer(display));
{
auto buffer = allocate(displayWidth, displayHeight);
ASSERT_NE(nullptr, buffer);
ASSERT_EQ(::android::OK, buffer->initCheck());
ASSERT_NE(nullptr, buffer->handle);
mWriter->selectLayer(layer);
mWriter->setLayerCompositionType(Composition::DEVICE);
mWriter->setLayerDisplayFrame(display.getFrameRect());
mWriter->setLayerPlaneAlpha(1);
mWriter->setLayerSourceCrop(display.getCrop());
mWriter->setLayerTransform(static_cast<Transform>(0));
mWriter->setLayerVisibleRegion(std::vector<Rect>(1, display.getFrameRect()));
mWriter->setLayerZOrder(10);
mWriter->setLayerBlendMode(BlendMode::NONE);
mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, display.getFrameRect()));
mWriter->setLayerBuffer(0, buffer->handle, -1);
mWriter->setLayerDataspace(common::Dataspace::UNKNOWN);
mWriter->validateDisplay();
execute();
ASSERT_EQ(0, mReader->mErrors.size());
mReader->mCompositionChanges.clear();
mWriter->presentDisplay();
execute();
ASSERT_EQ(0, mReader->mErrors.size());
}
{
auto buffer = allocate(displayWidth, displayHeight);
ASSERT_NE(nullptr, buffer->handle);
mWriter->selectLayer(layer);
mWriter->setLayerBuffer(0, buffer->handle, -1);
mWriter->setLayerSurfaceDamage(std::vector<Rect>(1, {0, 0, 10, 10}));
mWriter->validateDisplay();
execute();
ASSERT_EQ(0, mReader->mErrors.size());
mReader->mCompositionChanges.clear();
mWriter->presentDisplay();
execute();
}
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
void waitForVsyncPeriodChange(int64_t display, const VsyncPeriodChangeTimeline& timeline,
int64_t desiredTimeNanos, int64_t oldPeriodNanos,
int64_t newPeriodNanos) {
const auto kChangeDeadline = toTimePoint(timeline.newVsyncAppliedTimeNanos) + 100ms;
while (std::chrono::steady_clock::now() <= kChangeDeadline) {
int32_t vsyncPeriodNanos;
EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos).isOk());
if (systemTime() <= desiredTimeNanos) {
EXPECT_EQ(vsyncPeriodNanos, oldPeriodNanos);
} else if (vsyncPeriodNanos == newPeriodNanos) {
break;
}
std::this_thread::sleep_for(std::chrono::nanoseconds(oldPeriodNanos));
}
}
void Test_setActiveConfigWithConstraints(const TestParameters& params) {
for (VtsDisplay& display : mDisplays) {
forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
setActiveConfig(display, config1);
sendRefreshFrame(display, nullptr);
int32_t vsyncPeriod1;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config1,
DisplayAttribute::VSYNC_PERIOD,
&vsyncPeriod1)
.isOk());
int32_t configGroup1;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config1,
DisplayAttribute::CONFIG_GROUP,
&configGroup1)
.isOk());
int32_t vsyncPeriod2;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config2,
DisplayAttribute::VSYNC_PERIOD,
&vsyncPeriod2)
.isOk());
int32_t configGroup2;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config2,
DisplayAttribute::CONFIG_GROUP,
&configGroup2)
.isOk());
if (vsyncPeriod1 == vsyncPeriod2) {
return; // continue
}
// We don't allow delayed change when changing config groups
if (params.delayForChange > 0 && configGroup1 != configGroup2) {
return; // continue
}
VsyncPeriodChangeTimeline timeline;
VsyncPeriodChangeConstraints constraints = {
.desiredTimeNanos = systemTime() + params.delayForChange,
.seamlessRequired = false};
EXPECT_TRUE(setActiveConfigWithConstraints(display, config2, constraints, &timeline)
.isOk());
EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
// Refresh rate should change within a reasonable time
constexpr std::chrono::nanoseconds kReasonableTimeForChange = 1s; // 1 second
EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
kReasonableTimeForChange.count());
if (timeline.refreshRequired) {
if (params.refreshMiss) {
// Miss the refresh frame on purpose to make sure the implementation sends a
// callback
std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) +
100ms);
}
sendRefreshFrame(display, &timeline);
}
waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos,
vsyncPeriod1, vsyncPeriod2);
// At this point the refresh rate should have changed already, however in rare
// cases the implementation might have missed the deadline. In this case a new
// timeline should have been provided.
auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
if (timeline.refreshRequired && params.refreshMiss) {
EXPECT_TRUE(newTimeline.has_value());
}
if (newTimeline.has_value()) {
if (newTimeline->refreshRequired) {
sendRefreshFrame(display, &newTimeline.value());
}
waitForVsyncPeriodChange(display.get(), newTimeline.value(),
constraints.desiredTimeNanos, vsyncPeriod1,
vsyncPeriod2);
}
int32_t vsyncPeriodNanos;
EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
.isOk());
EXPECT_EQ(vsyncPeriodNanos, vsyncPeriod2);
});
}
}
void setPowerMode(int64_t display, PowerMode powerMode) { void setPowerMode(int64_t display, PowerMode powerMode) {
::ndk::ScopedAStatus error = mComposerClient->setPowerMode(display, powerMode); ::ndk::ScopedAStatus error = mComposerClient->setPowerMode(display, powerMode);
ASSERT_TRUE(error.isOk() || ASSERT_TRUE(error.isOk() ||
@ -181,7 +497,7 @@ class GraphicsComposerAidlTest : public ::testing::TestWithParam<std::string> {
DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {} DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
bool isVirtual; bool isVirtual;
std::unordered_set<int32_t> layers; std::unordered_set<int64_t> layers;
}; };
std::shared_ptr<IComposer> mComposer; std::shared_ptr<IComposer> mComposer;
@ -190,6 +506,10 @@ class GraphicsComposerAidlTest : public ::testing::TestWithParam<std::string> {
int64_t mPrimaryDisplay; int64_t mPrimaryDisplay;
std::vector<VtsDisplay> mDisplays; std::vector<VtsDisplay> mDisplays;
std::shared_ptr<GraphicsComposerCallback> mComposerCallback; std::shared_ptr<GraphicsComposerCallback> mComposerCallback;
std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<TestCommandReader> mReader;
// use the slot count usually set by SF
static constexpr uint32_t kBufferSlotCount = 64;
std::unordered_map<int64_t, DisplayResource> mDisplayResources; std::unordered_map<int64_t, DisplayResource> mDisplayResources;
}; };
@ -209,6 +529,94 @@ TEST_P(GraphicsComposerAidlTest, getDisplayCapabilities) {
} }
} }
TEST_P(GraphicsComposerAidlTest, getDisplayVsyncPeriod) {
for (VtsDisplay& display : mDisplays) {
std::vector<int32_t> configs;
EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
for (int32_t config : configs) {
int32_t expectedVsyncPeriodNanos = -1;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config,
DisplayAttribute::VSYNC_PERIOD,
&expectedVsyncPeriodNanos)
.isOk());
VsyncPeriodChangeTimeline timeline;
VsyncPeriodChangeConstraints constraints;
constraints.desiredTimeNanos = systemTime();
constraints.seamlessRequired = false;
EXPECT_TRUE(mComposerClient
->setActiveConfigWithConstraints(display.get(), config, constraints,
&timeline)
.isOk());
if (timeline.refreshRequired) {
sendRefreshFrame(display, &timeline);
}
waitForVsyncPeriodChange(display.get(), timeline, constraints.desiredTimeNanos, 0,
expectedVsyncPeriodNanos);
int32_t vsyncPeriodNanos;
int retryCount = 100;
do {
std::this_thread::sleep_for(10ms);
vsyncPeriodNanos = 0;
EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
.isOk());
--retryCount;
} while (vsyncPeriodNanos != expectedVsyncPeriodNanos && retryCount > 0);
EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
// Make sure that the vsync period stays the same if the active config is not
// changed.
auto timeout = 1ms;
for (int i = 0; i < 10; i++) {
std::this_thread::sleep_for(timeout);
timeout *= 2;
vsyncPeriodNanos = 0;
EXPECT_TRUE(mComposerClient->getDisplayVsyncPeriod(display.get(), &vsyncPeriodNanos)
.isOk());
EXPECT_EQ(vsyncPeriodNanos, expectedVsyncPeriodNanos);
}
}
}
}
TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
VsyncPeriodChangeTimeline timeline;
VsyncPeriodChangeConstraints constraints;
constraints.seamlessRequired = true;
constraints.desiredTimeNanos = systemTime();
for (VtsDisplay& display : mDisplays) {
forEachTwoConfigs(display.get(), [&](int32_t config1, int32_t config2) {
int32_t configGroup1;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config1,
DisplayAttribute::CONFIG_GROUP, &configGroup1)
.isOk());
int32_t configGroup2;
EXPECT_TRUE(mComposerClient
->getDisplayAttribute(display.get(), config2,
DisplayAttribute::CONFIG_GROUP, &configGroup2)
.isOk());
if (configGroup1 != configGroup2) {
setActiveConfig(display, config1);
sendRefreshFrame(display, nullptr);
EXPECT_EQ(IComposerClient::EX_SEAMLESS_NOT_ALLOWED,
setActiveConfigWithConstraints(display, config2, constraints, &timeline)
.getServiceSpecificError());
}
});
}
}
TEST_P(GraphicsComposerAidlTest, setActiveConfigWithConstraints) {
Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
}
TEST_P(GraphicsComposerAidlTest, GetDisplayIdentificationData) { TEST_P(GraphicsComposerAidlTest, GetDisplayIdentificationData) {
DisplayIdentification displayIdentification0; DisplayIdentification displayIdentification0;
@ -423,9 +831,9 @@ TEST_P(GraphicsComposerAidlTest, GetDisplayedContentSample) {
&displayContentSamplingAttributes) &displayContentSamplingAttributes)
.isOk()); .isOk());
uint64_t maxFrames = 10; int64_t maxFrames = 10;
uint64_t timestamp = 0; int64_t timestamp = 0;
uint64_t frameCount = 0; int64_t frameCount = 0;
DisplayContentSample displayContentSample; DisplayContentSample displayContentSample;
auto error = mComposerClient->getDisplayedContentSample(mPrimaryDisplay, maxFrames, timestamp, auto error = mComposerClient->getDisplayedContentSample(mPrimaryDisplay, maxFrames, timestamp,
&displayContentSample); &displayContentSample);
@ -440,12 +848,10 @@ TEST_P(GraphicsComposerAidlTest, GetDisplayedContentSample) {
displayContentSample.sampleComponent0, displayContentSample.sampleComponent1, displayContentSample.sampleComponent0, displayContentSample.sampleComponent1,
displayContentSample.sampleComponent2, displayContentSample.sampleComponent3}; displayContentSample.sampleComponent2, displayContentSample.sampleComponent3};
for (auto i = 0; i < histogram.size(); i++) { for (size_t i = 0; i < histogram.size(); i++) {
if (static_cast<int>(displayContentSamplingAttributes.componentMask) & (1 << i)) { const bool shouldHaveHistogram =
EXPECT_NE(histogram[i].size(), 0); static_cast<int>(displayContentSamplingAttributes.componentMask) & (1 << i);
} else { EXPECT_EQ(shouldHaveHistogram, !histogram[i].empty());
EXPECT_EQ(histogram[i].size(), 0);
}
} }
} }
@ -510,7 +916,7 @@ TEST_P(GraphicsComposerAidlTest, getDisplayConnectionType) {
TEST_P(GraphicsComposerAidlTest, getDisplayAttribute) { TEST_P(GraphicsComposerAidlTest, getDisplayAttribute) {
for (const auto& display : mDisplays) { for (const auto& display : mDisplays) {
std::vector<int32_t> configs; std::vector<int32_t> configs;
mComposerClient->getDisplayConfigs(display.get(), &configs); EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
for (const auto& config : configs) { for (const auto& config : configs) {
const std::array<DisplayAttribute, 4> requiredAttributes = {{ const std::array<DisplayAttribute, 4> requiredAttributes = {{
DisplayAttribute::WIDTH, DisplayAttribute::WIDTH,
@ -546,7 +952,7 @@ TEST_P(GraphicsComposerAidlTest, getDisplayAttribute) {
TEST_P(GraphicsComposerAidlTest, checkConfigsAreValid) { TEST_P(GraphicsComposerAidlTest, checkConfigsAreValid) {
for (const auto& display : mDisplays) { for (const auto& display : mDisplays) {
std::vector<int32_t> configs; std::vector<int32_t> configs;
mComposerClient->getDisplayConfigs(display.get(), &configs); EXPECT_TRUE(mComposerClient->getDisplayConfigs(display.get(), &configs).isOk());
EXPECT_FALSE(std::any_of(configs.begin(), configs.end(), [](auto config) { EXPECT_FALSE(std::any_of(configs.begin(), configs.end(), [](auto config) {
return config == IComposerClient::INVALID_CONFIGURATION; return config == IComposerClient::INVALID_CONFIGURATION;
@ -748,7 +1154,7 @@ TEST_P(GraphicsComposerAidlTest, getLayerGenericMetadataKeys) {
std::regex reverseDomainName("^[a-zA-Z-]{2,}(\\.[a-zA-Z0-9-]+)+$"); std::regex reverseDomainName("^[a-zA-Z-]{2,}(\\.[a-zA-Z0-9-]+)+$");
std::unordered_set<std::string> uniqueNames; std::unordered_set<std::string> uniqueNames;
for (const auto& key : keys) { for (const auto& key : keys) {
std::string name(key.name.c_str()); std::string name(key.name);
// Keys must not start with 'android' or 'com.android' // Keys must not start with 'android' or 'com.android'
EXPECT_FALSE(name.find("android") == 0); EXPECT_FALSE(name.find("android") == 0);
@ -862,7 +1268,7 @@ TEST_P(GraphicsComposerAidlTest, SetPowerModeBadParameter) {
TEST_P(GraphicsComposerAidlTest, SetPowerModeUnsupported) { TEST_P(GraphicsComposerAidlTest, SetPowerModeUnsupported) {
bool isDozeSupported = false; bool isDozeSupported = false;
mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported); EXPECT_TRUE(mComposerClient->getDozeSupport(mPrimaryDisplay, &isDozeSupported).isOk());
if (!isDozeSupported) { if (!isDozeSupported) {
auto error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE); auto error = mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::DOZE);
EXPECT_FALSE(error.isOk()); EXPECT_FALSE(error.isOk());

View file

@ -28,17 +28,38 @@ cc_library_static {
defaults: ["hidl_defaults"], defaults: ["hidl_defaults"],
srcs: [ srcs: [
"GraphicsComposerCallback.cpp", "GraphicsComposerCallback.cpp",
"TestCommandReader.cpp",
],
header_libs: [
"android.hardware.graphics.composer3-command-buffer",
], ],
static_libs: [ static_libs: [
"android.hardware.graphics.composer3-V1-ndk", "android.hardware.graphics.composer3-V1-ndk",
"android.hardware.graphics.common-V3-ndk", "android.hardware.graphics.common-V3-ndk",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"libgtest", "libgtest",
"libbase", "libbase",
"libfmq",
"libsync",
"libaidlcommonsupport",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0-vts",
],
shared_libs: [
"libbinder_ndk",
"libhidlbase",
"android.hardware.graphics.composer3-V1-ndk",
], ],
cflags: [ cflags: [
"-O0", "-O0",
"-g", "-g",
"-DLOG_TAG=\"ComposerVts\"", "-DLOG_TAG=\"ComposerVts\"",
"-Wconversion",
],
export_header_lib_headers: [
"android.hardware.graphics.composer3-command-buffer",
], ],
export_include_dirs: ["include"], export_include_dirs: ["include"],
} }

View file

@ -0,0 +1,92 @@
/**
* Copyright (c) 2021, 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.
*/
#include "include/TestCommandReader.h"
#include <gtest/gtest.h>
namespace aidl::android::hardware::graphics::composer3::vts {
void TestCommandReader::parse() {
mErrors.clear();
mCompositionChanges.clear();
while (!isEmpty()) {
int32_t command;
uint16_t length;
ASSERT_TRUE(beginCommand(&command, &length));
parseSingleCommand(command, length);
endCommand();
}
}
void TestCommandReader::parseSingleCommand(int32_t commandRaw, uint16_t length) {
auto command = static_cast<Command>(commandRaw);
switch (command) {
case Command::SET_CLIENT_TARGET_PROPERTY:
ASSERT_EQ(2, length);
read();
close(readFence());
break;
case Command::SELECT_DISPLAY:
ASSERT_EQ(2, length);
read64(); // display
break;
case Command::SET_ERROR: {
ASSERT_EQ(2, length);
auto loc = read();
auto err = readSigned();
std::pair<uint32_t, uint32_t> error(loc, err);
mErrors.push_back(error);
} break;
case Command::SET_CHANGED_COMPOSITION_TYPES:
ASSERT_EQ(0, length % 3);
for (uint16_t count = 0; count < length / 3; ++count) {
uint64_t layerId = read64();
uint32_t composition = read();
std::pair<uint64_t, uint32_t> compositionChange(layerId, composition);
mCompositionChanges.push_back(compositionChange);
}
break;
case Command::SET_DISPLAY_REQUESTS:
ASSERT_EQ(1, length % 3);
read(); // displayRequests, ignored for now
for (uint16_t count = 0; count < (length - 1) / 3; ++count) {
read64(); // layer
// silently eat requests to clear the client target, since we won't be testing
// client composition anyway
ASSERT_EQ(1u, read());
}
break;
case Command::SET_PRESENT_FENCE:
ASSERT_EQ(1, length);
close(readFence());
break;
case Command::SET_RELEASE_FENCES:
ASSERT_EQ(0, length % 3);
for (uint16_t count = 0; count < length / 3; ++count) {
read64();
close(readFence());
}
break;
default:
GTEST_FAIL() << "unexpected return command " << std::hex << static_cast<int>(command);
break;
}
}
} // namespace aidl::android::hardware::graphics::composer3::vts

View file

@ -15,12 +15,18 @@
*/ */
#pragma once #pragma once
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h> // TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
#include <android-base/thread_annotations.h> #include <android-base/thread_annotations.h>
#include <mutex> #include <mutex>
#include <unordered_set> #include <unordered_set>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion
namespace aidl::android::hardware::graphics::composer3::vts { namespace aidl::android::hardware::graphics::composer3::vts {
// IComposerCallback to be installed with IComposerClient::registerCallback. // IComposerCallback to be installed with IComposerClient::registerCallback.

View file

@ -0,0 +1,41 @@
/**
* Copyright (c) 2021, 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.
*/
#pragma once
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#include <android/hardware/graphics/composer3/command-buffer.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion
namespace aidl::android::hardware::graphics::composer3::vts {
class TestCommandReader : public CommandReaderBase {
public:
virtual ~TestCommandReader() = default;
std::vector<std::pair<uint32_t, uint32_t>> mErrors;
std::vector<std::pair<uint64_t, uint32_t>> mCompositionChanges;
// Parse all commands in the return command queue. Call GTEST_FAIL() for
// unexpected errors or commands.
void parse();
virtual void parseSingleCommand(int32_t commandRaw, uint16_t length);
};
} // namespace aidl::android::hardware::graphics::composer3::vts