summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPin-chih Lin <johnylin@google.com>2021-01-26 16:39:19 +0800
committerCommit Bot <commit-bot@chromium.org>2021-02-25 17:38:41 +0000
commitd8a4e5d26c4de095f449de51cd6dab7855d532f8 (patch)
treee7a01ce364dcbbc4c386d3b2929d1fbecbc71c2a
parent0e3c7b3a0929bee57f68056c51caaed8029afbad (diff)
downloadadhd-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.c26
-rw-r--r--cras/src/server/cras_alsa_ucm.c69
-rw-r--r--cras/src/server/cras_alsa_ucm.h22
-rw-r--r--cras/src/server/cras_iodev.c10
-rw-r--r--cras/src/server/cras_iodev.h11
-rw-r--r--cras/src/server/cras_iodev_list.c18
-rw-r--r--cras/src/server/cras_iodev_list.h5
-rw-r--r--cras/src/server/cras_system_state.c7
-rw-r--r--cras/src/tests/alsa_io_unittest.cc15
-rw-r--r--cras/src/tests/alsa_ucm_unittest.cc70
-rw-r--r--cras/src/tests/iodev_list_unittest.cc45
-rw-r--r--cras/src/tests/system_state_unittest.cc33
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