• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdio.h>
6 #include <gtest/gtest.h>
7 #include <map>
8 #include <string>
9 #include <syslog.h>
10 #include <vector>
11 
12 extern "C" {
13 #include "cras_alsa_mixer.h"
14 #include "cras_alsa_mixer_name.h"
15 #include "cras_types.h"
16 #include "cras_util.h"
17 #include "cras_volume_curve.h"
18 #include "utlist.h"
19 
20 //  Include C file to test static functions and use the definition of some
21 //  structure.
22 #include "cras_alsa_mixer.c"
23 }
24 
25 namespace {
26 
27 static size_t snd_mixer_open_called;
28 static int snd_mixer_open_return_value;
29 static size_t snd_mixer_close_called;
30 static size_t snd_mixer_attach_called;
31 static int snd_mixer_attach_return_value;
32 const char *snd_mixer_attach_mixdev;
33 static size_t snd_mixer_selem_register_called;
34 static int snd_mixer_selem_register_return_value;
35 static size_t snd_mixer_load_called;
36 static int snd_mixer_load_return_value;
37 static size_t snd_mixer_first_elem_called;
38 static snd_mixer_elem_t *snd_mixer_first_elem_return_value;
39 static int snd_mixer_elem_next_called;
40 static snd_mixer_elem_t **snd_mixer_elem_next_return_values;
41 static int snd_mixer_elem_next_return_values_index;
42 static int snd_mixer_elem_next_return_values_length;
43 static int snd_mixer_selem_set_playback_dB_all_called;
44 static long *snd_mixer_selem_set_playback_dB_all_values;
45 static int snd_mixer_selem_set_playback_dB_all_values_length;
46 static int snd_mixer_selem_set_playback_switch_all_called;
47 static int snd_mixer_selem_set_playback_switch_all_value;
48 static int snd_mixer_selem_has_playback_volume_called;
49 static int *snd_mixer_selem_has_playback_volume_return_values;
50 static int snd_mixer_selem_has_playback_volume_return_values_length;
51 static int snd_mixer_selem_has_playback_switch_called;
52 static int *snd_mixer_selem_has_playback_switch_return_values;
53 static int snd_mixer_selem_has_playback_switch_return_values_length;
54 static int snd_mixer_selem_set_capture_dB_all_called;
55 static long *snd_mixer_selem_set_capture_dB_all_values;
56 static int snd_mixer_selem_set_capture_dB_all_values_length;
57 static int snd_mixer_selem_set_capture_switch_all_called;
58 static int snd_mixer_selem_set_capture_switch_all_value;
59 static int snd_mixer_selem_has_capture_volume_called;
60 static int *snd_mixer_selem_has_capture_volume_return_values;
61 static int snd_mixer_selem_has_capture_volume_return_values_length;
62 static int snd_mixer_selem_has_capture_switch_called;
63 static int *snd_mixer_selem_has_capture_switch_return_values;
64 static int snd_mixer_selem_has_capture_switch_return_values_length;
65 static int snd_mixer_selem_get_name_called;
66 static const char **snd_mixer_selem_get_name_return_values;
67 static int snd_mixer_selem_get_name_return_values_length;
68 static int snd_mixer_selem_get_playback_dB_called;
69 static long *snd_mixer_selem_get_playback_dB_return_values;
70 static int snd_mixer_selem_get_playback_dB_return_values_length;
71 static int snd_mixer_selem_get_capture_dB_called;
72 static long *snd_mixer_selem_get_capture_dB_return_values;
73 static int snd_mixer_selem_get_capture_dB_return_values_length;
74 static size_t cras_volume_curve_destroy_called;
75 static size_t snd_mixer_selem_get_playback_dB_range_called;
76 static size_t snd_mixer_selem_get_playback_dB_range_values_length;
77 static const long *snd_mixer_selem_get_playback_dB_range_min_values;
78 static const long *snd_mixer_selem_get_playback_dB_range_max_values;
79 static size_t snd_mixer_selem_get_capture_dB_range_called;
80 static size_t snd_mixer_selem_get_capture_dB_range_values_length;
81 static const long *snd_mixer_selem_get_capture_dB_range_min_values;
82 static const long *snd_mixer_selem_get_capture_dB_range_max_values;
83 static size_t iniparser_getstring_return_index;
84 static size_t iniparser_getstring_return_length;
85 static char **iniparser_getstring_returns;
86 static size_t snd_mixer_find_selem_called;
87 static std::map<std::string, snd_mixer_elem_t*> snd_mixer_find_elem_map;
88 static std::string snd_mixer_find_elem_id_name;
89 
ResetStubData()90 static void ResetStubData() {
91   iniparser_getstring_return_index = 0;
92   iniparser_getstring_return_length = 0;
93   snd_mixer_open_called = 0;
94   snd_mixer_open_return_value = 0;
95   snd_mixer_close_called = 0;
96   snd_mixer_attach_called = 0;
97   snd_mixer_attach_return_value = 0;
98   snd_mixer_attach_mixdev = static_cast<const char *>(NULL);
99   snd_mixer_selem_register_called = 0;
100   snd_mixer_selem_register_return_value = 0;
101   snd_mixer_load_called = 0;
102   snd_mixer_load_return_value = 0;
103   snd_mixer_first_elem_called = 0;
104   snd_mixer_first_elem_return_value = static_cast<snd_mixer_elem_t *>(NULL);
105   snd_mixer_elem_next_called = 0;
106   snd_mixer_elem_next_return_values = static_cast<snd_mixer_elem_t **>(NULL);
107   snd_mixer_elem_next_return_values_index = 0;
108   snd_mixer_elem_next_return_values_length = 0;
109   snd_mixer_selem_set_playback_dB_all_called = 0;
110   snd_mixer_selem_set_playback_dB_all_values = static_cast<long *>(NULL);
111   snd_mixer_selem_set_playback_dB_all_values_length = 0;
112   snd_mixer_selem_set_playback_switch_all_called = 0;
113   snd_mixer_selem_has_playback_volume_called = 0;
114   snd_mixer_selem_has_playback_volume_return_values = static_cast<int *>(NULL);
115   snd_mixer_selem_has_playback_volume_return_values_length = 0;
116   snd_mixer_selem_has_playback_switch_called = 0;
117   snd_mixer_selem_has_playback_switch_return_values = static_cast<int *>(NULL);
118   snd_mixer_selem_has_playback_switch_return_values_length = 0;
119   snd_mixer_selem_set_capture_dB_all_called = 0;
120   snd_mixer_selem_set_capture_dB_all_values = static_cast<long *>(NULL);
121   snd_mixer_selem_set_capture_dB_all_values_length = 0;
122   snd_mixer_selem_set_capture_switch_all_called = 0;
123   snd_mixer_selem_has_capture_volume_called = 0;
124   snd_mixer_selem_has_capture_volume_return_values = static_cast<int *>(NULL);
125   snd_mixer_selem_has_capture_volume_return_values_length = 0;
126   snd_mixer_selem_has_capture_switch_called = 0;
127   snd_mixer_selem_has_capture_switch_return_values = static_cast<int *>(NULL);
128   snd_mixer_selem_has_capture_switch_return_values_length = 0;
129   snd_mixer_selem_get_name_called = 0;
130   snd_mixer_selem_get_name_return_values = static_cast<const char **>(NULL);
131   snd_mixer_selem_get_name_return_values_length = 0;
132   snd_mixer_selem_get_playback_dB_called = 0;
133   snd_mixer_selem_get_playback_dB_return_values = static_cast<long *>(NULL);
134   snd_mixer_selem_get_playback_dB_return_values_length = 0;
135   snd_mixer_selem_get_capture_dB_called = 0;
136   snd_mixer_selem_get_capture_dB_return_values = static_cast<long *>(NULL);
137   snd_mixer_selem_get_capture_dB_return_values_length = 0;
138   cras_volume_curve_destroy_called = 0;
139   snd_mixer_selem_get_playback_dB_range_called = 0;
140   snd_mixer_selem_get_playback_dB_range_values_length = 0;
141   snd_mixer_selem_get_playback_dB_range_min_values = static_cast<long *>(NULL);
142   snd_mixer_selem_get_playback_dB_range_max_values = static_cast<long *>(NULL);
143   snd_mixer_selem_get_capture_dB_range_called = 0;
144   snd_mixer_selem_get_capture_dB_range_values_length = 0;
145   snd_mixer_selem_get_capture_dB_range_min_values = static_cast<long *>(NULL);
146   snd_mixer_selem_get_capture_dB_range_max_values = static_cast<long *>(NULL);
147   snd_mixer_find_selem_called = 0;
148   snd_mixer_find_elem_map.clear();
149   snd_mixer_find_elem_id_name.clear();
150 }
151 
create_mixer_and_add_controls_by_name_matching(const char * card_name,struct mixer_name * extra_controls,struct mixer_name * coupled_controls)152 struct cras_alsa_mixer *create_mixer_and_add_controls_by_name_matching(
153     const char *card_name,
154     struct mixer_name *extra_controls,
155     struct mixer_name *coupled_controls) {
156   struct cras_alsa_mixer *cmix = cras_alsa_mixer_create(card_name);
157   cras_alsa_mixer_add_controls_by_name_matching(
158       cmix, extra_controls, coupled_controls);
159   return cmix;
160 }
161 
TEST(AlsaMixer,CreateFailOpen)162 TEST(AlsaMixer, CreateFailOpen) {
163   struct cras_alsa_mixer *c;
164 
165   ResetStubData();
166   snd_mixer_open_return_value = -1;
167   c = cras_alsa_mixer_create("hw:0");
168   EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
169   EXPECT_EQ(1, snd_mixer_open_called);
170   cras_alsa_mixer_destroy(c);
171 }
172 
TEST(AlsaMixer,CreateFailAttach)173 TEST(AlsaMixer, CreateFailAttach) {
174   struct cras_alsa_mixer *c;
175 
176   ResetStubData();
177   snd_mixer_attach_return_value = -1;
178   c = cras_alsa_mixer_create("hw:0");
179   EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
180   EXPECT_EQ(1, snd_mixer_open_called);
181   EXPECT_EQ(1, snd_mixer_attach_called);
182   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
183   EXPECT_EQ(1, snd_mixer_close_called);
184   cras_alsa_mixer_destroy(c);
185 }
186 
TEST(AlsaMixer,CreateFailSelemRegister)187 TEST(AlsaMixer, CreateFailSelemRegister) {
188   struct cras_alsa_mixer *c;
189 
190   ResetStubData();
191   snd_mixer_selem_register_return_value = -1;
192   c = cras_alsa_mixer_create("hw:0");
193   EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
194   EXPECT_EQ(1, snd_mixer_open_called);
195   EXPECT_EQ(1, snd_mixer_attach_called);
196   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
197   EXPECT_EQ(1, snd_mixer_selem_register_called);
198   EXPECT_EQ(1, snd_mixer_close_called);
199   cras_alsa_mixer_destroy(c);
200 }
201 
TEST(AlsaMixer,CreateFailLoad)202 TEST(AlsaMixer, CreateFailLoad) {
203   struct cras_alsa_mixer *c;
204 
205   ResetStubData();
206   snd_mixer_load_return_value = -1;
207   c = cras_alsa_mixer_create("hw:0");
208   EXPECT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
209   EXPECT_EQ(1, snd_mixer_open_called);
210   EXPECT_EQ(1, snd_mixer_attach_called);
211   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
212   EXPECT_EQ(1, snd_mixer_selem_register_called);
213   EXPECT_EQ(1, snd_mixer_load_called);
214   EXPECT_EQ(1, snd_mixer_close_called);
215   cras_alsa_mixer_destroy(c);
216 }
217 
TEST(AlsaMixer,CreateNoElements)218 TEST(AlsaMixer, CreateNoElements) {
219   struct cras_alsa_mixer *c;
220 
221   ResetStubData();
222   c = create_mixer_and_add_controls_by_name_matching(
223       "hw:0", NULL, NULL);
224   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
225   EXPECT_EQ(1, snd_mixer_open_called);
226   EXPECT_EQ(1, snd_mixer_attach_called);
227   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
228   EXPECT_EQ(1, snd_mixer_selem_register_called);
229   EXPECT_EQ(1, snd_mixer_load_called);
230   EXPECT_EQ(0, snd_mixer_close_called);
231 
232   /* set mute shouldn't call anything. */
233   cras_alsa_mixer_set_mute(c, 0, NULL);
234   EXPECT_EQ(0, snd_mixer_selem_set_playback_switch_all_called);
235   /* set volume shouldn't call anything. */
236   cras_alsa_mixer_set_dBFS(c, 0, NULL);
237   EXPECT_EQ(0, snd_mixer_selem_set_playback_dB_all_called);
238 
239   cras_alsa_mixer_destroy(c);
240   EXPECT_EQ(1, snd_mixer_close_called);
241 }
242 
TEST(AlsaMixer,CreateOneUnknownElementWithoutVolume)243 TEST(AlsaMixer, CreateOneUnknownElementWithoutVolume) {
244   struct cras_alsa_mixer *c;
245   int element_playback_volume[] = {
246     0,
247   };
248   int element_playback_switches[] = {
249     1,
250   };
251   const char *element_names[] = {
252     "Unknown",
253   };
254   struct mixer_control *mixer_output;
255   int rc;
256 
257   ResetStubData();
258   snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1);
259   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
260   snd_mixer_selem_has_playback_volume_return_values_length =
261       ARRAY_SIZE(element_playback_volume);
262   snd_mixer_selem_get_name_return_values = element_names;
263   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
264   c = create_mixer_and_add_controls_by_name_matching(
265       "hw:0", NULL, NULL);
266   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
267   EXPECT_EQ(1, snd_mixer_open_called);
268   EXPECT_EQ(1, snd_mixer_attach_called);
269   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
270   EXPECT_EQ(1, snd_mixer_selem_register_called);
271   EXPECT_EQ(1, snd_mixer_load_called);
272   EXPECT_EQ(0, snd_mixer_close_called);
273   EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called);
274   EXPECT_EQ(1, snd_mixer_selem_get_name_called);
275   EXPECT_EQ(0, snd_mixer_selem_get_playback_dB_range_called);
276 
277   /* set mute shouldn't call anything. */
278   cras_alsa_mixer_set_mute(c, 0, NULL);
279   EXPECT_EQ(0, snd_mixer_selem_set_playback_switch_all_called);
280 
281   ResetStubData();
282   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
283   snd_mixer_selem_has_playback_switch_return_values_length =
284       ARRAY_SIZE(element_playback_switches);
285   snd_mixer_selem_get_name_return_values = element_names;
286   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
287   rc = mixer_control_create(&mixer_output, NULL,
288                             reinterpret_cast<snd_mixer_elem_t *>(1),
289                             CRAS_STREAM_OUTPUT);
290   EXPECT_EQ(0, rc);
291   EXPECT_EQ(1, snd_mixer_selem_get_name_called);
292   EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called);
293   EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called);
294   EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called);
295 
296   /* if passed a mixer output then it should mute that. */
297   cras_alsa_mixer_set_mute(c, 0, mixer_output);
298   EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called);
299   /* set volume shouldn't call anything. */
300   cras_alsa_mixer_set_dBFS(c, 0, NULL);
301   EXPECT_EQ(0, snd_mixer_selem_set_playback_dB_all_called);
302 
303   cras_alsa_mixer_destroy(c);
304   EXPECT_EQ(1, snd_mixer_close_called);
305   mixer_control_destroy(mixer_output);
306 }
307 
TEST(AlsaMixer,CreateOneUnknownElementWithVolume)308 TEST(AlsaMixer, CreateOneUnknownElementWithVolume) {
309   struct cras_alsa_mixer *c;
310   static const long min_volumes[] = {-500};
311   static const long max_volumes[] = {40};
312   int element_playback_volume[] = {
313     1,
314     0,
315   };
316   int element_playback_switches[] = {
317     0,
318     1,
319   };
320   const char *element_names[] = {
321     "Unknown",
322     "Playback",
323   };
324   struct mixer_control *mixer_output;
325   int rc;
326 
327   ResetStubData();
328   snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1);
329   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
330   snd_mixer_selem_has_playback_volume_return_values_length =
331       ARRAY_SIZE(element_playback_volume);
332   snd_mixer_selem_get_name_return_values = element_names;
333   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
334   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
335   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
336   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
337   c = create_mixer_and_add_controls_by_name_matching(
338       "hw:0", NULL, NULL);
339   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
340   EXPECT_EQ(1, snd_mixer_open_called);
341   EXPECT_EQ(1, snd_mixer_attach_called);
342   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
343   EXPECT_EQ(1, snd_mixer_selem_register_called);
344   EXPECT_EQ(1, snd_mixer_load_called);
345   EXPECT_EQ(0, snd_mixer_close_called);
346   EXPECT_EQ(3, snd_mixer_selem_has_playback_volume_called);
347   EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_range_called);
348   EXPECT_EQ(3, snd_mixer_selem_get_name_called);
349 
350   /* Should use "Playback" since it has playback switch. */
351   cras_alsa_mixer_set_mute(c, 0, NULL);
352   EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called);
353 
354   ResetStubData();
355   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
356   snd_mixer_selem_has_playback_volume_return_values_length =
357       ARRAY_SIZE(element_playback_volume);
358   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
359   snd_mixer_selem_has_playback_switch_return_values_length =
360       ARRAY_SIZE(element_playback_switches);
361   snd_mixer_selem_get_name_return_values = element_names;
362   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
363   rc = mixer_control_create(&mixer_output, NULL,
364                             reinterpret_cast<snd_mixer_elem_t *>(2),
365                             CRAS_STREAM_OUTPUT);
366   EXPECT_EQ(0, rc);
367   EXPECT_EQ(1, snd_mixer_selem_get_name_called);
368   EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called);
369   EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called);
370   EXPECT_EQ(0, snd_mixer_selem_get_playback_dB_range_called);
371 
372   /*
373    * If passed a mixer output then it should mute both "Playback" and that
374    * mixer_output.
375    */
376   cras_alsa_mixer_set_mute(c, 0, mixer_output);
377   EXPECT_EQ(2, snd_mixer_selem_set_playback_switch_all_called);
378   cras_alsa_mixer_set_dBFS(c, 0, NULL);
379   EXPECT_EQ(1, snd_mixer_selem_set_playback_dB_all_called);
380 
381   cras_alsa_mixer_destroy(c);
382   EXPECT_EQ(1, snd_mixer_close_called);
383   mixer_control_destroy(mixer_output);
384 }
385 
TEST(AlsaMixer,CreateOneMasterElement)386 TEST(AlsaMixer, CreateOneMasterElement) {
387   struct cras_alsa_mixer *c;
388   int element_playback_volume[] = {
389     1,
390     1,
391   };
392   int element_playback_switches[] = {
393     1,
394     1,
395   };
396   const char *element_names[] = {
397     "Master",
398     "Playback"
399   };
400   struct mixer_control *mixer_output;
401   int rc;
402   long set_dB_values[3];
403   static const long min_volumes[] = {0, 0};
404   static const long max_volumes[] = {950, 950};
405 
406   ResetStubData();
407   snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1);
408   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
409   snd_mixer_selem_has_playback_volume_return_values_length =
410       ARRAY_SIZE(element_playback_volume);
411   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
412   snd_mixer_selem_has_playback_switch_return_values_length =
413       ARRAY_SIZE(element_playback_switches);
414   snd_mixer_selem_get_name_return_values = element_names;
415   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
416   c = create_mixer_and_add_controls_by_name_matching(
417       "hw:0", NULL, NULL);
418   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
419   EXPECT_EQ(1, snd_mixer_open_called);
420   EXPECT_EQ(1, snd_mixer_attach_called);
421   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
422   EXPECT_EQ(1, snd_mixer_selem_register_called);
423   EXPECT_EQ(1, snd_mixer_load_called);
424   EXPECT_EQ(0, snd_mixer_close_called);
425   EXPECT_EQ(3, snd_mixer_selem_get_name_called);
426   EXPECT_EQ(1, snd_mixer_elem_next_called);
427 
428   /* set mute should be called for Master. */
429   cras_alsa_mixer_set_mute(c, 0, NULL);
430   EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called);
431   /* set volume should be called for Master. */
432   cras_alsa_mixer_set_dBFS(c, 0, NULL);
433   EXPECT_EQ(1, snd_mixer_selem_set_playback_dB_all_called);
434 
435   ResetStubData();
436   snd_mixer_selem_set_playback_dB_all_values = set_dB_values;
437   snd_mixer_selem_set_playback_dB_all_values_length =
438       ARRAY_SIZE(set_dB_values);
439   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
440   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
441   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
442   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
443   snd_mixer_selem_has_playback_volume_return_values_length =
444       ARRAY_SIZE(element_playback_volume);
445   snd_mixer_selem_get_name_return_values = element_names;
446   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
447   rc = mixer_control_create(&mixer_output, NULL,
448                             reinterpret_cast<snd_mixer_elem_t *>(2),
449                             CRAS_STREAM_OUTPUT);
450   EXPECT_EQ(0, rc);
451   EXPECT_EQ(1, snd_mixer_selem_get_name_called);
452   EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called);
453   EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called);
454   EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called);
455 
456   /* if passed a mixer output then it should set the volume for that too. */
457   cras_alsa_mixer_set_dBFS(c, 0, mixer_output);
458   EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called);
459   EXPECT_EQ(950, set_dB_values[0]);
460   EXPECT_EQ(950, set_dB_values[1]);
461 
462   cras_alsa_mixer_destroy(c);
463   EXPECT_EQ(1, snd_mixer_close_called);
464   mixer_control_destroy(mixer_output);
465 }
466 
TEST(AlsaMixer,CreateTwoMainVolumeElements)467 TEST(AlsaMixer, CreateTwoMainVolumeElements) {
468   struct cras_alsa_mixer *c;
469   snd_mixer_elem_t *elements[] = {
470     reinterpret_cast<snd_mixer_elem_t *>(2),
471   };
472   int element_playback_volume[] = {
473     1,
474     1,
475     1,
476   };
477   int element_playback_switches[] = {
478     1,
479     1,
480     1,
481   };
482   const char *element_names[] = {
483     "Master",
484     "PCM",
485     "Other",
486   };
487   struct mixer_control *mixer_output;
488   int rc;
489   static const long min_volumes[] = {-500, -1250, -500};
490   static const long max_volumes[] = {40, 40, 0};
491   long get_dB_returns[] = {0, 0, 0};
492   long set_dB_values[3];
493 
494   ResetStubData();
495   snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1);
496   snd_mixer_elem_next_return_values = elements;
497   snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements);
498   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
499   snd_mixer_selem_has_playback_volume_return_values_length =
500       ARRAY_SIZE(element_playback_volume);
501   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
502   snd_mixer_selem_has_playback_switch_return_values_length =
503       ARRAY_SIZE(element_playback_switches);
504   snd_mixer_selem_get_name_return_values = element_names;
505   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
506   snd_mixer_selem_get_playback_dB_range_called = 0;
507   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
508   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
509   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
510   snd_mixer_selem_set_playback_dB_all_values = set_dB_values;
511   snd_mixer_selem_set_playback_dB_all_values_length =
512       ARRAY_SIZE(set_dB_values);
513   c = create_mixer_and_add_controls_by_name_matching(
514       "hw:0", NULL, NULL);
515   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
516   EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_range_called);
517   EXPECT_EQ(1, snd_mixer_open_called);
518   EXPECT_EQ(1, snd_mixer_attach_called);
519   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
520   EXPECT_EQ(1, snd_mixer_selem_register_called);
521   EXPECT_EQ(1, snd_mixer_load_called);
522   EXPECT_EQ(0, snd_mixer_close_called);
523   EXPECT_EQ(2, snd_mixer_elem_next_called);
524   EXPECT_EQ(5, snd_mixer_selem_get_name_called);
525   EXPECT_EQ(3, snd_mixer_selem_has_playback_switch_called);
526 
527   /* Set mute should be called for Master only. */
528   cras_alsa_mixer_set_mute(c, 0, NULL);
529   EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called);
530 
531   /* Set volume should be called for Master and PCM. If Master doesn't set to
532    * anything but zero then the entire volume should be passed to the PCM
533    * control.*/
534 
535   /* Set volume should be called for Master and PCM. (without mixer_output) */
536   snd_mixer_selem_get_playback_dB_return_values = get_dB_returns;
537   snd_mixer_selem_get_playback_dB_return_values_length =
538       ARRAY_SIZE(get_dB_returns);
539   cras_alsa_mixer_set_dBFS(c, -50, NULL);
540   EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called);
541   EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called);
542   /* volume should be set relative to max volume (40 + 40). */
543   EXPECT_EQ(30, set_dB_values[0]);
544   EXPECT_EQ(30, set_dB_values[1]);
545 
546   ResetStubData();
547   snd_mixer_selem_set_playback_dB_all_values = set_dB_values;
548   snd_mixer_selem_set_playback_dB_all_values_length = ARRAY_SIZE(set_dB_values);
549   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
550   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
551   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
552   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
553   snd_mixer_selem_has_playback_volume_return_values_length =
554       ARRAY_SIZE(element_playback_volume);
555   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
556   snd_mixer_selem_has_playback_switch_return_values_length =
557       ARRAY_SIZE(element_playback_switches);
558   snd_mixer_selem_get_name_return_values = element_names;
559   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
560   rc = mixer_control_create(&mixer_output, NULL,
561                             reinterpret_cast<snd_mixer_elem_t *>(3),
562                             CRAS_STREAM_OUTPUT);
563   EXPECT_EQ(0, rc);
564   EXPECT_EQ(1, snd_mixer_selem_get_name_called);
565   EXPECT_EQ(1, snd_mixer_selem_has_playback_volume_called);
566   EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called);
567   EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called);
568 
569   /* Set volume should be called for Master, PCM, and the mixer_output passed
570    * in. If Master doesn't set to anything but zero then the entire volume
571    * should be passed to the PCM control.*/
572   cras_alsa_mixer_set_dBFS(c, -50, mixer_output);
573   EXPECT_EQ(3, snd_mixer_selem_set_playback_dB_all_called);
574   EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called);
575   EXPECT_EQ(30, set_dB_values[0]);
576   EXPECT_EQ(30, set_dB_values[1]);
577   EXPECT_EQ(30, set_dB_values[2]);
578   /* Set volume should be called for Master and PCM. Since the controls were
579    * sorted, Master should get the volume remaining after PCM is set, in this
580    * case -50 - -24 = -26. */
581   long get_dB_returns2[] = {
582     -25,
583     -24,
584   };
585   snd_mixer_selem_get_playback_dB_return_values = get_dB_returns2;
586   snd_mixer_selem_get_playback_dB_return_values_length =
587       ARRAY_SIZE(get_dB_returns2);
588   snd_mixer_selem_set_playback_dB_all_called = 0;
589   snd_mixer_selem_get_playback_dB_called = 0;
590   mixer_output->has_volume = 0;
591   mixer_output->min_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID;
592   mixer_output->max_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID;
593   cras_alsa_mixer_set_dBFS(c, -50, mixer_output);
594   EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called);
595   EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called);
596   EXPECT_EQ(54, set_dB_values[0]); // Master
597   EXPECT_EQ(30, set_dB_values[1]); // PCM
598 
599   cras_alsa_mixer_destroy(c);
600   EXPECT_EQ(1, snd_mixer_close_called);
601   mixer_control_destroy(mixer_output);
602 }
603 
TEST(AlsaMixer,CreateTwoMainCaptureElements)604 TEST(AlsaMixer, CreateTwoMainCaptureElements) {
605   struct cras_alsa_mixer *c;
606   snd_mixer_elem_t *elements[] = {
607     reinterpret_cast<snd_mixer_elem_t *>(2),
608   };
609   int element_capture_volume[] = {
610     1,
611     1,
612     1,
613   };
614   int element_capture_switches[] = {
615     1,
616     1,
617     1,
618   };
619   const char *element_names[] = {
620     "Capture",
621     "Digital Capture",
622     "Mic",
623   };
624   struct mixer_control *mixer_input;
625   int rc;
626 
627   ResetStubData();
628   snd_mixer_first_elem_return_value = reinterpret_cast<snd_mixer_elem_t *>(1);
629   snd_mixer_elem_next_return_values = elements;
630   snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements);
631   snd_mixer_selem_has_capture_volume_return_values = element_capture_volume;
632   snd_mixer_selem_has_capture_volume_return_values_length =
633       ARRAY_SIZE(element_capture_volume);
634   snd_mixer_selem_has_capture_switch_return_values = element_capture_switches;
635   snd_mixer_selem_has_capture_switch_return_values_length =
636       ARRAY_SIZE(element_capture_switches);
637   snd_mixer_selem_get_name_return_values = element_names;
638   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
639   c = create_mixer_and_add_controls_by_name_matching(
640       "hw:0", NULL, NULL);
641   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
642   EXPECT_EQ(1, snd_mixer_open_called);
643   EXPECT_EQ(1, snd_mixer_attach_called);
644   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
645   EXPECT_EQ(1, snd_mixer_selem_register_called);
646   EXPECT_EQ(1, snd_mixer_load_called);
647   EXPECT_EQ(0, snd_mixer_close_called);
648   EXPECT_EQ(2, snd_mixer_elem_next_called);
649   EXPECT_EQ(5, snd_mixer_selem_get_name_called);
650   EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called);
651 
652   /* Set mute should be called for Master only. */
653   cras_alsa_mixer_set_capture_mute(c, 0, NULL);
654   EXPECT_EQ(1, snd_mixer_selem_set_capture_switch_all_called);
655   /* Set volume should be called for Capture and Digital Capture. If Capture
656    * doesn't set to anything but zero then the entire volume should be passed to
657    * the Digital Capture control. */
658   long get_dB_returns[] = {
659     0,
660     0,
661   };
662   long set_dB_values[2];
663   snd_mixer_selem_get_capture_dB_return_values = get_dB_returns;
664   snd_mixer_selem_get_capture_dB_return_values_length =
665       ARRAY_SIZE(get_dB_returns);
666   snd_mixer_selem_set_capture_dB_all_values = set_dB_values;
667   snd_mixer_selem_set_capture_dB_all_values_length =
668       ARRAY_SIZE(set_dB_values);
669   cras_alsa_mixer_set_capture_dBFS(c, -10, NULL);
670   EXPECT_EQ(2, snd_mixer_selem_set_capture_dB_all_called);
671   EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_called);
672   EXPECT_EQ(-10, set_dB_values[0]);
673   EXPECT_EQ(-10, set_dB_values[1]);
674   /* Set volume should be called for Capture and Digital Capture. Capture should
675    * get the gain remaining after Mic Boos is set, in this case 20 - 25 = -5. */
676   long get_dB_returns2[] = {
677     25,
678     -5,
679   };
680   snd_mixer_selem_get_capture_dB_return_values = get_dB_returns2;
681   snd_mixer_selem_get_capture_dB_return_values_length =
682       ARRAY_SIZE(get_dB_returns2);
683   snd_mixer_selem_set_capture_dB_all_values = set_dB_values;
684   snd_mixer_selem_set_capture_dB_all_values_length =
685       ARRAY_SIZE(set_dB_values);
686   snd_mixer_selem_set_capture_dB_all_called = 0;
687   snd_mixer_selem_get_capture_dB_called = 0;
688   cras_alsa_mixer_set_capture_dBFS(c, 20, NULL);
689   EXPECT_EQ(2, snd_mixer_selem_set_capture_dB_all_called);
690   EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_called);
691   EXPECT_EQ(20, set_dB_values[0]);
692   EXPECT_EQ(-5, set_dB_values[1]);
693 
694   /* Set volume to the two main controls plus additional specific input
695    * volume control */
696 
697   long get_dB_returns3[] = {
698     0,
699     0,
700     0,
701   };
702   long set_dB_values3[3];
703 
704   snd_mixer_selem_get_capture_dB_return_values = get_dB_returns3;
705   snd_mixer_selem_get_capture_dB_return_values_length =
706       ARRAY_SIZE(get_dB_returns3);
707   snd_mixer_selem_get_capture_dB_called = 0;
708   snd_mixer_selem_set_capture_dB_all_values = set_dB_values3;
709   snd_mixer_selem_set_capture_dB_all_values_length =
710       ARRAY_SIZE(set_dB_values3);
711   snd_mixer_selem_set_capture_dB_all_called = 0;
712   snd_mixer_selem_has_capture_volume_return_values = element_capture_volume;
713   snd_mixer_selem_has_capture_volume_return_values_length =
714       ARRAY_SIZE(element_capture_volume);
715   snd_mixer_selem_has_capture_switch_return_values = element_capture_switches;
716   snd_mixer_selem_has_capture_switch_return_values_length =
717       ARRAY_SIZE(element_capture_switches);
718   snd_mixer_selem_get_name_return_values = element_names;
719   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
720   snd_mixer_selem_get_name_called = 0;
721   snd_mixer_selem_has_capture_volume_called = 0;
722   snd_mixer_selem_has_capture_switch_called = 0;
723   snd_mixer_selem_get_capture_dB_range_called = 0;
724   rc = mixer_control_create(&mixer_input, NULL,
725                             reinterpret_cast<snd_mixer_elem_t *>(3),
726                             CRAS_STREAM_INPUT);
727   EXPECT_EQ(0, rc);
728   EXPECT_EQ(1, snd_mixer_selem_get_name_called);
729   EXPECT_EQ(1, snd_mixer_selem_has_capture_volume_called);
730   EXPECT_EQ(1, snd_mixer_selem_has_capture_switch_called);
731   EXPECT_EQ(1, snd_mixer_selem_get_capture_dB_range_called);
732   EXPECT_EQ(1, mixer_input->has_volume);
733 
734   cras_alsa_mixer_set_capture_dBFS(c, 20, mixer_input);
735 
736   EXPECT_EQ(3, snd_mixer_selem_set_capture_dB_all_called);
737   EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_called);
738   EXPECT_EQ(20, set_dB_values3[0]);
739   EXPECT_EQ(20, set_dB_values3[1]);
740   EXPECT_EQ(20, set_dB_values3[2]);
741 
742   cras_alsa_mixer_destroy(c);
743   EXPECT_EQ(1, snd_mixer_close_called);
744   mixer_control_destroy(mixer_input);
745 }
746 
747 class AlsaMixerOutputs : public testing::Test {
748  protected:
SetUp()749   virtual void SetUp() {
750     output_called_values_.clear();
751     output_callback_called_ = 0;
752     static snd_mixer_elem_t *elements[] = {
753       reinterpret_cast<snd_mixer_elem_t *>(2),  // PCM
754       reinterpret_cast<snd_mixer_elem_t *>(3),  // Headphone
755       reinterpret_cast<snd_mixer_elem_t *>(4),  // Speaker
756       reinterpret_cast<snd_mixer_elem_t *>(5),  // HDMI
757       reinterpret_cast<snd_mixer_elem_t *>(6),  // IEC958
758       reinterpret_cast<snd_mixer_elem_t *>(7),  // Mic Boost
759       reinterpret_cast<snd_mixer_elem_t *>(8),  // Capture
760     };
761     static int element_playback_volume[] = {
762       1,
763       1,
764       1,
765       0,
766       0,
767       1,
768       1,
769     };
770     static int element_playback_switches[] = {
771       1,
772       1,
773       1,
774       0,
775       1,
776       1,
777       1,
778     };
779     static int element_capture_volume[] = {0, 0, 0, 0, 0, 0,
780       1,
781       1,
782     };
783     static int element_capture_switches[] = {0, 0, 0, 0, 0, 0,
784       1,
785       1,
786     };
787     static const long min_volumes[] = {0, 0, 0, 0, 0, 0, 500, -1250};
788     static const long max_volumes[] = {0, 0, 0, 0, 0, 0, 3000, 400};
789     static const char *element_names[] = {
790       "Master",
791       "PCM",
792       "Headphone",
793       "Speaker",
794       "HDMI",
795       "IEC958",
796       "Capture",
797       "Digital Capture",
798     };
799     static const char *output_names_extra[] = {
800       "IEC958"
801     };
802     static char *iniparser_returns[] = {
803       NULL,
804     };
805     struct mixer_name *extra_controls =
806         mixer_name_add_array(NULL, output_names_extra,
807                              ARRAY_SIZE(output_names_extra),
808                              CRAS_STREAM_OUTPUT,
809                              MIXER_NAME_VOLUME);
810 
811     ResetStubData();
812     snd_mixer_first_elem_return_value =
813         reinterpret_cast<snd_mixer_elem_t *>(1);  // Master
814     snd_mixer_elem_next_return_values = elements;
815     snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements);
816     snd_mixer_selem_has_playback_volume_return_values =
817         element_playback_volume;
818     snd_mixer_selem_has_playback_volume_return_values_length =
819       ARRAY_SIZE(element_playback_volume);
820     snd_mixer_selem_has_playback_switch_return_values =
821         element_playback_switches;
822     snd_mixer_selem_has_playback_switch_return_values_length =
823       ARRAY_SIZE(element_playback_switches);
824     snd_mixer_selem_has_capture_volume_return_values =
825         element_capture_volume;
826     snd_mixer_selem_has_capture_volume_return_values_length =
827       ARRAY_SIZE(element_capture_volume);
828     snd_mixer_selem_has_capture_switch_return_values =
829         element_capture_switches;
830     snd_mixer_selem_has_capture_switch_return_values_length =
831       ARRAY_SIZE(element_capture_switches);
832     snd_mixer_selem_get_name_return_values = element_names;
833     snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
834     snd_mixer_selem_get_capture_dB_range_called = 0;
835     snd_mixer_selem_get_capture_dB_range_min_values = min_volumes;
836     snd_mixer_selem_get_capture_dB_range_max_values = max_volumes;
837     snd_mixer_selem_get_capture_dB_range_values_length =
838         ARRAY_SIZE(min_volumes);
839     iniparser_getstring_returns = iniparser_returns;
840     iniparser_getstring_return_length = ARRAY_SIZE(iniparser_returns);
841     cras_mixer_ = create_mixer_and_add_controls_by_name_matching(
842         "hw:0", extra_controls, NULL);
843     ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), cras_mixer_);
844     EXPECT_EQ(1, snd_mixer_open_called);
845     EXPECT_EQ(1, snd_mixer_attach_called);
846     EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
847     EXPECT_EQ(1, snd_mixer_selem_register_called);
848     EXPECT_EQ(1, snd_mixer_load_called);
849     EXPECT_EQ(0, snd_mixer_close_called);
850     EXPECT_EQ(ARRAY_SIZE(elements) + 1, snd_mixer_elem_next_called);
851     EXPECT_EQ(8, snd_mixer_selem_has_playback_volume_called);
852     EXPECT_EQ(7, snd_mixer_selem_has_playback_switch_called);
853     EXPECT_EQ(4, snd_mixer_selem_has_capture_volume_called);
854     EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called);
855     mixer_name_free(extra_controls);
856   }
857 
TearDown()858   virtual void TearDown() {
859     cras_alsa_mixer_destroy(cras_mixer_);
860     EXPECT_EQ(1, snd_mixer_close_called);
861   }
862 
OutputCallback(struct mixer_control * out,void * arg)863   static void OutputCallback(struct mixer_control *out, void *arg) {
864     output_callback_called_++;
865     output_called_values_.push_back(out);
866   }
867 
868   struct cras_alsa_mixer *cras_mixer_;
869   static size_t output_callback_called_;
870   static std::vector<struct mixer_control *> output_called_values_;
871 };
872 
873 size_t AlsaMixerOutputs::output_callback_called_;
874 std::vector<struct mixer_control *>
875     AlsaMixerOutputs::output_called_values_;
876 
TEST_F(AlsaMixerOutputs,CheckFourOutputs)877 TEST_F(AlsaMixerOutputs, CheckFourOutputs) {
878   cras_alsa_mixer_list_outputs(cras_mixer_,
879                                AlsaMixerOutputs::OutputCallback,
880                                reinterpret_cast<void*>(555));
881   EXPECT_EQ(4, output_callback_called_);
882 }
883 
TEST_F(AlsaMixerOutputs,CheckFindOutputByNameNoMatch)884 TEST_F(AlsaMixerOutputs, CheckFindOutputByNameNoMatch) {
885   struct mixer_control *out;
886 
887   out = cras_alsa_mixer_get_output_matching_name(cras_mixer_,
888                                                  "AAAAA Jack");
889   EXPECT_EQ(static_cast<struct mixer_control *>(NULL), out);
890 }
891 
TEST_F(AlsaMixerOutputs,CheckFindOutputByName)892 TEST_F(AlsaMixerOutputs, CheckFindOutputByName) {
893   struct mixer_control *out;
894 
895   out = cras_alsa_mixer_get_output_matching_name(cras_mixer_,
896                                                  "Headphone Jack");
897   EXPECT_NE(static_cast<struct mixer_control *>(NULL), out);
898 }
899 
TEST_F(AlsaMixerOutputs,CheckFindOutputHDMIByName)900 TEST_F(AlsaMixerOutputs, CheckFindOutputHDMIByName) {
901   struct mixer_control *out;
902 
903   out = cras_alsa_mixer_get_output_matching_name(cras_mixer_,
904                                                  "HDMI Jack");
905   EXPECT_NE(static_cast<struct mixer_control *>(NULL), out);
906 }
907 
TEST_F(AlsaMixerOutputs,CheckFindInputNameWorkaround)908 TEST_F(AlsaMixerOutputs, CheckFindInputNameWorkaround) {
909   struct mixer_control *control;
910   snd_mixer_elem_t *elements[] = {
911     reinterpret_cast<snd_mixer_elem_t *>(1),  // Speaker
912     reinterpret_cast<snd_mixer_elem_t *>(2),  // Headphone
913     reinterpret_cast<snd_mixer_elem_t *>(3),  // MIC
914   };
915   const char *element_names[] = {
916     "Speaker",
917     "Headphone",
918     "MIC",
919   };
920   size_t i;
921 
922   ResetStubData();
923   for (i = 0; i < ARRAY_SIZE(elements); i++)
924     snd_mixer_find_elem_map[element_names[i]] = elements[i];
925 
926   snd_mixer_selem_get_name_called = 0;
927   snd_mixer_selem_get_name_return_values = element_names;
928   snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
929   control = cras_alsa_mixer_get_input_matching_name(cras_mixer_,
930                                                     "MIC");
931   EXPECT_NE(static_cast<struct mixer_control *>(NULL), control);
932   /* This exercises the 'workaround' where the control is added if it was
933    * previouly missing in cras_alsa_mixer_get_input_matching_name().
934    * snd_mixer_find_selem is called once for the missing control. */
935   EXPECT_EQ(1, snd_mixer_find_selem_called);
936   EXPECT_EQ(1, snd_mixer_selem_has_capture_volume_called);
937   EXPECT_EQ(1, snd_mixer_selem_has_capture_switch_called);
938 }
939 
TEST_F(AlsaMixerOutputs,ActivateDeactivate)940 TEST_F(AlsaMixerOutputs, ActivateDeactivate) {
941   int rc;
942 
943   cras_alsa_mixer_list_outputs(cras_mixer_,
944                                AlsaMixerOutputs::OutputCallback,
945                                reinterpret_cast<void*>(555));
946   EXPECT_EQ(4, output_callback_called_);
947   EXPECT_EQ(4, output_called_values_.size());
948 
949   rc = cras_alsa_mixer_set_output_active_state(output_called_values_[0], 0);
950   ASSERT_EQ(0, rc);
951   EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called);
952   cras_alsa_mixer_set_output_active_state(output_called_values_[0], 1);
953   EXPECT_EQ(2, snd_mixer_selem_set_playback_switch_all_called);
954 }
955 
TEST_F(AlsaMixerOutputs,MinMaxCaptureGain)956 TEST_F(AlsaMixerOutputs, MinMaxCaptureGain) {
957   long min, max;
958   min = cras_alsa_mixer_get_minimum_capture_gain(cras_mixer_,
959 		  NULL);
960   EXPECT_EQ(-750, min);
961   max = cras_alsa_mixer_get_maximum_capture_gain(cras_mixer_,
962 		  NULL);
963   EXPECT_EQ(3400, max);
964 }
965 
TEST_F(AlsaMixerOutputs,MinMaxCaptureGainWithActiveInput)966 TEST_F(AlsaMixerOutputs, MinMaxCaptureGainWithActiveInput) {
967   struct mixer_control *mixer_input;
968   long min, max;
969 
970   mixer_input = (struct mixer_control *)calloc(1, sizeof(*mixer_input));
971   mixer_input->min_volume_dB = 50;
972   mixer_input->max_volume_dB = 60;
973   mixer_input->has_volume = 1;
974   min = cras_alsa_mixer_get_minimum_capture_gain(cras_mixer_, mixer_input);
975   max = cras_alsa_mixer_get_maximum_capture_gain(cras_mixer_, mixer_input);
976   EXPECT_EQ(-700, min);
977   EXPECT_EQ(3460, max);
978 
979   free((void *)mixer_input);
980 }
981 
TEST(AlsaMixer,CreateWithCoupledOutputControls)982 TEST(AlsaMixer, CreateWithCoupledOutputControls) {
983   struct cras_alsa_mixer *c;
984   struct mixer_control *output_control;
985   struct mixer_control_element *c1, *c2, *c3, *c4;
986 
987   static const long min_volumes[] = {-70, -70};
988   static const long max_volumes[] = {30, 30};
989 
990   long set_dB_values[2];
991 
992   const char *coupled_output_names[] = {"Left Master",
993                                         "Right Master",
994                                         "Left Speaker",
995                                         "Right Speaker"};
996   struct mixer_name *coupled_controls =
997       mixer_name_add_array(NULL, coupled_output_names,
998                            ARRAY_SIZE(coupled_output_names),
999                            CRAS_STREAM_OUTPUT,
1000                            MIXER_NAME_VOLUME);
1001   int element_playback_volume[] = {1, 1, 0, 0};
1002   int element_playback_switches[] = {0, 0, 1, 1};
1003 
1004   long target_dBFS = -30;
1005   long expected_dB_value = target_dBFS + max_volumes[0];
1006 
1007   ResetStubData();
1008 
1009   snd_mixer_find_elem_map[std::string("Left Master")] =
1010       reinterpret_cast<snd_mixer_elem_t *>(1);
1011   snd_mixer_find_elem_map[std::string("Right Master")] =
1012       reinterpret_cast<snd_mixer_elem_t *>(2);
1013   snd_mixer_find_elem_map[std::string("Left Speaker")] =
1014       reinterpret_cast<snd_mixer_elem_t *>(3);
1015   snd_mixer_find_elem_map[std::string("Right Speaker")] =
1016       reinterpret_cast<snd_mixer_elem_t *>(4);
1017 
1018   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
1019   snd_mixer_selem_has_playback_volume_return_values_length =
1020       ARRAY_SIZE(element_playback_volume);
1021   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
1022   snd_mixer_selem_has_playback_switch_return_values_length =
1023       ARRAY_SIZE(element_playback_switches);
1024 
1025   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
1026   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
1027   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
1028 
1029   c = create_mixer_and_add_controls_by_name_matching(
1030       "hw:0", NULL, coupled_controls);
1031 
1032   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
1033   EXPECT_EQ(1, snd_mixer_open_called);
1034   EXPECT_EQ(1, snd_mixer_attach_called);
1035   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
1036   EXPECT_EQ(1, snd_mixer_selem_register_called);
1037   EXPECT_EQ(1, snd_mixer_load_called);
1038   EXPECT_EQ(0, snd_mixer_close_called);
1039 
1040   output_control = c->output_controls;
1041   EXPECT_EQ(NULL, output_control->next);
1042   c1 = output_control->elements;
1043   c2 = c1->next;
1044   c3 = c2->next;
1045   c4 = c3->next;
1046   EXPECT_EQ(c1->elem, reinterpret_cast<snd_mixer_elem_t *>(1));
1047   EXPECT_EQ(c2->elem, reinterpret_cast<snd_mixer_elem_t *>(2));
1048   EXPECT_EQ(c3->elem, reinterpret_cast<snd_mixer_elem_t *>(3));
1049   EXPECT_EQ(c4->elem, reinterpret_cast<snd_mixer_elem_t *>(4));
1050   EXPECT_EQ(c4->next, reinterpret_cast<mixer_control_element *>(NULL));
1051   EXPECT_EQ(c1->has_volume, 1);
1052   EXPECT_EQ(c1->has_mute, 0);
1053   EXPECT_EQ(c2->has_volume, 1);
1054   EXPECT_EQ(c2->has_mute, 0);
1055   EXPECT_EQ(c3->has_volume, 0);
1056   EXPECT_EQ(c3->has_mute, 1);
1057   EXPECT_EQ(c4->has_volume, 0);
1058   EXPECT_EQ(c4->has_mute, 1);
1059   EXPECT_EQ(output_control->max_volume_dB, max_volumes[0]);
1060   EXPECT_EQ(output_control->min_volume_dB, min_volumes[0]);
1061 
1062   snd_mixer_selem_set_playback_dB_all_values = set_dB_values;
1063   snd_mixer_selem_set_playback_dB_all_values_length =
1064       ARRAY_SIZE(set_dB_values);
1065 
1066   cras_alsa_mixer_set_dBFS(c, target_dBFS, output_control);
1067 
1068   /* Set volume should set playback dB on two of the coupled controls. */
1069   EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called);
1070   EXPECT_EQ(set_dB_values[0], expected_dB_value);
1071   EXPECT_EQ(set_dB_values[1], expected_dB_value);
1072 
1073   /* Mute should set playback switch on two of the coupled controls. */
1074   cras_alsa_mixer_set_mute(c, 1, output_control);
1075   EXPECT_EQ(2, snd_mixer_selem_set_playback_switch_all_called);
1076   EXPECT_EQ(0, snd_mixer_selem_set_playback_switch_all_value);
1077 
1078   /* Unmute should set playback switch on two of the coupled controls. */
1079   cras_alsa_mixer_set_mute(c, 0, output_control);
1080   EXPECT_EQ(4, snd_mixer_selem_set_playback_switch_all_called);
1081   EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_value);
1082 
1083   EXPECT_EQ(max_volumes[0] - min_volumes[0],
1084             cras_alsa_mixer_get_output_dB_range(output_control));
1085 
1086   cras_alsa_mixer_destroy(c);
1087   EXPECT_EQ(1, snd_mixer_close_called);
1088   mixer_name_free(coupled_controls);
1089 }
1090 
TEST(AlsaMixer,CoupledOutputHasMuteNoVolume)1091 TEST(AlsaMixer, CoupledOutputHasMuteNoVolume) {
1092   struct cras_alsa_mixer *c;
1093   struct mixer_control *output_control;
1094   struct mixer_control_element *c1, *c2, *c3, *c4;
1095 
1096   static const long min_volumes[] = {-70};
1097   static const long max_volumes[] = {30};
1098 
1099   const char *coupled_output_names[] = {"Left Master",
1100                                         "Right Master",
1101                                         "Left Speaker",
1102                                         "Right Speaker"};
1103   struct mixer_name *coupled_controls =
1104       mixer_name_add_array(NULL, coupled_output_names,
1105                            ARRAY_SIZE(coupled_output_names),
1106                            CRAS_STREAM_OUTPUT,
1107                            MIXER_NAME_VOLUME);
1108   int element_playback_volume[] = {0, 0, 0, 0};
1109   int element_playback_switches[] = {0, 0, 1, 1};
1110 
1111   ResetStubData();
1112 
1113   snd_mixer_find_elem_map[std::string("Left Master")] =
1114       reinterpret_cast<snd_mixer_elem_t *>(1);
1115   snd_mixer_find_elem_map[std::string("Right Master")] =
1116       reinterpret_cast<snd_mixer_elem_t *>(2);
1117   snd_mixer_find_elem_map[std::string("Left Speaker")] =
1118       reinterpret_cast<snd_mixer_elem_t *>(3);
1119   snd_mixer_find_elem_map[std::string("Right Speaker")] =
1120       reinterpret_cast<snd_mixer_elem_t *>(4);
1121 
1122   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
1123   snd_mixer_selem_has_playback_volume_return_values_length =
1124       ARRAY_SIZE(element_playback_volume);
1125   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
1126   snd_mixer_selem_has_playback_switch_return_values_length =
1127       ARRAY_SIZE(element_playback_switches);
1128 
1129   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
1130   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
1131   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
1132 
1133   c = create_mixer_and_add_controls_by_name_matching(
1134       "hw:0", NULL, coupled_controls);
1135 
1136   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
1137   EXPECT_EQ(1, snd_mixer_open_called);
1138   EXPECT_EQ(1, snd_mixer_attach_called);
1139   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
1140   EXPECT_EQ(1, snd_mixer_selem_register_called);
1141   EXPECT_EQ(1, snd_mixer_load_called);
1142   EXPECT_EQ(0, snd_mixer_close_called);
1143 
1144   output_control = c->output_controls;
1145   EXPECT_EQ(NULL, output_control->next);
1146   c1 = output_control->elements;
1147   c2 = c1->next;
1148   c3 = c2->next;
1149   c4 = c3->next;
1150   EXPECT_EQ(c1->elem, reinterpret_cast<snd_mixer_elem_t *>(1));
1151   EXPECT_EQ(c2->elem, reinterpret_cast<snd_mixer_elem_t *>(2));
1152   EXPECT_EQ(c3->elem, reinterpret_cast<snd_mixer_elem_t *>(3));
1153   EXPECT_EQ(c4->elem, reinterpret_cast<snd_mixer_elem_t *>(4));
1154   EXPECT_EQ(c4->next, reinterpret_cast<mixer_control_element *>(NULL));
1155   EXPECT_EQ(c1->has_volume, 0);
1156   EXPECT_EQ(c1->has_mute, 0);
1157   EXPECT_EQ(c2->has_volume, 0);
1158   EXPECT_EQ(c2->has_mute, 0);
1159   EXPECT_EQ(c3->has_volume, 0);
1160   EXPECT_EQ(c3->has_mute, 1);
1161   EXPECT_EQ(c4->has_volume, 0);
1162   EXPECT_EQ(c4->has_mute, 1);
1163 
1164   EXPECT_EQ(0, cras_alsa_mixer_has_volume(output_control));
1165   EXPECT_EQ(1, output_control->has_mute);
1166 
1167   cras_alsa_mixer_destroy(c);
1168   EXPECT_EQ(1, snd_mixer_close_called);
1169   mixer_name_free(coupled_controls);
1170 }
1171 
TEST(AlsaMixer,CoupledOutputHasVolumeNoMute)1172 TEST(AlsaMixer, CoupledOutputHasVolumeNoMute) {
1173   struct cras_alsa_mixer *c;
1174   struct mixer_control *output_control;
1175   struct mixer_control_element *c1, *c2, *c3, *c4;
1176 
1177   static const long min_volumes[] = {-70, -70};
1178   static const long max_volumes[] = {30, 30};
1179 
1180   const char *coupled_output_names[] = {"Left Master",
1181                                         "Right Master",
1182                                         "Left Speaker",
1183                                         "Right Speaker"};
1184   struct mixer_name *coupled_controls =
1185       mixer_name_add_array(NULL, coupled_output_names,
1186                            ARRAY_SIZE(coupled_output_names),
1187                            CRAS_STREAM_OUTPUT,
1188                            MIXER_NAME_VOLUME);
1189   int element_playback_volume[] = {1, 1, 0, 0};
1190   int element_playback_switches[] = {0, 0, 0, 0};
1191 
1192   ResetStubData();
1193 
1194   snd_mixer_find_elem_map[std::string("Left Master")] =
1195       reinterpret_cast<snd_mixer_elem_t *>(1);
1196   snd_mixer_find_elem_map[std::string("Right Master")] =
1197       reinterpret_cast<snd_mixer_elem_t *>(2);
1198   snd_mixer_find_elem_map[std::string("Left Speaker")] =
1199       reinterpret_cast<snd_mixer_elem_t *>(3);
1200   snd_mixer_find_elem_map[std::string("Right Speaker")] =
1201       reinterpret_cast<snd_mixer_elem_t *>(4);
1202 
1203   snd_mixer_selem_has_playback_volume_return_values = element_playback_volume;
1204   snd_mixer_selem_has_playback_volume_return_values_length =
1205       ARRAY_SIZE(element_playback_volume);
1206   snd_mixer_selem_has_playback_switch_return_values = element_playback_switches;
1207   snd_mixer_selem_has_playback_switch_return_values_length =
1208       ARRAY_SIZE(element_playback_switches);
1209 
1210   snd_mixer_selem_get_playback_dB_range_min_values = min_volumes;
1211   snd_mixer_selem_get_playback_dB_range_max_values = max_volumes;
1212   snd_mixer_selem_get_playback_dB_range_values_length = ARRAY_SIZE(min_volumes);
1213 
1214   c = create_mixer_and_add_controls_by_name_matching(
1215       "hw:0", NULL, coupled_controls);
1216 
1217   ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), c);
1218   EXPECT_EQ(1, snd_mixer_open_called);
1219   EXPECT_EQ(1, snd_mixer_attach_called);
1220   EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
1221   EXPECT_EQ(1, snd_mixer_selem_register_called);
1222   EXPECT_EQ(1, snd_mixer_load_called);
1223   EXPECT_EQ(0, snd_mixer_close_called);
1224 
1225   output_control = c->output_controls;
1226   EXPECT_EQ(NULL, output_control->next);
1227   c1 = output_control->elements;
1228   c2 = c1->next;
1229   c3 = c2->next;
1230   c4 = c3->next;
1231   EXPECT_EQ(c1->elem, reinterpret_cast<snd_mixer_elem_t *>(1));
1232   EXPECT_EQ(c2->elem, reinterpret_cast<snd_mixer_elem_t *>(2));
1233   EXPECT_EQ(c3->elem, reinterpret_cast<snd_mixer_elem_t *>(3));
1234   EXPECT_EQ(c4->elem, reinterpret_cast<snd_mixer_elem_t *>(4));
1235   EXPECT_EQ(c4->next, reinterpret_cast<mixer_control_element *>(NULL));
1236   EXPECT_EQ(c1->has_volume, 1);
1237   EXPECT_EQ(c1->has_mute, 0);
1238   EXPECT_EQ(c2->has_volume, 1);
1239   EXPECT_EQ(c2->has_mute, 0);
1240   EXPECT_EQ(c3->has_volume, 0);
1241   EXPECT_EQ(c3->has_mute, 0);
1242   EXPECT_EQ(c4->has_volume, 0);
1243   EXPECT_EQ(c4->has_mute, 0);
1244 
1245   EXPECT_EQ(1, cras_alsa_mixer_has_volume(output_control));
1246   EXPECT_EQ(0, output_control->has_mute);
1247 
1248   cras_alsa_mixer_destroy(c);
1249   EXPECT_EQ(1, snd_mixer_close_called);
1250   mixer_name_free(coupled_controls);
1251 }
1252 
TEST(AlsaMixer,MixerName)1253 TEST(AlsaMixer, MixerName) {
1254   struct mixer_name *names;
1255   struct mixer_name *control;
1256   size_t mixer_name_count;
1257   static const char *element_names[] = {
1258     "Master",
1259     "PCM",
1260     "Headphone",
1261     "Speaker",
1262     "HDMI",
1263     "IEC958",
1264   };
1265 
1266   names = mixer_name_add_array(NULL, element_names,
1267                                ARRAY_SIZE(element_names),
1268                                CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME);
1269   names = mixer_name_add(names, "Playback",
1270                          CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME);
1271   names = mixer_name_add(names, "Main",
1272                          CRAS_STREAM_OUTPUT, MIXER_NAME_MAIN_VOLUME);
1273   names = mixer_name_add(names, "Mic",
1274                          CRAS_STREAM_INPUT, MIXER_NAME_VOLUME);
1275   names = mixer_name_add(names, "Capture",
1276                          CRAS_STREAM_INPUT, MIXER_NAME_MAIN_VOLUME);
1277 
1278   /* Number of items (test mixer_name_add(_array)). */
1279   mixer_name_count = 0;
1280   DL_FOREACH(names, control) {
1281     mixer_name_count++;
1282   }
1283   EXPECT_EQ(10, mixer_name_count);
1284 
1285   /* Item not in the list: mismatch direction. */
1286   control = mixer_name_find(names, "Main",
1287                             CRAS_STREAM_INPUT, MIXER_NAME_UNDEFINED);
1288   EXPECT_EQ(1, control == NULL);
1289 
1290   /* Item not in the list: mismatch type. */
1291   control = mixer_name_find(names, "Main",
1292                             CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME);
1293   EXPECT_EQ(1, control == NULL);
1294 
1295   /* Find by name and direction. */
1296   control = mixer_name_find(names, "Main",
1297                             CRAS_STREAM_OUTPUT, MIXER_NAME_UNDEFINED);
1298   EXPECT_EQ(0, strcmp("Main", control->name));
1299 
1300   /* Find by type and direction. */
1301   control = mixer_name_find(names, NULL,
1302                             CRAS_STREAM_INPUT, MIXER_NAME_VOLUME);
1303   EXPECT_EQ(0, strcmp("Mic", control->name));
1304 
1305   mixer_name_free(names);
1306 }
1307 
1308 class AlsaMixerFullySpeced : public testing::Test {
1309  protected:
SetUp()1310   virtual void SetUp() {
1311     callback_values_.clear();
1312     callback_called_ = 0;
1313     static snd_mixer_elem_t *elements[] = {
1314       reinterpret_cast<snd_mixer_elem_t *>(1),  // HP-L
1315       reinterpret_cast<snd_mixer_elem_t *>(2),  // HP-R
1316       reinterpret_cast<snd_mixer_elem_t *>(3),  // SPK-L
1317       reinterpret_cast<snd_mixer_elem_t *>(4),  // SPK-R
1318       reinterpret_cast<snd_mixer_elem_t *>(5),  // HDMI
1319       reinterpret_cast<snd_mixer_elem_t *>(6),  // CAPTURE
1320       reinterpret_cast<snd_mixer_elem_t *>(7),  // MIC-L
1321       reinterpret_cast<snd_mixer_elem_t *>(8),  // MIC-R
1322       reinterpret_cast<snd_mixer_elem_t *>(0),  // Unknown
1323     };
1324     static int element_playback_volume[] = {
1325       1,
1326       1,
1327       1,
1328       1,
1329       1,
1330       0, 0, 0,
1331     };
1332     static int element_playback_switches[] = {
1333       0,
1334       0,
1335       0,
1336       0,
1337       1,
1338       0, 0, 0,
1339     };
1340     static int element_capture_volume[] = {0, 0, 0, 0, 0,
1341       0,
1342       1,
1343       1,
1344     };
1345     static int element_capture_switches[] = {0, 0, 0, 0, 0,
1346       1,
1347       0,
1348       0,
1349     };
1350     static const long min_volumes[] = {-84, -84, -84, -84, -84, 0, 0, 0};
1351     static const long max_volumes[] = {0, 0, 0, 0, 0, 0, 84, 84};
1352     static const char *element_names[] = {
1353       "HP-L",
1354       "HP-R",
1355       "SPK-L",
1356       "SPK-R",
1357       "HDMI",
1358       "CAPTURE",
1359       "MIC-L",
1360       "MIC-R",
1361       "Unknown"
1362     };
1363     struct ucm_section *sections = NULL;
1364     struct ucm_section *section;
1365     size_t i;
1366 
1367     ResetStubData();
1368 
1369     for (i = 0; i < ARRAY_SIZE(elements); i++)
1370        snd_mixer_find_elem_map[element_names[i]] = elements[i];
1371 
1372     section = ucm_section_create("NullElement", 0, CRAS_STREAM_OUTPUT,
1373                                  NULL, NULL);
1374     ucm_section_set_mixer_name(section, "Unknown");
1375     DL_APPEND(sections, section);
1376     section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
1377                                  "my-sound-card Headset Jack", "gpio");
1378     ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME);
1379     ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME);
1380     DL_APPEND(sections, section);
1381     section = ucm_section_create("Speaker", 0, CRAS_STREAM_OUTPUT,
1382                                  NULL, NULL);
1383     ucm_section_add_coupled(section, "SPK-L", MIXER_NAME_VOLUME);
1384     ucm_section_add_coupled(section, "SPK-R", MIXER_NAME_VOLUME);
1385     DL_APPEND(sections, section);
1386     section = ucm_section_create("Mic", 0, CRAS_STREAM_INPUT,
1387                                  "my-sound-card Headset Jack", "gpio");
1388     ucm_section_set_mixer_name(section, "CAPTURE");
1389     DL_APPEND(sections, section);
1390     section = ucm_section_create("Internal Mic", 0, CRAS_STREAM_INPUT,
1391                                  NULL, NULL);
1392     ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME);
1393     ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME);
1394     DL_APPEND(sections, section);
1395     section = ucm_section_create("HDMI", 0, CRAS_STREAM_OUTPUT,
1396                                  NULL, NULL);
1397     ucm_section_set_mixer_name(section, "HDMI");
1398     DL_APPEND(sections, section);
1399     ASSERT_NE(sections, (struct ucm_section *)NULL);
1400 
1401     snd_mixer_selem_has_playback_volume_return_values =
1402         element_playback_volume;
1403     snd_mixer_selem_has_playback_volume_return_values_length =
1404       ARRAY_SIZE(element_playback_volume);
1405     snd_mixer_selem_has_playback_switch_return_values =
1406         element_playback_switches;
1407     snd_mixer_selem_has_playback_switch_return_values_length =
1408       ARRAY_SIZE(element_playback_switches);
1409     snd_mixer_selem_has_capture_volume_return_values =
1410         element_capture_volume;
1411     snd_mixer_selem_has_capture_volume_return_values_length =
1412       ARRAY_SIZE(element_capture_volume);
1413     snd_mixer_selem_has_capture_switch_return_values =
1414         element_capture_switches;
1415     snd_mixer_selem_has_capture_switch_return_values_length =
1416       ARRAY_SIZE(element_capture_switches);
1417     snd_mixer_selem_get_name_return_values = element_names;
1418     snd_mixer_selem_get_name_return_values_length = ARRAY_SIZE(element_names);
1419     snd_mixer_selem_get_capture_dB_range_min_values = min_volumes;
1420     snd_mixer_selem_get_capture_dB_range_max_values = max_volumes;
1421     snd_mixer_selem_get_capture_dB_range_values_length =
1422         ARRAY_SIZE(min_volumes);
1423 
1424     cras_mixer_ = cras_alsa_mixer_create("hw:0");
1425     ASSERT_NE(static_cast<struct cras_alsa_mixer *>(NULL), cras_mixer_);
1426     EXPECT_EQ(1, snd_mixer_open_called);
1427     EXPECT_EQ(1, snd_mixer_attach_called);
1428     EXPECT_EQ(0, strcmp(snd_mixer_attach_mixdev, "hw:0"));
1429     EXPECT_EQ(1, snd_mixer_selem_register_called);
1430     EXPECT_EQ(1, snd_mixer_load_called);
1431     EXPECT_EQ(0, snd_mixer_close_called);
1432 
1433     section = sections;
1434     EXPECT_EQ(-ENOENT,\
1435               cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1436     ASSERT_NE((struct ucm_section *)NULL, section->next);
1437     section = section->next;
1438     EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1439     ASSERT_NE((struct ucm_section *)NULL, section->next);
1440     section = section->next;
1441     EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1442     ASSERT_NE((struct ucm_section *)NULL, section->next);
1443     section = section->next;
1444     EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1445     ASSERT_NE((struct ucm_section *)NULL, section->next);
1446     section = section->next;
1447     EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1448     ASSERT_NE((struct ucm_section *)NULL, section->next);
1449     section = section->next;
1450     EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section(cras_mixer_, section));
1451     EXPECT_EQ(section->next, (struct ucm_section*)NULL);
1452 
1453     EXPECT_EQ(9, snd_mixer_find_selem_called);
1454     EXPECT_EQ(5, snd_mixer_selem_has_playback_volume_called);
1455     EXPECT_EQ(5, snd_mixer_selem_has_playback_switch_called);
1456     EXPECT_EQ(3, snd_mixer_selem_has_capture_volume_called);
1457     EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called);
1458     EXPECT_EQ(5, snd_mixer_selem_get_playback_dB_range_called);
1459     EXPECT_EQ(2, snd_mixer_selem_get_capture_dB_range_called);
1460 
1461     sections_ = sections;
1462   }
1463 
TearDown()1464   virtual void TearDown() {
1465     ucm_section_free_list(sections_);
1466     cras_alsa_mixer_destroy(cras_mixer_);
1467     EXPECT_EQ(1, snd_mixer_close_called);
1468   }
1469 
Callback(struct mixer_control * control,void * arg)1470   static void Callback(struct mixer_control *control, void *arg) {
1471     callback_called_++;
1472     callback_values_.push_back(control);
1473   }
1474 
1475   struct cras_alsa_mixer *cras_mixer_;
1476   static size_t callback_called_;
1477   static std::vector<struct mixer_control *> callback_values_;
1478   struct ucm_section *sections_;
1479 };
1480 
1481 size_t AlsaMixerFullySpeced::callback_called_;
1482 std::vector<struct mixer_control *> AlsaMixerFullySpeced::callback_values_;
1483 
TEST_F(AlsaMixerFullySpeced,CheckControlCounts)1484 TEST_F(AlsaMixerFullySpeced, CheckControlCounts) {
1485   cras_alsa_mixer_list_outputs(cras_mixer_,
1486                                AlsaMixerFullySpeced::Callback,
1487                                reinterpret_cast<void*>(555));
1488   EXPECT_EQ(3, callback_called_);
1489   callback_called_ = 0;
1490   cras_alsa_mixer_list_inputs(cras_mixer_,
1491                                AlsaMixerFullySpeced::Callback,
1492                                reinterpret_cast<void*>(555));
1493   EXPECT_EQ(2, callback_called_);
1494 }
1495 
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByNameNoMatch)1496 TEST_F(AlsaMixerFullySpeced, CheckFindOutputByNameNoMatch) {
1497   struct mixer_control *out;
1498 
1499   out = cras_alsa_mixer_get_output_matching_name(cras_mixer_,
1500                                                  "AAAAA Jack");
1501   EXPECT_EQ(static_cast<struct mixer_control *>(NULL), out);
1502 }
1503 
TEST_F(AlsaMixerFullySpeced,CheckFindOutputByName)1504 TEST_F(AlsaMixerFullySpeced, CheckFindOutputByName) {
1505   struct mixer_control *out;
1506 
1507   out = cras_alsa_mixer_get_output_matching_name(cras_mixer_,
1508                                                  "Headphone Jack");
1509   EXPECT_NE(static_cast<struct mixer_control *>(NULL), out);
1510 }
1511 
TEST_F(AlsaMixerFullySpeced,CheckFindControlForSection)1512 TEST_F(AlsaMixerFullySpeced, CheckFindControlForSection) {
1513   struct mixer_control *control;
1514   struct ucm_section *section = sections_;
1515 
1516   // Look for the control for the Headphone section.
1517   // We've already asserted that section != NULL above.
1518   // Matching the control created by CoupledMixers.
1519   section = section->next;
1520   control = cras_alsa_mixer_get_control_for_section(cras_mixer_, section);
1521   ASSERT_NE(static_cast<struct mixer_control *>(NULL), control);
1522   EXPECT_EQ(0, strcmp(control->name, "Headphone"));
1523 
1524   // Look for the control for the Mic section.
1525   // Matching the control created by MixerName.
1526   section = section->next->next;
1527   control = cras_alsa_mixer_get_control_for_section(cras_mixer_, section);
1528   ASSERT_NE(static_cast<struct mixer_control *>(NULL), control);
1529   EXPECT_EQ(0, strcmp(control->name, "CAPTURE"));
1530 }
1531 
1532 /* Stubs */
1533 
1534 extern "C" {
snd_mixer_open(snd_mixer_t ** mixer,int mode)1535 int snd_mixer_open(snd_mixer_t **mixer, int mode) {
1536   snd_mixer_open_called++;
1537   *mixer = reinterpret_cast<snd_mixer_t *>(2);
1538   return snd_mixer_open_return_value;
1539 }
snd_mixer_attach(snd_mixer_t * mixer,const char * name)1540 int snd_mixer_attach(snd_mixer_t *mixer, const char *name) {
1541   snd_mixer_attach_called++;
1542   snd_mixer_attach_mixdev = name;
1543   return snd_mixer_attach_return_value;
1544 }
snd_mixer_selem_register(snd_mixer_t * mixer,struct snd_mixer_selem_regopt * options,snd_mixer_class_t ** classp)1545 int snd_mixer_selem_register(snd_mixer_t *mixer,
1546                              struct snd_mixer_selem_regopt *options,
1547                              snd_mixer_class_t **classp) {
1548   snd_mixer_selem_register_called++;
1549   return snd_mixer_selem_register_return_value;
1550 }
snd_mixer_load(snd_mixer_t * mixer)1551 int snd_mixer_load(snd_mixer_t *mixer) {
1552   snd_mixer_load_called++;
1553   return snd_mixer_load_return_value;
1554 }
snd_mixer_selem_get_name(snd_mixer_elem_t * elem)1555 const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem) {
1556   int index = reinterpret_cast<size_t>(elem) - 1;
1557   snd_mixer_selem_get_name_called++;
1558   if (index >= snd_mixer_selem_get_name_return_values_length)
1559     return static_cast<char *>(NULL);
1560 
1561   return snd_mixer_selem_get_name_return_values[index];
1562 }
snd_mixer_selem_get_index(snd_mixer_elem_t * elem)1563 unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem) {
1564   return 0;
1565 }
snd_mixer_selem_has_playback_volume(snd_mixer_elem_t * elem)1566 int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem) {
1567   int index = reinterpret_cast<size_t>(elem) - 1;
1568   snd_mixer_selem_has_playback_volume_called++;
1569   if (index >= snd_mixer_selem_has_playback_volume_return_values_length)
1570     return -1;
1571 
1572   return snd_mixer_selem_has_playback_volume_return_values[index];
1573 }
snd_mixer_selem_has_playback_switch(snd_mixer_elem_t * elem)1574 int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem) {
1575   int index = reinterpret_cast<size_t>(elem) - 1;
1576   snd_mixer_selem_has_playback_switch_called++;
1577   if (index >= snd_mixer_selem_has_playback_switch_return_values_length)
1578     return -1;
1579 
1580   return snd_mixer_selem_has_playback_switch_return_values[index];
1581 }
snd_mixer_selem_has_capture_volume(snd_mixer_elem_t * elem)1582 int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem) {
1583   int index = reinterpret_cast<size_t>(elem) - 1;
1584   snd_mixer_selem_has_capture_volume_called++;
1585   if (index >= snd_mixer_selem_has_capture_volume_return_values_length)
1586     return -1;
1587 
1588   return snd_mixer_selem_has_capture_volume_return_values[index];
1589 }
snd_mixer_selem_has_capture_switch(snd_mixer_elem_t * elem)1590 int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem) {
1591   int index = reinterpret_cast<size_t>(elem) - 1;
1592   snd_mixer_selem_has_capture_switch_called++;
1593   if (index >= snd_mixer_selem_has_capture_switch_return_values_length)
1594     return -1;
1595 
1596   return snd_mixer_selem_has_capture_switch_return_values[index];
1597 }
snd_mixer_first_elem(snd_mixer_t * mixer)1598 snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer) {
1599   snd_mixer_first_elem_called++;
1600   return snd_mixer_first_elem_return_value;
1601 }
snd_mixer_elem_next(snd_mixer_elem_t * elem)1602 snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem) {
1603   snd_mixer_elem_next_called++;
1604   if (snd_mixer_elem_next_return_values_index >=
1605       snd_mixer_elem_next_return_values_length)
1606     return static_cast<snd_mixer_elem_t *>(NULL);
1607 
1608   return snd_mixer_elem_next_return_values[
1609       snd_mixer_elem_next_return_values_index++];
1610 }
snd_mixer_close(snd_mixer_t * mixer)1611 int snd_mixer_close(snd_mixer_t *mixer) {
1612   snd_mixer_close_called++;
1613   return 0;
1614 }
snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t * elem,long value,int dir)1615 int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem,
1616                                         long value,
1617                                         int dir) {
1618   int index = reinterpret_cast<size_t>(elem) - 1;
1619   snd_mixer_selem_set_playback_dB_all_called++;
1620   if (index < snd_mixer_selem_set_playback_dB_all_values_length)
1621     snd_mixer_selem_set_playback_dB_all_values[index] = value;
1622   return 0;
1623 }
snd_mixer_selem_get_playback_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)1624 int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem,
1625                                     snd_mixer_selem_channel_id_t channel,
1626                                     long *value) {
1627   int index = reinterpret_cast<size_t>(elem) - 1;
1628   snd_mixer_selem_get_playback_dB_called++;
1629   if (index >= snd_mixer_selem_get_playback_dB_return_values_length)
1630     *value = 0;
1631   else
1632     *value = snd_mixer_selem_get_playback_dB_return_values[index];
1633   return 0;
1634 }
snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t * elem,int value)1635 int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value) {
1636   snd_mixer_selem_set_playback_switch_all_called++;
1637   snd_mixer_selem_set_playback_switch_all_value = value;
1638   return 0;
1639 }
snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t * elem,long value,int dir)1640 int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem,
1641                                        long value,
1642                                        int dir) {
1643   int index = reinterpret_cast<size_t>(elem) - 1;
1644   snd_mixer_selem_set_capture_dB_all_called++;
1645   if (index < snd_mixer_selem_set_capture_dB_all_values_length)
1646     snd_mixer_selem_set_capture_dB_all_values[index] = value;
1647   return 0;
1648 }
snd_mixer_selem_get_capture_dB(snd_mixer_elem_t * elem,snd_mixer_selem_channel_id_t channel,long * value)1649 int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem,
1650                                    snd_mixer_selem_channel_id_t channel,
1651                                    long *value) {
1652   int index = reinterpret_cast<size_t>(elem) - 1;
1653   snd_mixer_selem_get_capture_dB_called++;
1654   if (index >= snd_mixer_selem_get_capture_dB_return_values_length)
1655     *value = 0;
1656   else
1657     *value = snd_mixer_selem_get_capture_dB_return_values[index];
1658   return 0;
1659 }
snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t * elem,int value)1660 int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value) {
1661   snd_mixer_selem_set_capture_switch_all_called++;
1662   snd_mixer_selem_set_capture_switch_all_value = value;
1663   return 0;
1664 }
snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t * elem,long * min,long * max)1665 int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem, long *min,
1666                                          long *max) {
1667   size_t index = reinterpret_cast<size_t>(elem) - 1;
1668   snd_mixer_selem_get_capture_dB_range_called++;
1669   if (index >= snd_mixer_selem_get_capture_dB_range_values_length) {
1670     *min = 0;
1671     *max = 0;
1672   } else {
1673     *min = snd_mixer_selem_get_capture_dB_range_min_values[index];
1674     *max = snd_mixer_selem_get_capture_dB_range_max_values[index];
1675   }
1676   return 0;
1677 }
snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t * elem,long * min,long * max)1678 int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem,
1679                                           long *min,
1680                                           long *max) {
1681   size_t index = reinterpret_cast<size_t>(elem) - 1;
1682   snd_mixer_selem_get_playback_dB_range_called++;
1683   if (index >= snd_mixer_selem_get_playback_dB_range_values_length) {
1684     *min = 0;
1685     *max = 0;
1686   } else {
1687     *min = snd_mixer_selem_get_playback_dB_range_min_values[index];
1688     *max = snd_mixer_selem_get_playback_dB_range_max_values[index];
1689   }
1690   return 0;
1691 }
1692 
snd_mixer_find_selem(snd_mixer_t * mixer,const snd_mixer_selem_id_t * id)1693 snd_mixer_elem_t *snd_mixer_find_selem(
1694     snd_mixer_t *mixer, const snd_mixer_selem_id_t *id) {
1695   std::string name(snd_mixer_selem_id_get_name(id));
1696   unsigned int index = snd_mixer_selem_id_get_index(id);
1697   snd_mixer_find_selem_called++;
1698   if (index != 0)
1699     return NULL;
1700   if (snd_mixer_find_elem_map.find(name) == snd_mixer_find_elem_map.end()) {
1701     return NULL;
1702   }
1703   return snd_mixer_find_elem_map[name];
1704 }
1705 
1706 //  From cras_volume_curve.
get_dBFS_default(const struct cras_volume_curve * curve,size_t volume)1707 static long get_dBFS_default(const struct cras_volume_curve *curve,
1708 			     size_t volume)
1709 {
1710   return 100 * (volume - 100);
1711 }
1712 
cras_volume_curve_create_default()1713 struct cras_volume_curve *cras_volume_curve_create_default()
1714 {
1715   struct cras_volume_curve *curve;
1716   curve = (struct cras_volume_curve *)calloc(1, sizeof(*curve));
1717   if (curve)
1718     curve->get_dBFS = get_dBFS_default;
1719   return curve;
1720 }
1721 
cras_volume_curve_destroy(struct cras_volume_curve * curve)1722 void cras_volume_curve_destroy(struct cras_volume_curve *curve)
1723 {
1724   cras_volume_curve_destroy_called++;
1725   free(curve);
1726 }
1727 
1728 // From libiniparser.
cras_card_config_get_volume_curve_for_control(const struct cras_card_config * card_config,const char * control_name)1729 struct cras_volume_curve *cras_card_config_get_volume_curve_for_control(
1730 		const struct cras_card_config *card_config,
1731 		const char *control_name)
1732 {
1733   struct cras_volume_curve *curve;
1734   curve = (struct cras_volume_curve *)calloc(1, sizeof(*curve));
1735   if (curve != NULL)
1736     curve->get_dBFS = get_dBFS_default;
1737   return curve;
1738 }
1739 
1740 } /* extern "C" */
1741 
1742 }  //  namespace
1743 
main(int argc,char ** argv)1744 int main(int argc, char **argv) {
1745   ::testing::InitGoogleTest(&argc, argv);
1746   openlog(NULL, LOG_PERROR, LOG_USER);
1747   return RUN_ALL_TESTS();
1748 }
1749