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