blob: 3ecd2407e10b0bb79f769c7a1905e6dfae1fcea4 [file] [log] [blame]
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <gtest/gtest.h>
extern "C" {
#include "cras_bt_log.h"
#include "cras_bt_profile.h"
#include "cras_hfp_ag_profile.h"
#include "cras_iodev.h"
}
static int with_sco_pcm;
static struct cras_iodev fake_sco_out, fake_sco_in;
static struct cras_bt_device* fake_device;
static struct cras_bt_profile* internal_bt_profile;
static size_t hfp_alsa_iodev_create_called;
static size_t hfp_alsa_iodev_destroy_called;
static size_t hfp_iodev_create_called;
static size_t hfp_iodev_destroy_called;
static size_t cras_bt_device_notify_profile_dropped_called;
static struct cras_bt_device* cras_bt_device_notify_profile_dropped_dev;
static enum cras_bt_device_profile
cras_bt_device_notify_profile_dropped_profile;
static void ResetStubData() {
hfp_alsa_iodev_create_called = 0;
hfp_alsa_iodev_destroy_called = 0;
hfp_iodev_create_called = 0;
hfp_iodev_destroy_called = 0;
cras_bt_device_notify_profile_dropped_called = 0;
}
namespace {
class HfpAgProfile : public testing::Test {
protected:
virtual void SetUp() {
btlog = cras_bt_event_log_init();
ResetStubData();
}
virtual void TearDown() { cras_bt_event_log_deinit(btlog); }
};
TEST_F(HfpAgProfile, StartWithoutScoPCM) {
int ret;
struct cras_bt_profile* bt_profile;
with_sco_pcm = 0;
fake_device = (struct cras_bt_device*)0xdeadbeef;
/* to get the cras_hfp_ag_profile */
cras_hfp_ag_profile_create(NULL);
bt_profile = internal_bt_profile;
bt_profile->new_connection(NULL, bt_profile, fake_device, 0);
ret = cras_hfp_ag_start(fake_device);
EXPECT_EQ(0, ret);
EXPECT_EQ(2, hfp_iodev_create_called);
/* Start ag twice won't create more iodev. */
ret = cras_hfp_ag_start(fake_device);
EXPECT_EQ(0, ret);
EXPECT_EQ(2, hfp_iodev_create_called);
bt_profile->release(bt_profile);
EXPECT_EQ(2, hfp_iodev_destroy_called);
}
TEST_F(HfpAgProfile, StartWithScoPCM) {
int ret;
struct cras_bt_profile* bt_profile;
with_sco_pcm = 1;
fake_device = (struct cras_bt_device*)0xdeadbeef;
/* to get the cras_hfp_ag_profile */
cras_hfp_ag_profile_create(NULL);
bt_profile = internal_bt_profile;
bt_profile->new_connection(NULL, bt_profile, fake_device, 0);
ret = cras_hfp_ag_start(fake_device);
EXPECT_EQ(0, ret);
EXPECT_EQ(2, hfp_alsa_iodev_create_called);
bt_profile->release(bt_profile);
EXPECT_EQ(2, hfp_alsa_iodev_destroy_called);
}
TEST_F(HfpAgProfile, RemoveConflictAG) {
struct cras_bt_profile* bt_profile;
struct cras_bt_device* new_dev =
reinterpret_cast<struct cras_bt_device*>(0x123);
;
with_sco_pcm = 0;
fake_device = (struct cras_bt_device*)0xdeadbeef;
/* to get the cras_hfp_ag_profile */
cras_hfp_ag_profile_create(NULL);
bt_profile = internal_bt_profile;
bt_profile->new_connection(NULL, bt_profile, fake_device, 0);
bt_profile->new_connection(NULL, bt_profile, new_dev, 0);
/* Expect removing conflict of new_dev triggers profile drop on
* fake_device. */
cras_hfp_ag_remove_conflict(new_dev);
EXPECT_EQ(1, cras_bt_device_notify_profile_dropped_called);
EXPECT_EQ(fake_device, cras_bt_device_notify_profile_dropped_dev);
EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE,
cras_bt_device_notify_profile_dropped_profile);
bt_profile->release(bt_profile);
}
} // namespace
extern "C" {
struct cras_bt_event_log* btlog;
struct cras_iodev* cras_iodev_list_get_sco_pcm_iodev(
enum CRAS_STREAM_DIRECTION direction) {
if (with_sco_pcm) {
if (direction == CRAS_STREAM_OUTPUT)
return &fake_sco_out;
else
return &fake_sco_in;
}
return NULL;
}
struct cras_iodev* hfp_alsa_iodev_create(enum CRAS_STREAM_DIRECTION dir,
struct cras_bt_device* device,
struct hfp_slc_handle* slc,
enum cras_bt_device_profile profile) {
hfp_alsa_iodev_create_called++;
return (struct cras_iodev*)0xdeadbeef;
}
void hfp_alsa_iodev_destroy(struct cras_iodev* iodev) {
hfp_alsa_iodev_destroy_called++;
}
struct cras_iodev* hfp_iodev_create(enum CRAS_STREAM_DIRECTION dir,
struct cras_bt_device* device,
struct hfp_slc_handle* slc,
enum cras_bt_device_profile profile,
struct hfp_info* info) {
hfp_iodev_create_called++;
return (struct cras_iodev*)0xdeadbeef;
}
void hfp_iodev_destroy(struct cras_iodev* iodev) {
hfp_iodev_destroy_called++;
}
int cras_bt_add_profile(DBusConnection* conn, struct cras_bt_profile* profile) {
internal_bt_profile = profile;
return 0;
}
int cras_bt_rm_profile(DBusConnection* conn, struct cras_bt_profile* profile) {
internal_bt_profile = NULL;
return 0;
}
int cras_bt_register_profile(DBusConnection* conn,
struct cras_bt_profile* profile) {
return 0;
}
int cras_bt_register_profiles(DBusConnection* conn) {
return 0;
}
int cras_bt_unregister_profile(DBusConnection* conn,
struct cras_bt_profile* profile) {
return 0;
}
struct hfp_info* hfp_info_create() {
return NULL;
}
int hfp_info_running(struct hfp_info* info) {
return 0;
}
int hfp_info_stop(struct hfp_info* info) {
return 0;
}
void hfp_info_destroy(struct hfp_info* info) {}
void hfp_slc_destroy(struct hfp_slc_handle* slc_handle) {}
int cras_bt_device_has_a2dp(struct cras_bt_device* device) {
return 0;
}
int cras_bt_device_disconnect(DBusConnection* conn,
struct cras_bt_device* device) {
return 0;
}
const char* cras_bt_device_name(const struct cras_bt_device* device) {
return NULL;
}
void cras_bt_device_set_append_iodev_cb(struct cras_bt_device* device,
void (*cb)(void* data)) {}
enum cras_bt_device_profile cras_bt_device_profile_from_uuid(const char* uuid) {
return CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY;
}
struct cras_bt_adapter* cras_bt_device_adapter(
const struct cras_bt_device* device) {
return reinterpret_cast<struct cras_bt_adapter*>(0x123);
}
int cras_bt_adapter_wbs_supported(struct cras_bt_adapter* adapter) {
return 1;
}
struct hfp_slc_handle* hfp_slc_create(int fd,
int is_hsp,
int ag_supported_features,
struct cras_bt_device* device,
hfp_slc_init_cb init_cb,
hfp_slc_disconnect_cb disconnect_cb) {
return NULL;
}
int hfp_slc_get_selected_codec(struct hfp_slc_handle* handle) {
return HFP_CODEC_ID_CVSD;
}
int hfp_slc_get_ag_codec_negotiation_supported(struct hfp_slc_handle* handle) {
return 1;
}
int hfp_slc_get_hf_codec_negotiation_supported(struct hfp_slc_handle* handle) {
return 1;
}
int hfp_slc_get_hf_supports_battery_indicator(struct hfp_slc_handle* handle) {
return 0;
}
int hfp_slc_get_hf_battery_level(struct hfp_slc_handle* handle) {
return -1;
}
struct cras_bt_device* cras_a2dp_connected_device() {
return NULL;
}
int cras_bt_device_supports_profile(const struct cras_bt_device* device,
enum cras_bt_device_profile profile) {
return 0;
}
void cras_a2dp_suspend_connected_device(struct cras_bt_device* device) {}
const char* cras_bt_device_address(const struct cras_bt_device* device) {
return "";
}
int cras_bt_device_audio_gateway_initialized(struct cras_bt_device* device) {
return 0;
}
void cras_bt_device_notify_profile_dropped(
struct cras_bt_device* device,
enum cras_bt_device_profile profile) {
cras_bt_device_notify_profile_dropped_called++;
cras_bt_device_notify_profile_dropped_dev = device;
cras_bt_device_notify_profile_dropped_profile = profile;
}
void hfp_info_set_wbs_logger(struct hfp_info* info,
struct packet_status_logger* wbs_logger) {}
void cras_observer_notify_bt_battery_changed(const char* address,
uint32_t level) {
return;
}
bool cras_system_get_bt_wbs_enabled() {
return true;
}
int cras_server_metrics_hfp_wideband_selected_codec(int codec) {
return HFP_CODEC_ID_MSBC;
}
} // extern "C"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}