diff options
author | Ben Zhang <benzh@chromium.org> | 2021-01-21 17:58:42 -0500 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-02-23 21:42:22 +0000 |
commit | 62943dff3cc9ae70895f1e4159d94765aa2fb3c5 (patch) | |
tree | f0f1c9ae1a869b57d2887216276efa7cf065552a | |
parent | 2e6ec22b09e3ded15cf150354b89ffcdd3a438fd (diff) | |
download | adhd-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.h | 6 | ||||
-rw-r--r-- | cras/src/server/config/cras_board_config.c | 7 | ||||
-rw-r--r-- | cras/src/server/config/cras_board_config.h | 1 | ||||
-rw-r--r-- | cras/src/server/cras_iodev_list.c | 24 | ||||
-rw-r--r-- | cras/src/server/cras_system_state.c | 12 | ||||
-rw-r--r-- | cras/src/server/cras_system_state.h | 6 | ||||
-rw-r--r-- | cras/src/tests/control_rclient_unittest.cc | 2 | ||||
-rw-r--r-- | cras/src/tests/iodev_list_unittest.cc | 68 |
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" |