diff options
Diffstat (limited to 'cras/src/tests/alsa_io_unittest.cc')
-rw-r--r-- | cras/src/tests/alsa_io_unittest.cc | 3045 |
1 files changed, 0 insertions, 3045 deletions
diff --git a/cras/src/tests/alsa_io_unittest.cc b/cras/src/tests/alsa_io_unittest.cc deleted file mode 100644 index 021b4789..00000000 --- a/cras/src/tests/alsa_io_unittest.cc +++ /dev/null @@ -1,3045 +0,0 @@ -// Copyright (c) 2012 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> -#include <stdio.h> -#include <syslog.h> - -#include <map> -#include <vector> - -extern "C" { - -#include "cras_alsa_mixer.h" -#include "cras_iodev.h" -#include "cras_shm.h" -#include "cras_system_state.h" -#include "cras_types.h" - -// Include C file to test static functions. -#include "cras_alsa_io.c" -} - -#define BUFFER_SIZE 8192 - -// Data for simulating functions stubbed below. -static int cras_alsa_open_called; -static int cras_iodev_append_stream_ret; -static int cras_alsa_get_avail_frames_ret; -static int cras_alsa_get_avail_frames_avail; -static int cras_alsa_start_called; -static uint8_t* cras_alsa_mmap_begin_buffer; -static size_t cras_alsa_mmap_begin_frames; -static size_t cras_alsa_fill_properties_called; -static bool cras_alsa_support_8_channels; -static size_t alsa_mixer_set_dBFS_called; -static int alsa_mixer_set_dBFS_value; -static const struct mixer_control* alsa_mixer_set_dBFS_output; -static size_t alsa_mixer_set_capture_dBFS_called; -static int alsa_mixer_set_capture_dBFS_value; -static const struct mixer_control* alsa_mixer_set_capture_dBFS_input; -static const struct mixer_control* - cras_alsa_mixer_get_minimum_capture_gain_mixer_input; -static const struct mixer_control* - cras_alsa_mixer_get_maximum_capture_gain_mixer_input; -static size_t cras_alsa_mixer_list_outputs_called; -static size_t cras_alsa_mixer_list_inputs_called; -static size_t cras_alsa_mixer_get_control_for_section_called; -static struct mixer_control* - cras_alsa_mixer_get_control_for_section_return_value; -static size_t sys_get_volume_called; -static size_t sys_get_volume_return_value; -static size_t alsa_mixer_set_mute_called; -static int alsa_mixer_set_mute_value; -static size_t alsa_mixer_get_dB_range_called; -static long alsa_mixer_get_dB_range_value; -static size_t alsa_mixer_get_output_dB_range_called; -static long alsa_mixer_get_output_dB_range_value; -static const struct mixer_control* alsa_mixer_set_mute_output; -static size_t alsa_mixer_set_capture_mute_called; -static int alsa_mixer_set_capture_mute_value; -static const struct mixer_control* alsa_mixer_set_capture_mute_input; -static size_t sys_get_mute_called; -static int sys_get_mute_return_value; -static size_t sys_get_capture_mute_called; -static int sys_get_capture_mute_return_value; -static struct cras_alsa_mixer* fake_mixer = (struct cras_alsa_mixer*)1; -static struct cras_card_config* fake_config = (struct cras_card_config*)2; -static struct mixer_control** cras_alsa_mixer_list_outputs_outputs; -static size_t cras_alsa_mixer_list_outputs_outputs_length; -static struct mixer_control** cras_alsa_mixer_list_inputs_outputs; -static size_t cras_alsa_mixer_list_inputs_outputs_length; -static size_t cras_alsa_mixer_set_output_active_state_called; -static std::vector<struct mixer_control*> - cras_alsa_mixer_set_output_active_state_outputs; -static std::vector<int> cras_alsa_mixer_set_output_active_state_values; -static cras_audio_format* fake_format; -static size_t sys_set_volume_limits_called; -static size_t cras_alsa_mixer_get_minimum_capture_gain_called; -static size_t cras_alsa_mixer_get_maximum_capture_gain_called; -static struct mixer_control* cras_alsa_jack_get_mixer_output_ret; -static struct mixer_control* cras_alsa_jack_get_mixer_input_ret; -static size_t cras_alsa_mixer_get_output_volume_curve_called; -typedef std::map<const struct mixer_control*, std::string> ControlNameMap; -static ControlNameMap cras_alsa_mixer_get_control_name_values; -static size_t cras_alsa_mixer_get_control_name_called; -static size_t cras_alsa_jack_list_create_called; -static size_t cras_alsa_jack_list_find_jacks_by_name_matching_called; -static size_t cras_alsa_jack_list_add_jack_for_section_called; -static struct cras_alsa_jack* - cras_alsa_jack_list_add_jack_for_section_result_jack; -static size_t cras_alsa_jack_list_destroy_called; -static int cras_alsa_jack_list_has_hctl_jacks_return_val; -static jack_state_change_callback* cras_alsa_jack_list_create_cb; -static void* cras_alsa_jack_list_create_cb_data; -static char test_card_name[] = "TestCard"; -static char test_pcm_name[] = "TestPCM"; -static char test_dev_name[] = "TestDev"; -static char test_dev_id[] = "TestDevId"; -static size_t cras_iodev_add_node_called; -static struct cras_ionode* cras_iodev_set_node_plugged_ionode; -static size_t cras_iodev_set_node_plugged_called; -static int cras_iodev_set_node_plugged_value; -static unsigned cras_alsa_jack_enable_ucm_called; -static unsigned ucm_set_enabled_called; -static size_t cras_iodev_update_dsp_called; -static const char* cras_iodev_update_dsp_name; -typedef std::map<const char*, std::string> DspNameMap; -static size_t ucm_get_dsp_name_for_dev_called; -static DspNameMap ucm_get_dsp_name_for_dev_values; -static size_t cras_iodev_free_resources_called; -static size_t cras_alsa_jack_update_node_type_called; -static int ucm_swap_mode_exists_ret_value; -static int ucm_enable_swap_mode_ret_value; -static size_t ucm_enable_swap_mode_called; -static int is_utf8_string_ret_value; -static const char* cras_alsa_jack_update_monitor_fake_name = 0; -static int cras_alsa_jack_get_name_called; -static const char* cras_alsa_jack_get_name_ret_value = 0; -static char default_jack_name[] = "Something Jack"; -static int auto_unplug_input_node_ret = 0; -static int auto_unplug_output_node_ret = 0; -static long cras_alsa_mixer_get_minimum_capture_gain_ret_value; -static long cras_alsa_mixer_get_maximum_capture_gain_ret_value; -static snd_pcm_state_t snd_pcm_state_ret; -static int cras_alsa_attempt_resume_called; -static snd_hctl_t* fake_hctl = (snd_hctl_t*)2; -static size_t ucm_get_dma_period_for_dev_called; -static unsigned int ucm_get_dma_period_for_dev_ret; -static int cras_card_config_get_volume_curve_for_control_called; -typedef std::map<std::string, struct cras_volume_curve*> VolCurveMap; -static VolCurveMap cras_card_config_get_volume_curve_vals; -static int cras_alsa_mmap_get_whole_buffer_called; -static int cras_iodev_fill_odev_zeros_called; -static unsigned int cras_iodev_fill_odev_zeros_frames; -static int cras_iodev_frames_queued_ret; -static int cras_iodev_buffer_avail_ret; -static int cras_alsa_resume_appl_ptr_called; -static int cras_alsa_resume_appl_ptr_ahead; -static const struct cras_volume_curve* fake_get_dBFS_volume_curve_val; -static int cras_iodev_dsp_set_swap_mode_for_node_called; -static std::map<std::string, long> ucm_get_default_node_gain_values; -static std::map<std::string, long> ucm_get_intrinsic_sensitivity_values; -static thread_callback audio_thread_cb; -static void* audio_thread_cb_data; -static int hotword_send_triggered_msg_called; -static struct timespec clock_gettime_retspec; -static unsigned cras_iodev_reset_rate_estimator_called; - -void ResetStubData() { - cras_alsa_open_called = 0; - cras_iodev_append_stream_ret = 0; - cras_alsa_get_avail_frames_ret = 0; - cras_alsa_get_avail_frames_avail = 0; - cras_alsa_start_called = 0; - cras_alsa_fill_properties_called = 0; - cras_alsa_support_8_channels = false; - sys_get_volume_called = 0; - alsa_mixer_set_dBFS_called = 0; - alsa_mixer_set_capture_dBFS_called = 0; - sys_get_mute_called = 0; - sys_get_capture_mute_called = 0; - alsa_mixer_set_mute_called = 0; - alsa_mixer_get_dB_range_called = 0; - alsa_mixer_get_output_dB_range_called = 0; - alsa_mixer_set_capture_mute_called = 0; - cras_alsa_mixer_get_control_for_section_called = 0; - cras_alsa_mixer_get_control_for_section_return_value = NULL; - cras_alsa_mixer_list_outputs_called = 0; - cras_alsa_mixer_list_outputs_outputs_length = 0; - cras_alsa_mixer_list_inputs_called = 0; - cras_alsa_mixer_list_inputs_outputs_length = 0; - cras_alsa_mixer_set_output_active_state_called = 0; - cras_alsa_mixer_set_output_active_state_outputs.clear(); - cras_alsa_mixer_set_output_active_state_values.clear(); - sys_set_volume_limits_called = 0; - cras_alsa_mixer_get_minimum_capture_gain_called = 0; - cras_alsa_mixer_get_maximum_capture_gain_called = 0; - cras_alsa_mixer_get_output_volume_curve_called = 0; - cras_alsa_jack_get_mixer_output_ret = NULL; - cras_alsa_jack_get_mixer_input_ret = NULL; - cras_alsa_mixer_get_control_name_values.clear(); - cras_alsa_mixer_get_control_name_called = 0; - cras_alsa_jack_list_create_called = 0; - cras_alsa_jack_list_find_jacks_by_name_matching_called = 0; - cras_alsa_jack_list_add_jack_for_section_called = 0; - cras_alsa_jack_list_add_jack_for_section_result_jack = NULL; - cras_alsa_jack_list_destroy_called = 0; - cras_alsa_jack_list_has_hctl_jacks_return_val = 1; - cras_iodev_add_node_called = 0; - cras_iodev_set_node_plugged_called = 0; - cras_alsa_jack_enable_ucm_called = 0; - ucm_set_enabled_called = 0; - cras_iodev_update_dsp_called = 0; - cras_iodev_update_dsp_name = 0; - ucm_get_dsp_name_for_dev_called = 0; - ucm_get_dsp_name_for_dev_values.clear(); - cras_iodev_free_resources_called = 0; - cras_alsa_jack_update_node_type_called = 0; - ucm_swap_mode_exists_ret_value = 0; - ucm_enable_swap_mode_ret_value = 0; - ucm_enable_swap_mode_called = 0; - is_utf8_string_ret_value = 1; - cras_alsa_jack_get_name_called = 0; - cras_alsa_jack_get_name_ret_value = default_jack_name; - cras_alsa_jack_update_monitor_fake_name = 0; - cras_card_config_get_volume_curve_for_control_called = 0; - cras_card_config_get_volume_curve_vals.clear(); - cras_alsa_mixer_get_minimum_capture_gain_ret_value = 0; - cras_alsa_mixer_get_maximum_capture_gain_ret_value = 0; - snd_pcm_state_ret = SND_PCM_STATE_RUNNING; - cras_alsa_attempt_resume_called = 0; - ucm_get_dma_period_for_dev_called = 0; - ucm_get_dma_period_for_dev_ret = 0; - cras_alsa_mmap_get_whole_buffer_called = 0; - cras_iodev_fill_odev_zeros_called = 0; - cras_iodev_fill_odev_zeros_frames = 0; - cras_iodev_frames_queued_ret = 0; - cras_iodev_buffer_avail_ret = 0; - cras_alsa_resume_appl_ptr_called = 0; - cras_alsa_resume_appl_ptr_ahead = 0; - fake_get_dBFS_volume_curve_val = NULL; - cras_iodev_dsp_set_swap_mode_for_node_called = 0; - ucm_get_default_node_gain_values.clear(); - ucm_get_intrinsic_sensitivity_values.clear(); - cras_iodev_reset_rate_estimator_called = 0; -} - -static long fake_get_dBFS(const struct cras_volume_curve* curve, - size_t volume) { - fake_get_dBFS_volume_curve_val = curve; - return (volume - 100) * 100; -} -static cras_volume_curve default_curve = { - .get_dBFS = fake_get_dBFS, -}; - -static struct cras_iodev* alsa_iodev_create_with_default_parameters( - size_t card_index, - const char* dev_id, - enum CRAS_ALSA_CARD_TYPE card_type, - int is_first, - struct cras_alsa_mixer* mixer, - struct cras_card_config* config, - struct cras_use_case_mgr* ucm, - enum CRAS_STREAM_DIRECTION direction) { - return alsa_iodev_create(card_index, test_card_name, 0, test_pcm_name, - test_dev_name, dev_id, card_type, is_first, mixer, - config, ucm, fake_hctl, direction, 0, 0, - (char*)"123"); -} - -namespace { -TEST(AlsaIoInit, InitializeInvalidDirection) { - struct alsa_io* aio; - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_NUM_DIRECTIONS); - ASSERT_EQ(aio, (void*)NULL); -} - -TEST(AlsaIoInit, InitializePlayback) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, test_dev_id, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - /* Get volume curve twice for iodev, and default node. */ - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); - EXPECT_EQ( - 0, strncmp(test_card_name, aio->base.info.name, strlen(test_card_name))); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ("", cras_iodev_update_dsp_name); - ASSERT_NE(reinterpret_cast<const char*>(NULL), aio->dev_name); - EXPECT_EQ(0, strcmp(test_dev_name, aio->dev_name)); - ASSERT_NE(reinterpret_cast<const char*>(NULL), aio->dev_id); - EXPECT_EQ(0, strcmp(test_dev_id, aio->dev_id)); - - alsa_iodev_destroy((struct cras_iodev*)aio); - EXPECT_EQ(1, cras_iodev_free_resources_called); -} - -TEST(AlsaIoInit, DefaultNodeInternalCard) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - ASSERT_STREQ(DEFAULT, aio->base.active_node->name); - ASSERT_EQ(1, aio->base.active_node->plugged); - ASSERT_EQ((void*)no_stream, (void*)aio->base.no_stream); - ASSERT_EQ((void*)is_free_running, (void*)aio->base.is_free_running); - alsa_iodev_destroy((struct cras_iodev*)aio); - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - ASSERT_STREQ(INTERNAL_SPEAKER, aio->base.active_node->name); - ASSERT_EQ(1, aio->base.active_node->plugged); - ASSERT_EQ((void*)no_stream, (void*)aio->base.no_stream); - ASSERT_EQ((void*)is_free_running, (void*)aio->base.is_free_running); - alsa_iodev_destroy((struct cras_iodev*)aio); - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - /* No more call to get volume curve for input device. */ - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - ASSERT_STREQ(DEFAULT, aio->base.active_node->name); - ASSERT_EQ(1, aio->base.active_node->plugged); - ASSERT_EQ((void*)no_stream, (void*)aio->base.no_stream); - ASSERT_EQ((void*)is_free_running, (void*)aio->base.is_free_running); - alsa_iodev_destroy((struct cras_iodev*)aio); - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - ASSERT_STREQ(INTERNAL_MICROPHONE, aio->base.active_node->name); - ASSERT_EQ(1, aio->base.active_node->plugged); - ASSERT_EQ((void*)no_stream, (void*)aio->base.no_stream); - ASSERT_EQ((void*)is_free_running, (void*)aio->base.is_free_running); - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, DefaultNodeUSBCard) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_USB, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - ASSERT_STREQ(DEFAULT, aio->base.active_node->name); - ASSERT_EQ(1, aio->base.active_node->plugged); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - alsa_iodev_destroy((struct cras_iodev*)aio); - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_USB, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - ASSERT_STREQ(DEFAULT, aio->base.active_node->name); - ASSERT_EQ(1, aio->base.active_node->plugged); - EXPECT_EQ(2, cras_iodev_set_node_plugged_called); - - /* No extra gain applied. */ - ASSERT_EQ(DEFAULT_CAPTURE_VOLUME_DBFS, - aio->base.active_node->intrinsic_sensitivity); - ASSERT_EQ(0, aio->base.active_node->capture_gain); - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, OpenPlayback) { - struct cras_iodev* iodev; - struct cras_audio_format format; - struct alsa_io* aio; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - /* Call open_dev once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_open_called); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - aio = (struct alsa_io*)iodev; - format.frame_rate = 48000; - format.num_channels = 1; - cras_iodev_set_format(iodev, &format); - - // Test that these flags are cleared after open_dev. - aio->free_running = 1; - aio->filled_zeros_for_draining = 512; - iodev->open_dev(iodev); - EXPECT_EQ(2, cras_alsa_open_called); - iodev->configure_dev(iodev); - EXPECT_EQ(2, cras_alsa_open_called); - EXPECT_EQ(1, sys_set_volume_limits_called); - EXPECT_EQ(1, alsa_mixer_set_dBFS_called); - EXPECT_EQ(0, cras_alsa_start_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_called); - EXPECT_EQ(0, aio->free_running); - EXPECT_EQ(0, aio->filled_zeros_for_draining); - EXPECT_EQ(SEVERE_UNDERRUN_MS * format.frame_rate / 1000, - aio->severe_underrun_frames); - - alsa_iodev_destroy(iodev); - free(fake_format); -} - -TEST(AlsaIoInit, UsbCardAutoPlug) { - struct cras_iodev* iodev; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_called); - alsa_iodev_destroy(iodev); - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters(0, NULL, ALSA_CARD_TYPE_USB, - 0, fake_mixer, fake_config, - NULL, CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_called); - alsa_iodev_destroy(iodev); - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters(0, NULL, ALSA_CARD_TYPE_USB, - 1, fake_mixer, fake_config, - NULL, CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - // Should assume USB devs are plugged when they appear. - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - EXPECT_EQ(1, iodev->active_node->plugged); - alsa_iodev_destroy(iodev); -} - -TEST(AlsaIoInit, UsbCardUseSoftwareVolume) { - struct cras_iodev* iodev; - - alsa_mixer_get_dB_range_value = 1000; - alsa_mixer_get_output_dB_range_value = 1000; - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters(0, NULL, ALSA_CARD_TYPE_USB, - 1, fake_mixer, fake_config, - NULL, CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(1, alsa_mixer_get_dB_range_called); - EXPECT_EQ(1, alsa_mixer_get_output_dB_range_called); - EXPECT_EQ(1, iodev->active_node->software_volume_needed); - alsa_iodev_destroy(iodev); - - alsa_mixer_get_dB_range_value = 3000; - alsa_mixer_get_output_dB_range_value = 2000; - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters(0, NULL, ALSA_CARD_TYPE_USB, - 1, fake_mixer, fake_config, - NULL, CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(1, alsa_mixer_get_dB_range_called); - EXPECT_EQ(1, alsa_mixer_get_output_dB_range_called); - EXPECT_EQ(0, iodev->active_node->software_volume_needed); - alsa_iodev_destroy(iodev); -} - -TEST(AlsaIoInit, SoftwareGainIntrinsicSensitivity) { - struct cras_iodev* iodev; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - long intrinsic_sensitivity = -2700; - - ResetStubData(); - - // Set intrinsic sensitivity to -2700 * 0.01 dBFS/Pa. - ucm_get_intrinsic_sensitivity_values[INTERNAL_MICROPHONE] = - intrinsic_sensitivity; - - // Assume this is the first device so it gets internal mic node name. - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - ASSERT_EQ(intrinsic_sensitivity, iodev->active_node->intrinsic_sensitivity); - ASSERT_EQ(DEFAULT_CAPTURE_VOLUME_DBFS - intrinsic_sensitivity, - iodev->active_node->capture_gain); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaIoInit, RouteBasedOnJackCallback) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_NE(aio, (void*)NULL); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); - EXPECT_EQ(1, cras_alsa_jack_list_create_called); - EXPECT_EQ(1, cras_alsa_jack_list_find_jacks_by_name_matching_called); - EXPECT_EQ(0, cras_alsa_jack_list_add_jack_for_section_called); - - cras_alsa_jack_list_create_cb(NULL, 1, cras_alsa_jack_list_create_cb_data); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_value); - cras_alsa_jack_list_create_cb(NULL, 0, cras_alsa_jack_list_create_cb_data); - EXPECT_EQ(2, cras_iodev_set_node_plugged_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_value); - - alsa_iodev_destroy((struct cras_iodev*)aio); - EXPECT_EQ(1, cras_alsa_jack_list_destroy_called); -} - -TEST(AlsaIoInit, RouteBasedOnInputJackCallback) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - ASSERT_NE(aio, (void*)NULL); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - EXPECT_EQ(1, cras_alsa_jack_list_create_called); - EXPECT_EQ(1, cras_alsa_jack_list_find_jacks_by_name_matching_called); - EXPECT_EQ(0, cras_alsa_jack_list_add_jack_for_section_called); - - cras_alsa_jack_list_create_cb(NULL, 1, cras_alsa_jack_list_create_cb_data); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_value); - cras_alsa_jack_list_create_cb(NULL, 0, cras_alsa_jack_list_create_cb_data); - EXPECT_EQ(2, cras_iodev_set_node_plugged_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_value); - - alsa_iodev_destroy((struct cras_iodev*)aio); - EXPECT_EQ(1, cras_alsa_jack_list_destroy_called); -} - -TEST(AlsaIoInit, InitializeCapture) { - struct alsa_io* aio; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - ASSERT_NE(aio, (void*)NULL); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - EXPECT_EQ(1, cras_alsa_mixer_list_inputs_called); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, OpenCapture) { - struct cras_iodev* iodev; - struct cras_audio_format format; - struct alsa_io* aio; - - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - - aio = (struct alsa_io*)iodev; - format.frame_rate = 48000; - format.num_channels = 1; - cras_iodev_set_format(iodev, &format); - - ResetStubData(); - iodev->open_dev(iodev); - EXPECT_EQ(1, cras_alsa_open_called); - iodev->configure_dev(iodev); - EXPECT_EQ(1, cras_alsa_open_called); - EXPECT_EQ(1, cras_alsa_mixer_get_minimum_capture_gain_called); - EXPECT_EQ(1, cras_alsa_mixer_get_maximum_capture_gain_called); - EXPECT_EQ(1, alsa_mixer_set_capture_dBFS_called); - EXPECT_EQ(1, sys_get_capture_mute_called); - EXPECT_EQ(1, alsa_mixer_set_capture_mute_called); - EXPECT_EQ(1, cras_alsa_start_called); - EXPECT_EQ(SEVERE_UNDERRUN_MS * format.frame_rate / 1000, - aio->severe_underrun_frames); - - alsa_iodev_destroy(iodev); - free(fake_format); -} - -TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithDefaultNodeGain) { - struct cras_iodev* iodev; - struct cras_audio_format format; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - long default_node_gain = 1000; - - ResetStubData(); - // Set default node gain to -1000 * 0.01 dB. - ucm_get_default_node_gain_values[INTERNAL_MICROPHONE] = default_node_gain; - - // Assume this is the first device so it gets internal mic node name. - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - - cras_iodev_set_format(iodev, &format); - - // Check the default node gain is the same as what specified in UCM. - EXPECT_EQ(default_node_gain, iodev->active_node->capture_gain); - cras_alsa_mixer_get_minimum_capture_gain_ret_value = 0; - cras_alsa_mixer_get_maximum_capture_gain_ret_value = 2000; - - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - iodev->close_dev(iodev); - - // Hardware gain is in the hardware gain range and set to 1000 * 0.01 dB. - EXPECT_EQ(default_node_gain, alsa_mixer_set_capture_dBFS_value); - - // Check we do respect the hardware maximum capture gain. - cras_alsa_mixer_get_maximum_capture_gain_ret_value = 500; - - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - iodev->close_dev(iodev); - - EXPECT_EQ(500, alsa_mixer_set_capture_dBFS_value); - - alsa_iodev_destroy(iodev); - free(fake_format); -} - -TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithSoftwareGain) { - struct cras_iodev* iodev; - struct cras_audio_format format; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - - /* Meet the requirements of using software gain. */ - ResetStubData(); - - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - - format.frame_rate = 48000; - format.num_channels = 1; - cras_iodev_set_format(iodev, &format); - - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - iodev->close_dev(iodev); - - /* Hardware gain is set to 0dB when software gain is used. */ - EXPECT_EQ(0, alsa_mixer_set_capture_dBFS_value); - - /* Test the case where software gain is not needed. */ - iodev->active_node->software_volume_needed = 0; - iodev->active_node->capture_gain = 1000; - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - iodev->close_dev(iodev); - - /* Hardware gain is set to 1000 * 0.01 dB as got from catpure_gain.*/ - EXPECT_EQ(0, alsa_mixer_set_capture_dBFS_value); - - alsa_iodev_destroy(iodev); - free(fake_format); -} - -TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithDefaultUsbDevice) { - struct cras_iodev* iodev; - struct cras_audio_format format; - - iodev = alsa_iodev_create_with_default_parameters(0, NULL, ALSA_CARD_TYPE_USB, - 0, fake_mixer, fake_config, - NULL, CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - - format.frame_rate = 48000; - format.num_channels = 1; - cras_iodev_set_format(iodev, &format); - - iodev->active_node->intrinsic_sensitivity = DEFAULT_CAPTURE_VOLUME_DBFS; - iodev->active_node->capture_gain = 0; - - ResetStubData(); - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - - EXPECT_EQ(1, sys_get_capture_mute_called); - EXPECT_EQ(1, alsa_mixer_set_capture_mute_called); - - /* Not change mixer controls for USB devices without UCM config. */ - EXPECT_EQ(0, alsa_mixer_set_capture_dBFS_called); - - alsa_iodev_destroy(iodev); - free(fake_format); -} - -TEST(AlsaIoInit, UpdateActiveNode) { - struct cras_iodev* iodev; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - - iodev->update_active_node(iodev, 0, 1); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaIoInit, StartDevice) { - struct cras_iodev* iodev; - int rc; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, NULL, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - - // Return right away if it is already running. - snd_pcm_state_ret = SND_PCM_STATE_RUNNING; - rc = iodev->start(iodev); - EXPECT_EQ(0, rc); - EXPECT_EQ(0, cras_alsa_start_called); - - // Otherwise, start the device. - snd_pcm_state_ret = SND_PCM_STATE_SETUP; - rc = iodev->start(iodev); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_start_called); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaIoInit, ResumeDevice) { - struct cras_iodev* iodev; - int rc; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, NULL, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - - // Attempt to resume if the device is suspended. - snd_pcm_state_ret = SND_PCM_STATE_SUSPENDED; - rc = iodev->start(iodev); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_attempt_resume_called); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaIoInit, DspNameDefault) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(1, ucm_get_dsp_name_for_dev_called); - EXPECT_STREQ("", cras_iodev_update_dsp_name); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, DspName) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - - ResetStubData(); - ucm_get_dsp_name_for_dev_values[DEFAULT] = "hello"; - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(1, ucm_get_dsp_name_for_dev_called); - EXPECT_STREQ("hello", cras_iodev_update_dsp_name); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, DspNameJackOverride) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - const struct cras_alsa_jack* jack = (struct cras_alsa_jack*)4; - static const char* jack_name = "jack"; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(1, ucm_get_dsp_name_for_dev_called); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_STREQ("", cras_iodev_update_dsp_name); - - cras_alsa_jack_get_name_ret_value = jack_name; - ucm_get_dsp_name_for_dev_values[jack_name] = "override_dsp"; - // Add the jack node. - cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); - EXPECT_EQ(2, cras_alsa_jack_get_name_called); - EXPECT_EQ(2, ucm_get_dsp_name_for_dev_called); - - // Mark the jack node as active. - alsa_iodev_set_active_node(&aio->base, aio->base.nodes->next, 1); - EXPECT_EQ(2, ucm_get_dsp_name_for_dev_called); - EXPECT_EQ(2, cras_iodev_update_dsp_called); - EXPECT_STREQ("override_dsp", cras_iodev_update_dsp_name); - - // Mark the default node as active. - alsa_iodev_set_active_node(&aio->base, aio->base.nodes, 1); - EXPECT_EQ(2, ucm_get_dsp_name_for_dev_called); - EXPECT_EQ(3, cras_iodev_update_dsp_called); - EXPECT_STREQ("", cras_iodev_update_dsp_name); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, NodeTypeOverride) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - const struct cras_alsa_jack* jack = (struct cras_alsa_jack*)4; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - // Add the jack node. - cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); - // Verify that cras_alsa_jack_update_node_type is called when an output device - // is created. - EXPECT_EQ(1, cras_alsa_jack_update_node_type_called); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaIoInit, SwapMode) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_ionode* const fake_node = - (cras_ionode*)calloc(1, sizeof(struct cras_ionode)); - ResetStubData(); - // Stub replies that swap mode does not exist. - ucm_swap_mode_exists_ret_value = 0; - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - - aio->base.set_swap_mode_for_node((cras_iodev*)aio, fake_node, 1); - /* Swap mode is implemented by dsp. */ - EXPECT_EQ(1, cras_iodev_dsp_set_swap_mode_for_node_called); - - // Stub replies that swap mode exists. - ucm_swap_mode_exists_ret_value = 1; - alsa_iodev_destroy((struct cras_iodev*)aio); - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - // Enable swap mode. - aio->base.set_swap_mode_for_node((cras_iodev*)aio, fake_node, 1); - - // Verify that ucm_enable_swap_mode is called when callback to enable - // swap mode is called. - EXPECT_EQ(1, ucm_enable_swap_mode_called); - - alsa_iodev_destroy((struct cras_iodev*)aio); - free(fake_node); -} - -TEST(AlsaIoInit, MaxSupportedChannels) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - int i; - - // i = 0: cras_alsa_support_8_channels is false, support 2 channels only. - // i = 1: cras_alsa_support_8_channels is true, support up to 8 channels. - for (i = 0; i < 2; i++) { - ResetStubData(); - cras_alsa_support_8_channels = (bool)i; - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, test_dev_id, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, - NULL, CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - uint32_t max_channels = (cras_alsa_support_8_channels) ? 8 : 2; - EXPECT_EQ(max_channels, aio->base.info.max_supported_channels); - alsa_iodev_destroy((struct cras_iodev*)aio); - EXPECT_EQ(1, cras_iodev_free_resources_called); - } -} - -// Test that system settins aren't touched if no streams active. -TEST(AlsaOutputNode, SystemSettingsWhenInactive) { - int rc; - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct mixer_control* outputs[2]; - - ResetStubData(); - outputs[0] = reinterpret_cast<struct mixer_control*>(3); - outputs[1] = reinterpret_cast<struct mixer_control*>(4); - cras_alsa_mixer_list_outputs_outputs = outputs; - cras_alsa_mixer_list_outputs_outputs_length = ARRAY_SIZE(outputs); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - /* Two mixer controls calls get volume curve. */ - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); - - ResetStubData(); - rc = alsa_iodev_set_active_node((struct cras_iodev*)aio, - aio->base.nodes->next, 1); - EXPECT_EQ(0, rc); - EXPECT_EQ(0, alsa_mixer_set_mute_called); - EXPECT_EQ(0, alsa_mixer_set_dBFS_called); - ASSERT_EQ(2, cras_alsa_mixer_set_output_active_state_called); - EXPECT_EQ(outputs[0], cras_alsa_mixer_set_output_active_state_outputs[0]); - EXPECT_EQ(0, cras_alsa_mixer_set_output_active_state_values[0]); - EXPECT_EQ(outputs[1], cras_alsa_mixer_set_output_active_state_outputs[1]); - EXPECT_EQ(1, cras_alsa_mixer_set_output_active_state_values[1]); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - // No jack is defined, and UCM is not used. - EXPECT_EQ(0, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(0, ucm_set_enabled_called); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -// Test handling of different amounts of outputs. -TEST(AlsaOutputNode, TwoOutputs) { - int rc; - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct mixer_control* outputs[2]; - - ResetStubData(); - outputs[0] = reinterpret_cast<struct mixer_control*>(3); - outputs[1] = reinterpret_cast<struct mixer_control*>(4); - cras_alsa_mixer_list_outputs_outputs = outputs; - cras_alsa_mixer_list_outputs_outputs_length = ARRAY_SIZE(outputs); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); - - aio->handle = (snd_pcm_t*)0x24; - - ResetStubData(); - rc = alsa_iodev_set_active_node((struct cras_iodev*)aio, - aio->base.nodes->next, 1); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, alsa_mixer_set_mute_called); - EXPECT_EQ(outputs[1], alsa_mixer_set_mute_output); - EXPECT_EQ(1, alsa_mixer_set_dBFS_called); - EXPECT_EQ(outputs[1], alsa_mixer_set_dBFS_output); - ASSERT_EQ(2, cras_alsa_mixer_set_output_active_state_called); - EXPECT_EQ(outputs[0], cras_alsa_mixer_set_output_active_state_outputs[0]); - EXPECT_EQ(0, cras_alsa_mixer_set_output_active_state_values[0]); - EXPECT_EQ(outputs[1], cras_alsa_mixer_set_output_active_state_outputs[1]); - EXPECT_EQ(1, cras_alsa_mixer_set_output_active_state_values[1]); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - // No jacks defined, and UCM is not used. - EXPECT_EQ(0, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(0, ucm_set_enabled_called); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaOutputNode, TwoJacksHeadphoneLineout) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - struct mixer_control* output; - struct ucm_section* section; - - ResetStubData(); - output = reinterpret_cast<struct mixer_control*>(3); - cras_alsa_mixer_get_control_name_values[output] = HEADPHONE; - - // Create the iodev - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); - - // First node 'Headphone' - section = ucm_section_create(HEADPHONE, "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - "fake-jack", "gpio"); - ucm_section_set_mixer_name(section, HEADPHONE); - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(10); - cras_alsa_mixer_get_control_for_section_return_value = output; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - ucm_section_free_list(section); - - // Second node 'Line Out' - section = ucm_section_create("Line Out", "hw:0.1", 0, -1, CRAS_STREAM_OUTPUT, - "fake-jack", "gpio"); - ucm_section_set_mixer_name(section, HEADPHONE); - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(20); - cras_alsa_mixer_get_control_for_section_return_value = output; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - EXPECT_EQ(7, cras_card_config_get_volume_curve_for_control_called); - ucm_section_free_list(section); - - // Both nodes are associated with the same mixer output. Different jack plug - // report should trigger different node attribute change. - cras_alsa_jack_get_mixer_output_ret = output; - jack_output_plug_event(reinterpret_cast<struct cras_alsa_jack*>(10), 0, aio); - EXPECT_STREQ(cras_iodev_set_node_plugged_ionode->name, HEADPHONE); - - jack_output_plug_event(reinterpret_cast<struct cras_alsa_jack*>(20), 0, aio); - EXPECT_STREQ(cras_iodev_set_node_plugged_ionode->name, "Line Out"); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, MaxSupportedChannels) { - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - struct ucm_section* section; - int i; - - // i = 0: cras_alsa_support_8_channels is false, support 2 channels only. - // i = 1: cras_alsa_support_8_channels is true, support up to 8 channels. - for (i = 0; i < 2; i++) { - ResetStubData(); - cras_alsa_support_8_channels = (bool)i; - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - - // Node without controls or jacks. - section = ucm_section_create(INTERNAL_SPEAKER, "hw:0,1", 1, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); - // Device index doesn't match. - EXPECT_EQ(-22, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - section->dev_idx = 0; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - uint32_t max_channels = (cras_alsa_support_8_channels) ? 8 : 2; - EXPECT_EQ(max_channels, iodev->info.max_supported_channels); - alsa_iodev_destroy(iodev); - } -} - -TEST(AlsaOutputNode, OutputsFromUCM) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Headset Jack"; - struct mixer_control* outputs[2]; - int rc; - struct ucm_section* section; - - ResetStubData(); - outputs[0] = reinterpret_cast<struct mixer_control*>(3); - outputs[1] = reinterpret_cast<struct mixer_control*>(4); - cras_alsa_mixer_list_outputs_outputs = outputs; - cras_alsa_mixer_list_outputs_outputs_length = ARRAY_SIZE(outputs); - cras_alsa_mixer_get_control_name_values[outputs[0]] = INTERNAL_SPEAKER; - cras_alsa_mixer_get_control_name_values[outputs[1]] = HEADPHONE; - ucm_get_dma_period_for_dev_ret = 1000; - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); - - // First node. - section = ucm_section_create(INTERNAL_SPEAKER, "hw:0,1", 0, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); - ucm_section_set_mixer_name(section, INTERNAL_SPEAKER); - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(1); - cras_alsa_mixer_get_control_for_section_return_value = outputs[0]; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - - // Add a second node (will use the same iodev). - section = ucm_section_create(HEADPHONE, "hw:0,2", 0, -1, CRAS_STREAM_OUTPUT, - jack_name, "hctl"); - ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME); - ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME); - cras_alsa_jack_list_add_jack_for_section_result_jack = NULL; - cras_alsa_mixer_get_control_for_section_return_value = outputs[1]; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - /* New nodes creation calls get volume curve once, NULL jack doesn't make - * more calls. */ - EXPECT_EQ(5, cras_card_config_get_volume_curve_for_control_called); - - // Jack plug of an unkonwn device should do nothing. - cras_alsa_jack_get_mixer_output_ret = NULL; - cras_alsa_jack_get_name_ret_value = "Some other jack"; - jack_output_plug_event(reinterpret_cast<struct cras_alsa_jack*>(4), 0, aio); - EXPECT_EQ(0, cras_iodev_set_node_plugged_called); - - // Complete initialization, and make first node active. - cras_alsa_support_8_channels = false; // Support 2 channels only. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(2, cras_alsa_jack_list_add_jack_for_section_called); - EXPECT_EQ(2, cras_alsa_mixer_get_control_for_section_called); - EXPECT_EQ(1, ucm_get_dma_period_for_dev_called); - EXPECT_EQ(ucm_get_dma_period_for_dev_ret, aio->dma_period_set_microsecs); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - EXPECT_EQ(2, iodev->info.max_supported_channels); - - aio->handle = (snd_pcm_t*)0x24; - - ResetStubData(); - rc = alsa_iodev_set_active_node(iodev, aio->base.nodes->next, 1); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, alsa_mixer_set_mute_called); - EXPECT_EQ(outputs[1], alsa_mixer_set_mute_output); - EXPECT_EQ(1, alsa_mixer_set_dBFS_called); - EXPECT_EQ(outputs[1], alsa_mixer_set_dBFS_output); - ASSERT_EQ(2, cras_alsa_mixer_set_output_active_state_called); - EXPECT_EQ(outputs[0], cras_alsa_mixer_set_output_active_state_outputs[0]); - EXPECT_EQ(0, cras_alsa_mixer_set_output_active_state_values[0]); - EXPECT_EQ(outputs[1], cras_alsa_mixer_set_output_active_state_outputs[1]); - EXPECT_EQ(1, cras_alsa_mixer_set_output_active_state_values[1]); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ(1, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(1, ucm_set_enabled_called); - - // Simulate jack plug event. - cras_alsa_support_8_channels = true; // Support up to 8 channels. - cras_alsa_jack_get_mixer_output_ret = outputs[1]; - cras_alsa_jack_get_name_ret_value = jack_name; - jack_output_plug_event(reinterpret_cast<struct cras_alsa_jack*>(4), 0, aio); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - /* Headphone plug event shouldn't trigger update_max_supported_channels. */ - EXPECT_EQ(0, cras_alsa_fill_properties_called); - EXPECT_EQ(2, iodev->info.max_supported_channels); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, OutputNoControlsUCM) { - struct alsa_io* aio; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - struct ucm_section* section; - - ResetStubData(); - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); - - // Node without controls or jacks. - section = ucm_section_create(INTERNAL_SPEAKER, "hw:0,1", 1, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); - // Device index doesn't match. - EXPECT_EQ(-22, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - section->dev_idx = 0; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called); - EXPECT_EQ(1, cras_iodev_add_node_called); - ucm_section_free_list(section); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(0, cras_alsa_mixer_get_control_name_called); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ(0, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(1, ucm_set_enabled_called); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, OutputFromJackUCM) { - struct alsa_io* aio; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Headset Jack"; - struct ucm_section* section; - - ResetStubData(); - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); - - // Node without controls or jacks. - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(1); - section = ucm_section_create(HEADPHONE, "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - jack_name, "hctl"); - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called); - EXPECT_EQ(1, cras_iodev_add_node_called); - EXPECT_EQ(1, cras_alsa_jack_list_add_jack_for_section_called); - ucm_section_free_list(section); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - EXPECT_EQ(0, cras_alsa_mixer_get_control_name_called); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ(1, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(0, ucm_set_enabled_called); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, InputsFromUCM) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct mixer_control* inputs[2]; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Headset Jack"; - int rc; - struct ucm_section* section; - long intrinsic_sensitivity = -2700; - - ResetStubData(); - inputs[0] = reinterpret_cast<struct mixer_control*>(3); - inputs[1] = reinterpret_cast<struct mixer_control*>(4); - cras_alsa_mixer_list_inputs_outputs = inputs; - cras_alsa_mixer_list_inputs_outputs_length = ARRAY_SIZE(inputs); - cras_alsa_mixer_get_control_name_values[inputs[0]] = INTERNAL_MICROPHONE; - cras_alsa_mixer_get_control_name_values[inputs[1]] = MIC; - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // First node. - cras_alsa_mixer_get_control_for_section_return_value = inputs[0]; - section = ucm_section_create(INTERNAL_MICROPHONE, "hw:0,1", 0, -1, - CRAS_STREAM_INPUT, NULL, NULL); - ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME); - ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME); - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Add a second node (will use the same iodev). - cras_alsa_mixer_get_control_name_called = 0; - // Set intrinsic sensitivity to enable software gain. - ucm_get_intrinsic_sensitivity_values[MIC] = intrinsic_sensitivity; - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(1); - cras_alsa_mixer_get_control_for_section_return_value = inputs[1]; - section = ucm_section_create(MIC, "hw:0,2", 0, -1, CRAS_STREAM_INPUT, - jack_name, "hctl"); - ucm_section_set_mixer_name(section, MIC); - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Jack plug of an unknown device should do nothing. - cras_alsa_jack_get_mixer_input_ret = NULL; - cras_alsa_jack_get_name_ret_value = "Some other jack"; - jack_input_plug_event(reinterpret_cast<struct cras_alsa_jack*>(4), 0, aio); - EXPECT_EQ(0, cras_iodev_set_node_plugged_called); - - // Simulate jack plug event. - cras_alsa_jack_get_mixer_input_ret = inputs[1]; - cras_alsa_jack_get_name_ret_value = jack_name; - jack_input_plug_event(reinterpret_cast<struct cras_alsa_jack*>(4), 0, aio); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - EXPECT_EQ(2, cras_alsa_jack_list_add_jack_for_section_called); - EXPECT_EQ(2, cras_alsa_mixer_get_control_for_section_called); - EXPECT_EQ(1, cras_alsa_mixer_get_control_name_called); - EXPECT_EQ(2, cras_iodev_add_node_called); - EXPECT_EQ(2, ucm_get_dma_period_for_dev_called); - EXPECT_EQ(0, aio->dma_period_set_microsecs); - - aio->handle = (snd_pcm_t*)0x24; - - ResetStubData(); - rc = alsa_iodev_set_active_node(iodev, aio->base.nodes->next, 1); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, alsa_mixer_set_capture_dBFS_called); - EXPECT_EQ(inputs[1], alsa_mixer_set_capture_dBFS_input); - EXPECT_EQ(0, alsa_mixer_set_capture_dBFS_value); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ(1, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(1, ucm_set_enabled_called); - EXPECT_EQ(1, alsa_mixer_set_capture_mute_called); - ASSERT_EQ(DEFAULT_CAPTURE_VOLUME_DBFS - intrinsic_sensitivity, - iodev->active_node->capture_gain); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, InputNoControlsUCM) { - struct alsa_io* aio; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - struct ucm_section* section; - - ResetStubData(); - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // Node without controls or jacks. - section = ucm_section_create(INTERNAL_MICROPHONE, "hw:0,1", 1, -1, - CRAS_STREAM_INPUT, NULL, NULL); - // Device index doesn't match. - EXPECT_EQ(-22, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - section->dev_idx = 0; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - EXPECT_EQ(1, cras_alsa_jack_list_add_jack_for_section_called); - EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called); - EXPECT_EQ(0, cras_alsa_mixer_get_control_name_called); - EXPECT_EQ(1, cras_iodev_add_node_called); - ucm_section_free_list(section); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - EXPECT_EQ(0, cras_alsa_mixer_get_control_name_called); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ(0, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(1, ucm_set_enabled_called); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, InputFromJackUCM) { - struct alsa_io* aio; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Headset Jack"; - struct ucm_section* section; - - ResetStubData(); - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // Node without controls or jacks. - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(1); - section = ucm_section_create(MIC, "hw:0,1", 0, -1, CRAS_STREAM_INPUT, - jack_name, "hctl"); - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called); - EXPECT_EQ(1, cras_iodev_add_node_called); - EXPECT_EQ(1, cras_alsa_jack_list_add_jack_for_section_called); - ucm_section_free_list(section); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - EXPECT_EQ(0, cras_alsa_mixer_get_control_name_called); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ(1, cras_alsa_jack_enable_ucm_called); - EXPECT_EQ(0, ucm_set_enabled_called); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaOutputNode, AutoUnplugOutputNode) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct mixer_control* outputs[2]; - const struct cras_alsa_jack* jack = (struct cras_alsa_jack*)4; - - ResetStubData(); - outputs[0] = reinterpret_cast<struct mixer_control*>(5); - outputs[1] = reinterpret_cast<struct mixer_control*>(6); - - cras_alsa_mixer_list_outputs_outputs = outputs; - cras_alsa_mixer_list_outputs_outputs_length = ARRAY_SIZE(outputs); - - cras_alsa_mixer_get_control_name_values[outputs[0]] = INTERNAL_SPEAKER; - cras_alsa_mixer_get_control_name_values[outputs[1]] = HEADPHONE; - auto_unplug_output_node_ret = 1; - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(3, cras_card_config_get_volume_curve_for_control_called); - EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); - EXPECT_EQ(2, cras_alsa_mixer_get_control_name_called); - - // Assert that the the internal speaker is plugged and other nodes aren't. - ASSERT_NE(aio->base.nodes, (void*)NULL); - EXPECT_EQ(aio->base.nodes->plugged, 1); - ASSERT_NE(aio->base.nodes->next, (void*)NULL); - EXPECT_EQ(aio->base.nodes->next->plugged, 0); - - // Plug headphone jack - cras_alsa_jack_get_name_ret_value = "Headphone Jack"; - is_utf8_string_ret_value = 1; - cras_alsa_jack_get_mixer_output_ret = outputs[1]; - cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); - - // Assert internal speaker is auto unplugged - EXPECT_EQ(aio->base.nodes->plugged, 0); - EXPECT_EQ(aio->base.nodes->next->plugged, 1); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaOutputNode, AutoUnplugInputNode) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct mixer_control* inputs[2]; - const struct cras_alsa_jack* jack = (struct cras_alsa_jack*)4; - - ResetStubData(); - inputs[0] = reinterpret_cast<struct mixer_control*>(5); - inputs[1] = reinterpret_cast<struct mixer_control*>(6); - - cras_alsa_mixer_list_inputs_outputs = inputs; - cras_alsa_mixer_list_inputs_outputs_length = ARRAY_SIZE(inputs); - - cras_alsa_mixer_get_control_name_values[inputs[0]] = INTERNAL_MICROPHONE; - cras_alsa_mixer_get_control_name_values[inputs[1]] = MIC; - auto_unplug_input_node_ret = 1; - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - EXPECT_EQ(1, cras_alsa_mixer_list_inputs_called); - EXPECT_EQ(2, cras_alsa_mixer_get_control_name_called); - - // Assert that the the internal speaker is plugged and other nodes aren't. - ASSERT_NE(aio->base.nodes, (void*)NULL); - EXPECT_EQ(aio->base.nodes->plugged, 1); - ASSERT_NE(aio->base.nodes->next, (void*)NULL); - EXPECT_EQ(aio->base.nodes->next->plugged, 0); - - // Plug headphone jack - cras_alsa_jack_get_name_ret_value = "Mic Jack"; - is_utf8_string_ret_value = 1; - cras_alsa_jack_get_mixer_input_ret = inputs[1]; - cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); - - // Assert internal speaker is auto unplugged - EXPECT_EQ(aio->base.nodes->plugged, 0); - EXPECT_EQ(aio->base.nodes->next->plugged, 1); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -TEST(AlsaLoopback, InitializePlayback) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Alsa Loopback"; - struct mixer_control* outputs[1]; - struct ucm_section* section; - - ResetStubData(); - outputs[0] = reinterpret_cast<struct mixer_control*>(3); - cras_alsa_mixer_list_outputs_outputs = outputs; - cras_alsa_mixer_list_outputs_outputs_length = ARRAY_SIZE(outputs); - cras_alsa_mixer_get_control_name_values[outputs[0]] = LOOPBACK_PLAYBACK; - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // Add node. - section = ucm_section_create(LOOPBACK_PLAYBACK, "hw:0,1", 0, -1, - CRAS_STREAM_OUTPUT, jack_name, NULL); - ucm_section_set_mixer_name(section, LOOPBACK_PLAYBACK); - cras_alsa_jack_list_add_jack_for_section_result_jack = NULL; - cras_alsa_mixer_get_control_for_section_return_value = outputs[0]; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Complete initialization, and check the loopback playback node is plugged as - // the active node. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - ASSERT_NE(aio->base.active_node, (void*)NULL); - EXPECT_STREQ(LOOPBACK_PLAYBACK, aio->base.active_node->name); - EXPECT_EQ(1, aio->base.active_node->plugged); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaLoopback, InitializeCapture) { - struct alsa_io* aio; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Alsa Loopback"; - struct ucm_section* section; - - ResetStubData(); - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // Node without controls or jacks. - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(1); - section = ucm_section_create(LOOPBACK_CAPTURE, "hw:0,1", 0, -1, - CRAS_STREAM_INPUT, jack_name, NULL); - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Complete initialization, and check the loopback capture node is plugged as - // the active node. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - ASSERT_NE(aio->base.active_node, (void*)NULL); - EXPECT_STREQ(LOOPBACK_CAPTURE, aio->base.active_node->name); - EXPECT_EQ(1, aio->base.active_node->plugged); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaInitNode, SetNodeInitialState) { - struct cras_ionode node; - struct cras_iodev dev; - - memset(&dev, 0, sizeof(dev)); - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Unknown"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(0, node.plugged_time.tv_sec); - ASSERT_EQ(CRAS_NODE_TYPE_UNKNOWN, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, INTERNAL_SPEAKER); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(1, node.plugged); - ASSERT_GT(node.plugged_time.tv_sec, 0); - ASSERT_EQ(CRAS_NODE_TYPE_INTERNAL_SPEAKER, node.type); - ASSERT_EQ(NODE_POSITION_INTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, INTERNAL_MICROPHONE); - dev.direction = CRAS_STREAM_INPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(1, node.plugged); - ASSERT_GT(node.plugged_time.tv_sec, 0); - ASSERT_EQ(CRAS_NODE_TYPE_MIC, node.type); - ASSERT_EQ(NODE_POSITION_INTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, HDMI); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(0, node.plugged_time.tv_sec); - ASSERT_EQ(CRAS_NODE_TYPE_HDMI, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "IEC958"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_HDMI, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "HDMI Jack"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_HDMI, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Something HDMI Jack"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_HDMI, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, HEADPHONE); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_HEADPHONE, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Headphone Jack"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_HEADPHONE, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, MIC); - dev.direction = CRAS_STREAM_INPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_MIC, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Front Mic"); - dev.direction = CRAS_STREAM_INPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(1, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_MIC, node.type); - ASSERT_EQ(NODE_POSITION_FRONT, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Rear Mic"); - dev.direction = CRAS_STREAM_INPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(1, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_MIC, node.type); - ASSERT_EQ(NODE_POSITION_REAR, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Mic Jack"); - dev.direction = CRAS_STREAM_INPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_MIC, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Unknown"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_USB); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_USB, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - dev.direction = CRAS_STREAM_INPUT; - strcpy(node.name, "DAISY-I2S Mic Jack"); - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_MIC, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - // Node name is changed to "MIC". - ASSERT_EQ(0, strcmp(node.name, MIC)); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - dev.direction = CRAS_STREAM_OUTPUT; - strcpy(node.name, "DAISY-I2S Headphone Jack"); - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(0, node.plugged); - ASSERT_EQ(CRAS_NODE_TYPE_HEADPHONE, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - // Node name is changed to "Headphone". - ASSERT_EQ(0, strcmp(node.name, HEADPHONE)); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, INTERNAL_SPEAKER); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_USB); - ASSERT_EQ(1, node.plugged); - ASSERT_GT(node.plugged_time.tv_sec, 0); - ASSERT_EQ(CRAS_NODE_TYPE_USB, node.type); - ASSERT_EQ(NODE_POSITION_EXTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Haptic"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(1, node.plugged); - ASSERT_GT(node.plugged_time.tv_sec, 0); - ASSERT_EQ(CRAS_NODE_TYPE_HAPTIC, node.type); - ASSERT_EQ(NODE_POSITION_INTERNAL, node.position); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Rumbler"); - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(1, node.plugged); - ASSERT_GT(node.plugged_time.tv_sec, 0); - ASSERT_EQ(CRAS_NODE_TYPE_HAPTIC, node.type); - ASSERT_EQ(NODE_POSITION_INTERNAL, node.position); -} - -TEST(AlsaInitNode, SetNodeInitialStateDropInvalidUTF8NodeName) { - struct cras_ionode node; - struct cras_iodev dev; - - memset(&dev, 0, sizeof(dev)); - memset(&node, 0, sizeof(node)); - node.dev = &dev; - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Something USB"); - // 0xfe can not appear in a valid UTF-8 string. - node.name[0] = 0xfe; - is_utf8_string_ret_value = 0; - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_USB); - ASSERT_EQ(CRAS_NODE_TYPE_USB, node.type); - ASSERT_STREQ(USB, node.name); - - memset(&node, 0, sizeof(node)); - node.dev = &dev; - strcpy(node.name, "Something HDMI Jack"); - // 0xfe can not appear in a valid UTF-8 string. - node.name[0] = 0xfe; - is_utf8_string_ret_value = 0; - dev.direction = CRAS_STREAM_OUTPUT; - set_node_initial_state(&node, ALSA_CARD_TYPE_INTERNAL); - ASSERT_EQ(CRAS_NODE_TYPE_HDMI, node.type); - ASSERT_STREQ(HDMI, node.name); -} - -TEST(AlsaIoInit, HDMIJackUpdateInvalidUTF8MonitorName) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - const struct cras_alsa_jack* jack = (struct cras_alsa_jack*)4; - - ResetStubData(); - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - - // Prepare the stub data such that the jack will be identified as an - // HDMI jack, and thus the callback creates an HDMI node. - cras_alsa_jack_get_name_ret_value = "HDMI Jack"; - // Set the jack name updated from monitor to be an invalid UTF8 string. - cras_alsa_jack_update_monitor_fake_name = "\xfeomething"; - is_utf8_string_ret_value = 0; - - // Add the jack node. - cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); - - EXPECT_EQ(2, cras_alsa_jack_get_name_called); - ASSERT_EQ(CRAS_NODE_TYPE_HDMI, aio->base.nodes->next->type); - // The node name should be "HDMI". - ASSERT_STREQ(HDMI, aio->base.nodes->next->name); - - alsa_iodev_destroy((struct cras_iodev*)aio); -} - -// Test thread add/rm stream, open_alsa, and iodev config. -class AlsaVolumeMuteSuite : public testing::Test { - protected: - virtual void SetUp() { - ResetStubData(); - output_control_ = reinterpret_cast<struct mixer_control*>(10); - cras_alsa_mixer_list_outputs_outputs = &output_control_; - cras_alsa_mixer_list_outputs_outputs_length = 1; - cras_alsa_mixer_get_control_name_values[output_control_] = INTERNAL_SPEAKER; - cras_alsa_mixer_list_outputs_outputs_length = 1; - aio_output_ = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - alsa_iodev_legacy_complete_init((struct cras_iodev*)aio_output_); - EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); - - struct cras_ionode* node; - int count = 0; - DL_FOREACH (aio_output_->base.nodes, node) { printf("node %d \n", count); } - aio_output_->base.direction = CRAS_STREAM_OUTPUT; - fmt_.frame_rate = 44100; - fmt_.num_channels = 2; - fmt_.format = SND_PCM_FORMAT_S16_LE; - aio_output_->base.format = &fmt_; - cras_alsa_get_avail_frames_ret = -1; - } - - virtual void TearDown() { - alsa_iodev_destroy((struct cras_iodev*)aio_output_); - cras_alsa_get_avail_frames_ret = 0; - } - - struct mixer_control* output_control_; - struct alsa_io* aio_output_; - struct cras_audio_format fmt_; -}; - -TEST_F(AlsaVolumeMuteSuite, GetDefaultVolumeCurve) { - int rc; - struct cras_audio_format* fmt; - - fmt = (struct cras_audio_format*)malloc(sizeof(*fmt)); - memcpy(fmt, &fmt_, sizeof(fmt_)); - aio_output_->base.format = fmt; - aio_output_->handle = (snd_pcm_t*)0x24; - - rc = aio_output_->base.configure_dev(&aio_output_->base); - ASSERT_EQ(0, rc); - EXPECT_EQ(&default_curve, fake_get_dBFS_volume_curve_val); - - aio_output_->base.set_volume(&aio_output_->base); - EXPECT_EQ(&default_curve, fake_get_dBFS_volume_curve_val); - free(fmt); -} - -TEST_F(AlsaVolumeMuteSuite, GetVolumeCurveFromNode) { - int rc; - struct cras_audio_format* fmt; - struct cras_alsa_jack* jack = (struct cras_alsa_jack*)4; - struct cras_ionode* node; - struct cras_volume_curve hp_curve = { - .get_dBFS = fake_get_dBFS, - }; - - // Headphone jack plugged and has its own volume curve. - cras_alsa_jack_get_mixer_output_ret = NULL; - cras_alsa_jack_get_name_ret_value = HEADPHONE; - cras_card_config_get_volume_curve_vals[HEADPHONE] = &hp_curve; - cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); - EXPECT_EQ(1, cras_alsa_jack_update_node_type_called); - EXPECT_EQ(3, cras_card_config_get_volume_curve_for_control_called); - - // These settings should be placed after plugging jacks to make it safer. - // If is HDMI jack, plug event will trigger update_max_supported_channels() - // and do open_dev() and close_dev() once. close_dev() will perform alsa_io - // cleanup. - // Headphone jack won't trigger, but we still place here due to coherence. - fmt = (struct cras_audio_format*)malloc(sizeof(*fmt)); - memcpy(fmt, &fmt_, sizeof(fmt_)); - aio_output_->base.format = fmt; - aio_output_->handle = (snd_pcm_t*)0x24; - - // Switch to node 'Headphone'. - node = aio_output_->base.nodes->next; - aio_output_->base.active_node = node; - - rc = aio_output_->base.configure_dev(&aio_output_->base); - ASSERT_EQ(0, rc); - EXPECT_EQ(&hp_curve, fake_get_dBFS_volume_curve_val); - - aio_output_->base.set_volume(&aio_output_->base); - EXPECT_EQ(&hp_curve, fake_get_dBFS_volume_curve_val); - free(fmt); -} - -TEST_F(AlsaVolumeMuteSuite, SetVolume) { - int rc; - struct cras_audio_format* fmt; - const size_t fake_system_volume = 55; - const size_t fake_system_volume_dB = (fake_system_volume - 100) * 100; - - fmt = (struct cras_audio_format*)malloc(sizeof(*fmt)); - memcpy(fmt, &fmt_, sizeof(fmt_)); - aio_output_->base.format = fmt; - aio_output_->handle = (snd_pcm_t*)0x24; - - sys_get_volume_return_value = fake_system_volume; - rc = aio_output_->base.configure_dev(&aio_output_->base); - ASSERT_EQ(0, rc); - EXPECT_EQ(1, alsa_mixer_set_dBFS_called); - EXPECT_EQ(fake_system_volume_dB, alsa_mixer_set_dBFS_value); - - alsa_mixer_set_dBFS_called = 0; - alsa_mixer_set_dBFS_value = 0; - sys_get_volume_return_value = 50; - sys_get_volume_called = 0; - aio_output_->base.set_volume(&aio_output_->base); - EXPECT_EQ(1, sys_get_volume_called); - EXPECT_EQ(1, alsa_mixer_set_dBFS_called); - EXPECT_EQ(-5000, alsa_mixer_set_dBFS_value); - EXPECT_EQ(output_control_, alsa_mixer_set_dBFS_output); - - alsa_mixer_set_dBFS_called = 0; - alsa_mixer_set_dBFS_value = 0; - sys_get_volume_return_value = 0; - sys_get_volume_called = 0; - aio_output_->base.set_volume(&aio_output_->base); - EXPECT_EQ(1, sys_get_volume_called); - EXPECT_EQ(1, alsa_mixer_set_dBFS_called); - EXPECT_EQ(-10000, alsa_mixer_set_dBFS_value); - - sys_get_volume_return_value = 80; - aio_output_->base.active_node->volume = 90; - aio_output_->base.set_volume(&aio_output_->base); - EXPECT_EQ(-3000, alsa_mixer_set_dBFS_value); - - // close the dev. - rc = aio_output_->base.close_dev(&aio_output_->base); - EXPECT_EQ(0, rc); - EXPECT_EQ((void*)NULL, aio_output_->handle); - - free(fmt); -} - -TEST_F(AlsaVolumeMuteSuite, SetMute) { - int muted; - - aio_output_->handle = (snd_pcm_t*)0x24; - - // Test mute. - ResetStubData(); - muted = 1; - - sys_get_mute_return_value = muted; - - aio_output_->base.set_mute(&aio_output_->base); - - EXPECT_EQ(1, sys_get_mute_called); - EXPECT_EQ(1, alsa_mixer_set_mute_called); - EXPECT_EQ(muted, alsa_mixer_set_mute_value); - EXPECT_EQ(output_control_, alsa_mixer_set_mute_output); - - // Test unmute. - ResetStubData(); - muted = 0; - - sys_get_mute_return_value = muted; - - aio_output_->base.set_mute(&aio_output_->base); - - EXPECT_EQ(1, sys_get_mute_called); - EXPECT_EQ(1, alsa_mixer_set_mute_called); - EXPECT_EQ(muted, alsa_mixer_set_mute_value); - EXPECT_EQ(output_control_, alsa_mixer_set_mute_output); -} - -// Test free run. -class AlsaFreeRunTestSuite : public testing::Test { - protected: - virtual void SetUp() { - ResetStubData(); - memset(&aio, 0, sizeof(aio)); - fmt_.format = SND_PCM_FORMAT_S16_LE; - fmt_.frame_rate = 48000; - fmt_.num_channels = 2; - aio.base.frames_queued = frames_queued; - aio.base.output_underrun = alsa_output_underrun; - aio.base.direction = CRAS_STREAM_OUTPUT; - aio.base.format = &fmt_; - aio.base.buffer_size = BUFFER_SIZE; - aio.base.min_cb_level = 240; - aio.base.min_buffer_level = 0; - aio.filled_zeros_for_draining = 0; - cras_alsa_mmap_begin_buffer = (uint8_t*)calloc( - BUFFER_SIZE * 2 * 2, sizeof(*cras_alsa_mmap_begin_buffer)); - memset(cras_alsa_mmap_begin_buffer, 0xff, - sizeof(*cras_alsa_mmap_begin_buffer)); - } - - virtual void TearDown() { free(cras_alsa_mmap_begin_buffer); } - - struct alsa_io aio; - struct cras_audio_format fmt_; -}; - -TEST_F(AlsaFreeRunTestSuite, FillWholeBufferWithZeros) { - int rc; - int16_t* zeros; - - rc = fill_whole_buffer_with_zeros(&aio.base); - - EXPECT_EQ(0, rc); - zeros = (int16_t*)calloc(BUFFER_SIZE * 2, sizeof(*zeros)); - EXPECT_EQ(0, memcmp(zeros, cras_alsa_mmap_begin_buffer, BUFFER_SIZE * 2 * 2)); - - free(zeros); -} - -TEST_F(AlsaFreeRunTestSuite, EnterFreeRunAlreadyFreeRunning) { - int rc; - - // Device is in free run state, no need to fill zeros or fill whole buffer. - aio.free_running = 1; - - rc = no_stream(&aio.base, 1); - - EXPECT_EQ(0, rc); - EXPECT_EQ(0, cras_alsa_mmap_get_whole_buffer_called); - EXPECT_EQ(0, cras_iodev_fill_odev_zeros_called); - EXPECT_EQ(0, cras_iodev_fill_odev_zeros_frames); -} - -TEST_F(AlsaFreeRunTestSuite, EnterFreeRunNotDrainedYetNeedToFillZeros) { - int rc, real_hw_level; - struct timespec hw_tstamp; - int fill_zeros_duration = 50; - // Device is not in free run state. There are still valid samples to play. - // In cras_alsa_io.c, we defined there are 50ms zeros to be filled. - real_hw_level = 200; - cras_alsa_get_avail_frames_avail = BUFFER_SIZE - real_hw_level; - - rc = aio.base.frames_queued(&aio.base, &hw_tstamp); - EXPECT_EQ(200, rc); - - rc = no_stream(&aio.base, 1); - - EXPECT_EQ(0, rc); - EXPECT_EQ(0, cras_alsa_mmap_get_whole_buffer_called); - EXPECT_EQ(1, cras_iodev_fill_odev_zeros_called); - EXPECT_EQ(fmt_.frame_rate / 1000 * fill_zeros_duration, - cras_iodev_fill_odev_zeros_frames); - EXPECT_EQ(fmt_.frame_rate / 1000 * fill_zeros_duration, - aio.filled_zeros_for_draining); - EXPECT_EQ(0, aio.free_running); -} - -TEST_F(AlsaFreeRunTestSuite, EnterFreeRunNotDrainedYetFillZerosExceedBuffer) { - int rc, real_hw_level; - - // Device is not in free run state. There are still valid samples to play. - // If frames avail is smaller than 50ms(48 * 50 = 2400 zeros), only fill - // zeros until buffer size. - real_hw_level = 7000; - cras_alsa_get_avail_frames_avail = BUFFER_SIZE - real_hw_level; - - rc = no_stream(&aio.base, 1); - - EXPECT_EQ(0, rc); - EXPECT_EQ(0, cras_alsa_mmap_get_whole_buffer_called); - EXPECT_EQ(1, cras_iodev_fill_odev_zeros_called); - EXPECT_EQ(cras_alsa_get_avail_frames_avail, - cras_iodev_fill_odev_zeros_frames); - EXPECT_EQ(cras_alsa_get_avail_frames_avail, aio.filled_zeros_for_draining); - EXPECT_EQ(0, aio.free_running); -} - -TEST_F(AlsaFreeRunTestSuite, EnterFreeRunDrained) { - int rc, real_hw_level; - - // Device is not in free run state. There are still valid samples to play. - // The number of valid samples is less than filled zeros. - // Should enter free run state and fill whole buffer with zeros. - real_hw_level = 40; - cras_alsa_get_avail_frames_avail = BUFFER_SIZE - real_hw_level; - aio.filled_zeros_for_draining = 100; - - rc = no_stream(&aio.base, 1); - - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_mmap_get_whole_buffer_called); - EXPECT_EQ(0, cras_iodev_fill_odev_zeros_called); - EXPECT_EQ(1, aio.free_running); -} - -TEST_F(AlsaFreeRunTestSuite, EnterFreeRunNoSamples) { - int rc, real_hw_level; - - // Device is not in free run state. There is no sample to play. - // Should enter free run state and fill whole buffer with zeros. - real_hw_level = 0; - cras_alsa_get_avail_frames_avail = BUFFER_SIZE - real_hw_level; - - rc = no_stream(&aio.base, 1); - - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_mmap_get_whole_buffer_called); - EXPECT_EQ(0, cras_iodev_fill_odev_zeros_called); - EXPECT_EQ(1, aio.free_running); -} - -TEST_F(AlsaFreeRunTestSuite, IsFreeRunning) { - aio.free_running = 1; - EXPECT_EQ(1, is_free_running(&aio.base)); - - aio.free_running = 0; - EXPECT_EQ(0, is_free_running(&aio.base)); -} - -TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunNotInFreeRunMoreRemain) { - int rc, real_hw_level; - - // Compare min_buffer_level + min_cb_level with valid samples left. - // 240 + 512 < 900 - 100, so we will get 900 - 100 in appl_ptr_ahead. - - aio.free_running = 0; - aio.filled_zeros_for_draining = 100; - aio.base.min_buffer_level = 512; - real_hw_level = 900; - cras_alsa_get_avail_frames_avail = BUFFER_SIZE - real_hw_level; - - rc = no_stream(&aio.base, 0); - - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_resume_appl_ptr_called); - EXPECT_EQ(800, cras_alsa_resume_appl_ptr_ahead); - EXPECT_EQ(0, cras_iodev_fill_odev_zeros_frames); - EXPECT_EQ(0, aio.free_running); - EXPECT_EQ(0, aio.filled_zeros_for_draining); - EXPECT_EQ(1, cras_iodev_reset_rate_estimator_called); -} - -TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunNotInFreeRunLessRemain) { - int rc, real_hw_level; - - // Compare min_buffer_level + min_cb_level with valid samples left. - // 240 + 256 > 400 - 500, so we will get 240 + 256 in appl_ptr_ahead. - // And it will fill 240 + 256 - 400 = 96 zeros frames into device. - - aio.free_running = 0; - aio.filled_zeros_for_draining = 500; - aio.base.min_buffer_level = 256; - real_hw_level = 400; - cras_alsa_get_avail_frames_avail = BUFFER_SIZE - real_hw_level; - - rc = no_stream(&aio.base, 0); - - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_resume_appl_ptr_called); - EXPECT_EQ(aio.base.min_buffer_level + aio.base.min_cb_level, - cras_alsa_resume_appl_ptr_ahead); - EXPECT_EQ(96, cras_iodev_fill_odev_zeros_frames); - EXPECT_EQ(0, aio.free_running); - EXPECT_EQ(0, aio.filled_zeros_for_draining); - EXPECT_EQ(1, cras_iodev_reset_rate_estimator_called); -} - -TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunInFreeRun) { - int rc; - - aio.free_running = 1; - aio.filled_zeros_for_draining = 100; - aio.base.min_buffer_level = 512; - - rc = no_stream(&aio.base, 0); - - EXPECT_EQ(0, rc); - EXPECT_EQ(1, cras_alsa_resume_appl_ptr_called); - EXPECT_EQ(aio.base.min_buffer_level + aio.base.min_cb_level, - cras_alsa_resume_appl_ptr_ahead); - EXPECT_EQ(0, aio.free_running); - EXPECT_EQ(0, aio.filled_zeros_for_draining); - EXPECT_EQ(1, cras_iodev_reset_rate_estimator_called); -} - -// Reuse AlsaFreeRunTestSuite for output underrun handling because they are -// similar. -TEST_F(AlsaFreeRunTestSuite, OutputUnderrun) { - int rc; - int16_t* zeros; - snd_pcm_uframes_t offset; - - // Ask alsa_io to handle output underrun. - rc = alsa_output_underrun(&aio.base); - EXPECT_EQ(0, rc); - - // mmap buffer should be filled with zeros. - zeros = (int16_t*)calloc(BUFFER_SIZE * 2, sizeof(*zeros)); - EXPECT_EQ(0, memcmp(zeros, cras_alsa_mmap_begin_buffer, BUFFER_SIZE * 2 * 2)); - - // appl_ptr should be moved to min_buffer_level + 1.5 * min_cb_level ahead of - // hw_ptr. - offset = aio.base.min_buffer_level + aio.base.min_cb_level + - aio.base.min_cb_level / 2; - EXPECT_EQ(1, cras_alsa_resume_appl_ptr_called); - EXPECT_EQ(offset, cras_alsa_resume_appl_ptr_ahead); - - free(zeros); -} - -TEST(AlsaHotwordNode, HotwordTriggeredSendMessage) { - struct cras_iodev* iodev; - struct cras_audio_format format; - struct alsa_input_node alsa_node; - struct cras_ionode* node = &alsa_node.base; - int rc; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_INPUT); - format.frame_rate = 16000; - format.num_channels = 1; - cras_iodev_set_format(iodev, &format); - - memset(&alsa_node, 0, sizeof(alsa_node)); - node->dev = iodev; - strcpy(node->name, HOTWORD_DEV); - set_node_initial_state(node, ALSA_CARD_TYPE_INTERNAL); - EXPECT_EQ(CRAS_NODE_TYPE_HOTWORD, node->type); - - iodev->active_node = node; - iodev->open_dev(iodev); - rc = iodev->configure_dev(iodev); - free(fake_format); - ASSERT_EQ(0, rc); - - ASSERT_NE(reinterpret_cast<thread_callback>(NULL), audio_thread_cb); - audio_thread_cb(audio_thread_cb_data, POLLIN); - EXPECT_EQ(1, hotword_send_triggered_msg_called); - alsa_iodev_destroy(iodev); -} - -TEST(AlsaGetValidFrames, GetValidFramesNormalState) { - struct cras_iodev* iodev; - struct alsa_io* aio; - struct timespec tstamp; - int rc; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - aio = (struct alsa_io*)iodev; - - aio->free_running = 0; - aio->filled_zeros_for_draining = 200; - cras_alsa_get_avail_frames_avail = iodev->buffer_size - 500; - cras_alsa_get_avail_frames_ret = 0; - clock_gettime_retspec.tv_sec = 123; - clock_gettime_retspec.tv_nsec = 321; - rc = iodev->get_valid_frames(iodev, &tstamp); - EXPECT_EQ(rc, 300); - EXPECT_EQ(tstamp.tv_sec, clock_gettime_retspec.tv_sec); - EXPECT_EQ(tstamp.tv_nsec, clock_gettime_retspec.tv_nsec); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaGetValidFrames, GetValidFramesFreeRunning) { - struct cras_iodev* iodev; - struct alsa_io* aio; - struct timespec tstamp; - int rc; - - ResetStubData(); - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, - CRAS_STREAM_OUTPUT); - aio = (struct alsa_io*)iodev; - - aio->free_running = 1; - clock_gettime_retspec.tv_sec = 123; - clock_gettime_retspec.tv_nsec = 321; - rc = iodev->get_valid_frames(iodev, &tstamp); - EXPECT_EQ(rc, 0); - EXPECT_EQ(tstamp.tv_sec, clock_gettime_retspec.tv_sec); - EXPECT_EQ(tstamp.tv_nsec, clock_gettime_retspec.tv_nsec); - - alsa_iodev_destroy(iodev); -} - -} // namespace - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - openlog(NULL, LOG_PERROR, LOG_USER); - return RUN_ALL_TESTS(); -} - -// Stubs - -extern "C" { - -// From iodev. -int cras_iodev_list_add_output(struct cras_iodev* output) { - return 0; -} -int cras_iodev_list_rm_output(struct cras_iodev* dev) { - return 0; -} - -int cras_iodev_list_add_input(struct cras_iodev* input) { - return 0; -} -int cras_iodev_list_rm_input(struct cras_iodev* dev) { - return 0; -} - -char* cras_iodev_list_get_hotword_models(cras_node_id_t node_id) { - return NULL; -} - -int cras_iodev_list_set_hotword_model(cras_node_id_t node_id, - const char* model_name) { - return 0; -} - -int cras_iodev_list_suspend_hotword_streams() { - return 0; -} - -int cras_iodev_list_resume_hotword_stream() { - return 0; -} - -struct audio_thread* cras_iodev_list_get_audio_thread() { - return NULL; -} - -// From alsa helper. -int cras_alsa_set_channel_map(snd_pcm_t* handle, - struct cras_audio_format* fmt) { - return 0; -} -int cras_alsa_get_channel_map(snd_pcm_t* handle, - struct cras_audio_format* fmt) { - return 0; -} -int cras_alsa_pcm_open(snd_pcm_t** handle, - const char* dev, - snd_pcm_stream_t stream) { - *handle = (snd_pcm_t*)0x24; - cras_alsa_open_called++; - return 0; -} -int cras_alsa_pcm_close(snd_pcm_t* handle) { - return 0; -} -int cras_alsa_pcm_start(snd_pcm_t* handle) { - cras_alsa_start_called++; - return 0; -} -int cras_alsa_pcm_drain(snd_pcm_t* handle) { - return 0; -} -int cras_alsa_fill_properties(snd_pcm_t* handle, - size_t** rates, - size_t** channel_counts, - snd_pcm_format_t** formats) { - *rates = (size_t*)malloc(sizeof(**rates) * 3); - (*rates)[0] = 44100; - (*rates)[1] = 48000; - (*rates)[2] = 0; - - if (cras_alsa_support_8_channels) { // Support up to 8 channels. - *channel_counts = (size_t*)malloc(sizeof(**channel_counts) * 6); - (*channel_counts)[0] = 6; - (*channel_counts)[1] = 4; - (*channel_counts)[2] = 2; - (*channel_counts)[3] = 1; - (*channel_counts)[4] = 8; - (*channel_counts)[5] = 0; - } else { // Support 2 channels only. - *channel_counts = (size_t*)malloc(sizeof(**channel_counts) * 2); - (*channel_counts)[0] = 2; - (*channel_counts)[1] = 0; - } - - *formats = (snd_pcm_format_t*)malloc(sizeof(**formats) * 2); - (*formats)[0] = SND_PCM_FORMAT_S16_LE; - (*formats)[1] = (snd_pcm_format_t)0; - - cras_alsa_fill_properties_called++; - return 0; -} -int cras_alsa_set_hwparams(snd_pcm_t* handle, - struct cras_audio_format* format, - snd_pcm_uframes_t* buffer_size, - int period_wakeup, - unsigned int dma_period_time) { - return 0; -} -int cras_alsa_set_swparams(snd_pcm_t* handle) { - return 0; -} -int cras_alsa_get_avail_frames(snd_pcm_t* handle, - snd_pcm_uframes_t buf_size, - snd_pcm_uframes_t severe_underrun_frames, - const char* dev_name, - snd_pcm_uframes_t* used, - struct timespec* tstamp) { - *used = cras_alsa_get_avail_frames_avail; - clock_gettime(CLOCK_MONOTONIC_RAW, tstamp); - return cras_alsa_get_avail_frames_ret; -} -int cras_alsa_get_delay_frames(snd_pcm_t* handle, - snd_pcm_uframes_t buf_size, - snd_pcm_sframes_t* delay) { - *delay = 0; - return 0; -} -int cras_alsa_mmap_begin(snd_pcm_t* handle, - unsigned int format_bytes, - uint8_t** dst, - snd_pcm_uframes_t* offset, - snd_pcm_uframes_t* frames) { - *dst = cras_alsa_mmap_begin_buffer; - *frames = cras_alsa_mmap_begin_frames; - return 0; -} -int cras_alsa_mmap_commit(snd_pcm_t* handle, - snd_pcm_uframes_t offset, - snd_pcm_uframes_t frames) { - return 0; -} -int cras_alsa_attempt_resume(snd_pcm_t* handle) { - cras_alsa_attempt_resume_called++; - return 0; -} - -// ALSA stubs. -int snd_pcm_format_physical_width(snd_pcm_format_t format) { - return 16; -} - -snd_pcm_state_t snd_pcm_state(snd_pcm_t* handle) { - return snd_pcm_state_ret; -} - -const char* snd_strerror(int errnum) { - return "Alsa Error in UT"; -} - -struct mixer_control* cras_alsa_mixer_get_control_for_section( - struct cras_alsa_mixer* cras_mixer, - const struct ucm_section* section) { - cras_alsa_mixer_get_control_for_section_called++; - return cras_alsa_mixer_get_control_for_section_return_value; -} - -const char* cras_alsa_mixer_get_control_name( - const struct mixer_control* control) { - ControlNameMap::iterator it; - cras_alsa_mixer_get_control_name_called++; - it = cras_alsa_mixer_get_control_name_values.find(control); - if (it == cras_alsa_mixer_get_control_name_values.end()) - return ""; - return it->second.c_str(); -} - -// From system_state. -size_t cras_system_get_volume() { - sys_get_volume_called++; - return sys_get_volume_return_value; -} - -int cras_system_get_mute() { - sys_get_mute_called++; - return sys_get_mute_return_value; -} - -int cras_system_get_capture_mute() { - sys_get_capture_mute_called++; - return sys_get_capture_mute_return_value; -} - -void cras_system_set_volume_limits(long min, long max) { - sys_set_volume_limits_called++; -} - -bool cras_system_get_noise_cancellation_enabled() { - return false; -} - -// From cras_alsa_mixer. -void cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer* m, - long dB_level, - struct mixer_control* output) { - alsa_mixer_set_dBFS_called++; - alsa_mixer_set_dBFS_value = dB_level; - alsa_mixer_set_dBFS_output = output; -} - -void cras_alsa_mixer_set_mute(struct cras_alsa_mixer* cras_mixer, - int muted, - struct mixer_control* mixer_output) { - alsa_mixer_set_mute_called++; - alsa_mixer_set_mute_value = muted; - alsa_mixer_set_mute_output = mixer_output; -} - -long cras_alsa_mixer_get_dB_range(struct cras_alsa_mixer* cras_mixer) { - alsa_mixer_get_dB_range_called++; - return alsa_mixer_get_dB_range_value; -} - -long cras_alsa_mixer_get_output_dB_range(struct mixer_control* mixer_output) { - alsa_mixer_get_output_dB_range_called++; - return alsa_mixer_get_output_dB_range_value; -} - -void cras_alsa_mixer_set_capture_dBFS(struct cras_alsa_mixer* m, - long dB_level, - struct mixer_control* mixer_input) { - alsa_mixer_set_capture_dBFS_called++; - alsa_mixer_set_capture_dBFS_value = dB_level; - alsa_mixer_set_capture_dBFS_input = mixer_input; -} - -void cras_alsa_mixer_set_capture_mute(struct cras_alsa_mixer* m, - int mute, - struct mixer_control* mixer_input) { - alsa_mixer_set_capture_mute_called++; - alsa_mixer_set_capture_mute_value = mute; - alsa_mixer_set_capture_mute_input = mixer_input; -} - -void cras_alsa_mixer_list_outputs(struct cras_alsa_mixer* cras_mixer, - cras_alsa_mixer_control_callback cb, - void* callback_arg) { - cras_alsa_mixer_list_outputs_called++; - for (size_t i = 0; i < cras_alsa_mixer_list_outputs_outputs_length; i++) { - cb(cras_alsa_mixer_list_outputs_outputs[i], callback_arg); - } -} - -void cras_alsa_mixer_list_inputs(struct cras_alsa_mixer* cras_mixer, - cras_alsa_mixer_control_callback cb, - void* callback_arg) { - cras_alsa_mixer_list_inputs_called++; - for (size_t i = 0; i < cras_alsa_mixer_list_inputs_outputs_length; i++) { - cb(cras_alsa_mixer_list_inputs_outputs[i], callback_arg); - } -} - -int cras_alsa_mixer_set_output_active_state(struct mixer_control* output, - int active) { - cras_alsa_mixer_set_output_active_state_called++; - cras_alsa_mixer_set_output_active_state_outputs.push_back(output); - cras_alsa_mixer_set_output_active_state_values.push_back(active); - return 0; -} - -void cras_volume_curve_destroy(struct cras_volume_curve* curve) {} - -long cras_alsa_mixer_get_minimum_capture_gain( - struct cras_alsa_mixer* cmix, - struct mixer_control* mixer_input) { - cras_alsa_mixer_get_minimum_capture_gain_called++; - cras_alsa_mixer_get_minimum_capture_gain_mixer_input = mixer_input; - return cras_alsa_mixer_get_minimum_capture_gain_ret_value; -} - -long cras_alsa_mixer_get_maximum_capture_gain( - struct cras_alsa_mixer* cmix, - struct mixer_control* mixer_input) { - cras_alsa_mixer_get_maximum_capture_gain_called++; - cras_alsa_mixer_get_maximum_capture_gain_mixer_input = mixer_input; - return cras_alsa_mixer_get_maximum_capture_gain_ret_value; -} - -int cras_alsa_mixer_has_main_volume(const struct cras_alsa_mixer* cras_mixer) { - return 1; -} - -int cras_alsa_mixer_has_volume(const struct mixer_control* mixer_control) { - return 1; -} - -// From cras_alsa_jack -struct cras_alsa_jack_list* cras_alsa_jack_list_create( - unsigned int card_index, - const char* card_name, - unsigned int device_index, - int check_gpio_jack, - struct cras_alsa_mixer* mixer, - struct cras_use_case_mgr* ucm, - snd_hctl_t* hctl, - enum CRAS_STREAM_DIRECTION direction, - jack_state_change_callback* cb, - void* cb_data) { - cras_alsa_jack_list_create_called++; - cras_alsa_jack_list_create_cb = cb; - cras_alsa_jack_list_create_cb_data = cb_data; - return (struct cras_alsa_jack_list*)0xfee; -} - -int cras_alsa_jack_list_find_jacks_by_name_matching( - struct cras_alsa_jack_list* jack_list) { - cras_alsa_jack_list_find_jacks_by_name_matching_called++; - return 0; -} - -int cras_alsa_jack_list_add_jack_for_section( - struct cras_alsa_jack_list* jack_list, - struct ucm_section* ucm_section, - struct cras_alsa_jack** result_jack) { - cras_alsa_jack_list_add_jack_for_section_called++; - if (result_jack) - *result_jack = cras_alsa_jack_list_add_jack_for_section_result_jack; - return 0; -} - -void cras_alsa_jack_list_destroy(struct cras_alsa_jack_list* jack_list) { - cras_alsa_jack_list_destroy_called++; -} - -int cras_alsa_jack_list_has_hctl_jacks(struct cras_alsa_jack_list* jack_list) { - return cras_alsa_jack_list_has_hctl_jacks_return_val; -} - -void cras_alsa_jack_list_report(const struct cras_alsa_jack_list* jack_list) {} - -void cras_alsa_jack_enable_ucm(const struct cras_alsa_jack* jack, int enable) { - cras_alsa_jack_enable_ucm_called++; -} - -const char* cras_alsa_jack_get_name(const struct cras_alsa_jack* jack) { - cras_alsa_jack_get_name_called++; - return cras_alsa_jack_get_name_ret_value; -} - -const char* ucm_get_dsp_name_for_dev(struct cras_use_case_mgr* mgr, - const char* dev) { - DspNameMap::iterator it; - ucm_get_dsp_name_for_dev_called++; - if (!dev) - return NULL; - it = ucm_get_dsp_name_for_dev_values.find(dev); - if (it == ucm_get_dsp_name_for_dev_values.end()) - return NULL; - return strdup(it->second.c_str()); -} - -struct mixer_control* cras_alsa_jack_get_mixer_output( - const struct cras_alsa_jack* jack) { - return cras_alsa_jack_get_mixer_output_ret; -} - -struct mixer_control* cras_alsa_jack_get_mixer_input( - const struct cras_alsa_jack* jack) { - return cras_alsa_jack_get_mixer_input_ret; -} - -int ucm_set_enabled(struct cras_use_case_mgr* mgr, - const char* dev, - int enabled) { - ucm_set_enabled_called++; - return 0; -} - -char* ucm_get_flag(struct cras_use_case_mgr* mgr, const char* flag_name) { - if ((!strcmp(flag_name, "AutoUnplugInputNode") && - auto_unplug_input_node_ret) || - (!strcmp(flag_name, "AutoUnplugOutputNode") && - auto_unplug_output_node_ret)) { - char* ret = (char*)malloc(8); - snprintf(ret, 8, "%s", "1"); - return ret; - } - - return NULL; -} - -int ucm_swap_mode_exists(struct cras_use_case_mgr* mgr) { - return ucm_swap_mode_exists_ret_value; -} - -int ucm_enable_swap_mode(struct cras_use_case_mgr* mgr, - const char* node_name, - int enable) { - ucm_enable_swap_mode_called++; - return ucm_enable_swap_mode_ret_value; -} - -int ucm_get_min_buffer_level(struct cras_use_case_mgr* mgr, - unsigned int* level) { - *level = 0; - return 0; -} - -unsigned int ucm_get_disable_software_volume(struct cras_use_case_mgr* mgr) { - return 0; -} - -char* ucm_get_hotword_models(struct cras_use_case_mgr* mgr) { - return NULL; -} - -int ucm_set_hotword_model(struct cras_use_case_mgr* mgr, const char* model) { - return 0; -} - -unsigned int ucm_get_dma_period_for_dev(struct cras_use_case_mgr* mgr, - const char* dev) { - ucm_get_dma_period_for_dev_called++; - return ucm_get_dma_period_for_dev_ret; -} - -int ucm_get_sample_rate_for_dev(struct cras_use_case_mgr* mgr, - const char* dev, - enum CRAS_STREAM_DIRECTION direction) { - return -EINVAL; -} - -int ucm_get_capture_chmap_for_dev(struct cras_use_case_mgr* mgr, - const char* dev, - int8_t* channel_layout) { - return -EINVAL; -} - -int ucm_get_preempt_hotword(struct cras_use_case_mgr* mgr, const char* dev) { - return 0; -} - -int ucm_get_channels_for_dev(struct cras_use_case_mgr* mgr, - const char* dev, - enum CRAS_STREAM_DIRECTION direction, - size_t* channels) { - return -EINVAL; -} - -int ucm_node_noise_cancellation_exists(struct cras_use_case_mgr* mgr, - const char* node_name) { - return 0; -} - -int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr* mgr, - const char* node_name, - int enable) { - return 0; -} - -struct cras_volume_curve* cras_volume_curve_create_default() { - return &default_curve; -} - -struct cras_volume_curve* cras_card_config_get_volume_curve_for_control( - const struct cras_card_config* card_config, - const char* control_name) { - VolCurveMap::iterator it; - cras_card_config_get_volume_curve_for_control_called++; - if (!control_name) - return NULL; - it = cras_card_config_get_volume_curve_vals.find(control_name); - if (it == cras_card_config_get_volume_curve_vals.end()) - return NULL; - return it->second; -} - -void cras_iodev_free_format(struct cras_iodev* iodev) {} - -int cras_iodev_set_format(struct cras_iodev* iodev, - const struct cras_audio_format* fmt) { - fake_format = (struct cras_audio_format*)calloc(1, sizeof(cras_audio_format)); - // Copy the content of format from fmt into format of iodev. - memcpy(fake_format, fmt, sizeof(cras_audio_format)); - iodev->format = fake_format; - return 0; -} - -struct audio_thread* audio_thread_create() { - return reinterpret_cast<audio_thread*>(0x323); -} - -void audio_thread_destroy(audio_thread* thread) {} - -void cras_iodev_update_dsp(struct cras_iodev* iodev) { - cras_iodev_update_dsp_called++; - cras_iodev_update_dsp_name = iodev->dsp_name ?: ""; -} - -void cras_iodev_set_node_plugged(struct cras_ionode* ionode, int plugged) { - cras_iodev_set_node_plugged_called++; - cras_iodev_set_node_plugged_ionode = ionode; - cras_iodev_set_node_plugged_value = plugged; - if (ionode) - ionode->plugged = plugged; -} - -void cras_iodev_add_node(struct cras_iodev* iodev, struct cras_ionode* node) { - cras_iodev_add_node_called++; - DL_APPEND(iodev->nodes, node); -} - -void cras_iodev_rm_node(struct cras_iodev* iodev, struct cras_ionode* node) { - DL_DELETE(iodev->nodes, node); -} - -void cras_iodev_set_active_node(struct cras_iodev* iodev, - struct cras_ionode* node) { - iodev->active_node = node; -} - -void cras_iodev_free_resources(struct cras_iodev* iodev) { - cras_iodev_free_resources_called++; -} - -void cras_alsa_jack_update_monitor_name(const struct cras_alsa_jack* jack, - char* name_buf, - unsigned int buf_size) { - if (cras_alsa_jack_update_monitor_fake_name) - strcpy(name_buf, cras_alsa_jack_update_monitor_fake_name); -} - -void cras_alsa_jack_update_node_type(const struct cras_alsa_jack* jack, - enum CRAS_NODE_TYPE* type) { - cras_alsa_jack_update_node_type_called++; -} - -const char* cras_alsa_jack_get_ucm_device(const struct cras_alsa_jack* jack) { - return NULL; -} - -void ucm_disable_all_hotword_models(struct cras_use_case_mgr* mgr) {} - -int ucm_enable_hotword_model(struct cras_use_case_mgr* mgr) { - return 0; -} - -int ucm_get_default_node_gain(struct cras_use_case_mgr* mgr, - const char* dev, - long* gain) { - if (ucm_get_default_node_gain_values.find(dev) == - ucm_get_default_node_gain_values.end()) - return 1; - - *gain = ucm_get_default_node_gain_values[dev]; - return 0; -} - -int ucm_get_intrinsic_sensitivity(struct cras_use_case_mgr* mgr, - const char* dev, - long* vol) { - if (ucm_get_intrinsic_sensitivity_values.find(dev) == - ucm_get_intrinsic_sensitivity_values.end()) - return 1; - - *vol = ucm_get_intrinsic_sensitivity_values[dev]; - return 0; -} - -void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) {} - -void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} - -int cras_iodev_reset_rate_estimator(const struct cras_iodev* iodev) { - cras_iodev_reset_rate_estimator_called++; - return 0; -} - -int cras_iodev_frames_queued(struct cras_iodev* iodev, - struct timespec* tstamp) { - clock_gettime(CLOCK_MONOTONIC_RAW, tstamp); - return cras_iodev_frames_queued_ret; -} - -int cras_iodev_buffer_avail(struct cras_iodev* iodev, unsigned hw_level) { - return cras_iodev_buffer_avail_ret; -} - -int cras_iodev_fill_odev_zeros(struct cras_iodev* odev, unsigned int frames) { - cras_iodev_fill_odev_zeros_called++; - cras_iodev_fill_odev_zeros_frames = frames; - return 0; -} - -void cras_audio_area_config_buf_pointers(struct cras_audio_area* area, - const struct cras_audio_format* fmt, - uint8_t* base_buffer) {} - -void audio_thread_add_events_callback(int fd, - thread_callback cb, - void* data, - int events) { - audio_thread_cb = cb; - audio_thread_cb_data = data; -} - -void audio_thread_rm_callback(int fd) {} - -int audio_thread_rm_callback_sync(struct audio_thread* thread, int fd) { - return 0; -} - -int cras_hotword_send_triggered_msg() { - hotword_send_triggered_msg_called++; - return 0; -} - -int snd_pcm_poll_descriptors_count(snd_pcm_t* pcm) { - return 1; -} - -int snd_pcm_poll_descriptors(snd_pcm_t* pcm, - struct pollfd* pfds, - unsigned int space) { - if (space >= 1) { - pfds[0].events = POLLIN; - pfds[0].fd = 99; - } - return 0; -} - -int is_utf8_string(const char* string) { - return is_utf8_string_ret_value; -} - -int cras_alsa_mmap_get_whole_buffer(snd_pcm_t* handle, uint8_t** dst) { - snd_pcm_uframes_t offset, frames; - - cras_alsa_mmap_get_whole_buffer_called++; - return cras_alsa_mmap_begin(handle, 0, dst, &offset, &frames); -} - -int cras_alsa_resume_appl_ptr(snd_pcm_t* handle, snd_pcm_uframes_t ahead) { - cras_alsa_resume_appl_ptr_called++; - cras_alsa_resume_appl_ptr_ahead = ahead; - return 0; -} - -int cras_iodev_default_no_stream_playback(struct cras_iodev* odev, int enable) { - return 0; -} - -int cras_iodev_output_underrun(struct cras_iodev* odev, - unsigned int hw_level, - unsigned int frames_written) { - return odev->output_underrun(odev); -} - -enum CRAS_IODEV_STATE cras_iodev_state(const struct cras_iodev* iodev) { - return iodev->state; -} - -int cras_iodev_dsp_set_swap_mode_for_node(struct cras_iodev* iodev, - struct cras_ionode* node, - int enable) { - cras_iodev_dsp_set_swap_mode_for_node_called++; - return 0; -} - -struct cras_ramp* cras_ramp_create() { - return (struct cras_ramp*)0x1; -} - -// From librt. -int clock_gettime(clockid_t clk_id, struct timespec* tp) { - tp->tv_sec = clock_gettime_retspec.tv_sec; - tp->tv_nsec = clock_gettime_retspec.tv_nsec; - return 0; -} - -} // extern "C" |