blob: 13774b4ed37caa3c72591b98d95b64722fdbfb81 [file] [log] [blame]
/*
* Copyright (C) 2016 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 <array>
#include <unordered_set>
#include <unordered_map>
#include <gtest/gtest.h>
#include <dlfcn.h>
#include <android-base/unique_fd.h>
#include <hardware/hardware.h>
#include <sync/sync.h>
#include <ui/GraphicTypes.h>
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
#include "Hwc2TestLayer.h"
#include "Hwc2TestLayers.h"
#include "Hwc2TestClientTarget.h"
#include "Hwc2TestVirtualDisplay.h"
using android::ui::ColorMode;
using android::ui::Dataspace;
void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
hwc2_display_t display, int32_t connected);
void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
hwc2_display_t display, int64_t timestamp);
class Hwc2Test : public testing::Test {
public:
virtual void SetUp()
{
hw_module_t const* hwc2Module;
int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwc2Module);
ASSERT_GE(err, 0) << "failed to get hwc hardware module: "
<< strerror(-err);
/* The following method will fail if you have not run
* "adb shell stop" */
err = hwc2_open(hwc2Module, &mHwc2Device);
ASSERT_GE(err, 0) << "failed to open hwc hardware module: "
<< strerror(-err);
populateDisplays();
}
virtual void TearDown()
{
for (auto itr = mLayers.begin(); itr != mLayers.end();) {
hwc2_display_t display = itr->first;
hwc2_layer_t layer = itr->second;
itr++;
/* Destroys and removes the layer from mLayers */
destroyLayer(display, layer);
}
for (auto itr = mActiveDisplays.begin(); itr != mActiveDisplays.end();) {
hwc2_display_t display = *itr;
itr++;
/* Sets power mode to off and removes the display from
* mActiveDisplays */
setPowerMode(display, HWC2_POWER_MODE_OFF);
}
for (auto itr = mVirtualDisplays.begin(); itr != mVirtualDisplays.end();) {
hwc2_display_t display = *itr;
itr++;
/* Destroys virtual displays */
destroyVirtualDisplay(display);
}
if (mHwc2Device)
hwc2_close(mHwc2Device);
}
void registerCallback(hwc2_callback_descriptor_t descriptor,
hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_REGISTER_CALLBACK>(
getFunction(HWC2_FUNCTION_REGISTER_CALLBACK));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, descriptor,
callbackData, pointer));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to register callback";
}
}
void getDisplayType(hwc2_display_t display, hwc2_display_type_t* outType,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_TYPE>(
getFunction(HWC2_FUNCTION_GET_DISPLAY_TYPE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
reinterpret_cast<int32_t*>(outType)));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display type";
}
}
/* If the populateDisplays function is still receiving displays and the
* display is connected, the display handle is stored in mDisplays. */
void hotplugCallback(hwc2_display_t display, int32_t connected)
{
std::lock_guard<std::mutex> lock(mHotplugMutex);
if (mHotplugStatus != Hwc2TestHotplugStatus::Receiving)
return;
if (connected == HWC2_CONNECTION_CONNECTED)
mDisplays.insert(display);
mHotplugCv.notify_all();
}
void createLayer(hwc2_display_t display, hwc2_layer_t* outLayer,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_CREATE_LAYER>(
getFunction(HWC2_FUNCTION_CREATE_LAYER));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
outLayer));
if (err == HWC2_ERROR_NONE)
mLayers.insert(std::make_pair(display, *outLayer));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
}
}
void destroyLayer(hwc2_display_t display, hwc2_layer_t layer,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_LAYER>(
getFunction(HWC2_FUNCTION_DESTROY_LAYER));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer));
if (err == HWC2_ERROR_NONE)
mLayers.erase(std::make_pair(display, layer));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy layer "
<< layer;
}
}
void getDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
hwc2_attribute_t attribute, int32_t* outValue,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
getFunction(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config,
attribute, outValue));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display attribute "
<< getAttributeName(attribute) << " for config " << config;
}
}
void getDisplayConfigs(hwc2_display_t display,
std::vector<hwc2_config_t>* outConfigs,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_CONFIGS>(
getFunction(HWC2_FUNCTION_GET_DISPLAY_CONFIGS));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t numConfigs = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numConfigs, nullptr));
if (err == HWC2_ERROR_NONE) {
outConfigs->resize(numConfigs);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numConfigs, outConfigs->data()));
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get configs for"
" display " << display;
}
}
void getActiveConfig(hwc2_display_t display, hwc2_config_t* outConfig,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_ACTIVE_CONFIG>(
getFunction(HWC2_FUNCTION_GET_ACTIVE_CONFIG));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
outConfig));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get active config on"
" display " << display;
}
}
void setActiveConfig(hwc2_display_t display, hwc2_config_t config,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_ACTIVE_CONFIG>(
getFunction(HWC2_FUNCTION_SET_ACTIVE_CONFIG));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set active config "
<< config;
}
}
void getDozeSupport(hwc2_display_t display, int32_t* outSupport,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_DOZE_SUPPORT>(
getFunction(HWC2_FUNCTION_GET_DOZE_SUPPORT));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
outSupport));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get doze support on"
" display " << display;
}
}
void setPowerMode(hwc2_display_t display, hwc2_power_mode_t mode,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_POWER_MODE>(
getFunction(HWC2_FUNCTION_SET_POWER_MODE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
mode));
if (outErr) {
*outErr = err;
if (err != HWC2_ERROR_NONE)
return;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set power mode "
<< getPowerModeName(mode) << " on display " << display;
}
if (mode == HWC2_POWER_MODE_OFF) {
mActiveDisplays.erase(display);
} else {
mActiveDisplays.insert(display);
}
}
void setVsyncEnabled(hwc2_display_t display, hwc2_vsync_t enabled,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_VSYNC_ENABLED>(
getFunction(HWC2_FUNCTION_SET_VSYNC_ENABLED));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
enabled));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set vsync enabled "
<< getVsyncName(enabled);
}
}
void vsyncCallback(hwc2_display_t display, int64_t timestamp)
{
std::lock_guard<std::mutex> lock(mVsyncMutex);
mVsyncDisplay = display;
mVsyncTimestamp = timestamp;
mVsyncCv.notify_all();
}
void getDisplayName(hwc2_display_t display, std::string* outName,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_NAME>(
getFunction(HWC2_FUNCTION_GET_DISPLAY_NAME));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t size = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
nullptr));
if (err == HWC2_ERROR_NONE) {
std::vector<char> name(size);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
name.data()));
outName->assign(name.data());
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display name for "
<< display;
}
}
void setLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
hwc2_composition_t composition, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
getFunction(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
composition));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer composition"
" type " << getCompositionName(composition);
}
}
void setCursorPosition(hwc2_display_t display, hwc2_layer_t layer,
int32_t x, int32_t y, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_CURSOR_POSITION>(
getFunction(HWC2_FUNCTION_SET_CURSOR_POSITION));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer, x,
y));
if (outErr) {
*outErr = err;
} else {
ASSERT_TRUE((err == HWC2_ERROR_NONE) ||
(err == HWC2_ERROR_BAD_LAYER)) <<
"failed to set cursor position";
}
}
void setLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
hwc2_blend_mode_t mode, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BLEND_MODE>(
getFunction(HWC2_FUNCTION_SET_LAYER_BLEND_MODE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
mode));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer blend mode "
<< getBlendModeName(mode);
}
}
void setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
buffer_handle_t buffer, int32_t acquireFence,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BUFFER>(
getFunction(HWC2_FUNCTION_SET_LAYER_BUFFER));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
buffer, acquireFence));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer buffer";
}
}
void setLayerColor(hwc2_display_t display, hwc2_layer_t layer,
hwc_color_t color, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COLOR>(
getFunction(HWC2_FUNCTION_SET_LAYER_COLOR));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
color));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer color";
}
}
void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
Dataspace dataspace, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DATASPACE>(
getFunction(HWC2_FUNCTION_SET_LAYER_DATASPACE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
layer, static_cast<int>(dataspace)));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer dataspace";
}
}
void setLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
const hwc_rect_t& displayFrame, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
getFunction(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
displayFrame));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer display"
" frame";
}
}
void setLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer,
float alpha, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
getFunction(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
alpha));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer plane alpha "
<< alpha;
}
}
void setLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
const hwc_frect_t& sourceCrop, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
getFunction(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
sourceCrop));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer source crop";
}
}
void setLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
const hwc_region_t& surfaceDamage, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
getFunction(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
surfaceDamage));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer surface"
" damage";
}
}
void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
hwc_transform_t transform, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_TRANSFORM>(
getFunction(HWC2_FUNCTION_SET_LAYER_TRANSFORM));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
transform));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer transform "
<< getTransformName(transform);
}
}
void setLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
const hwc_region_t& visibleRegion, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
getFunction(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
visibleRegion));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer visible"
" region";
}
}
void setLayerZOrder(hwc2_display_t display, hwc2_layer_t layer,
uint32_t zOrder, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_Z_ORDER>(
getFunction(HWC2_FUNCTION_SET_LAYER_Z_ORDER));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
zOrder));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer z order "
<< zOrder;
}
}
void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
uint32_t* outNumRequests, hwc2_error_t* outErr)
{
auto pfn = reinterpret_cast<HWC2_PFN_VALIDATE_DISPLAY>(
getFunction(HWC2_FUNCTION_VALIDATE_DISPLAY));
ASSERT_TRUE(pfn) << "failed to get function";
*outErr = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
outNumTypes, outNumRequests));
}
void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
uint32_t* outNumRequests, bool* outHasChanges)
{
hwc2_error_t err = HWC2_ERROR_NONE;
EXPECT_NO_FATAL_FAILURE(validateDisplay(display, outNumTypes,
outNumRequests, &err));
if (err != HWC2_ERROR_HAS_CHANGES) {
*outHasChanges = false;
EXPECT_EQ(err, HWC2_ERROR_NONE) << "failed to validate display";
} else {
*outHasChanges = true;
}
}
void getDisplayRequests(hwc2_display_t display,
hwc2_display_request_t* outDisplayRequests,
std::vector<hwc2_layer_t>* outLayers,
std::vector<hwc2_layer_request_t>* outLayerRequests,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_REQUESTS>(
getFunction(HWC2_FUNCTION_GET_DISPLAY_REQUESTS));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t numElements = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
nullptr, nullptr));
if (err == HWC2_ERROR_NONE && numElements > 0) {
outLayers->resize(numElements);
outLayerRequests->resize(numElements);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
reinterpret_cast<uint64_t*>(outLayers->data()),
reinterpret_cast<int32_t*>(outLayerRequests->data())));
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display requests";
}
}
void handleRequests(hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers, uint32_t numRequests,
std::set<hwc2_layer_t>* outClearLayers = nullptr,
bool* outFlipClientTarget = nullptr)
{
hwc2_display_request_t displayRequest =
static_cast<hwc2_display_request_t>(0);
std::vector<hwc2_layer_t> requestedLayers;
std::vector<hwc2_layer_request_t> requests;
ASSERT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequest,
&requestedLayers, &requests));
EXPECT_EQ(numRequests, requests.size()) << "validate returned "
<< numRequests << " requests and get display requests returned "
<< requests.size() << " requests";
for (size_t i = 0; i < requests.size(); i++) {
hwc2_layer_t requestedLayer = requestedLayers.at(i);
hwc2_layer_request_t request = requests.at(i);
EXPECT_EQ(std::count(layers.begin(), layers.end(), requestedLayer),
1) << "get display requests returned an unknown layer";
EXPECT_NE(request, 0) << "returned empty request for layer "
<< requestedLayer;
if (outClearLayers && request
== HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET)
outClearLayers->insert(requestedLayer);
}
if (outFlipClientTarget)
*outFlipClientTarget = displayRequest
& HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET;
}
void getChangedCompositionTypes(hwc2_display_t display,
std::vector<hwc2_layer_t>* outLayers,
std::vector<hwc2_composition_t>* outTypes,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
getFunction(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t numElements = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numElements, nullptr, nullptr));
if (err == HWC2_ERROR_NONE && numElements > 0) {
outLayers->resize(numElements);
outTypes->resize(numElements);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numElements, reinterpret_cast<uint64_t*>(outLayers->data()),
reinterpret_cast<int32_t*>(outTypes->data())));
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get changed"
" composition types";
}
}
void handleCompositionChanges(hwc2_display_t display,
const Hwc2TestLayers& testLayers,
const std::vector<hwc2_layer_t>& layers, uint32_t numTypes,
std::set<hwc2_layer_t>* outClientLayers = nullptr)
{
std::vector<hwc2_layer_t> changedLayers;
std::vector<hwc2_composition_t> types;
ASSERT_NO_FATAL_FAILURE(getChangedCompositionTypes(display,
&changedLayers, &types));
EXPECT_EQ(numTypes, types.size()) << "validate returned "
<< numTypes << " types and get changed composition types"
" returned " << types.size() << " types";
for (size_t i = 0; i < types.size(); i++) {
auto layer = std::find(layers.begin(), layers.end(),
changedLayers.at(i));
EXPECT_TRUE(layer != layers.end() || !testLayers.contains(*layer))
<< "get changed composition types returned an unknown layer";
hwc2_composition_t requestedType = testLayers.getComposition(*layer);
hwc2_composition_t returnedType = types.at(i);
EXPECT_NE(returnedType, HWC2_COMPOSITION_INVALID) << "get changed"
" composition types returned invalid composition";
switch (requestedType) {
case HWC2_COMPOSITION_CLIENT:
EXPECT_TRUE(false) << getCompositionName(returnedType)
<< " cannot be changed";
break;
case HWC2_COMPOSITION_DEVICE:
case HWC2_COMPOSITION_SOLID_COLOR:
EXPECT_EQ(returnedType, HWC2_COMPOSITION_CLIENT)
<< "composition of type "
<< getCompositionName(requestedType)
<< " can only be changed to "
<< getCompositionName(HWC2_COMPOSITION_CLIENT);
break;
case HWC2_COMPOSITION_CURSOR:
case HWC2_COMPOSITION_SIDEBAND:
EXPECT_TRUE(returnedType == HWC2_COMPOSITION_CLIENT
|| returnedType == HWC2_COMPOSITION_DEVICE)
<< "composition of type "
<< getCompositionName(requestedType)
<< " can only be changed to "
<< getCompositionName(HWC2_COMPOSITION_CLIENT) << " or "
<< getCompositionName(HWC2_COMPOSITION_DEVICE);
break;
default:
EXPECT_TRUE(false) << "unknown type "
<< getCompositionName(requestedType);
break;
}
if (outClientLayers)
if (returnedType == HWC2_COMPOSITION_CLIENT)
outClientLayers->insert(*layer);
}
if (outClientLayers) {
for (auto layer : layers) {
if (testLayers.getComposition(layer) == HWC2_COMPOSITION_CLIENT)
outClientLayers->insert(layer);
}
}
}
void acceptDisplayChanges(hwc2_display_t display,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
getFunction(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to accept display changes";
}
}
void getClientTargetSupport(hwc2_display_t display, int32_t width,
int32_t height, android_pixel_format_t format,
Dataspace dataspace, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
getFunction(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, width,
height, format, static_cast<int>(dataspace)));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get client target"
" support";
}
}
void setClientTarget(hwc2_display_t display, buffer_handle_t handle,
int32_t acquireFence, Dataspace dataspace,
hwc_region_t damage, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_CLIENT_TARGET>(
getFunction(HWC2_FUNCTION_SET_CLIENT_TARGET));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, handle,
acquireFence, static_cast<int>(dataspace), damage));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set client target";
}
}
void presentDisplay(hwc2_display_t display, int32_t* outPresentFence,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_PRESENT_DISPLAY>(
getFunction(HWC2_FUNCTION_PRESENT_DISPLAY));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
outPresentFence));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to present display";
}
}
void getReleaseFences(hwc2_display_t display,
std::vector<hwc2_layer_t>* outLayers,
std::vector<int32_t>* outFences, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_RELEASE_FENCES>(
getFunction(HWC2_FUNCTION_GET_RELEASE_FENCES));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t numElements = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numElements, nullptr, nullptr));
if (err == HWC2_ERROR_NONE) {
outLayers->resize(numElements);
outFences->resize(numElements);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numElements, outLayers->data(), outFences->data()));
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get release fences";
}
}
void getColorModes(hwc2_display_t display,
std::vector<ColorMode>* outColorModes,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_COLOR_MODES>(
getFunction(HWC2_FUNCTION_GET_COLOR_MODES));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t numColorModes = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numColorModes, nullptr));
if (err == HWC2_ERROR_NONE) {
outColorModes->resize(numColorModes);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numColorModes,
reinterpret_cast<int32_t*>(outColorModes->data())));
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get color modes for"
" display " << display;
}
}
void setColorMode(hwc2_display_t display, ColorMode colorMode,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_MODE>(
getFunction(HWC2_FUNCTION_SET_COLOR_MODE));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
static_cast<int32_t>(colorMode)));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode "
<< static_cast<int>(colorMode);
}
}
void getHdrCapabilities(hwc2_display_t display,
std::vector<android_hdr_t>* outTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_HDR_CAPABILITIES>(
getFunction(HWC2_FUNCTION_GET_HDR_CAPABILITIES));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t numTypes = 0;
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
&numTypes, nullptr, outMaxLuminance, outMaxAverageLuminance,
outMinLuminance));
if (err == HWC2_ERROR_NONE) {
outTypes->resize(numTypes);
err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &numTypes,
reinterpret_cast<int32_t*>(outTypes->data()), outMaxLuminance,
outMaxAverageLuminance, outMinLuminance));
}
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get hdr capabilities"
" for display " << display;
}
}
void setColorTransform(hwc2_display_t display,
const std::array<float, 16>& matrix, android_color_transform_t hint,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_TRANSFORM>(
getFunction(HWC2_FUNCTION_SET_COLOR_TRANSFORM));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
matrix.data(), hint));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color transform "
<< hint;
}
}
void createVirtualDisplay(uint32_t width, uint32_t height,
android_pixel_format_t* outFormat, hwc2_display_t* outDisplay,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
getFunction(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, width, height,
reinterpret_cast<int32_t*>(outFormat), outDisplay));
if (err == HWC2_ERROR_NONE)
mVirtualDisplays.insert(*outDisplay);
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create virtual display";
}
}
void destroyVirtualDisplay(hwc2_display_t display,
hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
getFunction(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
if (err == HWC2_ERROR_NONE)
mVirtualDisplays.erase(display);
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy virtual display";
}
}
void getMaxVirtualDisplayCount(uint32_t* outMaxCnt)
{
auto pfn = reinterpret_cast<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
getFunction(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT));
ASSERT_TRUE(pfn) << "failed to get function";
*outMaxCnt = pfn(mHwc2Device);
}
void setOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
int32_t releaseFence, hwc2_error_t* outErr = nullptr)
{
auto pfn = reinterpret_cast<HWC2_PFN_SET_OUTPUT_BUFFER>(
getFunction(HWC2_FUNCTION_SET_OUTPUT_BUFFER));
ASSERT_TRUE(pfn) << "failed to get function";
auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, buffer,
releaseFence));
if (outErr) {
*outErr = err;
} else {
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set output buffer";
}
}
void dump(std::string* outBuffer)
{
auto pfn = reinterpret_cast<HWC2_PFN_DUMP>(
getFunction(HWC2_FUNCTION_DUMP));
ASSERT_TRUE(pfn) << "failed to get function";
uint32_t size = 0;
pfn(mHwc2Device, &size, nullptr);
std::vector<char> buffer(size);
pfn(mHwc2Device, &size, buffer.data());
outBuffer->assign(buffer.data());
}
void getBadDisplay(hwc2_display_t* outDisplay)
{
for (hwc2_display_t display = 0; display < UINT64_MAX; display++) {
if (mDisplays.count(display) == 0) {
*outDisplay = display;
return;
}
}
ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays"
" are registered. This should never happen.";
}
void waitForVsync(hwc2_display_t* outDisplay = nullptr,
int64_t* outTimestamp = nullptr)
{
std::unique_lock<std::mutex> lock(mVsyncMutex);
ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)),
std::cv_status::no_timeout) << "timed out attempting to get"
" vsync callback";
if (outDisplay)
*outDisplay = mVsyncDisplay;
if (outTimestamp)
*outTimestamp = mVsyncTimestamp;
}
void enableVsync(hwc2_display_t display)
{
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this,
reinterpret_cast<hwc2_function_pointer_t>(
hwc2TestVsyncCallback)));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
}
void disableVsync(hwc2_display_t display)
{
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
}
protected:
hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor)
{
return mHwc2Device->getFunction(mHwc2Device, descriptor);
}
void getCapabilities(std::vector<hwc2_capability_t>* outCapabilities)
{
uint32_t num = 0;
mHwc2Device->getCapabilities(mHwc2Device, &num, nullptr);
outCapabilities->resize(num);
mHwc2Device->getCapabilities(mHwc2Device, &num,
reinterpret_cast<int32_t*>(outCapabilities->data()));
}
/* Registers a hotplug callback and waits for hotplug callbacks. This
* function will have no effect if called more than once. */
void populateDisplays()
{
/* Sets the hotplug status to receiving */
{
std::lock_guard<std::mutex> lock(mHotplugMutex);
if (mHotplugStatus != Hwc2TestHotplugStatus::Init)
return;
mHotplugStatus = Hwc2TestHotplugStatus::Receiving;
}
/* Registers the callback. This function call cannot be locked because
* a callback could happen on the same thread */
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_HOTPLUG, this,
reinterpret_cast<hwc2_function_pointer_t>(
hwc2TestHotplugCallback)));
/* Waits for hotplug events. If a hotplug event has not come within 1
* second, stop waiting. */
std::unique_lock<std::mutex> lock(mHotplugMutex);
while (mHotplugCv.wait_for(lock, std::chrono::seconds(1)) !=
std::cv_status::timeout) { }
/* Sets the hotplug status to done. Future calls will have no effect */
mHotplugStatus = Hwc2TestHotplugStatus::Done;
}
/* NOTE: will create min(newlayerCnt, max supported layers) layers */
void createLayers(hwc2_display_t display,
std::vector<hwc2_layer_t>* outLayers, size_t newLayerCnt)
{
std::vector<hwc2_layer_t> newLayers;
hwc2_layer_t layer;
hwc2_error_t err = HWC2_ERROR_NONE;
for (size_t i = 0; i < newLayerCnt; i++) {
EXPECT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
if (err == HWC2_ERROR_NO_RESOURCES)
break;
if (err != HWC2_ERROR_NONE) {
newLayers.clear();
ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
}
newLayers.push_back(layer);
}
*outLayers = std::move(newLayers);
}
void destroyLayers(hwc2_display_t display,
std::vector<hwc2_layer_t>&& layers)
{
for (hwc2_layer_t layer : layers) {
EXPECT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
}
void getInvalidConfig(hwc2_display_t display, hwc2_config_t* outConfig)
{
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
hwc2_config_t CONFIG_MAX = UINT32_MAX;
ASSERT_LE(configs.size() - 1, CONFIG_MAX) << "every config value"
" (2^32 values) has been taken which shouldn't happen";
hwc2_config_t config;
for (config = 0; config < CONFIG_MAX; config++) {
if (std::count(configs.begin(), configs.end(), config) == 0)
break;
}
*outConfig = config;
}
/* Calls a set property function from Hwc2Test to set a property value from
* Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */
using TestLayerPropertyFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
/* Calls a set property function from Hwc2Test to set property values from
* Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */
using TestLayerPropertiesFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayers* testLayers);
/* Calls a set property function from Hwc2Test to set a bad property value
* on hwc2_layer_t on hwc2_display_t */
using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
/* Calls a set property function from Hwc2Test to set a bad property value
* on hwc2_layer_t on hwc2_display_t */
using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr);
/* Is called after a display is powered on and all layer properties have
* been set. It should be used to test functions such as validate, accepting
* changes, present, etc. */
using TestDisplayLayersFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* testLayers);
/* It is called on an non validated display */
using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, std::vector<hwc2_layer_t>* layers);
/* Tests client target support on a particular display and config */
using TestClientTargetSupportFunction = void (*)(Hwc2Test* test,
hwc2_display_t display,
const Hwc2TestClientTargetSupport& testClientTargetSupport);
/* Tests a particular active display config */
using TestActiveDisplayConfigFunction = void (*)(Hwc2Test* test,
hwc2_display_t display);
/* Tests a newly created virtual display */
using TestCreateVirtualDisplayFunction = void (*)(Hwc2Test* test,
hwc2_display_t display, Hwc2TestVirtualDisplay* testVirtualDisplay);
/* Advances a property of Hwc2TestLayer */
using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer);
/* Advances properties of Hwc2TestLayers */
using AdvanceProperties = bool (*)(Hwc2TestLayers* testLayer);
/* Advances properties of Hwc2TestClientTargetSupport */
using AdvanceClientTargetSupport = bool (*)(
Hwc2TestClientTargetSupport* testClientTargetSupport);
/* For each active display it cycles through each display config and tests
* each property value. It creates a layer, sets the property and then
* destroys the layer */
void setLayerProperty(Hwc2TestCoverage coverage,
TestLayerPropertyFunction function, AdvanceProperty advance)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
hwc2_layer_t layer;
Area displayArea;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
Hwc2TestLayer testLayer(coverage, displayArea);
do {
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
&testLayer, nullptr));
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
} while (advance(&testLayer));
}
}
}
/* For each active display it cycles through each display config and tests
* each property value. It creates a layer, cycles through each property
* value and updates the layer property value and then destroys the layer */
void setLayerPropertyUpdate(Hwc2TestCoverage coverage,
TestLayerPropertyFunction function, AdvanceProperty advance)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
hwc2_layer_t layer;
Area displayArea;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
Hwc2TestLayer testLayer(coverage, displayArea);
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
do {
ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
&testLayer, nullptr));
} while (advance(&testLayer));
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
}
}
/* For each active display it cycles through each display config and tests
* each property value. It creates multiple layers, calls the
* TestLayerPropertiesFunction to set property values and then
* destroys the layers */
void setLayerProperties(Hwc2TestCoverage coverage, size_t layerCnt,
TestLayerPropertiesFunction function, AdvanceProperties advance)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
std::vector<hwc2_layer_t> layers;
Area displayArea;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
Hwc2TestLayers testLayers(layers, coverage, displayArea);
do {
for (auto layer : layers) {
EXPECT_NO_FATAL_FAILURE(function(this, display, layer,
&testLayers));
}
} while (advance(&testLayers));
ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
}
}
}
/* For each active display it cycles through each display config.
* 1) It attempts to set a valid property value to bad layer handle.
* 2) It creates a layer x and attempts to set a valid property value to
* layer x + 1
* 3) It destroys the layer x and attempts to set a valid property value to
* the destroyed layer x.
*/
void setLayerPropertyBadLayer(Hwc2TestCoverage coverage,
TestLayerPropertyBadLayerFunction function)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
hwc2_layer_t layer = 0;
Area displayArea;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
Hwc2TestLayer testLayer(coverage, displayArea);
ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
&testLayer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1,
&testLayer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
&testLayer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
}
}
}
/* For each active display it cycles through each display config and tests
* each property value. It creates a layer, sets a bad property value and
* then destroys the layer */
void setLayerPropertyBadParameter(TestLayerPropertyBadParameterFunction function)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
hwc2_layer_t layer;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
ASSERT_NO_FATAL_FAILURE(function(this, display, layer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong"
" error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
}
}
/* For each active display it powers on the display, cycles through each
* config and creates a set of layers with a certain amount of coverage.
* For each active display, for each config and for each set of layers,
* it calls the TestDisplayLayersFunction */
void displayLayers(Hwc2TestCoverage coverage, size_t layerCnt,
TestDisplayLayersFunction function)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
Area displayArea;
std::vector<hwc2_layer_t> layers;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
Hwc2TestLayers testLayers(layers, coverage, displayArea);
do {
bool skip;
ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
&testLayers, &skip));
if (!skip)
EXPECT_NO_FATAL_FAILURE(function(this, display, layers,
&testLayers));
} while (testLayers.advance());
ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
std::move(layers)));
}
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* For each active display, it calls the
* TestDisplayNonValidatedLayersFunction on a variety on non-validated
* layer combinations */
void displayNonValidatedLayers(size_t layerCnt,
TestDisplayNonValidatedLayersFunction function)
{
for (auto display : mDisplays) {
uint32_t numTypes, numRequests;
std::vector<hwc2_layer_t> layers;
bool hasChanges;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
for (auto layer : layers) {
ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
HWC2_COMPOSITION_CLIENT));
}
EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
for (auto layer : layers) {
ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
HWC2_COMPOSITION_DEVICE));
}
EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* Test client target support on each config on each active display */
void setClientTargetSupport(Hwc2TestCoverage coverage,
TestClientTargetSupportFunction function,
AdvanceClientTargetSupport advance)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
Area displayArea;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
Hwc2TestClientTargetSupport testClientTargetSupport(coverage,
displayArea);
do {
EXPECT_NO_FATAL_FAILURE(function(this, display,
testClientTargetSupport));
} while (advance(&testClientTargetSupport));
}
}
}
/* Cycles through each config on each active display and calls
* a TestActiveDisplayConfigFunction */
void setActiveDisplayConfig(TestActiveDisplayConfigFunction function)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
EXPECT_NO_FATAL_FAILURE(function(this, display));
}
}
}
/* Creates a virtual display for testing */
void createVirtualDisplay(Hwc2TestCoverage coverage,
TestCreateVirtualDisplayFunction function)
{
Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
do {
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
const UnsignedArea& dimension =
testVirtualDisplay.getDisplayDimension();
android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
dimension.height, &desiredFormat, &display, &err));
EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
|| err == HWC2_ERROR_UNSUPPORTED)
<< "returned wrong error code";
EXPECT_GE(desiredFormat, 0) << "invalid format";
if (err != HWC2_ERROR_NONE)
continue;
EXPECT_NO_FATAL_FAILURE(function(this, display,
&testVirtualDisplay));
ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
} while (testVirtualDisplay.advance());
}
void getActiveConfigAttribute(hwc2_display_t display,
hwc2_attribute_t attribute, int32_t* outValue)
{
hwc2_config_t config;
ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &config));
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
attribute, outValue));
ASSERT_GE(*outValue, 0) << "failed to get valid "
<< getAttributeName(attribute);
}
void getActiveDisplayArea(hwc2_display_t display, Area* displayArea)
{
ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
HWC2_ATTRIBUTE_WIDTH, &displayArea->width));
ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
HWC2_ATTRIBUTE_HEIGHT, &displayArea->height));
}
void closeFences(hwc2_display_t display, int32_t presentFence)
{
std::vector<hwc2_layer_t> layers;
std::vector<int32_t> fences;
const int msWait = 3000;
if (presentFence >= 0) {
ASSERT_GE(sync_wait(presentFence, msWait), 0);
close(presentFence);
}
ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences));
EXPECT_EQ(layers.size(), fences.size());
for (int32_t fence : fences) {
if (fence >= 0) {
EXPECT_GE(sync_wait(fence, msWait), 0);
close(fence);
}
}
}
void setLayerProperties(hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayers* testLayers, bool* outSkip)
{
hwc2_composition_t composition;
buffer_handle_t handle = nullptr;
int32_t acquireFence;
hwc2_error_t err = HWC2_ERROR_NONE;
*outSkip = true;
if (!testLayers->contains(layer))
return;
composition = testLayers->getComposition(layer);
/* If the device cannot support a buffer format, then do not continue */
if ((composition == HWC2_COMPOSITION_DEVICE
|| composition == HWC2_COMPOSITION_CURSOR)
&& testLayers->getBuffer(layer, &handle, &acquireFence) < 0)
return;
EXPECT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
composition, &err));
if (err == HWC2_ERROR_UNSUPPORTED)
EXPECT_TRUE(composition != HWC2_COMPOSITION_CLIENT
&& composition != HWC2_COMPOSITION_DEVICE);
const hwc_rect_t cursor = testLayers->getCursorPosition(layer);
EXPECT_NO_FATAL_FAILURE(setLayerBuffer(display, layer, handle,
acquireFence));
EXPECT_NO_FATAL_FAILURE(setLayerBlendMode(display, layer,
testLayers->getBlendMode(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerColor(display, layer,
testLayers->getColor(layer)));
if (composition == HWC2_COMPOSITION_CURSOR)
EXPECT_NO_FATAL_FAILURE(setCursorPosition(display, layer,
cursor.left, cursor.top));
EXPECT_NO_FATAL_FAILURE(setLayerDataspace(display, layer,
testLayers->getDataspace(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerDisplayFrame(display, layer,
testLayers->getDisplayFrame(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerPlaneAlpha(display, layer,
testLayers->getPlaneAlpha(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerSourceCrop(display, layer,
testLayers->getSourceCrop(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerSurfaceDamage(display, layer,
testLayers->getSurfaceDamage(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerTransform(display, layer,
testLayers->getTransform(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerVisibleRegion(display, layer,
testLayers->getVisibleRegion(layer)));
EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer,
testLayers->getZOrder(layer)));
*outSkip = false;
}
void setLayerProperties(hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* testLayers, bool* outSkip)
{
for (auto layer : layers) {
EXPECT_NO_FATAL_FAILURE(setLayerProperties(display, layer,
testLayers, outSkip));
if (*outSkip)
return;
}
}
void setClientTarget(hwc2_display_t display,
Hwc2TestClientTarget* testClientTarget,
const Hwc2TestLayers& testLayers,
const std::set<hwc2_layer_t>& clientLayers,
const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
const Area& displayArea)
{
Dataspace dataspace = Dataspace::UNKNOWN;
hwc_region_t damage = { };
buffer_handle_t handle;
int32_t acquireFence;
ASSERT_EQ(testClientTarget->getBuffer(testLayers, clientLayers,
clearLayers, flipClientTarget, displayArea, &handle,
&acquireFence), 0);
EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
dataspace, damage));
}
void presentDisplays(size_t layerCnt, Hwc2TestCoverage coverage,
const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
coverageExceptions, bool optimize)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(enableVsync(display));
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
Area displayArea;
std::vector<hwc2_layer_t> layers;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
Hwc2TestLayers testLayers(layers, coverage, displayArea,
coverageExceptions);
if (optimize && !testLayers.optimizeLayouts())
continue;
std::set<hwc2_layer_t> clientLayers;
std::set<hwc2_layer_t> clearLayers;
Hwc2TestClientTarget testClientTarget;
do {
uint32_t numTypes, numRequests;
bool hasChanges, skip;
bool flipClientTarget;
int32_t presentFence;
ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
&testLayers, &skip));
if (skip)
continue;
ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
<< "wrong number of requests";
ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
testLayers, layers, numTypes, &clientLayers));
ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
numRequests, &clearLayers, &flipClientTarget));
ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
&testClientTarget, testLayers, clientLayers,
clearLayers, flipClientTarget, displayArea));
ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
ASSERT_NO_FATAL_FAILURE(waitForVsync());
EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
&presentFence));
ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
} while (testLayers.advance());
ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
std::move(layers)));
}
ASSERT_NO_FATAL_FAILURE(disableVsync(display));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
void createAndPresentVirtualDisplay(size_t layerCnt,
Hwc2TestCoverage coverage,
const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
coverageExceptions)
{
Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
hwc2_display_t display;
android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
do {
// Items dependent on the display dimensions
hwc2_error_t err = HWC2_ERROR_NONE;
const UnsignedArea& dimension =
testVirtualDisplay.getDisplayDimension();
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
dimension.height, &desiredFormat, &display, &err));
ASSERT_TRUE(err == HWC2_ERROR_NONE)
<< "Cannot allocate virtual display";
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(enableVsync(display));
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
Area displayArea;
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
&displayArea));
std::vector<hwc2_layer_t> layers;
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers,
layerCnt));
Hwc2TestLayers testLayers(layers, coverage, displayArea,
coverageExceptions);
/*
* Layouts that do not cover an entire virtual display will
* cause undefined behavior.
* Enable optimizeLayouts to avoid this.
*/
testLayers.optimizeLayouts();
do {
// Items dependent on the testLayers properties
std::set<hwc2_layer_t> clientLayers;
std::set<hwc2_layer_t> clearLayers;
uint32_t numTypes, numRequests;
bool hasChanges, skip;
bool flipClientTarget;
int32_t presentFence;
Hwc2TestClientTarget testClientTarget;
buffer_handle_t outputBufferHandle;
android::base::unique_fd outputBufferReleaseFence;
ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
&testLayers, &skip));
if (skip)
continue;
ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
<< "wrong number of requests";
ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
testLayers, layers, numTypes, &clientLayers));
ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
numRequests, &clearLayers, &flipClientTarget));
ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
&testClientTarget, testLayers, clientLayers,
clearLayers, flipClientTarget, displayArea));
ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
ASSERT_EQ(testVirtualDisplay.getOutputBuffer(
&outputBufferHandle, &outputBufferReleaseFence), 0);
ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display,
outputBufferHandle, outputBufferReleaseFence));
EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
&presentFence));
ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
ASSERT_EQ(testVirtualDisplay.verifyOutputBuffer(&testLayers,
&layers, &clearLayers), 0);
/*
* Upscaling the image causes minor pixel differences.
* Work around this by using some threshold.
*
* Fail test if we are off by more than 1% of our
* pixels.
*/
ComparatorResult& comparatorResult = ComparatorResult::get();
int threshold = (dimension.width * dimension.height) / 100;
double diffPercent = (comparatorResult.getDifferentPixelCount() * 100.0) /
(dimension.width * dimension.height);
if (comparatorResult.getDifferentPixelCount() != 0)
EXPECT_TRUE(false)
<< comparatorResult.getDifferentPixelCount() << " pixels ("
<< diffPercent << "%) are different.";
if (comparatorResult.getDifferentPixelCount() > threshold) {
EXPECT_TRUE(false)
<< "Mismatched pixel count exceeds threshold. "
<< "Writing buffers to file.";
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()
->current_test_info();
EXPECT_EQ(testVirtualDisplay.writeBuffersToFile(
test_info->name()), 0)
<< "Failed to write buffers.";
}
ASSERT_LE(comparatorResult.getDifferentPixelCount(), threshold)
<< comparatorResult.getDifferentPixelCount() << " pixels ("
<< diffPercent << "%) are different. "
<< "Exceeds 1% threshold, terminating test. "
<< "Test case: " << testLayers.dump();
} while (testLayers.advance());
ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
std::move(layers)));
}
ASSERT_NO_FATAL_FAILURE(disableVsync(display));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
} while (testVirtualDisplay.advance());
}
hwc2_device_t* mHwc2Device = nullptr;
enum class Hwc2TestHotplugStatus {
Init = 1,
Receiving,
Done,
};
std::mutex mHotplugMutex;
std::condition_variable mHotplugCv;
Hwc2TestHotplugStatus mHotplugStatus = Hwc2TestHotplugStatus::Init;
std::unordered_set<hwc2_display_t> mDisplays;
/* Store all created layers that have not been destroyed. If an ASSERT_*
* fails, then destroy the layers on exit */
std::set<std::pair<hwc2_display_t, hwc2_layer_t>> mLayers;
/* Store the power mode state. If it is not HWC2_POWER_MODE_OFF when
* tearing down the test cases, change it to HWC2_POWER_MODE_OFF */
std::set<hwc2_display_t> mActiveDisplays;
/* Store all created virtual displays that have not been destroyed. If an
* ASSERT_* fails, then destroy the virtual displays on exit */
std::set<hwc2_display_t> mVirtualDisplays;
std::mutex mVsyncMutex;
std::condition_variable mVsyncCv;
hwc2_display_t mVsyncDisplay;
int64_t mVsyncTimestamp = -1;
};
void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
hwc2_display_t display, int32_t connection)
{
if (callbackData)
static_cast<Hwc2Test*>(callbackData)->hotplugCallback(display,
connection);
}
void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
hwc2_display_t display, int64_t timestamp)
{
if (callbackData)
static_cast<Hwc2Test*>(callbackData)->vsyncCallback(display,
timestamp);
}
void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
testLayer->getBlendMode(), outErr));
}
void setBuffer(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
buffer_handle_t handle;
android::base::unique_fd acquireFence;
hwc2_composition_t composition = testLayer->getComposition();
if (composition == HWC2_COMPOSITION_CLIENT
|| composition == HWC2_COMPOSITION_SOLID_COLOR
|| composition == HWC2_COMPOSITION_SIDEBAND)
return;
if (testLayer->getBuffer(&handle, &acquireFence) < 0)
return;
ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
composition));
EXPECT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
handle, acquireFence, outErr));
}
void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
layer, HWC2_COMPOSITION_SOLID_COLOR));
ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
layer, testLayer->getPlaneAlpha()));
ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
layer, testLayer->getBlendMode()));
EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
testLayer->getColor(), outErr));
}
void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
hwc2_composition_t composition = testLayer->getComposition();
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
composition, &err));
if (outErr) {
*outErr = err;
return;
}
if (composition != HWC2_COMPOSITION_SIDEBAND) {
EXPECT_EQ(err, HWC2_ERROR_NONE) << "returned wrong error code";
} else {
EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
<< "returned wrong error code";
}
}
void setCursorPosition(Hwc2Test* test, hwc2_display_t display,
hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
layer, HWC2_COMPOSITION_CURSOR));
const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
cursorPosition.left, cursorPosition.top, outErr));
}
void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer,
testLayer->getDataspace(), outErr));
}
void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer,
testLayer->getDisplayFrame(), outErr));
}
void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t *outErr)
{
ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
testLayer->getBlendMode()));
EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer,
testLayer->getPlaneAlpha(), outErr));
}
void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer,
testLayer->getSourceCrop(), outErr));
}
void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer,
testLayer->getSurfaceDamage(), outErr));
}
void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer,
testLayer->getTransform(), outErr));
}
void setVisibleRegion(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display, layer,
testLayer->getVisibleRegion(), outErr));
}
void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
{
EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
testLayer->getZOrder(), outErr));
}
bool advanceBlendMode(Hwc2TestLayer* testLayer)
{
return testLayer->advanceBlendMode();
}
bool advanceBuffer(Hwc2TestLayer* testLayer)
{
if (testLayer->advanceComposition())
return true;
return testLayer->advanceBufferArea();
}
bool advanceColor(Hwc2TestLayer* testLayer)
{
/* Color depends on blend mode so advance blend mode last so color is not
* force to update as often */
if (testLayer->advancePlaneAlpha())
return true;
if (testLayer->advanceColor())
return true;
return testLayer->advanceBlendMode();
}
bool advanceComposition(Hwc2TestLayer* testLayer)
{
return testLayer->advanceComposition();
}
bool advanceCursorPosition(Hwc2TestLayer* testLayer)
{
return testLayer->advanceCursorPosition();
}
bool advanceDataspace(Hwc2TestLayer* testLayer)
{
return testLayer->advanceDataspace();
}
bool advanceDisplayFrame(Hwc2TestLayer* testLayer)
{
return testLayer->advanceDisplayFrame();
}
bool advancePlaneAlpha(Hwc2TestLayer* testLayer)
{
return testLayer->advancePlaneAlpha();
}
bool advanceSourceCrop(Hwc2TestLayer* testLayer)
{
if (testLayer->advanceSourceCrop())
return true;
return testLayer->advanceBufferArea();
}
bool advanceSurfaceDamage(Hwc2TestLayer* testLayer)
{
if (testLayer->advanceSurfaceDamage())
return true;
return testLayer->advanceBufferArea();
}
bool advanceTransform(Hwc2TestLayer* testLayer)
{
return testLayer->advanceTransform();
}
bool advanceVisibleRegions(Hwc2TestLayers* testLayers)
{
return testLayers->advanceVisibleRegions();
}
bool advanceClientTargetSupport(
Hwc2TestClientTargetSupport* testClientTargetSupport)
{
return testClientTargetSupport->advance();
}
static const std::array<hwc2_function_descriptor_t, 42> requiredFunctions = {{
HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
HWC2_FUNCTION_CREATE_LAYER,
HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
HWC2_FUNCTION_DESTROY_LAYER,
HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
HWC2_FUNCTION_DUMP,
HWC2_FUNCTION_GET_ACTIVE_CONFIG,
HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
HWC2_FUNCTION_GET_COLOR_MODES,
HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
HWC2_FUNCTION_GET_DISPLAY_NAME,
HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
HWC2_FUNCTION_GET_DISPLAY_TYPE,
HWC2_FUNCTION_GET_DOZE_SUPPORT,
HWC2_FUNCTION_GET_HDR_CAPABILITIES,
HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
HWC2_FUNCTION_GET_RELEASE_FENCES,
HWC2_FUNCTION_PRESENT_DISPLAY,
HWC2_FUNCTION_REGISTER_CALLBACK,
HWC2_FUNCTION_SET_ACTIVE_CONFIG,
HWC2_FUNCTION_SET_CLIENT_TARGET,
HWC2_FUNCTION_SET_COLOR_MODE,
HWC2_FUNCTION_SET_COLOR_TRANSFORM,
HWC2_FUNCTION_SET_CURSOR_POSITION,
HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
HWC2_FUNCTION_SET_LAYER_BUFFER,
HWC2_FUNCTION_SET_LAYER_COLOR,
HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
HWC2_FUNCTION_SET_LAYER_DATASPACE,
HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
HWC2_FUNCTION_SET_LAYER_TRANSFORM,
HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
HWC2_FUNCTION_SET_LAYER_Z_ORDER,
HWC2_FUNCTION_SET_OUTPUT_BUFFER,
HWC2_FUNCTION_SET_POWER_MODE,
HWC2_FUNCTION_SET_VSYNC_ENABLED,
HWC2_FUNCTION_VALIDATE_DISPLAY,
}};
/* TESTCASE: Tests that the HWC2 supports all required functions. */
TEST_F(Hwc2Test, GET_FUNCTION)
{
for (hwc2_function_descriptor_t descriptor : requiredFunctions) {
hwc2_function_pointer_t pfn = getFunction(descriptor);
EXPECT_TRUE(pfn) << "failed to get function "
<< getFunctionDescriptorName(descriptor);
}
}
/* TESTCASE: Tests that the HWC2 fails to retrieve and invalid function. */
TEST_F(Hwc2Test, GET_FUNCTION_invalid_function)
{
hwc2_function_pointer_t pfn = getFunction(HWC2_FUNCTION_INVALID);
EXPECT_FALSE(pfn) << "failed to get invalid function";
}
/* TESTCASE: Tests that the HWC2 does not return an invalid capability. */
TEST_F(Hwc2Test, GET_CAPABILITIES)
{
std::vector<hwc2_capability_t> capabilities;
getCapabilities(&capabilities);
EXPECT_EQ(std::count(capabilities.begin(), capabilities.end(),
HWC2_CAPABILITY_INVALID), 0);
}
static const std::array<hwc2_callback_descriptor_t, 3> callbackDescriptors = {{
HWC2_CALLBACK_HOTPLUG,
HWC2_CALLBACK_REFRESH,
HWC2_CALLBACK_VSYNC,
}};
/* TESTCASE: Tests that the HWC2 can successfully register all required
* callback functions. */
TEST_F(Hwc2Test, REGISTER_CALLBACK)
{
hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
const_cast<char*>("data"));
for (auto descriptor : callbackDescriptors) {
ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
[]() { return; }));
}
}
/* TESTCASE: Test that the HWC2 fails to register invalid callbacks. */
TEST_F(Hwc2Test, REGISTER_CALLBACK_bad_parameter)
{
hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
const_cast<char*>("data"));
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_INVALID, data,
[]() { return; }, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can register a callback with null data. */
TEST_F(Hwc2Test, REGISTER_CALLBACK_null_data)
{
hwc2_callback_data_t data = nullptr;
for (auto descriptor : callbackDescriptors) {
ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
[]() { return; }));
}
}
/* TESTCASE: Tests that the HWC2 returns the correct display type for each
* physical display. */
TEST_F(Hwc2Test, GET_DISPLAY_TYPE)
{
for (auto display : mDisplays) {
hwc2_display_type_t type;
ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type));
EXPECT_EQ(type, HWC2_DISPLAY_TYPE_PHYSICAL) << "failed to return"
" correct display type";
}
}
/* TESTCASE: Tests that the HWC2 returns an error when the display type of a bad
* display is requested. */
TEST_F(Hwc2Test, GET_DISPLAY_TYPE_bad_display)
{
hwc2_display_t display;
hwc2_display_type_t type;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can create and destroy layers. */
TEST_F(Hwc2Test, CREATE_DESTROY_LAYER)
{
for (auto display : mDisplays) {
hwc2_layer_t layer;
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
}
/* TESTCASE: Tests that the HWC2 cannot create a layer for a bad display */
TEST_F(Hwc2Test, CREATE_LAYER_bad_display)
{
hwc2_display_t display;
hwc2_layer_t layer;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 will either support a large number of resources
* or will return no resources. */
TEST_F(Hwc2Test, CREATE_LAYER_no_resources)
{
const size_t layerCnt = 1000;
for (auto display : mDisplays) {
std::vector<hwc2_layer_t> layers;
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
}
}
/* TESTCASE: Tests that the HWC2 cannot destroy a layer for a bad display */
TEST_F(Hwc2Test, DESTROY_LAYER_bad_display)
{
hwc2_display_t badDisplay;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&badDisplay));
for (auto display : mDisplays) {
hwc2_layer_t layer = 0;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
}
/* TESTCASE: Tests that the HWC2 cannot destory a bad layer */
TEST_F(Hwc2Test, DESTROY_LAYER_bad_layer)
{
for (auto display : mDisplays) {
hwc2_layer_t layer;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX / 2, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 0, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX - 1, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 1, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer + 1, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
}
}
static const std::array<hwc2_attribute_t, 2> requiredAttributes = {{
HWC2_ATTRIBUTE_WIDTH,
HWC2_ATTRIBUTE_HEIGHT,
}};
static const std::array<hwc2_attribute_t, 3> optionalAttributes = {{
HWC2_ATTRIBUTE_VSYNC_PERIOD,
HWC2_ATTRIBUTE_DPI_X,
HWC2_ATTRIBUTE_DPI_Y,
}};
/* TESTCASE: Tests that the HWC2 can return display attributes for a valid
* config. */
TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
int32_t value;
for (auto attribute : requiredAttributes) {
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
attribute, &value));
EXPECT_GE(value, 0) << "missing required attribute "
<< getAttributeName(attribute) << " for config "
<< config;
}
for (auto attribute : optionalAttributes) {
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
attribute, &value));
}
}
}
}
/* TESTCASE: Tests that the HWC2 will return a value of -1 for an invalid
* attribute */
TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_invalid_attribute)
{
const hwc2_attribute_t attribute = HWC2_ATTRIBUTE_INVALID;
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
int32_t value;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
attribute, &value, &err));
EXPECT_EQ(value, -1) << "failed to return -1 for an invalid"
" attribute for config " << config;
}
}
}
/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad display */
TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_display)
{
hwc2_display_t display;
const hwc2_config_t config = 0;
int32_t value;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
for (auto attribute : requiredAttributes) {
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
&value, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
for (auto attribute : optionalAttributes) {
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
&value, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
}
/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad config */
TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_config)
{
for (auto display : mDisplays) {
hwc2_config_t config;
int32_t value;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
for (auto attribute : requiredAttributes) {
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
attribute, &value, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
}
for (auto attribute : optionalAttributes) {
ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
attribute, &value, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
}
}
}
/* TESTCASE: Tests that the HWC2 will get display configs for active displays */
TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
}
}
/* TESTCASE: Tests that the HWC2 will not get display configs for bad displays */
TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_bad_display)
{
hwc2_display_t display;
std::vector<hwc2_config_t> configs;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
EXPECT_TRUE(configs.empty()) << "returned configs for bad display";
}
/* TESTCASE: Tests that the HWC2 will return the same config list multiple
* times in a row. */
TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_same)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs1, configs2;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs1));
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs2));
EXPECT_TRUE(std::is_permutation(configs1.begin(), configs1.end(),
configs2.begin())) << "returned two different config sets";
}
}
/* TESTCASE: Tests that the HWC2 does not return duplicate display configs */
TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_duplicate)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
std::unordered_set<hwc2_config_t> configsSet(configs.begin(),
configs.end());
EXPECT_EQ(configs.size(), configsSet.size()) << "returned duplicate"
" configs";
}
}
/* TESTCASE: Tests that the HWC2 returns the active config for a display */
TEST_F(Hwc2Test, GET_ACTIVE_CONFIG)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
hwc2_config_t activeConfig;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig));
EXPECT_EQ(activeConfig, config) << "failed to get active config";
}
}
}
/* TESTCASE: Tests that the HWC2 does not return an active config for a bad
* display. */
TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_display)
{
hwc2_display_t display;
hwc2_config_t activeConfig;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 either begins with a valid active config
* or returns an error when getActiveConfig is called. */
TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_config)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
hwc2_config_t activeConfig;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
if (configs.empty())
return;
ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
if (err == HWC2_ERROR_NONE) {
EXPECT_NE(std::count(configs.begin(), configs.end(),
activeConfig), 0) << "active config is not found in "
" configs for display";
} else {
EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
}
}
}
/* TESTCASE: Tests that the HWC2 can set every display config as an active
* config */
TEST_F(Hwc2Test, SET_ACTIVE_CONFIG)
{
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
EXPECT_NO_FATAL_FAILURE(setActiveConfig(display, config));
}
}
}
/* TESTCASE: Tests that the HWC2 cannot set an active config for a bad display */
TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_display)
{
hwc2_display_t display;
const hwc2_config_t config = 0;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot set an invalid active config */
TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_config)
{
for (auto display : mDisplays) {
hwc2_config_t config;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
}
}
/* TESTCASE: Tests that the HWC2 returns a valid value for getDozeSupport. */
TEST_F(Hwc2Test, GET_DOZE_SUPPORT)
{
for (auto display : mDisplays) {
int32_t support = -1;
ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
EXPECT_TRUE(support == 0 || support == 1) << "invalid doze support value";
}
}
/* TESTCASE: Tests that the HWC2 cannot get doze support for a bad display. */
TEST_F(Hwc2Test, GET_DOZE_SUPPORT_bad_display)
{
hwc2_display_t display;
int32_t support = -1;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can set all supported power modes */
TEST_F(Hwc2Test, SET_POWER_MODE)
{
for (auto display : mDisplays) {
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
int32_t support = -1;
ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
if (support != 1)
return;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
HWC2_POWER_MODE_DOZE_SUSPEND));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 cannot set a power mode for a bad display. */
TEST_F(Hwc2Test, SET_POWER_MODE_bad_display)
{
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
int32_t support = -1;
ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
if (support != 1)
return;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE_SUSPEND,
&err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot set an invalid power mode value. */
TEST_F(Hwc2Test, SET_POWER_MODE_bad_parameter)
{
for (auto display : mDisplays) {
hwc2_power_mode_t mode = static_cast<hwc2_power_mode_t>(
HWC2_POWER_MODE_DOZE_SUSPEND + 1);
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, mode, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code "
<< mode;
}
}
/* TESTCASE: Tests that the HWC2 will return unsupported if it does not support
* an optional power mode. */
TEST_F(Hwc2Test, SET_POWER_MODE_unsupported)
{
for (auto display : mDisplays) {
int32_t support = -1;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
if (support == 1)
return;
ASSERT_EQ(support, 0) << "invalid doze support value";
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE,
&err));
EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
HWC2_POWER_MODE_DOZE_SUSPEND, &err));
EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
}
}
/* TESTCASE: Tests that the HWC2 can set the same power mode multiple times. */
TEST_F(Hwc2Test, SET_POWER_MODE_stress)
{
for (auto display : mDisplays) {
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
int32_t support = -1;
ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
if (support != 1)
return;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
HWC2_POWER_MODE_DOZE_SUSPEND));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
HWC2_POWER_MODE_DOZE_SUSPEND));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 can enable and disable vsync on active
* displays */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED)
{
for (auto display : mDisplays) {
hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
const_cast<char*>("data"));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
[]() { return; }));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 issues a valid vsync callback. */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED_callback)
{
for (auto display : mDisplays) {
hwc2_display_t receivedDisplay;
int64_t receivedTimestamp;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(enableVsync(display));
ASSERT_NO_FATAL_FAILURE(waitForVsync(&receivedDisplay,
&receivedTimestamp));
EXPECT_EQ(receivedDisplay, display) << "failed to get correct display";
EXPECT_GE(receivedTimestamp, 0) << "failed to get valid timestamp";
ASSERT_NO_FATAL_FAILURE(disableVsync(display));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 cannot enable a vsync for a bad display */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_display)
{
hwc2_display_t display;
hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
const_cast<char*>("data"));
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
[]() { return; }));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot enable an invalid vsync value */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_parameter)
{
for (auto display : mDisplays) {
hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
const_cast<char*>("data"));
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
[]() { return; }));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_INVALID,
&err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 can enable and disable a vsync value multiple
* times. */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED_stress)
{
for (auto display : mDisplays) {
hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
const_cast<char*>("data"));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
[]() { return; }));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 can set a vsync enable value when the display
* is off and no callback is registered. */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback_no_power)
{
const uint secs = 1;
for (auto display : mDisplays) {
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
sleep(secs);
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
}
}
/* TESTCASE: Tests that the HWC2 can set a vsync enable value when no callback
* is registered. */
TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback)
{
const uint secs = 1;
for (auto display : mDisplays) {
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
sleep(secs);
ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 returns a display name for each display */
TEST_F(Hwc2Test, GET_DISPLAY_NAME)
{
for (auto display : mDisplays) {
std::string name;
ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name));
}
}
/* TESTCASE: Tests that the HWC2 does not return a display name for a bad
* display */
TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display)
{
hwc2_display_t display;
std::string name;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can set basic composition types. */
TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setComposition, advanceComposition));
}
/* TESTCASE: Tests that the HWC2 can update a basic composition type on a
* layer. */
TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setComposition, advanceComposition));
}
/* TESTCASE: Tests that the HWC2 cannot set a composition type for a bad layer */
TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setComposition));
}
/* TESTCASE: Tests that the HWC2 cannot set a bad composition type */
TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
hwc2_error_t* outErr) {
ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
layer, HWC2_COMPOSITION_INVALID, outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer. */
TEST_F(Hwc2Test, SET_CURSOR_POSITION)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
::setCursorPosition, advanceCursorPosition));
}
/* TESTCASE: Tests that the HWC2 can update the cursor position of a layer. */
TEST_F(Hwc2Test, SET_CURSOR_POSITION_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
::setCursorPosition, advanceCursorPosition));
}
/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer when the
* composition type has not been set to HWC2_COMPOSITION_CURSOR. */
TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
cursorPosition.left, cursorPosition.top, outErr));
},
advanceCursorPosition));
}
/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad
* display. */
TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_display)
{
hwc2_display_t display;
hwc2_layer_t layer = 0;
int32_t x = 0, y = 0;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(setCursorPosition(display, layer, x, y, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad layer. */
TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display,
badLayer, cursorPosition.left, cursorPosition.top,
outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set a blend mode value of a layer. */
TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setBlendMode, advanceBlendMode));
}
/* TESTCASE: Tests that the HWC2 can update a blend mode value of a layer. */
TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setBlendMode, advanceBlendMode));
}
/* TESTCASE: Tests that the HWC2 cannot set a blend mode for a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setBlendMode));
}
/* TESTCASE: Tests that the HWC2 cannot set an invalid blend mode. */
TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
hwc2_error_t* outErr) {
ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
layer, HWC2_BLEND_MODE_INVALID, outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set the buffer of a layer. */
TEST_F(Hwc2Test, SET_LAYER_BUFFER)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setBuffer, advanceBuffer));
}
/* TESTCASE: Tests that the HWC2 can update the buffer of a layer. */
TEST_F(Hwc2Test, SET_LAYER_BUFFER_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setBuffer, advanceBuffer));
}
/* TESTCASE: Tests that the HWC2 cannot set the buffer of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
buffer_handle_t handle = nullptr;
android::base::unique_fd acquireFence;
/* If there is not available buffer for the given buffer
* properties, it should not fail this test case */
if (testLayer->getBuffer(&handle, &acquireFence) == 0) {
*outErr = HWC2_ERROR_BAD_LAYER;
return;
}
ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, badLayer,
handle, acquireFence, outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set an invalid buffer for a layer. */
TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_parameter)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
hwc2_error_t* outErr) {
buffer_handle_t handle = nullptr;
int32_t acquireFence = -1;
ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
handle, acquireFence, outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set the color of a layer. */
TEST_F(Hwc2Test, SET_LAYER_COLOR)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setColor, advanceColor));
}
/* TESTCASE: Tests that the HWC2 can update the color of a layer. */
TEST_F(Hwc2Test, SET_LAYER_COLOR_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setColor, advanceColor));
}
/* TESTCASE: Tests that the HWC2 can set the color of a layer when the
* composition type has not been set to HWC2_COMPOSITION_SOLID_COLOR. */
TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
testLayer->getColor(), outErr));
},
advanceColor));
}
/* TESTCASE: Tests that the HWC2 cannot set the color of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer,
testLayer->getColor(), outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set the dataspace of a layer. */
TEST_F(Hwc2Test, SET_LAYER_DATASPACE)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setDataspace, advanceDataspace));
}
/* TESTCASE: Tests that the HWC2 can update the dataspace of a layer. */
TEST_F(Hwc2Test, SET_LAYER_DATASPACE_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setDataspace, advanceDataspace));
}
/* TESTCASE: Tests that the HWC2 cannot set a dataspace for a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setDataspace));
}
/* TESTCASE: Tests that the HWC2 can set the display frame of a layer. */
TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setDisplayFrame, advanceDisplayFrame));
}
/* TESTCASE: Tests that the HWC2 can update the display frame of a layer. */
TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setDisplayFrame, advanceDisplayFrame));
}
/* TESTCASE: Tests that the HWC2 cannot set the display frame of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setDisplayFrame));
}
/* TESTCASE: Tests that the HWC2 can set the plane alpha of a layer. */
TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setPlaneAlpha, advancePlaneAlpha));
}
/* TESTCASE: Tests that the HWC2 can update the plane alpha of a layer. */
TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setPlaneAlpha, advancePlaneAlpha));
}
/* TESTCASE: Tests that the HWC2 cannot set a plane alpha for a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
Hwc2TestLayer* testLayer, hwc2_error_t *outErr) {
EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
badLayer, testLayer->getPlaneAlpha(), outErr));
}
));
}
/* TESTCASE: Tests that the HWC2 can set the source crop of a layer. */
TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setSourceCrop, advanceSourceCrop));
}
/* TESTCASE: Tests that the HWC2 can update the source crop of a layer. */
TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setSourceCrop, advanceSourceCrop));
}
/* TESTCASE: Tests that the HWC2 cannot set the source crop of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setSourceCrop));
}
/* TESTCASE: Tests that the HWC2 can set the surface damage of a layer. */
TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setSurfaceDamage, advanceSurfaceDamage));
}
/* TESTCASE: Tests that the HWC2 can update the surface damage of a layer. */
TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setSurfaceDamage, advanceSurfaceDamage));
}
/* TESTCASE: Tests that the HWC2 cannot set the surface damage of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setSurfaceDamage));
}
/* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */
TEST_F(Hwc2Test, SET_LAYER_TRANSFORM)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
setTransform, advanceTransform));
}
/* TESTCASE: Tests that the HWC2 can update the transform value of a layer. */
TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_update)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
setTransform, advanceTransform));
}
/* TESTCASE: Tests that the HWC2 cannot set the transform for a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setTransform));
}
/* TESTCASE: Tests that the HWC2 can set the visible region of a layer. */
TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Basic, 5,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayers* testLayers) {
EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display,
layer, testLayers->getVisibleRegion(layer)));
},
advanceVisibleRegions));
}
/* TESTCASE: Tests that the HWC2 cannot set the visible region of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setVisibleRegion));
}
/* TESTCASE: Tests that the HWC2 can set the z order of a layer. */
TEST_F(Hwc2Test, SET_LAYER_Z_ORDER)
{
ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10,
[] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
Hwc2TestLayers* testLayers) {
EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
testLayers->getZOrder(layer)));
},
/* TestLayer z orders are set during the construction of TestLayers
* and cannot be updated. There is no need (or ability) to cycle
* through additional z order configurations. */
[] (Hwc2TestLayers* /*testLayers*/) {
return false;
}
));
}
/* TESTCASE: Tests that the HWC2 can update the z order of a layer. */
TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_update)
{
const std::vector<uint32_t> zOrders = { static_cast<uint32_t>(0),
static_cast<uint32_t>(1), static_cast<uint32_t>(UINT32_MAX / 4),
static_cast<uint32_t>(UINT32_MAX / 2),
static_cast<uint32_t>(UINT32_MAX) };
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
hwc2_layer_t layer;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
for (uint32_t zOrder : zOrders) {
EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer, zOrder));
}
ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
}
}
}
/* TESTCASE: Tests that the HWC2 cannot set the z order of a bad layer. */
TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_bad_layer)
{
ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
setZOrder));
}
/* TESTCASE: Tests that the HWC2 can display a layer with basic property
* coverage */
TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic)
{
ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
[] (Hwc2Test* test, hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* /*testLayers*/) {
uint32_t numTypes, numRequests;
bool hasChanges = false;
EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
<< "wrong number of requests";
}
));
}
/* TESTCASE: Tests that the HWC2 can display 5 layers with default coverage. */
TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5)
{
ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5,
[] (Hwc2Test* test, hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* /*testLayers*/) {
uint32_t numTypes, numRequests;
bool hasChanges = false;
EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
<< "wrong number of requests";
}
));
}
/* TESTCASE: Tests that the HWC2 cannot validate a bad display */
TEST_F(Hwc2Test, VALIDATE_DISPLAY_bad_display)
{
hwc2_display_t display;
uint32_t numTypes, numRequests;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, &numRequests,
&err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can get display requests after validating a
* basic layer. */
TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_basic)
{
ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
[] (Hwc2Test* test, hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* /*testLayers*/) {
uint32_t numTypes, numRequests;
bool hasChanges = false;
ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, layers.size())
<< "wrong number of requests";
EXPECT_NO_FATAL_FAILURE(test->handleRequests(display, layers,
numRequests));
}
));
}
/* TESTCASE: Tests that the HWC2 cannot get display requests from a bad display */
TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_bad_display)
{
hwc2_display_t display;
hwc2_display_request_t displayRequests;
std::vector<hwc2_layer_t> layers;
std::vector<hwc2_layer_request_t> layerRequests;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
EXPECT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequests,
&layers, &layerRequests, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot get display requests from an non
* validated display. */
TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_not_validated)
{
ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
[] (Hwc2Test* test, hwc2_display_t display,
std::vector<hwc2_layer_t>* layers) {
hwc2_display_request_t displayRequests;
std::vector<hwc2_layer_request_t> layerRequests;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->getDisplayRequests(display,
&displayRequests, layers, &layerRequests, &err));
EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
<< "returned wrong error code";
}
));
}
/* TESTCASE: Tests that the HWC2 can get changed composition types after
* validating a basic layer. */
TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic)
{
ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
[] (Hwc2Test* test, hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* testLayers) {
uint32_t numTypes, numRequests;
bool hasChanges = false;
ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, layers.size())
<< "wrong number of requests";
EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
*testLayers, layers, numTypes));
}
));
}
/* TESTCASE: Tests that the HWC2 cannot get changed composition types from a bad
* display */
TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_bad_display)
{
hwc2_display_t display;
std::vector<hwc2_layer_t> layers;
std::vector<hwc2_composition_t> types;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
EXPECT_NO_FATAL_FAILURE(getChangedCompositionTypes(display, &layers,
&types, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot get changed composition types from an non
* validated display. */
TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_not_validated)
{
ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
[] (Hwc2Test* test, hwc2_display_t display,
std::vector<hwc2_layer_t>* layers) {
std::vector<hwc2_composition_t> types;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->getChangedCompositionTypes(
display, layers, &types, &err));
EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
<< "returned wrong error code";
}
));
}
/* TESTCASE: Tests that the HWC2 can accept display changes after validating a
* basic layer. */
TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic)
{
ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
[] (Hwc2Test* test, hwc2_display_t display,
const std::vector<hwc2_layer_t>& layers,
Hwc2TestLayers* testLayers) {
uint32_t numTypes, numRequests;
bool hasChanges = false;
ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, layers.size())
<< "wrong number of requests";
ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
*testLayers, layers, numTypes));
EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display));
}
));
}
/* TESTCASE: Tests that the HWC2 cannot accept display changes from a bad
* display */
TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_bad_display)
{
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
EXPECT_NO_FATAL_FAILURE(acceptDisplayChanges(display, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot accept display changes from an non
* validated display. */
TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_not_validated)
{
ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
[] (Hwc2Test* test, hwc2_display_t display,
std::vector<hwc2_layer_t>* /*layers*/) {
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display, &err));
EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
<< "returned wrong error code";
}
));
}
/* TESTCASE: Tests that the HWC2 supports client target with required values */
TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT)
{
ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t display,
const Hwc2TestClientTargetSupport& testClientTargetSupport) {
const Area bufferArea = testClientTargetSupport.getBufferArea();
const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
bufferArea.width, bufferArea.height, format,
testClientTargetSupport.getDataspace()));
},
advanceClientTargetSupport));
}
/* TESTCASE: Tests that the HWC2 cannot get client target support for a bad
* display. */
TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_bad_display)
{
ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t /*display*/,
const Hwc2TestClientTargetSupport& testClientTargetSupport) {
const Area bufferArea = testClientTargetSupport.getBufferArea();
const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
hwc2_display_t badDisplay;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(badDisplay,
bufferArea.width, bufferArea.height, format,
testClientTargetSupport.getDataspace(), &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
},
advanceClientTargetSupport));
}
/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
* for a variety of client target values. */
TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_unsupported)
{
ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Complete,
[] (Hwc2Test* test, hwc2_display_t display,
const Hwc2TestClientTargetSupport& testClientTargetSupport) {
const Area bufferArea = testClientTargetSupport.getBufferArea();
const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
bufferArea.width, bufferArea.height, format,
testClientTargetSupport.getDataspace(), &err));
EXPECT_TRUE(err == HWC2_ERROR_NONE
|| err == HWC2_ERROR_UNSUPPORTED)
<< "returned wrong error code";
},
advanceClientTargetSupport));
}
/* TESTCASE: Tests that the HWC2 can set a client target buffer for a basic
* layer. */
TEST_F(Hwc2Test, SET_CLIENT_TARGET_basic)
{
const Dataspace dataspace = Dataspace::UNKNOWN;
const hwc_region_t damage = { };
const size_t layerCnt = 1;
for (auto display : mDisplays) {
std::vector<hwc2_config_t> configs;
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
for (auto config : configs) {
Area displayArea;
std::vector<hwc2_layer_t> layers;
ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Basic,
displayArea);
if (!testLayers.optimizeLayouts())
continue;
Hwc2TestClientTarget testClientTarget;
do {
std::set<hwc2_layer_t> clientLayers;
std::set<hwc2_layer_t> clearLayers;
uint32_t numTypes, numRequests;
bool hasChanges, skip;
bool flipClientTarget;
buffer_handle_t handle;
int32_t acquireFence;
ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
&testLayers, &skip));
if (skip)
continue;
ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
&numRequests, &hasChanges));
if (hasChanges)
EXPECT_LE(numTypes, layers.size())
<< "wrong number of requests";
ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
testLayers, layers, numTypes, &clientLayers));
ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
numRequests, &clearLayers, &flipClientTarget));
ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
clearLayers, flipClientTarget, displayArea, &handle,
&acquireFence), 0);
EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle,
acquireFence, dataspace, damage));
if (acquireFence >= 0)
close(acquireFence);
} while (testLayers.advance());
ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
}
ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
}
}
/* TESTCASE: Tests that the HWC2 cannot set a client target for a bad display. */
TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display)
{
hwc2_display_t display;
std::vector<hwc2_layer_t> layers;
const Area displayArea = {0, 0};
Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Default, displayArea);
std::set<hwc2_layer_t> clientLayers;
std::set<hwc2_layer_t> flipClientTargetLayers;
bool flipClientTarget = true;
const Dataspace dataspace = Dataspace::UNKNOWN;
const hwc_region_t damage = { };
buffer_handle_t handle;
int32_t acquireFence;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
Hwc2TestClientTarget testClientTarget;
ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
flipClientTargetLayers, flipClientTarget, displayArea, &handle,
&acquireFence), 0);
EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
dataspace, damage, &err));
if (acquireFence >= 0)
close(acquireFence);
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can present 1 default layer. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_default_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 default layers. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_default_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 3 default layers. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_default_3)
{
const size_t layerCnt = 3;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 4 default layers. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_default_4)
{
const size_t layerCnt = 4;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 5 default layers. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_default_5)
{
const size_t layerCnt = 5;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 6 default layers. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_default_6)
{
const size_t layerCnt = 6;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* blend mode. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Basic},
{Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* blend mode. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* buffer. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_buffer_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* color. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_color_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::Color, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* color. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_color_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
{Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic},
{Hwc2TestPropertyName::Color, Hwc2TestCoverage::Basic}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* composition. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_composition_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* cursor. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* cursor. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* dataspace. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_dataspace_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* display frame. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* display frame. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 3 layers with complete coverage of
* display frame. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_3)
{
const size_t layerCnt = 3;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 4 layers with complete coverage of
* display frame. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_4)
{
const size_t layerCnt = 4;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* plane alpha. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
{Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* plane alpha. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
{Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
bool optimize = false;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* source crop. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* source crop. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* surface damage. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_surface_damage_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::SurfaceDamage, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* transform. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
* transform. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_2)
{
const size_t layerCnt = 2;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
{{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete},
{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
* basic. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_basic_1)
{
const size_t layerCnt = 1;
Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
bool optimize = true;
ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
optimize));
}
/* TESTCASE: Tests that the HWC2 cannot present a bad display. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_bad_display)
{
hwc2_display_t display;
int32_t presentFence;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(presentDisplay(display, &presentFence, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot present an unvalidated display. */
TEST_F(Hwc2Test, PRESENT_DISPLAY_not_validated)
{
ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 1,
[] (Hwc2Test* test, hwc2_display_t display,
const std::vector<hwc2_layer_t>& /*layers*/,
Hwc2TestLayers* /*testLayers*/) {
int32_t presentFence;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
HWC2_POWER_MODE_ON));
ASSERT_NO_FATAL_FAILURE(test->enableVsync(display));
ASSERT_NO_FATAL_FAILURE(test->waitForVsync());
ASSERT_NO_FATAL_FAILURE(test->presentDisplay(display,
&presentFence, &err));
EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
<< "returned wrong error code";
ASSERT_NO_FATAL_FAILURE(test->disableVsync(display));
ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
HWC2_POWER_MODE_OFF));
}
));
}
/* TESTCASE: Tests that the HWC2 cannot get release fences from a bad display. */
TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display)
{
hwc2_display_t display;
std::vector<hwc2_layer_t> layers;
std::vector<int32_t> fences;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
static const std::array<ColorMode, 9> androidColorModes = {{
ColorMode::NATIVE,
ColorMode::STANDARD_BT601_625,
ColorMode::STANDARD_BT601_625_UNADJUSTED,
ColorMode::STANDARD_BT601_525,
ColorMode::STANDARD_BT601_525_UNADJUSTED,
ColorMode::STANDARD_BT709,
ColorMode::DCI_P3,
ColorMode::SRGB,
ColorMode::ADOBE_RGB,
}};
/* TESTCASE: Tests that the HWC2 can get the color modes for a display. The
* display must support ColorMode::NATIVE */
TEST_F(Hwc2Test, GET_COLOR_MODES)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
std::vector<ColorMode> colorModes;
ASSERT_NO_FATAL_FAILURE(test->getColorModes(display,
&colorModes));
EXPECT_NE(std::count(colorModes.begin(), colorModes.end(),
ColorMode::NATIVE), 0) << "all displays"
" must support ColorMode::NATIVE";
}
));
}
/* TESTCASE: Tests that the HWC2 cannot get color modes from a bad display. */
TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display)
{
hwc2_display_t display;
std::vector<ColorMode> colorModes;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getColorModes(display, &colorModes, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 can set the required color mode on a display. */
TEST_F(Hwc2Test, SET_COLOR_MODES)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
const ColorMode colorMode = ColorMode::NATIVE;
EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode));
}
));
}
/* TESTCASE: Tests that the HWC2 cannot set a color mode on a bad display. */
TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display)
{
hwc2_display_t display;
const ColorMode colorMode = ColorMode::NATIVE;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(setColorMode(display, colorMode, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot set an invalid color mode. */
TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
const ColorMode colorMode = static_cast<ColorMode>(-1);
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode,
&err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
<< "returned wrong error code";
}
));
}
/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
* for all valid color modes. */
TEST_F(Hwc2Test, SET_COLOR_MODES_unsupported)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
for (auto colorMode : androidColorModes) {
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setColorMode(display,
colorMode, &err));
EXPECT_TRUE(err == HWC2_ERROR_NONE
|| err == HWC2_ERROR_UNSUPPORTED)
<< "returned wrong error code";
}
}
));
}
/* TESTCASE: Tests that the HWC2 gets the HDR capabilities for a display and
* test if they are valid. */
TEST_F(Hwc2Test, GET_HDR_CAPABILITIES)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
std::vector<android_hdr_t> hdrCapabilities;
float maxLuminance, maxAverageLuminance, minLuminance;
EXPECT_NO_FATAL_FAILURE(test->getHdrCapabilities(display,
&hdrCapabilities, &maxLuminance, &maxAverageLuminance,
&minLuminance));
if (hdrCapabilities.empty())
return;
EXPECT_GE(maxLuminance, maxAverageLuminance);
EXPECT_GE(maxAverageLuminance, minLuminance);
}
));
}
/* TESTCASE: Tests that the HWC2 cannot get hdr capabilities from a bad display */
TEST_F(Hwc2Test, GET_HDR_CAPABILITIES_bad_display)
{
hwc2_display_t display;
std::vector<android_hdr_t> hdrCapabilities;
float maxLuminance, maxAverageLuminance, minLuminance;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(getHdrCapabilities(display, &hdrCapabilities,
&maxLuminance, &maxAverageLuminance, &minLuminance, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
static const std::array<float, 16> identityMatrix = {{
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
}};
/* Values for the color transform matrices were precomputed using the source code
* in surfaceflinger/Effects/Daltonizer.cpp. */
static const std::array<const std::array<float, 16>, 5> exampleMatrices = {{
identityMatrix,
/* Converts RGB color to the XYZ space */
{{ 0.4124, 0.2126, 0.0193, 0,
0.3576, 0.7152, 0.1192, 0,
0.1805, 0.0722, 0.9505, 0,
0 , 0 , 0 , 1 }},
/* Protanomaly */
{{ 0.068493, 0.931506, 0, 0,
0.068493, 0.931507, 0, 0,
0.013626, -0.013626, 1, 0,
0, 0, 0, 1 }},
/* Deuteranomaly */
{{ 0.288299, 0.711701, 0, 0,
0.052709, 0.947291, 0, 0,
-0.257912, 0.257912, 1, 0,
0, 0, 0, 1 }},
/* Tritanomaly */
{{ 1, -0.805712, 0.805712, 0,
0, 0.378838, 0.621162, 0,
0, 0.104823, 0.895177, 0,
0, 0, 0, 1 }},
}};
/* TESTCASE: Tests that the HWC2 can set the identity color transform */
TEST_F(Hwc2Test, SET_COLOR_TRANSFORM)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
identityMatrix, HAL_COLOR_TRANSFORM_IDENTITY));
}
));
}
/* TESTCASE: Tests that the HWC2 cannot set the color transform for a bad
* display. */
TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_display)
{
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(setColorTransform(display, identityMatrix,
HAL_COLOR_TRANSFORM_IDENTITY, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot set an invalid color transform. */
TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_parameter)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
const android_color_transform_t hint =
static_cast<android_color_transform_t>(-1);
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setColorTransform(display,
identityMatrix, hint, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
<< "returned wrong error code";
}
));
}
/* TESTCASE: Tests that the HWC2 can set an arbitrary color matrix. */
TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_arbitrary_matrix)
{
ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
[] (Hwc2Test* test, hwc2_display_t display) {
const android_color_transform_t hint =
HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
for (const std::array<float, 16>& matrix : exampleMatrices) {
EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
matrix, hint));
}
}
));
}
/* TESTCASE: Tests that the HWC2 create an destory virtual displays. */
TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY)
{
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
[] (Hwc2Test* /*test*/, hwc2_display_t /*display*/,
Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) { }));
}
/* TESTCASE: Tests that the HWC2 can create and destroy multiple virtual
* displays. */
TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY_multiple)
{
Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
std::vector<hwc2_display_t> displays;
do {
const UnsignedArea& dimension =
testVirtualDisplay.getDisplayDimension();
android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
dimension.height, &desiredFormat, &display, &err));
EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
|| err == HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
EXPECT_GE(desiredFormat, 0) << "invalid format";
if (err == HWC2_ERROR_NONE)
displays.push_back(display);
} while (testVirtualDisplay.advance());
for (hwc2_display_t display : displays) {
EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
}
}
/* TESTCASE: Tests that the HWC2 cannot destroy a bad virtual displays. */
TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_display)
{
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
}
/* TESTCASE: Tests that the HWC2 cannot destroy a physical display. */
TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_parameter)
{
hwc2_error_t err = HWC2_ERROR_NONE;
for (auto display : mDisplays) {
ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
}
}
/* TESTCASE: Tests that the HWC2 can get the max virtual display count. */
TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT)
{
uint32_t maxCnt;
ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
}
/* TESTCASE: Tests that the HWC2 returns the same max virtual display count for
* each call. */
TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_duplicate)
{
uint32_t maxCnt1, maxCnt2;
ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt1));
ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt2));
EXPECT_EQ(maxCnt1, maxCnt2) << "returned two different max virtual display"
" counts";
}
/* TESTCASE: Tests that the HWC2 can create the max number of virtual displays
* that it reports. */
TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_create_max)
{
std::vector<hwc2_display_t> displays;
uint32_t maxCnt;
ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
while (displays.size() < maxCnt) {
uint32_t width = 1920, height = 1080;
android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
hwc2_display_t display;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(width, height,
&desiredFormat, &display, &err));
EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
<< "returned wrong error code";
if (err != HWC2_ERROR_NONE)
break;
displays.push_back(display);
}
for (hwc2_display_t display : displays) {
EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
}
}
/* TESTCASE: Tests that the HWC2 can set an output buffer for a virtual
* display. */
TEST_F(Hwc2Test, SET_OUTPUT_BUFFER)
{
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
[] (Hwc2Test* test, hwc2_display_t display,
Hwc2TestVirtualDisplay* testVirtualDisplay) {
buffer_handle_t handle;
android::base::unique_fd acquireFence;
if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) >= 0)
EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display,
handle, acquireFence));
}));
}
/* TESTCASE: Tests that the HWC2 cannot set an output buffer for a bad display */
TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_display)
{
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t /*display*/,
Hwc2TestVirtualDisplay* testVirtualDisplay) {
hwc2_display_t badDisplay;
buffer_handle_t handle;
android::base::unique_fd acquireFence;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) < 0)
return;
ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay,
handle, acquireFence, &err));
EXPECT_TRUE(err == HWC2_ERROR_BAD_DISPLAY)
<< "returned wrong error code";
}));
}
/* TESTCASE: Tests that the HWC2 cannot set an invalid output buffer. */
TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_parameter)
{
ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
[] (Hwc2Test* test, hwc2_display_t display,
Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) {
const buffer_handle_t handle = nullptr;
uint32_t releaseFence = -1;
hwc2_error_t err = HWC2_ERROR_NONE;
ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(display, handle,
releaseFence, &err));
EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
<< "returned wrong error code";
}));
}
/* TESTCASE: Tests that the HWC2 cannot set an output buffer for non virtual
* display */
TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_unsupported)
{
for (auto display : mDisplays) {
Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
do {
buffer_handle_t handle;
android::base::unique_fd acquireFence;
hwc2_error_t err = HWC2_ERROR_NONE;
if (testVirtualDisplay.getOutputBuffer(&handle, &acquireFence) < 0)
continue;
ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle,
acquireFence, &err));
EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
} while (testVirtualDisplay.advance());
}
}
/* TESTCASE: Tests that the HWC2 can dump debug information. */
TEST_F(Hwc2Test, DUMP)
{
std::string buffer;
ASSERT_NO_FATAL_FAILURE(dump(&buffer));
}
/*
* TODO(b/64724708): Hwc2TestPropertyName::BufferArea MUST be default for all
* virtual display tests as we don't handle this case correctly.
*
* Only default dataspace is supported in our drawing code.
*/
const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>
virtualDisplayExceptions =
{{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Default},
{Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Default}};
/* TESTCASE: Tests that the HWC2 can present 1 layer with default coverage on a
* virtual display. */
TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_1)
{
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
const size_t layerCnt = 1;
ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
virtualDisplayExceptions));
}
/* TESTCASE: Tests that the HWC2 can present 1 layer with basic coverage on a
* virtual display. */
TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_basic_1)
{
Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
const size_t layerCnt = 1;
ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
virtualDisplayExceptions));
}
/* TESTCASE: Tests that the HWC2 can present 2 layers with default coverage on a
* virtual display. */
TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_2)
{
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
const size_t layerCnt = 2;
ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
virtualDisplayExceptions));
}
/* TESTCASE: Tests that the HWC2 can present 3 layers with default coverage on a
* virtual display. */
TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_3)
{
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
const size_t layerCnt = 3;
ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
virtualDisplayExceptions));
}
/* TESTCASE: Tests that the HWC2 can present 4 layers with default coverage on a
* virtual display. */
TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_4)
{
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
const size_t layerCnt = 4;
ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
virtualDisplayExceptions));
}
/* TESTCASE: Tests that the HWC2 can present 5 layers with default coverage on a
* virtual display. */
TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_5)
{
Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
const size_t layerCnt = 5;
ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
virtualDisplayExceptions));
}