blob: 0819f6c0882f16af870b8c8bb12f8811b3d054ce [file]
/*
* Copyright 2023 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 "le_audio_health_status.h"
#include <base/functional/callback.h>
#include <base/functional/callback_forward.h>
#include <base/functional/callback_helpers.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "bta/include/bta_groups.h"
#include "common/init_flags.h"
#include "test/common/mock_functions.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
using bluetooth::groups::kGroupUnknown;
using bluetooth::le_audio::DeviceConnectState;
using bluetooth::le_audio::LeAudioDevice;
using bluetooth::le_audio::LeAudioDeviceGroup;
using bluetooth::le_audio::LeAudioHealthBasedAction;
using bluetooth::le_audio::LeAudioHealthDeviceStatType;
using bluetooth::le_audio::LeAudioHealthGroupStatType;
using bluetooth::le_audio::LeAudioHealthStatus;
LeAudioHealthBasedAction recommendation_in_callback =
LeAudioHealthBasedAction::NONE;
RawAddress address_in_callback = RawAddress::kEmpty;
int group_id_in_callback = kGroupUnknown;
static void healthCallback(const RawAddress& address, int group_id,
LeAudioHealthBasedAction recommendation) {
address_in_callback = address;
group_id_in_callback = group_id;
recommendation_in_callback = recommendation;
}
class LeAudioHealthStatusTest : public ::testing::Test {
protected:
void SetUp() override {
reset_mock_function_count_map();
group_ = new LeAudioDeviceGroup(group_id_);
le_audio_health_status_instance_ = LeAudioHealthStatus::Get();
le_audio_health_status_instance_->RegisterCallback(
base::BindRepeating(healthCallback));
}
void TearDown() override {
le_audio_health_status_instance_->Cleanup();
delete group_;
recommendation_in_callback = LeAudioHealthBasedAction::NONE;
address_in_callback = RawAddress::kEmpty;
}
LeAudioHealthStatus* le_audio_health_status_instance_;
const int group_id_ = 0;
LeAudioDeviceGroup* group_ = nullptr;
};
RawAddress GetTestAddress(uint8_t index) {
EXPECT_LT(index, UINT8_MAX);
RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}};
return result;
}
TEST_F(LeAudioHealthStatusTest, test_initialize) {
ASSERT_TRUE(le_audio_health_status_instance_ != nullptr);
}
TEST_F(LeAudioHealthStatusTest, test_invalid_db) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(
test_address0, DeviceConnectState::DISCONNECTED);
le_audio_health_status_instance_->AddStatisticForDevice(
device.get(), LeAudioHealthDeviceStatType::INVALID_DB);
ASSERT_TRUE(address_in_callback == test_address0);
ASSERT_TRUE(recommendation_in_callback == LeAudioHealthBasedAction::DISABLE);
}
TEST_F(LeAudioHealthStatusTest, test_invalid_csis_member) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(
test_address0, DeviceConnectState::DISCONNECTED);
le_audio_health_status_instance_->AddStatisticForDevice(
device.get(), LeAudioHealthDeviceStatType::INVALID_CSIS);
ASSERT_TRUE(address_in_callback == test_address0);
ASSERT_TRUE(recommendation_in_callback == LeAudioHealthBasedAction::DISABLE);
}
TEST_F(LeAudioHealthStatusTest, test_remove_statistic) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(
test_address0, DeviceConnectState::DISCONNECTED);
group_->AddNode(device);
le_audio_health_status_instance_->AddStatisticForDevice(
device.get(), LeAudioHealthDeviceStatType::INVALID_CSIS);
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
le_audio_health_status_instance_->RemoveStatistics(test_address0, group_id_);
}
TEST_F(LeAudioHealthStatusTest, test_all_is_good) {
for (int i = 0; i < 100; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
ASSERT_TRUE(group_id_in_callback == kGroupUnknown);
}
TEST_F(LeAudioHealthStatusTest, test_disable_cis_no_stream_creation) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(test_address0,
DeviceConnectState::CONNECTED);
group_->AddNode(device);
for (int i = 0; i < 3; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
ASSERT_TRUE(group_id_in_callback == group_id_);
ASSERT_TRUE(recommendation_in_callback == LeAudioHealthBasedAction::DISABLE);
}
TEST_F(LeAudioHealthStatusTest, test_disable_signaling_no_stream_creation) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(test_address0,
DeviceConnectState::CONNECTED);
group_->AddNode(device);
for (int i = 0; i < 3; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED);
}
/* No recommendation shall be sent */
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
ASSERT_TRUE(group_id_in_callback == group_id_);
ASSERT_TRUE(recommendation_in_callback == LeAudioHealthBasedAction::DISABLE);
}
TEST_F(LeAudioHealthStatusTest, test_disable_signaling_cis_no_stream_creation) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(test_address0,
DeviceConnectState::CONNECTED);
group_->AddNode(device);
for (int i = 0; i < 2; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED);
}
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
/* No recommendation shall be sent */
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
ASSERT_TRUE(group_id_in_callback == group_id_);
ASSERT_TRUE(recommendation_in_callback == LeAudioHealthBasedAction::DISABLE);
}
TEST_F(LeAudioHealthStatusTest, test_consider_disabling) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(test_address0,
DeviceConnectState::CONNECTED);
group_->AddNode(device);
for (int i = 0; i < 10; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
}
for (int i = 0; i < 2; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
for (int i = 0; i < 2; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
for (int i = 0; i < 3; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
ASSERT_TRUE(group_id_in_callback == group_id_);
ASSERT_TRUE(recommendation_in_callback ==
LeAudioHealthBasedAction::CONSIDER_DISABLING);
}
TEST_F(LeAudioHealthStatusTest, test_inactivate_group) {
const RawAddress test_address0 = GetTestAddress(0);
auto device = std::make_shared<LeAudioDevice>(test_address0,
DeviceConnectState::CONNECTED);
group_->AddNode(device);
for (int i = 0; i < 10; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
}
for (int i = 0; i < 2; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
for (int i = 0; i < 1; i++) {
le_audio_health_status_instance_->AddStatisticForGroup(
group_, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE);
}
ASSERT_TRUE(address_in_callback == RawAddress::kEmpty);
ASSERT_TRUE(group_id_in_callback == group_id_);
ASSERT_TRUE(recommendation_in_callback ==
LeAudioHealthBasedAction::INACTIVATE_GROUP);
}