892 lines
30 KiB
C++
892 lines
30 KiB
C++
|
#include <android-base/properties.h>
|
||
|
#include <base/logging.h>
|
||
|
#include <cutils/properties.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 {
|
||
|
|
||
|
using ::testing::Test;
|
||
|
|
||
|
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)};
|
||
|
}
|
||
|
|
||
|
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)};
|
||
|
}
|
||
|
|
||
|
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)};
|
||
|
}
|
||
|
|
||
|
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 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(Test, 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(Test, 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;
|
||
|
DvrNativeBufferMetadata metadata;
|
||
|
int fence_fd = -1;
|
||
|
int error = dvrWriteBufferQueueGainBuffer(write_queue.get(), /*timeout=*/1000,
|
||
|
&buffer, &metadata, &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(Test, ConfigurationData) {
|
||
|
// TODO(hendrikw): Move this test and GetConfigData helper function out of the
|
||
|
// display manager tests.
|
||
|
auto data1 = 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 = 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
|