diff options
author | Chinyue Chen <chinyue@chromium.org> | 2016-12-05 16:51:42 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-12-09 07:23:30 -0800 |
commit | fa88cc31818bb74c9b7832d9bcba9b025a69a845 (patch) | |
tree | 0b66bae2bf1f7eec7adb65ae7e2c9d6d06f9a366 | |
parent | 9b631e24e0943ab1690cb93ffb916ffe23afe410 (diff) | |
download | adhd-fa88cc31818bb74c9b7832d9bcba9b025a69a845.tar.gz |
CRAS: UCM - Extract and expose ucm_set_use_case function.
The new ucm_set_ues_case function will be used later to change use case
in run-time. It checks if the UCM config for the requested use case is
availalble, and uses default use case if not.
BUG=chromium:643039
TEST=make check
Change-Id: I499e2be999ad74c2996ee26d56e42e39892a02ee
Reviewed-on: https://chromium-review.googlesource.com/416531
Commit-Ready: Chinyue Chen <chinyue@chromium.org>
Tested-by: Chinyue Chen <chinyue@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
-rw-r--r-- | cras/src/server/cras_alsa_ucm.c | 62 | ||||
-rw-r--r-- | cras/src/server/cras_alsa_ucm.h | 10 | ||||
-rw-r--r-- | cras/src/tests/alsa_ucm_unittest.cc | 68 |
3 files changed, 134 insertions, 6 deletions
diff --git a/cras/src/server/cras_alsa_ucm.c b/cras/src/server/cras_alsa_ucm.c index a28f8235..896cd197 100644 --- a/cras/src/server/cras_alsa_ucm.c +++ b/cras/src/server/cras_alsa_ucm.c @@ -40,6 +40,15 @@ static const char fully_specified_ucm_var[] = "FullySpecifiedUCM"; static const char main_volume_names[] = "MainVolumeNames"; static const char enable_htimestamp_var[] = "EnableHtimestamp"; +/* Use case verbs corresponding to CRAS_STREAM_TYPE. */ +static const char *use_case_verbs[] = { + "HiFi", + "Multimedia", + "Voice Call", + "Voice", + "Pro Audio", +}; + /* Represents a list of section names found in UCM. */ struct section_name { const char* name; @@ -48,9 +57,16 @@ struct section_name { struct cras_use_case_mgr { snd_use_case_mgr_t *mgr; + const char *name; + unsigned int avail_use_cases; enum CRAS_STREAM_TYPE use_case; }; +static inline const char *uc_verb(struct cras_use_case_mgr *mgr) +{ + return use_case_verbs[mgr->use_case]; +} + static int device_enabled(struct cras_use_case_mgr *mgr, const char *dev) { const char **list; @@ -320,6 +336,8 @@ struct cras_use_case_mgr *ucm_create(const char *name) { struct cras_use_case_mgr *mgr; int rc; + const char **list; + int num_verbs, i, j; if (!name) return NULL; @@ -335,14 +353,23 @@ struct cras_use_case_mgr *ucm_create(const char *name) goto cleanup; } - mgr->use_case = CRAS_STREAM_TYPE_DEFAULT; + mgr->name = name; + mgr->avail_use_cases = 0; + num_verbs = snd_use_case_get_list(mgr->mgr, "_verbs", &list); + for (i = 0; i < num_verbs; i += 2) { + for (j = 0; j < CRAS_STREAM_NUM_TYPES; ++j) { + if (strcmp(list[i], use_case_verbs[j]) == 0) + break; + } + if (j < CRAS_STREAM_NUM_TYPES) + mgr->avail_use_cases |= (1 << j); + } + if (num_verbs > 0) + snd_use_case_free_list(list, num_verbs); - rc = snd_use_case_set(mgr->mgr, "_verb", default_verb); - if (rc) { - syslog(LOG_ERR, "Can not set verb %s for card %s, rc = %d", - default_verb, name, rc); + rc = ucm_set_use_case(mgr, CRAS_STREAM_TYPE_DEFAULT); + if (rc) goto cleanup_mgr; - } return mgr; @@ -359,6 +386,29 @@ void ucm_destroy(struct cras_use_case_mgr *mgr) free(mgr); } +int ucm_set_use_case(struct cras_use_case_mgr *mgr, + enum CRAS_STREAM_TYPE use_case) +{ + int rc; + + if (mgr->avail_use_cases & (1 << use_case)) { + mgr->use_case = use_case; + } else { + syslog(LOG_ERR, "Unavailable use case %d for card %s", + use_case, mgr->name); + return -1; + } + + rc = snd_use_case_set(mgr->mgr, "_verb", uc_verb(mgr)); + if (rc) { + syslog(LOG_ERR, "Can not set verb %s for card %s, rc = %d", + uc_verb(mgr), mgr->name, rc); + return rc; + } + + return 0; +} + int ucm_swap_mode_exists(struct cras_use_case_mgr *mgr) { return ucm_mod_exists_with_suffix(mgr, swap_mode_suffix); diff --git a/cras/src/server/cras_alsa_ucm.h b/cras/src/server/cras_alsa_ucm.h index a66db692..95c51eef 100644 --- a/cras/src/server/cras_alsa_ucm.h +++ b/cras/src/server/cras_alsa_ucm.h @@ -38,6 +38,16 @@ struct cras_use_case_mgr *ucm_create(const char *name); */ void ucm_destroy(struct cras_use_case_mgr *mgr); +/* Sets the new use case for the given cras_use_case_mgr. + * Args: + * mgr - The cras_use_case_mgr pointer returned from ucm_create. + * use_case - The new use case to be set. + * Returns: + * 0 on success or negative error code on failure. + */ +int ucm_set_use_case(struct cras_use_case_mgr *mgr, + enum CRAS_STREAM_TYPE use_case); + /* Checks if modifier for left right swap mode exists in ucm. * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. diff --git a/cras/src/tests/alsa_ucm_unittest.cc b/cras/src/tests/alsa_ucm_unittest.cc index 933a84c8..8e604253 100644 --- a/cras/src/tests/alsa_ucm_unittest.cc +++ b/cras/src/tests/alsa_ucm_unittest.cc @@ -37,6 +37,7 @@ static unsigned snd_use_case_free_list_called; static std::vector<std::string> list_devices_callback_names; static std::vector<void*> list_devices_callback_args; static struct cras_use_case_mgr cras_ucm_mgr; +static const char *avail_verbs[] = { "HiFi", "Comment for Verb1" }; static void ResetStubData() { snd_use_case_mgr_open_called = 0; @@ -51,6 +52,8 @@ static void ResetStubData() { snd_use_case_get_value.clear(); fake_list.clear(); fake_list_size.clear(); + fake_list["_verbs"] = avail_verbs; + fake_list_size["_verbs"] = 2; list_devices_callback_names.clear(); list_devices_callback_args.clear(); snd_use_case_mgr_open_mgr_ptr = reinterpret_cast<snd_use_case_mgr_t*>(0x55); @@ -1267,6 +1270,71 @@ TEST(AlsaUcm, GetSectionsBadPCM) { EXPECT_EQ(NULL, sections); } +TEST(AlsaUcm, CheckUseCaseVerbs) { + struct cras_use_case_mgr *mgr = &cras_ucm_mgr; + + /* Verifies the mapping between stream types and verbs are correct. */ + mgr->use_case = CRAS_STREAM_TYPE_DEFAULT; + EXPECT_EQ(0, strcmp("HiFi", uc_verb(mgr))); + mgr->use_case = CRAS_STREAM_TYPE_MULTIMEDIA; + EXPECT_EQ(0, strcmp("Multimedia", uc_verb(mgr))); + mgr->use_case = CRAS_STREAM_TYPE_VOICE_COMMUNICATION; + EXPECT_EQ(0, strcmp("Voice Call", uc_verb(mgr))); + mgr->use_case = CRAS_STREAM_TYPE_VOICE_RECOGNITION; + EXPECT_EQ(0, strcmp("Voice", uc_verb(mgr))); + mgr->use_case = CRAS_STREAM_TYPE_PRO_AUDIO; + EXPECT_EQ(0, strcmp("Pro Audio", uc_verb(mgr))); +} + +TEST(AlsaUcm, GetAvailUseCases) { + struct cras_use_case_mgr *mgr; + const char *verbs[] = { "HiFi", "Comment for Verb1", + "Voice Call", "Comment for Verb2", + "Voice", "Comment for Verb3" }; + + ResetStubData(); + + fake_list["_verbs"] = verbs; + fake_list_size["_verbs"] = 6; + + mgr = ucm_create("foo"); + EXPECT_EQ(0x0D, mgr->avail_use_cases); + ucm_destroy(mgr); +} + +TEST(AlsaUcm, SetUseCase) { + struct cras_use_case_mgr *mgr; + const char *verbs[] = { "HiFi", "Comment for Verb1", + "Voice Call", "Comment for Verb2", + "Voice", "Comment for Verb3" }; + int rc; + + ResetStubData(); + + fake_list["_verbs"] = verbs; + fake_list_size["_verbs"] = 6; + + mgr = ucm_create("foo"); + EXPECT_EQ(snd_use_case_set_param[0], + std::make_pair(std::string("_verb"), std::string("HiFi"))); + + rc = ucm_set_use_case(mgr, CRAS_STREAM_TYPE_VOICE_COMMUNICATION); + EXPECT_EQ(0, rc); + EXPECT_EQ(mgr->use_case, CRAS_STREAM_TYPE_VOICE_COMMUNICATION); + EXPECT_EQ(snd_use_case_set_param[1], + std::make_pair(std::string("_verb"), std::string("Voice Call"))); + + /* Request unavailable use case will fail. */ + rc = ucm_set_use_case(mgr, CRAS_STREAM_TYPE_PRO_AUDIO); + EXPECT_EQ(-1, rc); + /* cras_use_case_mgr's use case should not be changed. */ + EXPECT_EQ(mgr->use_case, CRAS_STREAM_TYPE_VOICE_COMMUNICATION); + /* And snd_use_case_set not being called. */ + EXPECT_EQ(2, snd_use_case_set_param.size()); + + ucm_destroy(mgr); +} + /* Stubs */ extern "C" { |