summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Zhang <benzh@chromium.org>2021-01-21 17:58:42 -0500
committerCommit Bot <commit-bot@chromium.org>2021-02-23 21:42:22 +0000
commit62943dff3cc9ae70895f1e4159d94765aa2fb3c5 (patch)
treef0f1c9ae1a869b57d2887216276efa7cf065552a
parent2e6ec22b09e3ded15cf150354b89ffcdd3a438fd (diff)
downloadadhd-62943dff3cc9ae70895f1e4159d94765aa2fb3c5.tar.gz
CRAS: Add a flag to pause hotword detection at system suspend
This patch adds a server state flag to optionally pause hotword detection at system suspend. Default value of the flag can be specified in board.ini BUG=b:178128172 TEST=Set the flag in board.ini on Delbin and verify if hotword can wake up the device from suspend. Repeated suspend/resume on Delbin with the flag set to 1 Change-Id: I6820c92dd418f51108b374ff186a2b82da031399 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/2652049 Tested-by: Ben Zhang <benzh@chromium.org> Commit-Queue: Ben Zhang <benzh@chromium.org> Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org>
-rw-r--r--cras/src/common/cras_types.h6
-rw-r--r--cras/src/server/config/cras_board_config.c7
-rw-r--r--cras/src/server/config/cras_board_config.h1
-rw-r--r--cras/src/server/cras_iodev_list.c24
-rw-r--r--cras/src/server/cras_system_state.c12
-rw-r--r--cras/src/server/cras_system_state.h6
-rw-r--r--cras/src/tests/control_rclient_unittest.cc2
-rw-r--r--cras/src/tests/iodev_list_unittest.cc68
8 files changed, 126 insertions, 0 deletions
diff --git a/cras/src/common/cras_types.h b/cras/src/common/cras_types.h
index 53f2f6aa..7c8a4229 100644
--- a/cras/src/common/cras_types.h
+++ b/cras/src/common/cras_types.h
@@ -574,6 +574,11 @@ struct __attribute__((__packed__)) cras_audio_thread_snapshot_buffer {
* num_input_streams_with_permission - An array containing numbers of input
* streams with permission in each client type.
* noise_cancellation_enabled - Whether or not Noise Cancellation is enabled.
+ * hotword_pause_at_suspend - 1 = Pause hotword detection when the system
+ * suspends. Hotword detection is resumed after system resumes.
+ * 0 - Hotword detection is allowed to continue running after system
+ * suspends, so a detected hotword can wake up the device.
+ *
*/
#define CRAS_SERVER_STATE_VERSION 2
struct __attribute__((packed, aligned(4))) cras_server_state {
@@ -614,6 +619,7 @@ struct __attribute__((packed, aligned(4))) cras_server_state {
struct main_thread_debug_info main_thread_debug_info;
uint32_t num_input_streams_with_permission[CRAS_NUM_CLIENT_TYPE];
int32_t noise_cancellation_enabled;
+ int32_t hotword_pause_at_suspend;
};
/* Actions for card add/remove/change. */
diff --git a/cras/src/server/config/cras_board_config.c b/cras/src/server/config/cras_board_config.c
index 14d3fa0c..e36ea3cf 100644
--- a/cras/src/server/config/cras_board_config.c
+++ b/cras/src/server/config/cras_board_config.c
@@ -14,6 +14,7 @@ static const int32_t AEC_SUPPORTED_DEFAULT = 0;
static const int32_t AEC_GROUP_ID_DEFAULT = -1;
static const int32_t BLUETOOTH_WBS_ENABLED_INI_DEFAULT = 1;
static const int32_t BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_DEFAULT = 0;
+static const int32_t HOTWORD_PAUSE_AT_SUSPEND_DEFAULT = 0;
#define CONFIG_NAME "board.ini"
#define DEFAULT_OUTPUT_BUF_SIZE_INI_KEY "output:default_output_buffer_size"
@@ -22,6 +23,7 @@ static const int32_t BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_DEFAULT = 0;
#define BLUETOOTH_WBS_ENABLED_INI_KEY "bluetooth:wbs_enabled"
#define BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_KEY "bluetooth:deprioritize_wbs_mic"
#define UCM_IGNORE_SUFFIX_KEY "ucm:ignore_suffix"
+#define HOTWORD_PAUSE_AT_SUSPEND "hotword:pause_at_suspend"
void cras_board_config_get(const char *config_path,
struct cras_board_config *board_config)
@@ -85,6 +87,11 @@ void cras_board_config_get(const char *config_path,
syslog(LOG_ERR, "Failed to call strdup: %d", errno);
}
+ snprintf(ini_key, MAX_INI_KEY_LENGTH, HOTWORD_PAUSE_AT_SUSPEND);
+ ini_key[MAX_INI_KEY_LENGTH] = 0;
+ board_config->hotword_pause_at_suspend = iniparser_getint(
+ ini, ini_key, HOTWORD_PAUSE_AT_SUSPEND_DEFAULT);
+
iniparser_freedict(ini);
syslog(LOG_DEBUG, "Loaded ini file %s", ini_name);
}
diff --git a/cras/src/server/config/cras_board_config.h b/cras/src/server/config/cras_board_config.h
index 2ecde265..d4bd8496 100644
--- a/cras/src/server/config/cras_board_config.h
+++ b/cras/src/server/config/cras_board_config.h
@@ -15,6 +15,7 @@ struct cras_board_config {
int32_t bt_wbs_enabled;
int32_t deprioritize_bt_wbs_mic;
char *ucm_ignore_suffix;
+ int32_t hotword_pause_at_suspend;
};
/* Gets a configuration based on the config file specified.
diff --git a/cras/src/server/cras_iodev_list.c b/cras/src/server/cras_iodev_list.c
index 17b04ecb..d887dfad 100644
--- a/cras/src/server/cras_iodev_list.c
+++ b/cras/src/server/cras_iodev_list.c
@@ -91,6 +91,9 @@ static int stream_list_suspended = 0;
static const unsigned int INIT_DEV_DELAY_MS = 1000;
/* Flag to indicate that hotword streams are suspended. */
static int hotword_suspended = 0;
+/* Flag to indicate that suspended hotword streams should be auto-resumed at
+ * system resume. */
+static int hotword_auto_resume = 0;
static void idle_dev_check(struct cras_timer *timer, void *data);
@@ -491,6 +494,11 @@ static void suspend_devs()
if (rstream->is_pinned) {
struct cras_iodev *dev;
+ /* Skip closing hotword stream in the first pass.
+ * Closing an input device may resume hotword stream
+ * with its post_close_iodev_hook so we should deal
+ * with hotword stream in the second pass.
+ */
if ((rstream->flags & HOTWORD_STREAM) == HOTWORD_STREAM)
continue;
@@ -514,6 +522,14 @@ static void suspend_devs()
DL_FOREACH (enabled_devs[CRAS_STREAM_INPUT], edev) {
close_dev(edev->dev);
}
+
+ /* Doing this check after all the other enabled iodevs are closed to
+ * ensure preempted hotword streams obey the pause_at_suspend flag.
+ */
+ if (cras_system_get_hotword_pause_at_suspend()) {
+ cras_iodev_list_suspend_hotword_streams();
+ hotword_auto_resume = 1;
+ }
}
static int stream_added_cb(struct cras_rstream *rstream);
@@ -528,6 +544,14 @@ static void resume_devs()
MAINLOG(main_log, MAIN_THREAD_RESUME_DEVS, 0, 0, 0);
+ /* Auto-resume based on the local flag in case the system state flag has
+ * changed.
+ */
+ if (hotword_auto_resume) {
+ cras_iodev_list_resume_hotword_stream();
+ hotword_auto_resume = 0;
+ }
+
/*
* To remove the short popped noise caused by applications that can not
* stop playback "right away" after resume, we mute all output devices
diff --git a/cras/src/server/cras_system_state.c b/cras/src/server/cras_system_state.c
index 22df0001..587c225f 100644
--- a/cras/src/server/cras_system_state.c
+++ b/cras/src/server/cras_system_state.c
@@ -160,6 +160,8 @@ void cras_system_state_init(const char *device_config_dir, const char *shm_name,
exp_state->deprioritize_bt_wbs_mic =
board_config.deprioritize_bt_wbs_mic;
exp_state->noise_cancellation_enabled = 0;
+ exp_state->hotword_pause_at_suspend =
+ board_config.hotword_pause_at_suspend;
if ((rc = pthread_mutex_init(&state.update_lock, 0) != 0)) {
syslog(LOG_ERR, "Fatal: system state mutex init");
@@ -427,6 +429,16 @@ bool cras_system_check_ignore_ucm_suffix(const char *card_name)
return false;
}
+bool cras_system_get_hotword_pause_at_suspend()
+{
+ return !!state.exp_state->hotword_pause_at_suspend;
+}
+
+void cras_system_set_hotword_pause_at_suspend(bool pause)
+{
+ state.exp_state->hotword_pause_at_suspend = pause;
+}
+
int cras_system_add_alsa_card(struct cras_alsa_card_info *alsa_card_info)
{
struct card_list *card;
diff --git a/cras/src/server/cras_system_state.h b/cras/src/server/cras_system_state.h
index 23fdd8e5..bd09395c 100644
--- a/cras/src/server/cras_system_state.h
+++ b/cras/src/server/cras_system_state.h
@@ -143,6 +143,12 @@ bool cras_system_get_noise_cancellation_enabled();
/* Checks if the card ignores the ucm suffix. */
bool cras_system_check_ignore_ucm_suffix(const char *card_name);
+/* Returns true if hotword detection is paused at system suspend. */
+bool cras_system_get_hotword_pause_at_suspend();
+
+/* Sets whether to pause hotword detection at system suspend. */
+void cras_system_set_hotword_pause_at_suspend(bool pause);
+
/* Adds a card at the given index to the system. When a new card is found
* (through a udev event notification) this will add the card to the system,
* causing its devices to become available for playback/capture.
diff --git a/cras/src/tests/control_rclient_unittest.cc b/cras/src/tests/control_rclient_unittest.cc
index d6067304..63e3c8f0 100644
--- a/cras/src/tests/control_rclient_unittest.cc
+++ b/cras/src/tests/control_rclient_unittest.cc
@@ -972,4 +972,6 @@ void detect_rtc_stream_pair(struct stream_list* list,
return;
}
+void cras_system_set_hotword_pause_at_suspend(bool pause) {}
+
} // extern "C"
diff --git a/cras/src/tests/iodev_list_unittest.cc b/cras/src/tests/iodev_list_unittest.cc
index 272537fc..5dbc7c8f 100644
--- a/cras/src/tests/iodev_list_unittest.cc
+++ b/cras/src/tests/iodev_list_unittest.cc
@@ -95,6 +95,7 @@ static struct cras_rstream* audio_thread_disconnect_stream_stream;
static int audio_thread_disconnect_stream_called;
static struct cras_iodev fake_sco_in_dev, fake_sco_out_dev;
static struct cras_ionode fake_sco_in_node, fake_sco_out_node;
+static int server_state_hotword_pause_at_suspend;
int dev_idx_in_vector(std::vector<unsigned int> v, unsigned int idx) {
return std::find(v.begin(), v.end(), idx) != v.end();
@@ -238,6 +239,7 @@ class IoDevTestSuite : public testing::Test {
mock_empty_iodev[1].state = CRAS_IODEV_STATE_CLOSE;
mock_empty_iodev[1].update_active_node = update_active_node;
mock_hotword_iodev.update_active_node = update_active_node;
+ server_state_hotword_pause_at_suspend = 0;
}
virtual void TearDown() {
@@ -1942,6 +1944,68 @@ TEST_F(IoDevTestSuite, GetSCOPCMIodevs) {
cras_iodev_list_deinit();
}
+TEST_F(IoDevTestSuite, HotwordStreamsPausedAtSystemSuspend) {
+ struct cras_rstream rstream;
+ struct cras_rstream* stream_list = NULL;
+ cras_iodev_list_init();
+
+ node1.type = CRAS_NODE_TYPE_HOTWORD;
+ d1_.direction = CRAS_STREAM_INPUT;
+ EXPECT_EQ(0, cras_iodev_list_add_input(&d1_));
+
+ d1_.format = &fmt_;
+
+ memset(&rstream, 0, sizeof(rstream));
+ rstream.is_pinned = 1;
+ rstream.pinned_dev_idx = d1_.info.idx;
+ rstream.flags = HOTWORD_STREAM;
+
+ /* Add a hotword stream. */
+ EXPECT_EQ(0, stream_add_cb(&rstream));
+ EXPECT_EQ(1, audio_thread_add_stream_called);
+ EXPECT_EQ(&d1_, audio_thread_add_stream_dev);
+ EXPECT_EQ(&rstream, audio_thread_add_stream_stream);
+
+ DL_APPEND(stream_list, &rstream);
+ stream_list_get_ret = stream_list;
+
+ server_state_hotword_pause_at_suspend = 1;
+
+ /* Trigger system suspend. Verify hotword stream is moved to empty dev. */
+ observer_ops->suspend_changed(NULL, 1);
+ EXPECT_EQ(1, audio_thread_disconnect_stream_called);
+ EXPECT_EQ(&rstream, audio_thread_disconnect_stream_stream);
+ EXPECT_EQ(&d1_, audio_thread_disconnect_stream_dev);
+ EXPECT_EQ(2, audio_thread_add_stream_called);
+ EXPECT_EQ(&rstream, audio_thread_add_stream_stream);
+ EXPECT_EQ(&mock_hotword_iodev, audio_thread_add_stream_dev);
+
+ /* Trigger system resume. Verify hotword stream is moved to real dev.*/
+ observer_ops->suspend_changed(NULL, 0);
+ EXPECT_EQ(2, audio_thread_disconnect_stream_called);
+ EXPECT_EQ(&rstream, audio_thread_disconnect_stream_stream);
+ EXPECT_EQ(&mock_hotword_iodev, audio_thread_disconnect_stream_dev);
+ EXPECT_EQ(3, audio_thread_add_stream_called);
+ EXPECT_EQ(&rstream, audio_thread_add_stream_stream);
+ EXPECT_EQ(&d1_, audio_thread_add_stream_dev);
+
+ server_state_hotword_pause_at_suspend = 0;
+ audio_thread_disconnect_stream_called = 0;
+ audio_thread_add_stream_called = 0;
+
+ /* Trigger system suspend. Verify hotword stream is not touched. */
+ observer_ops->suspend_changed(NULL, 1);
+ EXPECT_EQ(0, audio_thread_disconnect_stream_called);
+ EXPECT_EQ(0, audio_thread_add_stream_called);
+
+ /* Trigger system resume. Verify hotword stream is not touched.*/
+ observer_ops->suspend_changed(NULL, 0);
+ EXPECT_EQ(0, audio_thread_disconnect_stream_called);
+ EXPECT_EQ(0, audio_thread_add_stream_called);
+
+ cras_iodev_list_deinit();
+}
+
} // namespace
int main(int argc, char** argv) {
@@ -2246,4 +2310,8 @@ int clock_gettime(clockid_t clk_id, struct timespec* tp) {
return 0;
}
+bool cras_system_get_hotword_pause_at_suspend() {
+ return !!server_state_hotword_pause_at_suspend;
+}
+
} // extern "C"