diff options
author | Pin-chih Lin <johnylin@google.com> | 2021-01-26 16:39:19 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-02-25 17:38:41 +0000 |
commit | d8a4e5d26c4de095f449de51cd6dab7855d532f8 (patch) | |
tree | e7a01ce364dcbbc4c386d3b2929d1fbecbc71c2a | |
parent | 0e3c7b3a0929bee57f68056c51caaed8029afbad (diff) | |
download | adhd-d8a4e5d26c4de095f449de51cd6dab7855d532f8.tar.gz |
CRAS: Enable/Disable Noise Cancellation by UCM Modifier
Noise Cancellation (NC) is the component to be utilized in input
pipelines of Audio DSP. The on/off sequence would be defined as UCM
SectionModifier according to models.
In CRAS, we use a system state flag to store the on/off state of NC,
which can be toggled by dbus_control. Per open of an alsa input device,
if it supports NC, sets NC enable/disable according to the system state
flag by UCM Modifier.
Per toggle of NC on/off via dbus_control, CRAS should check if there is
opened input device and NC-supported, performs suspend and resume to
re-open that device for setting NC enable/disable.
BUG=b:170281884
TEST=Manual test
Change-Id: I7fcc5f376a2c886e2ac465148dc12c1a65bc148c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/2649865
Tested-by: Pin-chih Lin <johnylin@chromium.org>
Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org>
Commit-Queue: Pin-chih Lin <johnylin@chromium.org>
Auto-Submit: Pin-chih Lin <johnylin@chromium.org>
-rw-r--r-- | cras/src/server/cras_alsa_io.c | 26 | ||||
-rw-r--r-- | cras/src/server/cras_alsa_ucm.c | 69 | ||||
-rw-r--r-- | cras/src/server/cras_alsa_ucm.h | 22 | ||||
-rw-r--r-- | cras/src/server/cras_iodev.c | 10 | ||||
-rw-r--r-- | cras/src/server/cras_iodev.h | 11 | ||||
-rw-r--r-- | cras/src/server/cras_iodev_list.c | 18 | ||||
-rw-r--r-- | cras/src/server/cras_iodev_list.h | 5 | ||||
-rw-r--r-- | cras/src/server/cras_system_state.c | 7 | ||||
-rw-r--r-- | cras/src/tests/alsa_io_unittest.cc | 15 | ||||
-rw-r--r-- | cras/src/tests/alsa_ucm_unittest.cc | 70 | ||||
-rw-r--r-- | cras/src/tests/iodev_list_unittest.cc | 45 | ||||
-rw-r--r-- | cras/src/tests/system_state_unittest.cc | 33 |
12 files changed, 328 insertions, 3 deletions
diff --git a/cras/src/server/cras_alsa_io.c b/cras/src/server/cras_alsa_io.c index 56fbecd3..32b22247 100644 --- a/cras/src/server/cras_alsa_io.c +++ b/cras/src/server/cras_alsa_io.c @@ -391,6 +391,7 @@ static int open_dev(struct cras_iodev *iodev) snd_pcm_t *handle; int rc; const char *pcm_name = NULL; + int enable_noise_cancellation; if (aio->base.direction == CRAS_STREAM_OUTPUT) { struct alsa_output_node *aout = @@ -412,6 +413,19 @@ static int open_dev(struct cras_iodev *iodev) aio->handle = handle; + /* Enable or disable noise cancellation if it supports. */ + if (iodev->direction == CRAS_STREAM_INPUT && + ucm_node_noise_cancellation_exists(aio->ucm, + iodev->active_node->name)) { + enable_noise_cancellation = + cras_system_get_noise_cancellation_enabled(); + rc = ucm_enable_node_noise_cancellation( + aio->ucm, iodev->active_node->name, + enable_noise_cancellation); + if (rc < 0) + return rc; + } + return 0; } @@ -2021,6 +2035,17 @@ static int get_valid_frames(struct cras_iodev *odev, struct timespec *tstamp) return 0; } +static int support_noise_cancellation(const struct cras_iodev *iodev) +{ + struct alsa_io *aio = (struct alsa_io *)iodev; + + if (!iodev->active_node) + return 0; + + return ucm_node_noise_cancellation_exists(aio->ucm, + iodev->active_node->name); +} + /* * Exported Interface. */ @@ -2098,6 +2123,7 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, iodev->get_num_severe_underruns = get_num_severe_underruns; iodev->get_valid_frames = get_valid_frames; iodev->set_swap_mode_for_node = cras_iodev_dsp_set_swap_mode_for_node; + iodev->support_noise_cancellation = support_noise_cancellation; if (card_type == ALSA_CARD_TYPE_USB) iodev->min_buffer_level = USB_EXTRA_BUFFER_FRAMES; diff --git a/cras/src/server/cras_alsa_ucm.c b/cras/src/server/cras_alsa_ucm.c index 8f922ed5..3e46f6a9 100644 --- a/cras/src/server/cras_alsa_ucm.c +++ b/cras/src/server/cras_alsa_ucm.c @@ -22,7 +22,6 @@ static const char override_type_name_var[] = "OverrideNodeType"; static const char dsp_name_var[] = "DspName"; static const char playback_mixer_elem_var[] = "PlaybackMixerElem"; static const char capture_mixer_elem_var[] = "CaptureMixerElem"; -static const char swap_mode_suffix[] = "Swap Mode"; static const char min_buffer_level_var[] = "MinBufferLevel"; static const char dma_period_var[] = "DmaPeriodMicrosecs"; static const char disable_software_volume[] = "DisableSoftwareVolume"; @@ -38,6 +37,11 @@ static const char dependent_device_name_var[] = "DependentPCM"; static const char preempt_hotword_var[] = "PreemptHotword"; static const char echo_reference_dev_name_var[] = "EchoReferenceDev"; +/* SectionModifier prefixes and suffixes. */ +static const char hotword_model_prefix[] = "Hotword Model"; +static const char swap_mode_suffix[] = "Swap Mode"; +static const char noise_cancellation_suffix[] = "Noise Cancellation"; + /* * Set this value in a SectionDevice to specify the intrinsic sensitivity in * 0.01 dBFS/Pa. It currently only supports input devices. You should get the @@ -54,7 +58,6 @@ static const char intrinsic_sensitivity_var[] = "IntrinsicSensitivity"; * 0.01 dB. */ static const char default_node_gain[] = "DefaultNodeGain"; -static const char hotword_model_prefix[] = "Hotword Model"; static const char fully_specified_ucm_var[] = "FullySpecifiedUCM"; static const char main_volume_names[] = "MainVolumeNames"; @@ -64,6 +67,8 @@ static const char *use_case_verbs[] = { "Speech", "Pro Audio", "Accessibility", }; +static const size_t max_section_name_len = 100; + /* Represents a list of section names found in UCM. */ struct section_name { const char *name; @@ -377,6 +382,21 @@ static struct mixer_name *ucm_get_mixer_names(struct cras_use_case_mgr *mgr, return names; } +/* Gets the modifier name of Noise Cancellation for the given node_name. */ +static void ucm_get_node_noise_cancellation_name(const char *node_name, + char *mod_name) +{ + size_t len = + strlen(node_name) + 1 + strlen(noise_cancellation_suffix) + 1; + if (len > max_section_name_len) { + syslog(LOG_ERR, + "Length of the given section name is %zu > %zu(max)", + len, max_section_name_len); + len = max_section_name_len; + } + snprintf(mod_name, len, "%s %s", node_name, noise_cancellation_suffix); +} + /* Exported Interface */ struct cras_use_case_mgr *ucm_create(const char *name) @@ -495,6 +515,51 @@ int ucm_enable_swap_mode(struct cras_use_case_mgr *mgr, const char *node_name, return rc; } +int ucm_node_noise_cancellation_exists(struct cras_use_case_mgr *mgr, + const char *node_name) +{ + char *node_modifier_name = NULL; + int exists; + + node_modifier_name = (char *)malloc(max_section_name_len); + if (!node_modifier_name) + return 0; + ucm_get_node_noise_cancellation_name(node_name, node_modifier_name); + exists = ucm_mod_exists_with_name(mgr, node_modifier_name); + free((void *)node_modifier_name); + return exists; +} + +int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr *mgr, + const char *node_name, int enable) +{ + char *node_modifier_name = NULL; + int rc; + + node_modifier_name = (char *)malloc(max_section_name_len); + if (!node_modifier_name) + return -ENOMEM; + ucm_get_node_noise_cancellation_name(node_name, node_modifier_name); + if (!ucm_mod_exists_with_name(mgr, node_modifier_name)) { + syslog(LOG_ERR, "Can not find modifier %s.", + node_modifier_name); + free((void *)node_modifier_name); + return -EPERM; + } + if (modifier_enabled(mgr, node_modifier_name) == !!enable) { + syslog(LOG_DEBUG, "Modifier %s is already %s.", + node_modifier_name, enable ? "enabled" : "disabled"); + free((void *)node_modifier_name); + return 0; + } + + syslog(LOG_DEBUG, "UCM %s Modifier %s", enable ? "enable" : "disable", + node_modifier_name); + rc = ucm_set_modifier_enabled(mgr, node_modifier_name, enable); + free((void *)node_modifier_name); + return rc; +} + int ucm_set_enabled(struct cras_use_case_mgr *mgr, const char *dev, int enable) { int rc; diff --git a/cras/src/server/cras_alsa_ucm.h b/cras/src/server/cras_alsa_ucm.h index 610afa92..55c3cf62 100644 --- a/cras/src/server/cras_alsa_ucm.h +++ b/cras/src/server/cras_alsa_ucm.h @@ -67,6 +67,28 @@ int ucm_swap_mode_exists(struct cras_use_case_mgr *mgr); int ucm_enable_swap_mode(struct cras_use_case_mgr *mgr, const char *node_name, int enable); +/* Checks if modifier of noise cancellation for given node_name exists in ucm. + * Args: + * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. + * node_name - The node name. + * Returns: + * 1 if it exists, 0 otherwise. + */ +int ucm_node_noise_cancellation_exists(struct cras_use_case_mgr *mgr, + const char *node_name); + +/* Enables or disables noise cancellation for the given node_name. First checks + * if the modifier is already enabled or disabled. + * Args: + * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. + * node_name - The node name. + * enable - Enable device if non-zero. + * Returns: + * 0 on success or negative error code on failure. + */ +int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr *mgr, + const char *node_name, int enable); + /* Enables or disables a UCM device. First checks if the device is already * enabled or disabled. * Args: diff --git a/cras/src/server/cras_iodev.c b/cras/src/server/cras_iodev.c index fd1ce805..fe78f63e 100644 --- a/cras/src/server/cras_iodev.c +++ b/cras/src/server/cras_iodev.c @@ -1695,3 +1695,13 @@ int cras_iodev_drop_frames_by_time(struct cras_iodev *iodev, struct timespec ts) return rc; } + +bool cras_iodev_support_noise_cancellation(const struct cras_iodev *iodev) +{ + if (iodev->direction != CRAS_STREAM_INPUT) + return false; + + if (iodev->support_noise_cancellation) + return !!iodev->support_noise_cancellation(iodev); + return false; +} diff --git a/cras/src/server/cras_iodev.h b/cras/src/server/cras_iodev.h index db16a0f8..efe1d3e0 100644 --- a/cras/src/server/cras_iodev.h +++ b/cras/src/server/cras_iodev.h @@ -184,6 +184,8 @@ struct cras_ionode { * audio thread can sleep before serving this playback dev the next time. * Not implementing this ops means fall back to default behavior in * cras_iodev_default_frames_to_play_in_sleep(). + * support_noise_cancellation - (Optional) Checks if the device supports noise + * cancellation. * format - The audio format being rendered or captured to hardware. * rate_est - Rate estimator to estimate the actual device rate. * area - Information about how the samples are stored. @@ -274,6 +276,7 @@ struct cras_iodev { unsigned int (*frames_to_play_in_sleep)(struct cras_iodev *iodev, unsigned int *hw_level, struct timespec *hw_tstamp); + int (*support_noise_cancellation)(const struct cras_iodev *iodev); struct cras_audio_format *format; struct rate_estimator *rate_est; struct cras_audio_area *area; @@ -833,4 +836,12 @@ void cras_iodev_update_highest_hw_level(struct cras_iodev *iodev, int cras_iodev_drop_frames_by_time(struct cras_iodev *iodev, struct timespec ts); +/* Checks if an input device supports noise cancellation. + * Args: + * iodev - The device. + * Returns: + * True if device supports noise cancellation. False otherwise. + */ +bool cras_iodev_support_noise_cancellation(const struct cras_iodev *iodev); + #endif /* CRAS_IODEV_H_ */ diff --git a/cras/src/server/cras_iodev_list.c b/cras/src/server/cras_iodev_list.c index d887dfad..b818c97b 100644 --- a/cras/src/server/cras_iodev_list.c +++ b/cras/src/server/cras_iodev_list.c @@ -1881,6 +1881,24 @@ void cras_iodev_list_unregister_loopback(enum CRAS_LOOPBACK_TYPE type, } } +void cras_iodev_list_reset_for_noise_cancellation() +{ + struct cras_iodev *dev; + bool enabled = cras_system_get_noise_cancellation_enabled(); + + DL_FOREACH (devs[CRAS_STREAM_INPUT].iodevs, dev) { + if (!cras_iodev_is_open(dev) || + !cras_iodev_support_noise_cancellation(dev)) + continue; + syslog(LOG_INFO, "Re-open %s for %s noise cancellation", + dev->info.name, enabled ? "enabling" : "disabling"); + possibly_enable_fallback(CRAS_STREAM_INPUT, false); + cras_iodev_list_suspend_dev(dev->info.idx); + cras_iodev_list_resume_dev(dev->info.idx); + possibly_disable_fallback(CRAS_STREAM_INPUT); + } +} + void cras_iodev_list_reset() { struct enabled_dev *edev; diff --git a/cras/src/server/cras_iodev_list.h b/cras/src/server/cras_iodev_list.h index 61c3a182..d6e9ba54 100644 --- a/cras/src/server/cras_iodev_list.h +++ b/cras/src/server/cras_iodev_list.h @@ -274,6 +274,11 @@ int cras_iodev_list_suspend_hotword_streams(); /* Resumes all hotwording streams. */ int cras_iodev_list_resume_hotword_stream(); +/* Sets the state of noise cancellation for input devices which supports noise + * cancellation by suspend, enable/disable, then resume. + */ +void cras_iodev_list_reset_for_noise_cancellation(); + /* For unit test only. */ void cras_iodev_list_reset(); diff --git a/cras/src/server/cras_system_state.c b/cras/src/server/cras_system_state.c index 587c225f..366afb5f 100644 --- a/cras/src/server/cras_system_state.c +++ b/cras/src/server/cras_system_state.c @@ -18,6 +18,7 @@ #include "cras_board_config.h" #include "cras_config.h" #include "cras_device_blocklist.h" +#include "cras_iodev_list.h" #include "cras_observer.h" #include "cras_shm.h" #include "cras_system_state.h" @@ -406,7 +407,11 @@ bool cras_system_get_bt_fix_a2dp_packet_size_enabled() void cras_system_set_noise_cancellation_enabled(bool enabled) { - state.exp_state->noise_cancellation_enabled = enabled; + /* When the flag is toggled, propagate to all iodevs immediately. */ + if (cras_system_get_noise_cancellation_enabled() != enabled) { + state.exp_state->noise_cancellation_enabled = enabled; + cras_iodev_list_reset_for_noise_cancellation(); + } } bool cras_system_get_noise_cancellation_enabled() diff --git a/cras/src/tests/alsa_io_unittest.cc b/cras/src/tests/alsa_io_unittest.cc index 4c14f750..021b4789 100644 --- a/cras/src/tests/alsa_io_unittest.cc +++ b/cras/src/tests/alsa_io_unittest.cc @@ -2559,6 +2559,10 @@ 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, @@ -2807,6 +2811,17 @@ int ucm_get_channels_for_dev(struct cras_use_case_mgr* mgr, 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; } diff --git a/cras/src/tests/alsa_ucm_unittest.cc b/cras/src/tests/alsa_ucm_unittest.cc index d0d6e600..1b351ddf 100644 --- a/cras/src/tests/alsa_ucm_unittest.cc +++ b/cras/src/tests/alsa_ucm_unittest.cc @@ -693,6 +693,76 @@ TEST(AlsaUcm, DisableSwapMode) { EXPECT_EQ(1, snd_use_case_set_called); } +TEST(AlsaUcm, NoiseCancellationExists) { + struct cras_use_case_mgr* mgr = &cras_ucm_mgr; + int rc; + const char* node = "Internal Mic"; + const char* modifiers_1[] = {"Internal Mic Noise Cancellation", "Comment"}; + const char* modifiers_2[] = {"Internal Mic Noise Augmentation", "Comment"}; + const char* modifiers_3[] = {"Microphone Noise Cancellation", "Comment"}; + + ResetStubData(); + + fake_list["_modifiers/HiFi"] = modifiers_1; + fake_list_size["_modifiers/HiFi"] = 2; + rc = ucm_node_noise_cancellation_exists(mgr, node); + EXPECT_EQ(1, rc); + + fake_list["_modifiers/HiFi"] = modifiers_2; + fake_list_size["_modifiers/HiFi"] = 2; + rc = ucm_node_noise_cancellation_exists(mgr, node); + EXPECT_EQ(0, rc); + + fake_list["_modifiers/HiFi"] = modifiers_3; + fake_list_size["_modifiers/HiFi"] = 2; + rc = ucm_node_noise_cancellation_exists(mgr, node); + EXPECT_EQ(0, rc); +} + +TEST(AlsaUcm, EnableDisableNoiseCancellation) { + struct cras_use_case_mgr* mgr = &cras_ucm_mgr; + int rc; + const char* modifiers[] = {"Internal Mic Noise Cancellation", "Comment1", + "Microphone Noise Cancellation", "Comment2"}; + const char* modifiers_enabled[] = {"Internal Mic Noise Cancellation"}; + + ResetStubData(); + + fake_list["_modifiers/HiFi"] = modifiers; + fake_list_size["_modifiers/HiFi"] = 4; + + fake_list["_enamods"] = modifiers_enabled; + fake_list_size["_enamods"] = 1; + + snd_use_case_set_return = 0; + + rc = ucm_enable_node_noise_cancellation(mgr, "Line In", 1); + EXPECT_EQ(-EPERM, rc); // Modifier is not existed + EXPECT_EQ(0, snd_use_case_set_called); + + rc = ucm_enable_node_noise_cancellation(mgr, "Line In", 0); + EXPECT_EQ(-EPERM, rc); // Modifier is not existed + EXPECT_EQ(0, snd_use_case_set_called); + + rc = ucm_enable_node_noise_cancellation(mgr, "Microphone", 0); + EXPECT_EQ(0, rc); // Modifier is already disabled + EXPECT_EQ(0, snd_use_case_set_called); + + rc = ucm_enable_node_noise_cancellation(mgr, "Microphone", 1); + EXPECT_EQ(0, rc); + EXPECT_EQ(1, snd_use_case_set_called); + + snd_use_case_set_called = 0; + + rc = ucm_enable_node_noise_cancellation(mgr, "Internal Mic", 1); + EXPECT_EQ(0, rc); // Modifier is already enabled + EXPECT_EQ(0, snd_use_case_set_called); + + rc = ucm_enable_node_noise_cancellation(mgr, "Internal Mic", 0); + EXPECT_EQ(0, rc); + EXPECT_EQ(1, snd_use_case_set_called); +} + TEST(AlsaFlag, GetFlag) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; char* flag_value; diff --git a/cras/src/tests/iodev_list_unittest.cc b/cras/src/tests/iodev_list_unittest.cc index 5dbc7c8f..8c71214a 100644 --- a/cras/src/tests/iodev_list_unittest.cc +++ b/cras/src/tests/iodev_list_unittest.cc @@ -2006,6 +2006,43 @@ TEST_F(IoDevTestSuite, HotwordStreamsPausedAtSystemSuspend) { cras_iodev_list_deinit(); } +TEST_F(IoDevTestSuite, SetNoiseCancellation) { + struct cras_rstream rstream; + struct cras_rstream* stream_list = NULL; + int rc; + + memset(&rstream, 0, sizeof(rstream)); + + cras_iodev_list_init(); + + d1_.direction = CRAS_STREAM_INPUT; + rc = cras_iodev_list_add_input(&d1_); + ASSERT_EQ(0, rc); + + d1_.format = &fmt_; + + rstream.direction = CRAS_STREAM_INPUT; + + audio_thread_add_open_dev_called = 0; + audio_thread_rm_open_dev_called = 0; + cras_iodev_list_add_active_node(CRAS_STREAM_INPUT, + cras_make_node_id(d1_.info.idx, 1)); + DL_APPEND(stream_list, &rstream); + stream_add_cb(&rstream); + stream_list_get_ret = stream_list; + EXPECT_EQ(1, audio_thread_add_stream_called); + EXPECT_EQ(1, audio_thread_add_open_dev_called); + + // reset_for_noise_cancellation causes device suspend & resume + // While suspending d1_: rm d1_, open fallback + // While resuming d1_: rm fallback, open d1_ + cras_iodev_list_reset_for_noise_cancellation(); + EXPECT_EQ(3, audio_thread_add_open_dev_called); + EXPECT_EQ(2, audio_thread_rm_open_dev_called); + + cras_iodev_list_deinit(); +} + } // namespace int main(int argc, char** argv) { @@ -2028,6 +2065,10 @@ int cras_system_get_mute() { return system_get_mute_return; } +bool cras_system_get_noise_cancellation_enabled() { + return false; +} + struct audio_thread* audio_thread_create() { return &thread; } @@ -2167,6 +2208,10 @@ void cras_iodev_set_node_plugged(struct cras_ionode* node, int plugged) { set_node_plugged_called++; } +bool cras_iodev_support_noise_cancellation(const struct cras_iodev* iodev) { + return true; +} + int cras_iodev_start_volume_ramp(struct cras_iodev* odev, unsigned int old_volume, unsigned int new_volume) { diff --git a/cras/src/tests/system_state_unittest.cc b/cras/src/tests/system_state_unittest.cc index e18429e2..45224bc9 100644 --- a/cras/src/tests/system_state_unittest.cc +++ b/cras/src/tests/system_state_unittest.cc @@ -39,6 +39,7 @@ static size_t cras_observer_notify_capture_mute_called; static size_t cras_observer_notify_suspend_changed_called; static size_t cras_observer_notify_num_active_streams_called; static size_t cras_observer_notify_input_streams_with_permission_called; +static size_t cras_iodev_list_reset_for_noise_cancellation_called; static struct cras_board_config fake_board_config; static size_t cras_alert_process_all_pending_alerts_called; @@ -62,6 +63,7 @@ static void ResetStubData() { cras_observer_notify_num_active_streams_called = 0; cras_observer_notify_input_streams_with_permission_called = 0; cras_alert_process_all_pending_alerts_called = 0; + cras_iodev_list_reset_for_noise_cancellation_called = 0; memset(&fake_board_config, 0, sizeof(fake_board_config)); } @@ -434,6 +436,33 @@ TEST(SystemStateSuite, IgnoreUCMSuffix) { cras_system_state_deinit(); } +TEST(SystemStateSuite, SetNoiseCancellationEnabled) { + ResetStubData(); + do_sys_init(); + + EXPECT_EQ(0, cras_system_get_noise_cancellation_enabled()); + + cras_system_set_noise_cancellation_enabled(0); + EXPECT_EQ(0, cras_system_get_noise_cancellation_enabled()); + EXPECT_EQ(0, cras_iodev_list_reset_for_noise_cancellation_called); + + cras_system_set_noise_cancellation_enabled(1); + EXPECT_EQ(1, cras_system_get_noise_cancellation_enabled()); + EXPECT_EQ(1, cras_iodev_list_reset_for_noise_cancellation_called); + + cras_system_set_noise_cancellation_enabled(1); + EXPECT_EQ(1, cras_system_get_noise_cancellation_enabled()); + // cras_iodev_list_reset_for_noise_cancellation shouldn't be called if state + // is already enabled/disabled. + EXPECT_EQ(1, cras_iodev_list_reset_for_noise_cancellation_called); + + cras_system_set_noise_cancellation_enabled(0); + EXPECT_EQ(0, cras_system_get_noise_cancellation_enabled()); + EXPECT_EQ(2, cras_iodev_list_reset_for_noise_cancellation_called); + + cras_system_state_deinit(); +} + extern "C" { struct cras_alsa_card* cras_alsa_card_create( @@ -534,6 +563,10 @@ void cras_alert_process_all_pending_alerts() { cras_alert_process_all_pending_alerts_called++; } +void cras_iodev_list_reset_for_noise_cancellation() { + cras_iodev_list_reset_for_noise_cancellation_called++; +} + } // extern "C" } // namespace |