368 lines
13 KiB
C++
368 lines
13 KiB
C++
|
|
/*
|
||
|
|
* Copyright 2022 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 "VtsHalTvInputTargetTest.h"
|
||
|
|
|
||
|
|
#include <android-base/properties.h>
|
||
|
|
#include <android/binder_ibinder.h>
|
||
|
|
#include <android/binder_process.h>
|
||
|
|
#include <android/binder_status.h>
|
||
|
|
|
||
|
|
using namespace VtsHalTvInputTargetTest;
|
||
|
|
|
||
|
|
TvInputAidlTest::TvInputCallback::TvInputCallback(shared_ptr<TvInputAidlTest> parent)
|
||
|
|
: parent_(parent) {}
|
||
|
|
|
||
|
|
::ndk::ScopedAStatus TvInputAidlTest::TvInputCallback::notify(const TvInputEvent& in_event) {
|
||
|
|
unique_lock<mutex> lock(parent_->mutex_);
|
||
|
|
|
||
|
|
switch (in_event.type) {
|
||
|
|
case TvInputEventType::DEVICE_AVAILABLE:
|
||
|
|
parent_->onDeviceAvailable(in_event.deviceInfo);
|
||
|
|
break;
|
||
|
|
case TvInputEventType::DEVICE_UNAVAILABLE:
|
||
|
|
parent_->onDeviceUnavailable(in_event.deviceInfo.deviceId);
|
||
|
|
break;
|
||
|
|
case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED:
|
||
|
|
parent_->onStreamConfigurationsChanged(in_event.deviceInfo.deviceId);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return ::ndk::ScopedAStatus::ok();
|
||
|
|
}
|
||
|
|
|
||
|
|
::ndk::ScopedAStatus TvInputAidlTest::TvInputCallback::notifyTvMessageEvent(
|
||
|
|
const TvMessageEvent& in_event) {
|
||
|
|
return ::ndk::ScopedAStatus::ok();
|
||
|
|
}
|
||
|
|
|
||
|
|
void TvInputAidlTest::SetUp() {
|
||
|
|
if (AServiceManager_isDeclared(GetParam().c_str())) {
|
||
|
|
::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
|
||
|
|
tv_input_ = ITvInput::fromBinder(binder);
|
||
|
|
} else {
|
||
|
|
tv_input_ = nullptr;
|
||
|
|
}
|
||
|
|
ASSERT_NE(tv_input_, nullptr);
|
||
|
|
|
||
|
|
tv_input_callback_ =
|
||
|
|
::ndk::SharedRefBase::make<TvInputCallback>(shared_ptr<TvInputAidlTest>(this));
|
||
|
|
ASSERT_NE(tv_input_callback_, nullptr);
|
||
|
|
|
||
|
|
tv_input_->setCallback(tv_input_callback_);
|
||
|
|
// All events received within the timeout should be handled.
|
||
|
|
sleep(WAIT_FOR_EVENT_TIMEOUT);
|
||
|
|
}
|
||
|
|
|
||
|
|
void TvInputAidlTest::TearDown() {
|
||
|
|
tv_input_ = nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
void TvInputAidlTest::onDeviceAvailable(const TvInputDeviceInfo& deviceInfo) {
|
||
|
|
ALOGD("onDeviceAvailable for device id %d", deviceInfo.deviceId);
|
||
|
|
device_info_.add(deviceInfo.deviceId, deviceInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
void TvInputAidlTest::onDeviceUnavailable(int32_t deviceId) {
|
||
|
|
ALOGD("onDeviceUnavailable for device id %d", deviceId);
|
||
|
|
device_info_.removeItem(deviceId);
|
||
|
|
stream_config_.removeItem(deviceId);
|
||
|
|
}
|
||
|
|
|
||
|
|
::ndk::ScopedAStatus TvInputAidlTest::onStreamConfigurationsChanged(int32_t deviceId) {
|
||
|
|
ALOGD("onStreamConfigurationsChanged for device id %d", deviceId);
|
||
|
|
return updateStreamConfigurations(deviceId);
|
||
|
|
}
|
||
|
|
|
||
|
|
::ndk::ScopedAStatus TvInputAidlTest::updateStreamConfigurations(int32_t deviceId) {
|
||
|
|
stream_config_.removeItem(deviceId);
|
||
|
|
vector<TvStreamConfig> list;
|
||
|
|
::ndk::ScopedAStatus status = tv_input_->getStreamConfigurations(deviceId, &list);
|
||
|
|
if (status.isOk()) {
|
||
|
|
stream_config_.add(deviceId, list);
|
||
|
|
}
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
void TvInputAidlTest::updateAllStreamConfigurations() {
|
||
|
|
for (size_t i = 0; i < device_info_.size(); i++) {
|
||
|
|
int32_t device_id = device_info_.keyAt(i);
|
||
|
|
updateStreamConfigurations(device_id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
vector<size_t> TvInputAidlTest::getConfigIndices() {
|
||
|
|
vector<size_t> indices;
|
||
|
|
for (size_t i = 0; i < stream_config_.size(); i++) {
|
||
|
|
if (stream_config_.valueAt(i).size() != 0) {
|
||
|
|
indices.push_back(i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return indices;
|
||
|
|
}
|
||
|
|
|
||
|
|
int32_t TvInputAidlTest::getNumNotIn(vector<int32_t>& nums) {
|
||
|
|
int32_t result = DEFAULT_ID;
|
||
|
|
int32_t size = static_cast<int32_t>(nums.size());
|
||
|
|
for (int32_t i = 0; i < size; i++) {
|
||
|
|
// Put every element to its target position, if possible.
|
||
|
|
int32_t target_pos = nums[i];
|
||
|
|
while (target_pos >= 0 && target_pos < size && i != target_pos &&
|
||
|
|
nums[i] != nums[target_pos]) {
|
||
|
|
swap(nums[i], nums[target_pos]);
|
||
|
|
target_pos = nums[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int32_t i = 0; i < size; i++) {
|
||
|
|
if (nums[i] != i) {
|
||
|
|
return i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool TvInputAidlTest::isValidHandle(NativeHandle& handle) {
|
||
|
|
if (handle.fds.empty()) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
for (size_t i = 0; i < handle.fds.size(); i++) {
|
||
|
|
int fd = handle.fds[i].get();
|
||
|
|
if (fcntl(fd, F_GETFL) < 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* GetStreamConfigTest:
|
||
|
|
* Calls updateStreamConfigurations() for each existing device
|
||
|
|
* Checks returned results
|
||
|
|
*/
|
||
|
|
TEST_P(TvInputAidlTest, GetStreamConfigTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
for (size_t i = 0; i < device_info_.size(); i++) {
|
||
|
|
int32_t device_id = device_info_.keyAt(i);
|
||
|
|
ALOGD("GetStreamConfigTest: device_id=%d", device_id);
|
||
|
|
ASSERT_TRUE(updateStreamConfigurations(device_id).isOk());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* OpenAndCloseStreamTest:
|
||
|
|
* Calls openStream() and then closeStream() for each existing stream
|
||
|
|
* Checks returned results
|
||
|
|
*/
|
||
|
|
TEST_P(TvInputAidlTest, OpenAndCloseStreamTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
updateAllStreamConfigurations();
|
||
|
|
|
||
|
|
for (size_t j = 0; j < stream_config_.size(); j++) {
|
||
|
|
int32_t device_id = stream_config_.keyAt(j);
|
||
|
|
vector<TvStreamConfig> config = stream_config_.valueAt(j);
|
||
|
|
for (size_t i = 0; i < config.size(); i++) {
|
||
|
|
NativeHandle handle;
|
||
|
|
int32_t stream_id = config[i].streamId;
|
||
|
|
ALOGD("OpenAndCloseStreamTest: open stream, device_id=%d, stream_id=%d", device_id,
|
||
|
|
stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
|
||
|
|
ASSERT_TRUE(isValidHandle(handle));
|
||
|
|
|
||
|
|
ALOGD("OpenAndCloseStreamTest: close stream, device_id=%d, stream_id=%d", device_id,
|
||
|
|
stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).isOk());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* InvalidDeviceIdTest:
|
||
|
|
* Calls updateStreamConfigurations(), openStream(), and closeStream()
|
||
|
|
* for a non-existing device
|
||
|
|
* Checks returned results
|
||
|
|
* The results should be ITvInput::STATUS_INVALID_ARGUMENTS
|
||
|
|
*/
|
||
|
|
TEST_P(TvInputAidlTest, InvalidDeviceIdTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
vector<int32_t> device_ids;
|
||
|
|
for (size_t i = 0; i < device_info_.size(); i++) {
|
||
|
|
device_ids.push_back(device_info_.keyAt(i));
|
||
|
|
}
|
||
|
|
// Get a non-existing device ID.
|
||
|
|
int32_t id = getNumNotIn(device_ids);
|
||
|
|
ALOGD("InvalidDeviceIdTest: update stream config, device_id=%d", id);
|
||
|
|
ASSERT_TRUE(updateStreamConfigurations(id).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_ARGUMENTS);
|
||
|
|
|
||
|
|
int32_t stream_id = 0;
|
||
|
|
NativeHandle handle;
|
||
|
|
|
||
|
|
ALOGD("InvalidDeviceIdTest: open stream, device_id=%d, stream_id=%d", id, stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->openStream(id, stream_id, &handle).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_ARGUMENTS);
|
||
|
|
|
||
|
|
ALOGD("InvalidDeviceIdTest: close stream, device_id=%d, stream_id=%d", id, stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->closeStream(id, stream_id).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_ARGUMENTS);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* InvalidStreamIdTest:
|
||
|
|
* Calls openStream(), and closeStream() for a non-existing stream
|
||
|
|
* Checks returned results
|
||
|
|
* The results should be ITvInput::STATUS_INVALID_ARGUMENTS
|
||
|
|
*/
|
||
|
|
TEST_P(TvInputAidlTest, InvalidStreamIdTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
if (device_info_.isEmpty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
updateAllStreamConfigurations();
|
||
|
|
|
||
|
|
int32_t device_id = device_info_.keyAt(0);
|
||
|
|
// Get a non-existing stream ID.
|
||
|
|
int32_t id = DEFAULT_ID;
|
||
|
|
if (stream_config_.indexOfKey(device_id) >= 0) {
|
||
|
|
vector<int32_t> stream_ids;
|
||
|
|
vector<TvStreamConfig> config = stream_config_.valueFor(device_id);
|
||
|
|
for (size_t i = 0; i < config.size(); i++) {
|
||
|
|
stream_ids.push_back(config[i].streamId);
|
||
|
|
}
|
||
|
|
id = getNumNotIn(stream_ids);
|
||
|
|
}
|
||
|
|
|
||
|
|
NativeHandle handle;
|
||
|
|
|
||
|
|
ALOGD("InvalidStreamIdTest: open stream, device_id=%d, stream_id=%d", device_id, id);
|
||
|
|
ASSERT_TRUE(tv_input_->openStream(device_id, id, &handle).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_ARGUMENTS);
|
||
|
|
|
||
|
|
ALOGD("InvalidStreamIdTest: close stream, device_id=%d, stream_id=%d", device_id, id);
|
||
|
|
ASSERT_TRUE(tv_input_->closeStream(device_id, id).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_ARGUMENTS);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* OpenAnOpenedStreamsTest:
|
||
|
|
* Calls openStream() twice for a stream (if any)
|
||
|
|
* Checks returned results
|
||
|
|
* The result of the second call should be ITvInput::STATUS_INVALID_STATE
|
||
|
|
*/
|
||
|
|
TEST_P(TvInputAidlTest, OpenAnOpenedStreamsTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
updateAllStreamConfigurations();
|
||
|
|
vector<size_t> indices = getConfigIndices();
|
||
|
|
if (indices.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t device_id = stream_config_.keyAt(indices[0]);
|
||
|
|
vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
|
||
|
|
if (streamConfigs.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t stream_id = streamConfigs[0].streamId;
|
||
|
|
NativeHandle handle;
|
||
|
|
|
||
|
|
ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
|
||
|
|
ASSERT_TRUE(isValidHandle(handle));
|
||
|
|
|
||
|
|
ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_STATE);
|
||
|
|
|
||
|
|
// close stream as subsequent tests assume no open streams
|
||
|
|
ALOGD("OpenAnOpenedStreamsTest: close stream, device_id=%d, stream_id=%d", device_id,
|
||
|
|
stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).isOk());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* CloseStreamBeforeOpenTest:
|
||
|
|
* Calls closeStream() without calling openStream() for a stream (if any)
|
||
|
|
* Checks the returned result
|
||
|
|
* The result should be ITvInput::STATUS_INVALID_STATE
|
||
|
|
*/
|
||
|
|
TEST_P(TvInputAidlTest, CloseStreamBeforeOpenTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
updateAllStreamConfigurations();
|
||
|
|
vector<size_t> indices = getConfigIndices();
|
||
|
|
if (indices.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t device_id = stream_config_.keyAt(indices[0]);
|
||
|
|
vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
|
||
|
|
if (streamConfigs.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t stream_id = streamConfigs[0].streamId;
|
||
|
|
|
||
|
|
ALOGD("CloseStreamBeforeOpenTest: close stream, device_id=%d, stream_id=%d", device_id,
|
||
|
|
stream_id);
|
||
|
|
ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).getServiceSpecificError() ==
|
||
|
|
ITvInput::STATUS_INVALID_STATE);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_P(TvInputAidlTest, SetTvMessageEnabledTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
updateAllStreamConfigurations();
|
||
|
|
vector<size_t> indices = getConfigIndices();
|
||
|
|
if (indices.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t device_id = stream_config_.keyAt(indices[0]);
|
||
|
|
vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
|
||
|
|
if (streamConfigs.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t stream_id = streamConfigs[0].streamId;
|
||
|
|
ALOGD("SetTvMessageEnabledTest: device_id=%d, stream_id=%d", device_id, stream_id);
|
||
|
|
tv_input_->setTvMessageEnabled(device_id, stream_id, TvMessageEventType::WATERMARK, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_P(TvInputAidlTest, GetTvMessageQueueTest) {
|
||
|
|
unique_lock<mutex> lock(mutex_);
|
||
|
|
|
||
|
|
updateAllStreamConfigurations();
|
||
|
|
vector<size_t> indices = getConfigIndices();
|
||
|
|
if (indices.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t device_id = stream_config_.keyAt(indices[0]);
|
||
|
|
vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
|
||
|
|
if (streamConfigs.empty()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int32_t stream_id = streamConfigs[0].streamId;
|
||
|
|
ALOGD("GetTvMessageQueueTest: device_id=%d, stream_id=%d", device_id, stream_id);
|
||
|
|
MQDescriptor<int8_t, SynchronizedReadWrite> queue;
|
||
|
|
tv_input_->getTvMessageQueueDesc(&queue, device_id, stream_id);
|
||
|
|
}
|
||
|
|
|
||
|
|
INSTANTIATE_TEST_SUITE_P(PerInstance, TvInputAidlTest,
|
||
|
|
testing::ValuesIn(android::getAidlHalInstanceNames(ITvInput::descriptor)),
|
||
|
|
android::PrintInstanceNameToString);
|
||
|
|
|
||
|
|
// TODO remove from the allow list once the cf tv target is enabled for testing
|
||
|
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TvInputAidlTest);
|