普通文本  |  378行  |  9.9 KB

/* Copyright (c) 2013 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_audio_area.h"
#include "cras_hfp_iodev.h"
#include "cras_iodev.h"
#include "cras_hfp_info.h"
}

static struct cras_iodev *iodev;
static struct cras_bt_device *fake_device;
static struct hfp_slc_handle *fake_slc;
static struct hfp_info *fake_info;
struct cras_audio_format fake_format;
static size_t cras_bt_device_append_iodev_called;
static size_t cras_bt_device_rm_iodev_called;
static size_t cras_iodev_add_node_called;
static size_t cras_iodev_rm_node_called;
static size_t cras_iodev_set_active_node_called;
static size_t cras_iodev_free_format_called;
static size_t cras_iodev_free_resources_called;
static size_t cras_bt_device_sco_connect_called;
static int cras_bt_transport_sco_connect_return_val;
static size_t hfp_info_add_iodev_called;
static size_t hfp_info_rm_iodev_called;
static size_t hfp_info_running_called;
static int hfp_info_running_return_val;
static size_t hfp_info_has_iodev_called;
static int hfp_info_has_iodev_return_val;
static size_t hfp_info_start_called;
static size_t hfp_info_stop_called;
static size_t hfp_buf_acquire_called;
static unsigned hfp_buf_acquire_return_val;
static size_t hfp_buf_release_called;
static unsigned hfp_buf_release_nwritten_val;
static cras_audio_area *dummy_audio_area;

void ResetStubData() {
  cras_bt_device_append_iodev_called = 0;
  cras_bt_device_rm_iodev_called = 0;
  cras_iodev_add_node_called = 0;
  cras_iodev_rm_node_called = 0;
  cras_iodev_set_active_node_called = 0;
  cras_iodev_free_format_called = 0;
  cras_iodev_free_resources_called = 0;
  cras_bt_device_sco_connect_called = 0;
  cras_bt_transport_sco_connect_return_val = 0;
  hfp_info_add_iodev_called = 0;
  hfp_info_rm_iodev_called = 0;
  hfp_info_running_called = 0;
  hfp_info_running_return_val = 1;
  hfp_info_has_iodev_called = 0;
  hfp_info_has_iodev_return_val = 0;
  hfp_info_start_called = 0;
  hfp_info_stop_called = 0;
  hfp_buf_acquire_called = 0;
  hfp_buf_acquire_return_val = 0;
  hfp_buf_release_called = 0;
  hfp_buf_release_nwritten_val = 0;

  fake_info = reinterpret_cast<struct hfp_info *>(0x123);

  if (!dummy_audio_area) {
    dummy_audio_area = (cras_audio_area*)calloc(1,
        sizeof(*dummy_audio_area) + sizeof(cras_channel_area) * 2);
  }
}

namespace {

class HfpIodev: public testing::Test {
  protected:
    virtual void SetUp() {
      ResetStubData();
    }

    virtual void TearDown() {
      free(dummy_audio_area);
      dummy_audio_area = NULL;
    }
};

TEST_F(HfpIodev, CreateHfpOutputIodev) {
  iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
                           CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY,
                		  	   fake_info);

  ASSERT_EQ(CRAS_STREAM_OUTPUT, iodev->direction);
  ASSERT_EQ(1, cras_bt_device_append_iodev_called);
  ASSERT_EQ(1, cras_iodev_add_node_called);
  ASSERT_EQ(1, cras_iodev_set_active_node_called);

  hfp_iodev_destroy(iodev);

  ASSERT_EQ(1, cras_bt_device_rm_iodev_called);
  ASSERT_EQ(1, cras_iodev_rm_node_called);
  ASSERT_EQ(1, cras_iodev_free_resources_called);
}

TEST_F(HfpIodev, CreateHfpInputIodev) {
  iodev = hfp_iodev_create(CRAS_STREAM_INPUT, fake_device, fake_slc,
                           CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, fake_info);

  ASSERT_EQ(CRAS_STREAM_INPUT, iodev->direction);
  ASSERT_EQ(1, cras_bt_device_append_iodev_called);
  ASSERT_EQ(1, cras_iodev_add_node_called);
  ASSERT_EQ(1, cras_iodev_set_active_node_called);
  /* Input device does not use software gain. */
  ASSERT_EQ(0, iodev->software_volume_needed);

  hfp_iodev_destroy(iodev);

  ASSERT_EQ(1, cras_bt_device_rm_iodev_called);
  ASSERT_EQ(1, cras_iodev_rm_node_called);
  ASSERT_EQ(1, cras_iodev_free_resources_called);
}

TEST_F(HfpIodev, OpenHfpIodev) {
  iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
                           CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY,
                           fake_info);
  iodev->format = &fake_format;

  /* hfp_info not start yet */
  hfp_info_running_return_val = 0;
  iodev->configure_dev(iodev);

  ASSERT_EQ(1, cras_bt_device_sco_connect_called);
  ASSERT_EQ(1, hfp_info_start_called);
  ASSERT_EQ(1, hfp_info_add_iodev_called);

  /* hfp_info is running now */
  hfp_info_running_return_val = 1;

  iodev->close_dev(iodev);
  hfp_iodev_destroy(iodev);
  ASSERT_EQ(1, hfp_info_rm_iodev_called);
  ASSERT_EQ(1, hfp_info_stop_called);
  ASSERT_EQ(1, cras_iodev_free_format_called);
  ASSERT_EQ(1, cras_iodev_free_resources_called);
}

TEST_F(HfpIodev, OpenIodevWithHfpInfoAlreadyRunning) {
  iodev = hfp_iodev_create(CRAS_STREAM_INPUT, fake_device, fake_slc,
                           CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY,
                           fake_info);

  iodev->format = &fake_format;

  /* hfp_info already started by another device */
  hfp_info_running_return_val = 1;
  iodev->configure_dev(iodev);

  ASSERT_EQ(0, cras_bt_device_sco_connect_called);
  ASSERT_EQ(0, hfp_info_start_called);
  ASSERT_EQ(1, hfp_info_add_iodev_called);

  hfp_info_has_iodev_return_val = 1;
  iodev->close_dev(iodev);
  hfp_iodev_destroy(iodev);
  ASSERT_EQ(1, hfp_info_rm_iodev_called);
  ASSERT_EQ(0, hfp_info_stop_called);
  ASSERT_EQ(1, cras_iodev_free_format_called);
  ASSERT_EQ(1, cras_iodev_free_resources_called);
}

TEST_F(HfpIodev, PutGetBuffer) {
  cras_audio_area *area;
  unsigned frames;

  ResetStubData();
  iodev = hfp_iodev_create(CRAS_STREAM_OUTPUT, fake_device, fake_slc,
                           CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY,
                  			   fake_info);
  iodev->format = &fake_format;
  iodev->configure_dev(iodev);

  hfp_buf_acquire_return_val = 100;
  iodev->get_buffer(iodev, &area, &frames);

  ASSERT_EQ(1, hfp_buf_acquire_called);
  ASSERT_EQ(100, frames);

  iodev->put_buffer(iodev, 40);
  ASSERT_EQ(1, hfp_buf_release_called);
  ASSERT_EQ(40, hfp_buf_release_nwritten_val);
  hfp_iodev_destroy(iodev);
  ASSERT_EQ(1, cras_iodev_free_resources_called);
}

} // namespace

extern "C" {
void cras_iodev_free_format(struct cras_iodev *iodev)
{
  cras_iodev_free_format_called++;
}

void cras_iodev_add_node(struct cras_iodev *iodev, struct cras_ionode *node)
{
  cras_iodev_add_node_called++;
  iodev->nodes = node;
}

void cras_iodev_rm_node(struct cras_iodev *iodev, struct cras_ionode *node)
{
  cras_iodev_rm_node_called++;
  iodev->nodes = NULL;
}

void cras_iodev_set_active_node(struct cras_iodev *iodev,
				struct cras_ionode *node)
{
  cras_iodev_set_active_node_called++;
  iodev->active_node = node;
}

//  From system_state.
size_t cras_system_get_volume()
{
  return 0;
}

// From bt device
int cras_bt_device_sco_connect(struct cras_bt_device *device)
{
  cras_bt_device_sco_connect_called++;
  return cras_bt_transport_sco_connect_return_val;
}

const char *cras_bt_device_name(const struct cras_bt_device *device)
{
  return "fake-device-name";
}

const char *cras_bt_device_address(const struct cras_bt_device *device) {
  return "1A:2B:3C:4D:5E:6F";
}

void cras_bt_device_append_iodev(struct cras_bt_device *device,
                                 struct cras_iodev *iodev,
                                 enum cras_bt_device_profile profile)
{
  cras_bt_device_append_iodev_called++;
}

void cras_bt_device_rm_iodev(struct cras_bt_device *device,
                             struct cras_iodev *iodev)
{
  cras_bt_device_rm_iodev_called++;
}

int cras_bt_device_sco_mtu(struct cras_bt_device *device, int sco_socket)
{
  return 48;
}
void cras_bt_device_iodev_buffer_size_changed(struct cras_bt_device *device)
{
}
const char *cras_bt_device_object_path(const struct cras_bt_device *device)
{
  return "/fake/object/path";
}

// From cras_hfp_info
int hfp_info_add_iodev(struct hfp_info *info, struct cras_iodev *dev)
{
  hfp_info_add_iodev_called++;
  return 0;
}

int hfp_info_rm_iodev(struct hfp_info *info, struct cras_iodev *dev)
{
  hfp_info_rm_iodev_called++;
  return 0;
}

int hfp_info_has_iodev(struct hfp_info *info)
{
  hfp_info_has_iodev_called++;
  return hfp_info_has_iodev_return_val;
}

int hfp_info_running(struct hfp_info *info)
{
  hfp_info_running_called++;
  return hfp_info_running_return_val;
}

int hfp_info_start(int fd, unsigned int mtu, struct hfp_info *info)
{
  hfp_info_start_called++;
  return 0;
}

int hfp_info_stop(struct hfp_info *info)
{
  hfp_info_stop_called++;
  return 0;
}

int hfp_buf_queued(struct hfp_info *info, const struct cras_iodev *dev)
{
  return 0;
}

int hfp_buf_size(struct hfp_info *info, struct cras_iodev *dev)
{
  /* 1008 / 2 */
  return 504;
}

void hfp_buf_acquire(struct hfp_info *info,  struct cras_iodev *dev,
		     uint8_t **buf, unsigned *count)
{
  hfp_buf_acquire_called++;
  *count = hfp_buf_acquire_return_val;
}

void hfp_buf_release(struct hfp_info *info, struct cras_iodev *dev,
		     unsigned written_bytes)
{
  hfp_buf_release_called++;
  hfp_buf_release_nwritten_val = written_bytes;
}

void hfp_register_packet_size_changed_callback(struct hfp_info *info,
                 void (*cb)(void *data),
                 void *data)
{
}

void hfp_unregister_packet_size_changed_callback(struct hfp_info *info,
             void *data)
{
}

void cras_iodev_init_audio_area(struct cras_iodev *iodev,
                                int num_channels) {
  iodev->area = dummy_audio_area;
}

void cras_iodev_free_audio_area(struct cras_iodev *iodev) {
}

void cras_iodev_free_resources(struct cras_iodev *iodev) {
    cras_iodev_free_resources_called++;
}

void cras_audio_area_config_buf_pointers(struct cras_audio_area *area,
					 const struct cras_audio_format *fmt,
					 uint8_t *base_buffer)
{
  dummy_audio_area->channels[0].buf = base_buffer;
}

int hfp_set_call_status(struct hfp_slc_handle *handle, int call)
{
  return 0;
}

int hfp_event_speaker_gain(struct hfp_slc_handle *handle, int gain)
{
  return 0;
}

} // extern "C"

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}