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