summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChinyue Chen <chinyue@chromium.org>2016-12-05 16:51:42 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-12-09 07:23:30 -0800
commitfa88cc31818bb74c9b7832d9bcba9b025a69a845 (patch)
tree0b66bae2bf1f7eec7adb65ae7e2c9d6d06f9a366
parent9b631e24e0943ab1690cb93ffb916ffe23afe410 (diff)
downloadadhd-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.c62
-rw-r--r--cras/src/server/cras_alsa_ucm.h10
-rw-r--r--cras/src/tests/alsa_ucm_unittest.cc68
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" {