blob: f83b26e86c498251ed3df0746a2a5c0c69e2125e [file] [log] [blame]
#include <android-base/properties.h>
#include <base/logging.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <poll.h>
#include <android/hardware_buffer.h>
#include <algorithm>
#include <array>
#include <set>
#include <thread>
#include <vector>
#include <dvr/dvr_configuration_data.h>
#include <dvr/dvr_deleter.h>
#include <dvr/dvr_display_manager.h>
#include <dvr/dvr_surface.h>
#include <pdx/status.h>
using android::pdx::ErrorStatus;
using android::pdx::Status;
namespace android {
namespace dvr {
namespace {
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, nullptr_t) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, int32_t value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
attribute.value.int32_value = value;
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, int64_t value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT64;
attribute.value.int64_value = value;
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, bool value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
attribute.value.bool_value = value;
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, float value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT;
attribute.value.float_value = value;
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
const std::array<float, 2>& value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2;
std::copy(value.begin(), value.end(), attribute.value.float2_value);
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
const std::array<float, 3>& value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3;
std::copy(value.begin(), value.end(), attribute.value.float3_value);
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
const std::array<float, 4>& value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4;
std::copy(value.begin(), value.end(), attribute.value.float4_value);
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
const std::array<float, 8>& value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8;
std::copy(value.begin(), value.end(), attribute.value.float8_value);
return attribute;
}
DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
const std::array<float, 16>& value) {
DvrSurfaceAttribute attribute;
attribute.key = key;
attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16;
std::copy(value.begin(), value.end(), attribute.value.float16_value);
return attribute;
}
Status<UniqueDvrSurface> CreateApplicationSurface(bool visible = false,
int32_t z_order = 0) {
DvrSurface* surface = nullptr;
DvrSurfaceAttribute attributes[] = {
MakeAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, z_order),
MakeAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, visible)};
const int ret = dvrSurfaceCreate(
attributes, std::extent<decltype(attributes)>::value, &surface);
if (ret < 0)
return ErrorStatus(-ret);
else
return {UniqueDvrSurface(surface)};
}
Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity,
size_t metadata_size) {
DvrWriteBufferQueue* queue;
const int ret = dvrSurfaceCreateWriteBufferQueue(
surface.get(), width, height, format, layer_count, usage, capacity,
metadata_size, &queue);
if (ret < 0)
return ErrorStatus(-ret);
else
return {UniqueDvrWriteBufferQueue(queue)};
}
class TestDisplayManager {
public:
TestDisplayManager(UniqueDvrDisplayManager display_manager,
UniqueDvrSurfaceState surface_state)
: display_manager_(std::move(display_manager)),
surface_state_(std::move(surface_state)) {
const int fd = dvrDisplayManagerGetEventFd(display_manager_.get());
LOG_IF(INFO, fd < 0) << "Failed to get event fd: " << strerror(-fd);
display_manager_event_fd_ = fd;
}
Status<UniqueDvrReadBufferQueue> GetReadBufferQueue(int surface_id,
int queue_id) {
DvrReadBufferQueue* queue;
const int ret = dvrDisplayManagerGetReadBufferQueue(
display_manager_.get(), surface_id, queue_id, &queue);
if (ret < 0)
return ErrorStatus(-ret);
else
return {UniqueDvrReadBufferQueue(queue)};
}
Status<void> UpdateSurfaceState() {
const int ret = dvrDisplayManagerGetSurfaceState(display_manager_.get(),
surface_state_.get());
if (ret < 0)
return ErrorStatus(-ret);
else
return {};
}
enum : int { kTimeoutMs = 10000 }; // 10s
Status<void> WaitForUpdate(int timeout_ms = kTimeoutMs) {
if (display_manager_event_fd_ < 0)
return ErrorStatus(-display_manager_event_fd_);
pollfd pfd = {display_manager_event_fd_, POLLIN, 0};
const int count = poll(&pfd, 1, timeout_ms);
if (count < 0)
return ErrorStatus(errno);
else if (count == 0)
return ErrorStatus(ETIMEDOUT);
int events;
const int ret = dvrDisplayManagerTranslateEpollEventMask(
display_manager_.get(), pfd.revents, &events);
if (ret < 0)
return ErrorStatus(-ret);
else if (events & POLLIN)
return UpdateSurfaceState();
else
return ErrorStatus(EPROTO);
}
Status<size_t> GetSurfaceCount() {
size_t count = 0;
const int ret =
dvrSurfaceStateGetSurfaceCount(surface_state_.get(), &count);
if (ret < 0)
return ErrorStatus(-ret);
else
return {count};
}
Status<DvrSurfaceUpdateFlags> GetUpdateFlags(size_t surface_index) {
DvrSurfaceUpdateFlags update_flags;
const int ret = dvrSurfaceStateGetUpdateFlags(surface_state_.get(),
surface_index, &update_flags);
if (ret < 0)
return ErrorStatus(-ret);
else
return {update_flags};
}
Status<int> GetSurfaceId(size_t surface_index) {
int surface_id;
const int ret = dvrSurfaceStateGetSurfaceId(surface_state_.get(),
surface_index, &surface_id);
if (ret < 0)
return ErrorStatus(-ret);
else
return {surface_id};
}
Status<int> GetProcessId(size_t surface_index) {
int process_id;
const int ret = dvrSurfaceStateGetProcessId(surface_state_.get(),
surface_index, &process_id);
if (ret < 0)
return ErrorStatus(-ret);
else
return {process_id};
}
Status<std::vector<DvrSurfaceAttribute>> GetAttributes(size_t surface_index) {
std::vector<DvrSurfaceAttribute> attributes;
size_t count = 0;
const int ret = dvrSurfaceStateGetAttributeCount(surface_state_.get(),
surface_index, &count);
if (ret < 0)
return ErrorStatus(-ret);
attributes.resize(count);
const ssize_t return_count = dvrSurfaceStateGetAttributes(
surface_state_.get(), surface_index, attributes.data(), count);
if (return_count < 0)
return ErrorStatus(-return_count);
attributes.resize(return_count);
return {std::move(attributes)};
}
Status<std::vector<int>> GetQueueIds(size_t surface_index) {
std::vector<int> queue_ids;
size_t count = 0;
const int ret = dvrSurfaceStateGetQueueCount(surface_state_.get(),
surface_index, &count);
if (ret < 0)
return ErrorStatus(-ret);
if (count > 0) {
queue_ids.resize(count);
const ssize_t return_count = dvrSurfaceStateGetQueueIds(
surface_state_.get(), surface_index, queue_ids.data(), count);
if (return_count < 0)
return ErrorStatus(-return_count);
queue_ids.resize(return_count);
}
return {std::move(queue_ids)};
}
Status<std::vector<uint8_t>> GetConfigData(int config_type) {
uint8_t* data = nullptr;
size_t data_size = 0;
int error = dvrConfigurationDataGet(config_type, &data, &data_size);
if (error < 0) {
return ErrorStatus(-error);
}
if (!data || data_size == 0) {
return ErrorStatus(EINVAL);
}
std::vector<uint8_t> data_result(data, data + data_size);
dvrConfigurationDataDestroy(data);
std::string s(data, data + data_size);
return {std::move(data_result)};
}
private:
UniqueDvrDisplayManager display_manager_;
UniqueDvrSurfaceState surface_state_;
// Owned by object in display_manager_, do not explicitly close.
int display_manager_event_fd_;
TestDisplayManager(const TestDisplayManager&) = delete;
void operator=(const TestDisplayManager&) = delete;
};
class DvrDisplayManagerTest : public ::testing::Test {
protected:
void SetUp() override {
int ret;
DvrDisplayManager* display_manager;
DvrSurfaceState* surface_state;
ret = dvrDisplayManagerCreate(&display_manager);
ASSERT_EQ(0, ret) << "Failed to create display manager client";
ASSERT_NE(nullptr, display_manager);
ret = dvrSurfaceStateCreate(&surface_state);
ASSERT_EQ(0, ret) << "Failed to create surface state object";
ASSERT_NE(nullptr, surface_state);
manager_.reset(
new TestDisplayManager(UniqueDvrDisplayManager(display_manager),
UniqueDvrSurfaceState(surface_state)));
}
void TearDown() override {}
std::unique_ptr<TestDisplayManager> manager_;
};
// TODO(eieio): Consider moving these somewhere more central because they are
// broadly useful.
template <typename T>
testing::AssertionResult StatusOk(const char* status_expression,
const Status<T>& status) {
if (!status.ok()) {
return testing::AssertionFailure()
<< "(" << status_expression
<< ") expected to indicate success but actually contains error ("
<< status.error() << ")";
} else {
return testing::AssertionSuccess();
}
}
template <typename T>
testing::AssertionResult StatusError(const char* status_expression,
const Status<T>& status) {
if (status.ok()) {
return testing::AssertionFailure()
<< "(" << status_expression
<< ") expected to indicate error but instead indicates success.";
} else {
return testing::AssertionSuccess();
}
}
template <typename T>
testing::AssertionResult StatusHasError(const char* status_expression,
const char* /*error_code_expression*/,
const Status<T>& status,
int error_code) {
if (status.ok()) {
return StatusError(status_expression, status);
} else if (status.error() != error_code) {
return testing::AssertionFailure()
<< "(" << status_expression << ") expected to indicate error ("
<< error_code << ") but actually indicates error (" << status.error()
<< ")";
} else {
return testing::AssertionSuccess();
}
}
template <typename T, typename U>
testing::AssertionResult StatusHasValue(const char* status_expression,
const char* /*value_expression*/,
const Status<T>& status,
const U& value) {
if (!status.ok()) {
return StatusOk(status_expression, status);
} else if (status.get() != value) {
return testing::AssertionFailure()
<< "(" << status_expression << ") expected to contain value ("
<< testing::PrintToString(value) << ") but actually contains value ("
<< testing::PrintToString(status.get()) << ")";
} else {
return testing::AssertionSuccess();
}
}
template <typename T, typename Op>
testing::AssertionResult StatusPred(const char* status_expression,
const char* pred_expression,
const Status<T>& status, Op pred) {
if (!status.ok()) {
return StatusOk(status_expression, status);
} else if (!pred(status.get())) {
return testing::AssertionFailure()
<< status_expression << " value ("
<< testing::PrintToString(status.get())
<< ") failed to pass predicate " << pred_expression;
} else {
return testing::AssertionSuccess();
}
}
#define ASSERT_STATUS_OK(status) ASSERT_PRED_FORMAT1(StatusOk, status)
#define ASSERT_STATUS_ERROR(status) ASSERT_PRED_FORMAT1(StatusError, status)
#define ASSERT_STATUS_ERROR_VALUE(value, status) \
ASSERT_PRED_FORMAT2(StatusHasError, status, value)
#define ASSERT_STATUS_EQ(value, status) \
ASSERT_PRED_FORMAT2(StatusHasValue, status, value)
#define EXPECT_STATUS_OK(status) EXPECT_PRED_FORMAT1(StatusOk, status)
#define EXPECT_STATUS_ERROR(status) EXPECT_PRED_FORMAT1(StatusError, status)
#define EXPECT_STATUS_ERROR_VALUE(value, status) \
EXPECT_PRED_FORMAT2(StatusHasError, status, value)
#define EXPECT_STATUS_EQ(value, status) \
EXPECT_PRED_FORMAT2(StatusHasValue, status, value)
#define EXPECT_STATUS_PRED(pred, status) \
EXPECT_PRED_FORMAT2(StatusPred, status, pred)
#if 0
// Verify utility predicate/macro functionality. This section is commented out
// because it is designed to fail in some cases to validate the helpers.
TEST_F(DvrDisplayManagerTest, ExpectVoid) {
Status<void> status_error{ErrorStatus{EINVAL}};
Status<void> status_ok{};
EXPECT_STATUS_ERROR(status_error);
EXPECT_STATUS_ERROR(status_ok);
EXPECT_STATUS_OK(status_error);
EXPECT_STATUS_OK(status_ok);
EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
}
TEST_F(DvrDisplayManagerTest, ExpectInt) {
Status<int> status_error{ErrorStatus{EINVAL}};
Status<int> status_ok{10};
EXPECT_STATUS_ERROR(status_error);
EXPECT_STATUS_ERROR(status_ok);
EXPECT_STATUS_OK(status_error);
EXPECT_STATUS_OK(status_ok);
EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
EXPECT_STATUS_EQ(10, status_error);
EXPECT_STATUS_EQ(20, status_error);
EXPECT_STATUS_EQ(10, status_ok);
EXPECT_STATUS_EQ(20, status_ok);
auto pred1 = [](const auto& value) { return value < 15; };
auto pred2 = [](const auto& value) { return value > 5; };
auto pred3 = [](const auto& value) { return value > 15; };
auto pred4 = [](const auto& value) { return value < 5; };
EXPECT_STATUS_PRED(pred1, status_error);
EXPECT_STATUS_PRED(pred2, status_error);
EXPECT_STATUS_PRED(pred3, status_error);
EXPECT_STATUS_PRED(pred4, status_error);
EXPECT_STATUS_PRED(pred1, status_ok);
EXPECT_STATUS_PRED(pred2, status_ok);
EXPECT_STATUS_PRED(pred3, status_ok);
EXPECT_STATUS_PRED(pred4, status_ok);
}
#endif
TEST_F(DvrDisplayManagerTest, SurfaceCreateEvent) {
// Get surface state and verify there are no surfaces.
ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
// Get flags for invalid surface index.
EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetUpdateFlags(0));
// Create an application surface.
auto surface_status = CreateApplicationSurface();
ASSERT_STATUS_OK(surface_status);
UniqueDvrSurface surface = surface_status.take();
ASSERT_NE(nullptr, surface.get());
const int surface_id = dvrSurfaceGetId(surface.get());
ASSERT_GE(surface_id, 0);
// Now there should be one new surface.
ASSERT_STATUS_OK(manager_->WaitForUpdate());
EXPECT_STATUS_EQ(1u, manager_->GetSurfaceCount());
// Verify the new surface flag is set.
auto check_flags = [](const auto& value) {
return value & DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE;
};
EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
// Verify the surface id matches.
EXPECT_STATUS_EQ(surface_id, manager_->GetSurfaceId(0));
// Verify the owning process of the surface.
EXPECT_STATUS_EQ(getpid(), manager_->GetProcessId(0));
surface.reset();
ASSERT_STATUS_OK(manager_->WaitForUpdate());
EXPECT_STATUS_EQ(0u, manager_->GetSurfaceCount());
}
TEST_F(DvrDisplayManagerTest, SurfaceAttributeEvent) {
// Get surface state and verify there are no surfaces.
ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
// Get attributes for an invalid surface index.
EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetAttributes(0));
const bool kInitialVisibility = true;
const int32_t kInitialZOrder = 10;
auto surface_status =
CreateApplicationSurface(kInitialVisibility, kInitialZOrder);
ASSERT_STATUS_OK(surface_status);
auto surface = surface_status.take();
ASSERT_NE(nullptr, surface.get());
ASSERT_STATUS_OK(manager_->WaitForUpdate());
ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
// Check the initial attribute values.
auto attribute_status = manager_->GetAttributes(0);
ASSERT_STATUS_OK(attribute_status);
auto attributes = attribute_status.take();
EXPECT_GE(attributes.size(), 2u);
std::set<int32_t> actual_keys;
std::set<int32_t> expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
DVR_SURFACE_ATTRIBUTE_VISIBLE};
// Collect all the keys in attributes that match the expected keys.
auto compare_keys = [](const auto& attributes, const auto& expected_keys) {
std::set<int32_t> keys;
for (const auto& attribute : attributes) {
if (expected_keys.find(attribute.key) != expected_keys.end())
keys.emplace(attribute.key);
}
return keys;
};
// If the sets match then attributes contained at least the expected keys,
// even if other keys were also present.
actual_keys = compare_keys(attributes, expected_keys);
EXPECT_EQ(expected_keys, actual_keys);
std::vector<DvrSurfaceAttribute> attributes_to_set = {
MakeAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, 0)};
// Test invalid args.
EXPECT_EQ(-EINVAL, dvrSurfaceSetAttributes(nullptr, attributes_to_set.data(),
attributes_to_set.size()));
EXPECT_EQ(-EINVAL, dvrSurfaceSetAttributes(surface.get(), nullptr,
attributes_to_set.size()));
// Test attribute change events.
ASSERT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
attributes_to_set.size()));
ASSERT_STATUS_OK(manager_->WaitForUpdate());
// Verify the attributes changed flag is set.
auto check_flags = [](const auto& value) {
return value & DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED;
};
EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
attribute_status = manager_->GetAttributes(0);
ASSERT_STATUS_OK(attribute_status);
attributes = attribute_status.take();
EXPECT_GE(attributes.size(), 2u);
expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
DVR_SURFACE_ATTRIBUTE_VISIBLE};
actual_keys.clear();
actual_keys = compare_keys(attributes, expected_keys);
EXPECT_EQ(expected_keys, actual_keys);
// Test setting and then deleting an attribute.
const DvrSurfaceAttributeKey kUserKey = 1;
attributes_to_set = {MakeAttribute(kUserKey, 1024)};
ASSERT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
attributes_to_set.size()));
ASSERT_STATUS_OK(manager_->WaitForUpdate());
EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
attribute_status = manager_->GetAttributes(0);
ASSERT_STATUS_OK(attribute_status);
attributes = attribute_status.take();
EXPECT_GE(attributes.size(), 2u);
expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER, DVR_SURFACE_ATTRIBUTE_VISIBLE,
kUserKey};
actual_keys.clear();
actual_keys = compare_keys(attributes, expected_keys);
EXPECT_EQ(expected_keys, actual_keys);
// Delete the attribute.
attributes_to_set = {MakeAttribute(kUserKey, nullptr)};
ASSERT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
attributes_to_set.size()));
ASSERT_STATUS_OK(manager_->WaitForUpdate());
EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
attribute_status = manager_->GetAttributes(0);
ASSERT_STATUS_OK(attribute_status);
attributes = attribute_status.take();
EXPECT_GE(attributes.size(), 2u);
expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER, DVR_SURFACE_ATTRIBUTE_VISIBLE,
kUserKey};
actual_keys.clear();
actual_keys = compare_keys(attributes, expected_keys);
EXPECT_NE(expected_keys, actual_keys);
// Test deleting a reserved attribute.
attributes_to_set = {MakeAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, nullptr)};
EXPECT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
attributes_to_set.size()));
// Failed attribute operations should not trigger update events.
const int kTimeoutMs = 100; // 0.1s
EXPECT_STATUS_ERROR_VALUE(ETIMEDOUT, manager_->WaitForUpdate(kTimeoutMs));
attribute_status = manager_->GetAttributes(0);
ASSERT_STATUS_OK(attribute_status);
attributes = attribute_status.take();
EXPECT_GE(attributes.size(), 2u);
expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
DVR_SURFACE_ATTRIBUTE_VISIBLE};
actual_keys.clear();
actual_keys = compare_keys(attributes, expected_keys);
EXPECT_EQ(expected_keys, actual_keys);
}
TEST_F(DvrDisplayManagerTest, SurfaceAttributeTypes) {
// Create an application surface.
auto surface_status = CreateApplicationSurface();
ASSERT_STATUS_OK(surface_status);
UniqueDvrSurface surface = surface_status.take();
ASSERT_NE(nullptr, surface.get());
enum : std::int32_t {
kInt32Key = 1,
kInt64Key,
kBoolKey,
kFloatKey,
kFloat2Key,
kFloat3Key,
kFloat4Key,
kFloat8Key,
kFloat16Key,
};
const std::vector<DvrSurfaceAttribute> attributes_to_set = {
MakeAttribute(kInt32Key, int32_t{0}),
MakeAttribute(kInt64Key, int64_t{0}),
MakeAttribute(kBoolKey, false),
MakeAttribute(kFloatKey, 0.0f),
MakeAttribute(kFloat2Key, std::array<float, 2>{{1.0f, 2.0f}}),
MakeAttribute(kFloat3Key, std::array<float, 3>{{3.0f, 4.0f, 5.0f}}),
MakeAttribute(kFloat4Key, std::array<float, 4>{{6.0f, 7.0f, 8.0f, 9.0f}}),
MakeAttribute(kFloat8Key,
std::array<float, 8>{{10.0f, 11.0f, 12.0f, 13.0f, 14.0f,
15.0f, 16.0f, 17.0f}}),
MakeAttribute(kFloat16Key, std::array<float, 16>{
{18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f,
24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f,
30.0f, 31.0f, 32.0f, 33.0f}})};
EXPECT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
attributes_to_set.size()));
ASSERT_STATUS_OK(manager_->WaitForUpdate());
auto attribute_status = manager_->GetAttributes(0);
ASSERT_STATUS_OK(attribute_status);
auto attributes = attribute_status.take();
EXPECT_GE(attributes.size(), attributes_to_set.size());
auto HasAttribute = [](const auto& attributes,
DvrSurfaceAttributeKey key) -> bool {
for (const auto& attribute : attributes) {
if (attribute.key == key)
return true;
}
return false;
};
auto AttributeType =
[](const auto& attributes,
DvrSurfaceAttributeKey key) -> DvrSurfaceAttributeType {
for (const auto& attribute : attributes) {
if (attribute.key == key)
return attribute.value.type;
}
return DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
};
ASSERT_TRUE(HasAttribute(attributes, kInt32Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
AttributeType(attributes, kInt32Key));
ASSERT_TRUE(HasAttribute(attributes, kInt64Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_INT64,
AttributeType(attributes, kInt64Key));
ASSERT_TRUE(HasAttribute(attributes, kBoolKey));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
AttributeType(attributes, kBoolKey));
ASSERT_TRUE(HasAttribute(attributes, kFloatKey));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT,
AttributeType(attributes, kFloatKey));
ASSERT_TRUE(HasAttribute(attributes, kFloat2Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2,
AttributeType(attributes, kFloat2Key));
ASSERT_TRUE(HasAttribute(attributes, kFloat3Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3,
AttributeType(attributes, kFloat3Key));
ASSERT_TRUE(HasAttribute(attributes, kFloat4Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4,
AttributeType(attributes, kFloat4Key));
ASSERT_TRUE(HasAttribute(attributes, kFloat8Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8,
AttributeType(attributes, kFloat8Key));
ASSERT_TRUE(HasAttribute(attributes, kFloat16Key));
EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16,
AttributeType(attributes, kFloat16Key));
}
TEST_F(DvrDisplayManagerTest, SurfaceQueueEvent) {
// Create an application surface.
auto surface_status = CreateApplicationSurface();
ASSERT_STATUS_OK(surface_status);
UniqueDvrSurface surface = surface_status.take();
ASSERT_NE(nullptr, surface.get());
const int surface_id = dvrSurfaceGetId(surface.get());
ASSERT_GE(surface_id, 0);
// Get surface state and verify there is one surface.
ASSERT_STATUS_OK(manager_->WaitForUpdate());
ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
// Verify there are no queues for the surface recorded in the state
// snapshot.
EXPECT_STATUS_EQ(std::vector<int>{}, manager_->GetQueueIds(0));
// Create a new queue in the surface.
auto write_queue_status = CreateSurfaceQueue(
surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 1,
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1, 0);
ASSERT_STATUS_OK(write_queue_status);
UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
ASSERT_NE(nullptr, write_queue.get());
const int queue_id = dvrWriteBufferQueueGetId(write_queue.get());
ASSERT_GE(queue_id, 0);
// Update surface state.
ASSERT_STATUS_OK(manager_->WaitForUpdate());
ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
// Verify the buffers changed flag is set.
auto check_flags = [](const auto& value) {
return value & DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED;
};
EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
auto queue_ids_status = manager_->GetQueueIds(0);
ASSERT_STATUS_OK(queue_ids_status);
auto queue_ids = queue_ids_status.take();
ASSERT_EQ(1u, queue_ids.size());
EXPECT_EQ(queue_id, queue_ids[0]);
auto read_queue_status = manager_->GetReadBufferQueue(surface_id, queue_id);
ASSERT_STATUS_OK(read_queue_status);
UniqueDvrReadBufferQueue read_queue = read_queue_status.take();
ASSERT_NE(nullptr, read_queue.get());
EXPECT_EQ(queue_id, dvrReadBufferQueueGetId(read_queue.get()));
write_queue.reset();
// Verify that destroying the queue generates a surface update event.
ASSERT_STATUS_OK(manager_->WaitForUpdate());
ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
// Verify that the buffers changed flag is set.
EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
// Verify that the queue ids reflect the change.
queue_ids_status = manager_->GetQueueIds(0);
ASSERT_STATUS_OK(queue_ids_status);
queue_ids = queue_ids_status.take();
ASSERT_EQ(0u, queue_ids.size());
}
TEST_F(DvrDisplayManagerTest, MultiLayerBufferQueue) {
// Create an application surface.
auto surface_status = CreateApplicationSurface();
ASSERT_STATUS_OK(surface_status);
UniqueDvrSurface surface = surface_status.take();
ASSERT_NE(nullptr, surface.get());
// Get surface state and verify there is one surface.
ASSERT_STATUS_OK(manager_->WaitForUpdate());
ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
// Create a new queue in the surface.
const uint32_t kLayerCount = 3;
auto write_queue_status = CreateSurfaceQueue(
surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kLayerCount,
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1, 0);
ASSERT_STATUS_OK(write_queue_status);
UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
ASSERT_NE(nullptr, write_queue.get());
DvrWriteBuffer* buffer = nullptr;
dvrWriteBufferCreateEmpty(&buffer);
int fence_fd = -1;
int error =
dvrWriteBufferQueueDequeue(write_queue.get(), 1000, buffer, &fence_fd);
ASSERT_EQ(0, error);
AHardwareBuffer* hardware_buffer = nullptr;
error = dvrWriteBufferGetAHardwareBuffer(buffer, &hardware_buffer);
ASSERT_EQ(0, error);
AHardwareBuffer_Desc desc = {};
AHardwareBuffer_describe(hardware_buffer, &desc);
ASSERT_EQ(kLayerCount, desc.layers);
AHardwareBuffer_release(hardware_buffer);
dvrWriteBufferDestroy(buffer);
}
TEST_F(DvrDisplayManagerTest, ConfigurationData) {
// TODO(hendrikw): Move this out of the display manager tests.
auto data1 = manager_->GetConfigData(-1);
ASSERT_STATUS_ERROR(data1);
const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
// This should be run on devices with and without built in metrics.
bool has_metric = !base::GetProperty(kDvrLensMetricsProperty, "").empty();
auto data2 = manager_->GetConfigData(DVR_CONFIGURATION_DATA_LENS_METRICS);
if (has_metric) {
ASSERT_STATUS_OK(data2);
ASSERT_NE(0u, data2.get().size());
} else {
ASSERT_STATUS_ERROR(data2);
}
}
} // namespace
} // namespace dvr
} // namespace android