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 <deque>
6 #include <linux/input.h>
7 #include <map>
8 #include <poll.h>
9 #include <stdio.h>
10 #include <sys/param.h>
11 #include <gtest/gtest.h>
12 #include <string>
13 #include <syslog.h>
14 #include <vector>
15 
16 extern "C" {
17 #include "cras_alsa_jack.h"
18 #include "cras_alsa_ucm_section.h"
19 #include "cras_gpio_jack.h"
20 #include "cras_tm.h"
21 #include "cras_types.h"
22 #include "cras_util.h"
23 }
24 
25 namespace {
26 
27 #define BITS_PER_BYTE		(8)
28 #define BITS_PER_LONG		(sizeof(long) * BITS_PER_BYTE)
29 #define NBITS(x)		((((x) - 1) / BITS_PER_LONG) + 1)
30 #define OFF(x)			((x) % BITS_PER_LONG)
31 #define BIT(x)			(1UL << OFF(x))
32 #define LONG(x)			((x) / BITS_PER_LONG)
33 #define IS_BIT_SET(bit, array)	!!((array[LONG(bit)]) & (1UL << OFF(bit)))
34 
35 static int fake_jack_cb_plugged;
36 static void *fake_jack_cb_data;
37 static size_t fake_jack_cb_called;
38 unsigned int snd_hctl_elem_get_device_return_val;
39 unsigned int snd_hctl_elem_get_device_called;
40 static size_t snd_hctl_first_elem_called;
41 static snd_hctl_elem_t *snd_hctl_first_elem_return_val;
42 static size_t snd_hctl_elem_next_called;
43 std::deque<snd_hctl_elem_t *> snd_hctl_elem_next_ret_vals;
44 std::deque<snd_hctl_elem_t *> snd_hctl_elem_next_ret_vals_poped;
45 static size_t snd_hctl_elem_get_name_called;
46 static size_t snd_hctl_elem_set_callback_called;
47 static snd_hctl_elem_t *snd_hctl_elem_set_callback_obj;
48 static snd_hctl_elem_callback_t snd_hctl_elem_set_callback_value;
49 static size_t snd_hctl_find_elem_called;
50 static std::vector<snd_hctl_elem_t *> snd_hctl_find_elem_return_vals;
51 static std::map<std::string, size_t> snd_ctl_elem_id_set_name_map;
52 static size_t cras_system_add_select_fd_called;
53 static std::vector<int> cras_system_add_select_fd_values;
54 static size_t cras_system_rm_select_fd_called;
55 static std::vector<int> cras_system_rm_select_fd_values;
56 static size_t snd_hctl_elem_set_callback_private_called;
57 static void *snd_hctl_elem_set_callback_private_value;
58 static size_t snd_hctl_elem_get_hctl_called;
59 static snd_hctl_t *snd_hctl_elem_get_hctl_return_value;
60 static size_t snd_ctl_elem_value_get_boolean_called;
61 static int snd_ctl_elem_value_get_boolean_return_value;
62 static void *fake_jack_cb_arg;
63 static struct cras_alsa_mixer *fake_mixer;
64 static size_t cras_alsa_mixer_get_output_matching_name_called;
65 static size_t cras_alsa_mixer_get_input_matching_name_called;
66 static size_t cras_alsa_mixer_get_control_for_section_called;
67 static struct mixer_control *
68     cras_alsa_mixer_get_output_matching_name_return_value;
69 static struct mixer_control *
70     cras_alsa_mixer_get_input_matching_name_return_value;
71 static struct mixer_control *
72     cras_alsa_mixer_get_control_for_section_return_value;
73 static size_t gpio_switch_list_for_each_called;
74 static std::vector<std::string> gpio_switch_list_for_each_dev_paths;
75 static std::vector<std::string> gpio_switch_list_for_each_dev_names;
76 static size_t gpio_switch_open_called;
77 static size_t gpio_switch_eviocgsw_called;
78 static size_t gpio_switch_eviocgbit_called;
79 static unsigned ucm_get_dev_for_jack_called;
80 static unsigned ucm_get_cap_control_called;
81 static char *ucm_get_cap_control_value;
82 static bool ucm_get_dev_for_jack_return;
83 static int ucm_set_enabled_value;
84 static unsigned long eviocbit_ret[NBITS(SW_CNT)];
85 static int gpio_switch_eviocgbit_fd;
86 static const char *edid_file_ret;
87 static size_t ucm_get_dsp_name_called;
88 static unsigned ucm_get_override_type_name_called;
89 static char *ucm_get_device_name_for_dev_value;
90 static snd_hctl_t *fake_hctl = (snd_hctl_t *)2;
91 
ResetStubData()92 static void ResetStubData() {
93   gpio_switch_list_for_each_called = 0;
94   gpio_switch_list_for_each_dev_paths.clear();
95   gpio_switch_list_for_each_dev_paths.push_back("/dev/input/event3");
96   gpio_switch_list_for_each_dev_paths.push_back("/dev/input/event2");
97   gpio_switch_list_for_each_dev_names.clear();
98   gpio_switch_open_called = 0;
99   gpio_switch_eviocgsw_called = 0;
100   gpio_switch_eviocgbit_called = 0;
101   snd_hctl_elem_get_device_return_val = 0;
102   snd_hctl_elem_get_device_called = 0;
103   snd_hctl_first_elem_called = 0;
104   snd_hctl_first_elem_return_val = reinterpret_cast<snd_hctl_elem_t *>(0x87);
105   snd_hctl_elem_next_called = 0;
106   snd_hctl_elem_next_ret_vals.clear();
107   snd_hctl_elem_next_ret_vals_poped.clear();
108   snd_hctl_elem_get_name_called = 0;
109   snd_hctl_elem_set_callback_called = 0;
110   snd_hctl_elem_set_callback_obj = NULL;
111   snd_hctl_elem_set_callback_value = NULL;
112   snd_hctl_find_elem_called = 0;
113   snd_hctl_find_elem_return_vals.clear();
114   snd_ctl_elem_id_set_name_map.clear();
115   cras_system_add_select_fd_called = 0;
116   cras_system_add_select_fd_values.clear();
117   cras_system_rm_select_fd_called = 0;
118   cras_system_rm_select_fd_values.clear();
119   snd_hctl_elem_set_callback_private_called = 0;
120   snd_hctl_elem_get_hctl_called = 0;
121   snd_ctl_elem_value_get_boolean_called = 0;
122   fake_jack_cb_called = 0;
123   fake_jack_cb_plugged = 0;
124   fake_jack_cb_arg = reinterpret_cast<void *>(0x987);
125   fake_mixer = reinterpret_cast<struct cras_alsa_mixer *>(0x789);
126   cras_alsa_mixer_get_output_matching_name_called = 0;
127   cras_alsa_mixer_get_input_matching_name_called = 0;
128   cras_alsa_mixer_get_control_for_section_called = 0;
129   cras_alsa_mixer_get_output_matching_name_return_value =
130       reinterpret_cast<struct mixer_control *>(0x456);
131   cras_alsa_mixer_get_input_matching_name_return_value = NULL;
132   cras_alsa_mixer_get_control_for_section_return_value =
133       reinterpret_cast<struct mixer_control *>(0x456);
134   ucm_get_dev_for_jack_called = 0;
135   ucm_get_cap_control_called = 0;
136   ucm_get_cap_control_value = NULL;
137   ucm_get_dev_for_jack_return = false;
138   edid_file_ret = NULL;
139   ucm_get_dsp_name_called = 0;
140   ucm_get_override_type_name_called = 0;
141   ucm_get_device_name_for_dev_value = NULL;
142 
143   memset(eviocbit_ret, 0, sizeof(eviocbit_ret));
144 }
145 
fake_jack_cb(const struct cras_alsa_jack * jack,int plugged,void * data)146 static void fake_jack_cb(const struct cras_alsa_jack *jack,
147                          int plugged,
148                          void *data)
149 {
150   fake_jack_cb_called++;
151   fake_jack_cb_plugged = plugged;
152   fake_jack_cb_data = data;
153 
154   // Check that jack enable callback is called if there is a ucm device.
155   ucm_set_enabled_value = !plugged;
156   cras_alsa_jack_enable_ucm(jack, plugged);
157   EXPECT_EQ(ucm_get_dev_for_jack_return ? plugged : !plugged,
158             ucm_set_enabled_value);
159 }
160 
TEST(AlsaJacks,CreateNullHctl)161 TEST(AlsaJacks, CreateNullHctl) {
162   struct cras_alsa_jack_list *jack_list;
163   ResetStubData();
164   jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
165                                          fake_mixer,
166                                          NULL, NULL,
167                                          CRAS_STREAM_OUTPUT,
168                                          fake_jack_cb,
169                                          fake_jack_cb_arg);
170   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
171   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
172   EXPECT_EQ(1, gpio_switch_list_for_each_called);
173   EXPECT_EQ(0, gpio_switch_open_called);
174   EXPECT_EQ(0, gpio_switch_eviocgsw_called);
175   EXPECT_EQ(0, gpio_switch_eviocgbit_called);
176 
177   cras_alsa_jack_list_destroy(jack_list);
178 }
179 
TEST(AlsaJacks,CreateNoElements)180 TEST(AlsaJacks, CreateNoElements) {
181   struct cras_alsa_jack_list *jack_list;
182 
183   ResetStubData();
184   snd_hctl_first_elem_return_val = NULL;
185   jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
186                                          fake_mixer,
187                                          NULL, fake_hctl,
188                                          CRAS_STREAM_OUTPUT,
189                                          fake_jack_cb,
190                                          fake_jack_cb_arg);
191   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
192   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
193   EXPECT_EQ(1, gpio_switch_list_for_each_called);
194   EXPECT_EQ(0, gpio_switch_open_called);
195   EXPECT_EQ(0, gpio_switch_eviocgsw_called);
196   EXPECT_EQ(0, gpio_switch_eviocgbit_called);
197   EXPECT_EQ(1, snd_hctl_first_elem_called);
198   EXPECT_EQ(0, snd_hctl_elem_next_called);
199 
200   cras_alsa_jack_list_destroy(jack_list);
201 }
202 
run_test_with_elem_list(CRAS_STREAM_DIRECTION direction,std::string * elems,unsigned int device_index,struct cras_use_case_mgr * ucm,size_t nelems,size_t nhdmi_jacks,size_t njacks)203 static struct cras_alsa_jack_list *run_test_with_elem_list(
204     CRAS_STREAM_DIRECTION direction,
205     std::string *elems,
206     unsigned int device_index,
207     struct cras_use_case_mgr *ucm,
208     size_t nelems,
209     size_t nhdmi_jacks,
210     size_t njacks) {
211   struct cras_alsa_jack_list *jack_list;
212 
213   snd_hctl_first_elem_return_val =
214       reinterpret_cast<snd_hctl_elem_t *>(&elems[0]);
215   for (unsigned int i = 1; i < nelems; i++)
216     snd_hctl_elem_next_ret_vals.push_front(
217         reinterpret_cast<snd_hctl_elem_t *>(&elems[i]));
218 
219   jack_list = cras_alsa_jack_list_create(0,
220                                          "card_name",
221                                          device_index,
222                                          1,
223                                          fake_mixer,
224                                          ucm, fake_hctl,
225                                          direction,
226                                          fake_jack_cb,
227                                          fake_jack_cb_arg);
228   if (jack_list == NULL)
229     return jack_list;
230   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
231   EXPECT_EQ(ucm ? njacks : 0, ucm_get_dev_for_jack_called);
232   EXPECT_EQ(ucm ? njacks : 0, ucm_get_override_type_name_called);
233   EXPECT_EQ(1 + nhdmi_jacks, snd_hctl_first_elem_called);
234   EXPECT_EQ(njacks, snd_hctl_elem_set_callback_called);
235 
236   /* For some functions, the number of calls to them could
237    * be larger then expected count if there is ELD control
238    * in given elements. */
239   EXPECT_GE(snd_hctl_elem_next_called, nelems + nhdmi_jacks);
240   EXPECT_GE(snd_hctl_elem_get_name_called, nelems + njacks);
241 
242   if (direction == CRAS_STREAM_OUTPUT) {
243     EXPECT_EQ(njacks, cras_alsa_mixer_get_output_matching_name_called);
244   }
245   if (direction == CRAS_STREAM_INPUT && ucm_get_dev_for_jack_return) {
246     EXPECT_EQ(njacks, ucm_get_cap_control_called);
247   }
248 
249   return jack_list;
250 }
251 
run_test_with_section(CRAS_STREAM_DIRECTION direction,std::string * elems,size_t nelems,unsigned int device_index,struct cras_use_case_mgr * ucm,struct ucm_section * ucm_section,int add_jack_rc,size_t njacks)252 static struct cras_alsa_jack_list *run_test_with_section(
253     CRAS_STREAM_DIRECTION direction,
254     std::string *elems,
255     size_t nelems,
256     unsigned int device_index,
257     struct cras_use_case_mgr *ucm,
258     struct ucm_section *ucm_section,
259     int add_jack_rc,
260     size_t njacks) {
261   struct cras_alsa_jack_list *jack_list;
262   struct cras_alsa_jack *jack;
263 
264   for (size_t i = 0; i < nelems; i++) {
265     snd_ctl_elem_id_set_name_map[elems[i]] = i;
266     snd_hctl_find_elem_return_vals.push_back(
267         reinterpret_cast<snd_hctl_elem_t*>(&elems[i]));
268   }
269 
270   jack_list = cras_alsa_jack_list_create(0,
271                                          "card_name",
272                                          device_index,
273                                          1,
274                                          fake_mixer,
275                                          ucm, fake_hctl,
276                                          direction,
277                                          fake_jack_cb,
278                                          fake_jack_cb_arg);
279   if (jack_list == NULL)
280     return jack_list;
281   EXPECT_EQ(add_jack_rc,
282       cras_alsa_jack_list_add_jack_for_section(jack_list, ucm_section, &jack));
283   if (add_jack_rc == 0) {
284     EXPECT_EQ(njacks, ucm_get_dsp_name_called);
285     EXPECT_NE(jack, reinterpret_cast<struct cras_alsa_jack *>(NULL));
286   } else {
287     EXPECT_EQ(jack, reinterpret_cast<struct cras_alsa_jack *>(NULL));
288   }
289   if (add_jack_rc != 0 || njacks != ucm_get_dsp_name_called) {
290       cras_alsa_jack_list_destroy(jack_list);
291       return NULL;
292   }
293   EXPECT_EQ(njacks, snd_hctl_elem_set_callback_called);
294   EXPECT_EQ(njacks, cras_alsa_mixer_get_control_for_section_called);
295 
296   return jack_list;
297 }
298 
TEST(AlsaJacks,ReportNull)299 TEST(AlsaJacks, ReportNull) {
300   cras_alsa_jack_list_report(NULL);
301 }
302 
TEST(AlsaJacks,CreateNoJacks)303 TEST(AlsaJacks, CreateNoJacks) {
304   static std::string elem_names[] = {
305     "Mic Jack",
306     "foo",
307     "bar",
308   };
309   struct cras_alsa_jack_list *jack_list;
310 
311   ResetStubData();
312   jack_list = run_test_with_elem_list(CRAS_STREAM_OUTPUT,
313                                       elem_names,
314                                       0,
315                                       NULL,
316                                       ARRAY_SIZE(elem_names),
317                                       0,
318                                       0);
319   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
320 
321   cras_alsa_jack_list_destroy(jack_list);
322   EXPECT_EQ(0, cras_system_rm_select_fd_called);
323 }
324 
TEST(AlsaJacks,CreateGPIOHp)325 TEST(AlsaJacks, CreateGPIOHp) {
326   struct cras_alsa_jack_list *jack_list;
327 
328   ResetStubData();
329   gpio_switch_list_for_each_dev_names.push_back("some-other-device");
330   gpio_switch_list_for_each_dev_names.push_back("c1 Headphone Jack");
331   eviocbit_ret[LONG(SW_HEADPHONE_INSERT)] |= 1 << OFF(SW_HEADPHONE_INSERT);
332   gpio_switch_eviocgbit_fd = 2;
333   snd_hctl_first_elem_return_val = NULL;
334   jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
335                                          fake_mixer,
336                                          NULL, fake_hctl,
337                                          CRAS_STREAM_OUTPUT,
338                                          fake_jack_cb,
339                                          fake_jack_cb_arg);
340   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
341   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
342   cras_alsa_jack_list_destroy(jack_list);
343   EXPECT_EQ(1, gpio_switch_list_for_each_called);
344   EXPECT_GT(gpio_switch_open_called, 1);
345   EXPECT_EQ(1, gpio_switch_eviocgsw_called);
346   EXPECT_GT(gpio_switch_eviocgbit_called, 1);
347   EXPECT_EQ(1, cras_system_add_select_fd_called);
348   EXPECT_EQ(1, cras_system_rm_select_fd_called);
349 }
350 
TEST(AlsaJacks,CreateGPIOMic)351 TEST(AlsaJacks, CreateGPIOMic) {
352   struct cras_alsa_jack_list *jack_list;
353   ResetStubData();
354   ucm_get_dev_for_jack_return = true;
355   gpio_switch_list_for_each_dev_names.push_back("c1 Mic Jack");
356   gpio_switch_list_for_each_dev_names.push_back("c1 Headphone Jack");
357   eviocbit_ret[LONG(SW_MICROPHONE_INSERT)] |= 1 << OFF(SW_MICROPHONE_INSERT);
358   gpio_switch_eviocgbit_fd = 3;
359   snd_hctl_first_elem_return_val = NULL;
360   ucm_get_cap_control_value = reinterpret_cast<char *>(0x1);
361 
362   cras_alsa_mixer_get_input_matching_name_return_value =
363       reinterpret_cast<struct mixer_control *>(malloc(1));
364 
365   jack_list = cras_alsa_jack_list_create(
366       0,
367       "c1",
368       0,
369       1,
370       fake_mixer,
371       reinterpret_cast<struct cras_use_case_mgr *>(0x55),
372       fake_hctl,
373       CRAS_STREAM_INPUT,
374       fake_jack_cb,
375       fake_jack_cb_arg);
376   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
377   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
378   EXPECT_EQ(ucm_get_cap_control_called, 1);
379   EXPECT_EQ(cras_alsa_mixer_get_input_matching_name_called, 1);
380   cras_alsa_jack_list_destroy(jack_list);
381   // Mixer will be free by alsa_card_destroy, we should free it explicitly here
382   free(cras_alsa_mixer_get_input_matching_name_return_value);
383 }
384 
TEST(AlsaJacks,CreateGPIOHdmi)385 TEST(AlsaJacks, CreateGPIOHdmi) {
386   struct cras_alsa_jack_list *jack_list;
387 
388   ResetStubData();
389   gpio_switch_list_for_each_dev_names.push_back("c1 HDMI Jack");
390   gpio_switch_list_for_each_dev_names.push_back("c1 Mic Jack");
391   eviocbit_ret[LONG(SW_LINEOUT_INSERT)] |= 1 << OFF(SW_LINEOUT_INSERT);
392   gpio_switch_eviocgbit_fd = 3;
393   snd_hctl_first_elem_return_val = NULL;
394   jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
395                                          fake_mixer,
396                                          NULL, fake_hctl,
397                                          CRAS_STREAM_OUTPUT,
398                                          fake_jack_cb,
399                                          fake_jack_cb_arg);
400   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
401   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
402   EXPECT_EQ(1, gpio_switch_eviocgsw_called);
403 
404   fake_jack_cb_called = 0;
405   cras_alsa_jack_list_report(jack_list);
406   EXPECT_EQ(1, fake_jack_cb_plugged);
407   EXPECT_EQ(1, fake_jack_cb_called);
408 
409   cras_alsa_jack_list_destroy(jack_list);
410   EXPECT_EQ(1, gpio_switch_list_for_each_called);
411   EXPECT_GT(gpio_switch_open_called, 1);
412   EXPECT_GT(gpio_switch_eviocgbit_called, 1);
413   EXPECT_EQ(1, cras_system_add_select_fd_called);
414   EXPECT_EQ(1, cras_system_rm_select_fd_called);
415 }
416 
run_gpio_jack_test(int device_index,int is_first_device,enum CRAS_STREAM_DIRECTION direction,int should_create_jack,const char * jack_name)417 void run_gpio_jack_test(
418     int device_index,
419     int is_first_device,
420     enum CRAS_STREAM_DIRECTION direction,
421     int should_create_jack,
422     const char* jack_name)
423 {
424   struct cras_alsa_jack_list *jack_list;
425   struct cras_use_case_mgr *ucm =
426       reinterpret_cast<struct cras_use_case_mgr *>(0x55);
427 
428   gpio_switch_list_for_each_dev_names.push_back("some-other-device one");
429   gpio_switch_eviocgbit_fd = 2;
430   if (direction == CRAS_STREAM_OUTPUT) {
431     eviocbit_ret[LONG(SW_HEADPHONE_INSERT)] |= 1 << OFF(SW_HEADPHONE_INSERT);
432   } else {
433     eviocbit_ret[LONG(SW_MICROPHONE_INSERT)] |= 1 << OFF(SW_MICROPHONE_INSERT);
434   }
435   gpio_switch_list_for_each_dev_names.push_back(jack_name);
436   snd_hctl_first_elem_return_val = NULL;
437 
438   jack_list = cras_alsa_jack_list_create(0, "c1", device_index,
439                                          is_first_device,
440                                          fake_mixer,
441                                          ucm, fake_hctl,
442                                          direction,
443                                          fake_jack_cb,
444                                          fake_jack_cb_arg);
445   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
446   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
447 
448   cras_alsa_jack_list_report(jack_list);
449   EXPECT_EQ(should_create_jack, fake_jack_cb_plugged);
450   EXPECT_EQ(should_create_jack, fake_jack_cb_called);
451 
452   cras_alsa_jack_list_destroy(jack_list);
453 }
454 
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMMatched)455 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMMatched) {
456   int device_index = 1;
457   int is_first_device = 0;
458   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
459   int should_create_jack = 1;
460 
461   ResetStubData();
462 
463   /* PlaybackPCM matched, so create jack even if this is not the first device.*/
464   ucm_get_dev_for_jack_return = true;
465   ucm_get_device_name_for_dev_value = strdup("hw:c1,1");
466 
467   run_gpio_jack_test(
468       device_index, is_first_device, direction, should_create_jack,
469       "c1 Headset Jack");
470 }
471 
TEST(AlsaJacks,CreateGPIOHpUCMCapturePCMMatched)472 TEST(AlsaJacks, CreateGPIOHpUCMCapturePCMMatched) {
473   int device_index = 1;
474   int is_first_device = 0;
475   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_INPUT;
476   int should_create_jack = 1;
477 
478   ResetStubData();
479 
480   /* CapturePCM matched, so create jack even if this is not the first device.*/
481   ucm_get_dev_for_jack_return = true;
482   ucm_get_device_name_for_dev_value = strdup("hw:c1,1");
483 
484   run_gpio_jack_test(
485       device_index, is_first_device, direction, should_create_jack,
486       "c1 Mic Jack");
487 }
488 
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMNotMatched)489 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotMatched) {
490   int device_index = 0;
491   int is_first_device = 1;
492   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
493   int should_create_jack = 0;
494 
495   ResetStubData();
496 
497   /* PlaybackPCM not matched, do not create jack. */
498   ucm_get_dev_for_jack_return = true;
499   ucm_get_device_name_for_dev_value = strdup("hw:c1,2");
500 
501   run_gpio_jack_test(
502       device_index, is_first_device, direction, should_create_jack,
503       "c1 Headset Jack");
504 }
505 
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMNotSpecifiedFirstDevice)506 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotSpecifiedFirstDevice) {
507   int device_index = 1;
508   int is_first_device = 1;
509   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
510   int should_create_jack = 1;
511 
512   ResetStubData();
513 
514   /* PlaybackPCM not specified, create jack for the first device. */
515   ucm_get_dev_for_jack_return = true;
516   ucm_get_device_name_for_dev_value = NULL;
517 
518   run_gpio_jack_test(
519       device_index, is_first_device, direction, should_create_jack,
520       "c1 Headset Jack");
521 }
522 
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMNotSpecifiedSecondDevice)523 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotSpecifiedSecondDevice) {
524   int device_index = 1;
525   int is_first_device = 0;
526   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
527   int should_create_jack = 0;
528 
529   ResetStubData();
530 
531   /* PlaybackPCM not specified, do not create jack for the second device. */
532   ucm_get_dev_for_jack_return = true;
533   ucm_get_device_name_for_dev_value = NULL;
534 
535   run_gpio_jack_test(
536       device_index, is_first_device, direction, should_create_jack,
537       "c1 Headset Jack");
538 }
539 
TEST(AlsaJacks,CreateGPIOHpNoUCMFirstDevice)540 TEST(AlsaJacks, CreateGPIOHpNoUCMFirstDevice) {
541   int device_index = 1;
542   int is_first_device = 1;
543   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
544   int should_create_jack = 1;
545 
546   ResetStubData();
547 
548   /* No UCM for this jack, create jack for the first device. */
549   ucm_get_dev_for_jack_return = false;
550   ucm_get_device_name_for_dev_value = NULL;
551 
552   run_gpio_jack_test(
553       device_index, is_first_device, direction, should_create_jack,
554       "c1 Headset Jack");
555 }
556 
TEST(AlsaJacks,CreateGPIOHpNoUCMSecondDevice)557 TEST(AlsaJacks, CreateGPIOHpNoUCMSecondDevice) {
558   int device_index = 1;
559   int is_first_device = 0;
560   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
561   int should_create_jack = 0;
562 
563   ResetStubData();
564 
565   /* No UCM for this jack, dot not create jack for the second device. */
566   ucm_get_dev_for_jack_return = false;
567   ucm_get_device_name_for_dev_value = NULL;
568 
569   run_gpio_jack_test(
570       device_index, is_first_device, direction, should_create_jack,
571       "c1 Headset Jack");
572 }
573 
TEST(AlsaJacks,CreateGPIOMicNoUCMFirstDeviceMicJack)574 TEST(AlsaJacks, CreateGPIOMicNoUCMFirstDeviceMicJack) {
575   int device_index = 1;
576   int is_first_device = 1;
577   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_INPUT;
578   int should_create_jack = 1;
579 
580   ResetStubData();
581 
582   // No UCM for this jack, create jack for the first device.
583   ucm_get_dev_for_jack_return = false;
584   ucm_get_device_name_for_dev_value = NULL;
585 
586   // Mic Jack is a valid name for microphone jack.
587   run_gpio_jack_test(
588       device_index, is_first_device, direction, should_create_jack,
589       "c1 Mic Jack");
590 }
591 
TEST(AlsaJacks,CreateGPIOMicNoUCMFirstDeviceHeadsetJack)592 TEST(AlsaJacks, CreateGPIOMicNoUCMFirstDeviceHeadsetJack) {
593   int device_index = 1;
594   int is_first_device = 1;
595   enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_INPUT;
596   int should_create_jack = 1;
597 
598   ResetStubData();
599 
600   // No UCM for this jack, create jack for the first device.
601   ucm_get_dev_for_jack_return = false;
602   ucm_get_device_name_for_dev_value = NULL;
603 
604   // Headset Jack is a valid name for microphone jack.
605   run_gpio_jack_test(
606       device_index, is_first_device, direction, should_create_jack,
607       "c1 Headset Jack");
608 }
609 
TEST(AlsaJacks,GPIOHdmiWithEdid)610 TEST(AlsaJacks, GPIOHdmiWithEdid) {
611   cras_alsa_jack_list* jack_list;
612 
613   ResetStubData();
614   ucm_get_dev_for_jack_return = 1;
615   edid_file_ret = static_cast<char*>(calloc(1, 1));  // Freed in destroy.
616   gpio_switch_list_for_each_dev_names.push_back("c1 HDMI Jack");
617   eviocbit_ret[LONG(SW_LINEOUT_INSERT)] |= 1 << OFF(SW_LINEOUT_INSERT);
618   gpio_switch_eviocgbit_fd = 3;
619   snd_hctl_first_elem_return_val = NULL;
620   jack_list = cras_alsa_jack_list_create(
621       0,
622       "c1",
623       0,
624       1,
625       fake_mixer,
626       reinterpret_cast<struct cras_use_case_mgr *>(0x55),
627       fake_hctl,
628       CRAS_STREAM_OUTPUT,
629       fake_jack_cb,
630       fake_jack_cb_arg);
631   ASSERT_NE(static_cast<cras_alsa_jack_list*>(NULL), jack_list);
632   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
633   EXPECT_EQ(1, gpio_switch_eviocgsw_called);
634 
635   // EDID shouldn't open, callback should be skipped until re-try.
636   fake_jack_cb_called = 0;
637   cras_alsa_jack_list_report(jack_list);
638   EXPECT_EQ(0, fake_jack_cb_called);
639 
640   cras_alsa_jack_list_destroy(jack_list);
641   EXPECT_EQ(1, gpio_switch_list_for_each_called);
642   EXPECT_GT(gpio_switch_open_called, 1);
643   EXPECT_GT(gpio_switch_eviocgbit_called, 1);
644   EXPECT_EQ(1, cras_system_add_select_fd_called);
645   EXPECT_EQ(1, cras_system_rm_select_fd_called);
646 }
647 
TEST(AlsaJacks,CreateGPIOHpNoNameMatch)648 TEST(AlsaJacks, CreateGPIOHpNoNameMatch) {
649   struct cras_alsa_jack_list *jack_list;
650 
651   ResetStubData();
652   gpio_switch_list_for_each_dev_names.push_back("some-other-device one");
653   gpio_switch_list_for_each_dev_names.push_back("some-other-device two");
654   snd_hctl_first_elem_return_val = NULL;
655   jack_list = cras_alsa_jack_list_create(0, "c2", 0, 1,
656                                          fake_mixer,
657                                          NULL, fake_hctl,
658                                          CRAS_STREAM_OUTPUT,
659                                          fake_jack_cb,
660                                          fake_jack_cb_arg);
661   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
662   EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
663 
664   cras_alsa_jack_list_destroy(jack_list);
665   EXPECT_EQ(1, gpio_switch_list_for_each_called);
666   EXPECT_EQ(0, gpio_switch_open_called);
667   EXPECT_EQ(0, cras_system_add_select_fd_called);
668   EXPECT_EQ(0, cras_system_rm_select_fd_called);
669 }
670 
TEST(AlsaJacks,CreateOneHpJack)671 TEST(AlsaJacks, CreateOneHpJack) {
672   std::string elem_names[] = {
673     "asdf",
674     "Headphone Jack, klasdjf",
675     "Mic Jack",
676   };
677   struct cras_alsa_jack_list *jack_list;
678 
679   ResetStubData();
680   jack_list = run_test_with_elem_list(CRAS_STREAM_OUTPUT,
681                                       elem_names,
682                                       0,
683                                       NULL,
684                                       ARRAY_SIZE(elem_names),
685                                       0,
686                                       1);
687   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
688   ASSERT_NE(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
689             snd_hctl_elem_set_callback_value);
690   EXPECT_EQ(1, snd_hctl_elem_set_callback_called);
691 
692   snd_hctl_elem_get_hctl_return_value = reinterpret_cast<snd_hctl_t *>(0x33);
693   snd_hctl_elem_get_name_called = 0;
694   snd_ctl_elem_value_get_boolean_return_value = 1;
695   snd_hctl_elem_set_callback_value(
696       reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]), 0);
697   EXPECT_EQ(1, snd_hctl_elem_get_name_called);
698   EXPECT_EQ(1, fake_jack_cb_plugged);
699   EXPECT_EQ(1, fake_jack_cb_called);
700   EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
701   EXPECT_EQ(reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]),
702             snd_hctl_elem_set_callback_obj);
703 
704   fake_jack_cb_called = 0;
705   cras_alsa_jack_list_report(jack_list);
706   EXPECT_EQ(1, fake_jack_cb_plugged);
707   EXPECT_EQ(1, fake_jack_cb_called);
708 
709   cras_alsa_jack_list_destroy(jack_list);
710   EXPECT_EQ(2, snd_hctl_elem_set_callback_called);
711   EXPECT_EQ(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
712             snd_hctl_elem_set_callback_value);
713 }
714 
TEST(AlsaJacks,CreateOneMicJack)715 TEST(AlsaJacks, CreateOneMicJack) {
716   static std::string elem_names[] = {
717     "asdf",
718     "Headphone Jack",
719     "HDMI/DP,pcm=5 Jack",
720     "HDMI/DP,pcm=6 Jack",
721     "Mic Jack",
722   };
723   struct cras_alsa_jack_list *jack_list;
724 
725   ResetStubData();
726   jack_list = run_test_with_elem_list(CRAS_STREAM_INPUT,
727                                       elem_names,
728                                       0,
729                                       NULL,
730                                       ARRAY_SIZE(elem_names),
731                                       0,
732                                       1);
733   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
734   ASSERT_NE(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
735             snd_hctl_elem_set_callback_value);
736   EXPECT_EQ(1, snd_hctl_elem_set_callback_called);
737 
738   cras_alsa_jack_list_destroy(jack_list);
739   EXPECT_EQ(0, cras_system_rm_select_fd_called);
740   EXPECT_EQ(2, snd_hctl_elem_set_callback_called);
741   EXPECT_EQ(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
742             snd_hctl_elem_set_callback_value);
743 }
744 
TEST(AlsaJacks,CreateHDMIJacksWithELD)745 TEST(AlsaJacks, CreateHDMIJacksWithELD) {
746   std::string elem_names[] = {
747     "asdf",
748     "HDMI/DP,pcm=3 Jack",
749     "ELD",
750     "HDMI/DP,pcm=4 Jack"
751   };
752   struct cras_alsa_jack_list *jack_list;
753 
754   ResetStubData();
755   snd_hctl_elem_get_device_return_val = 3;
756 
757   jack_list = run_test_with_elem_list(
758       CRAS_STREAM_OUTPUT,
759       elem_names,
760       3,
761       NULL,
762       ARRAY_SIZE(elem_names),
763       1,
764       1);
765   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
766 
767   /* Assert get device is called for the ELD control */
768   EXPECT_EQ(1, snd_hctl_elem_get_device_called);
769   cras_alsa_jack_list_destroy(jack_list);
770 }
771 
TEST(AlsaJacks,CreateOneHpTwoHDMIJacks)772 TEST(AlsaJacks, CreateOneHpTwoHDMIJacks) {
773   std::string elem_names[] = {
774     "asdf",
775     "Headphone Jack, klasdjf",
776     "HDMI/DP,pcm=5 Jack",
777     "HDMI/DP,pcm=6 Jack",
778     "Mic Jack",
779   };
780   struct cras_alsa_jack_list *jack_list;
781 
782   ResetStubData();
783   ucm_get_dev_for_jack_return = true;
784   jack_list = run_test_with_elem_list(
785       CRAS_STREAM_OUTPUT,
786       elem_names,
787       5,
788       reinterpret_cast<struct cras_use_case_mgr *>(0x55),
789       ARRAY_SIZE(elem_names),
790       1,
791       1);
792   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
793 
794   snd_hctl_elem_get_hctl_return_value = reinterpret_cast<snd_hctl_t *>(0x33);
795   snd_hctl_elem_get_name_called = 0;
796   snd_ctl_elem_value_get_boolean_return_value = 1;
797   snd_hctl_elem_set_callback_value(
798       reinterpret_cast<snd_hctl_elem_t *>(&elem_names[2]), 0);
799   EXPECT_EQ(1, snd_hctl_elem_get_name_called);
800   EXPECT_EQ(1, fake_jack_cb_plugged);
801   EXPECT_EQ(1, fake_jack_cb_called);
802   EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
803   EXPECT_EQ(reinterpret_cast<snd_hctl_elem_t *>(&elem_names[2]),
804             snd_hctl_elem_set_callback_obj);
805 
806   fake_jack_cb_called = 0;
807   cras_alsa_jack_list_report(jack_list);
808   EXPECT_EQ(1, fake_jack_cb_plugged);
809   EXPECT_EQ(1, fake_jack_cb_called);
810 
811   cras_alsa_jack_list_destroy(jack_list);
812 }
813 
TEST(AlsaJacks,CreateHCTLHeadphoneJackFromUCM)814 TEST(AlsaJacks, CreateHCTLHeadphoneJackFromUCM) {
815   std::string elem_names[] = {
816     "HP/DP,pcm=5 Jack",
817     "Headphone Jack",
818   };
819   struct cras_alsa_jack_list *jack_list;
820   struct ucm_section *section;
821 
822   section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
823                                "Headphone Jack", "hctl");
824 
825   ResetStubData();
826   ucm_get_dev_for_jack_return = true;
827 
828   jack_list = run_test_with_section(
829       CRAS_STREAM_OUTPUT,
830       elem_names,
831       ARRAY_SIZE(elem_names),
832       5,
833       reinterpret_cast<struct cras_use_case_mgr *>(0x55),
834       section,
835       0,
836       1);
837   ASSERT_NE(reinterpret_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
838 
839   snd_hctl_elem_get_hctl_return_value = reinterpret_cast<snd_hctl_t *>(0x33);
840   snd_ctl_elem_value_get_boolean_return_value = 1;
841   snd_hctl_elem_set_callback_value(
842       reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]), 0);
843   EXPECT_EQ(1, snd_hctl_elem_get_name_called);
844   EXPECT_EQ(1, fake_jack_cb_plugged);
845   EXPECT_EQ(1, fake_jack_cb_called);
846   EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
847   EXPECT_EQ(reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]),
848             snd_hctl_elem_set_callback_obj);
849 
850   fake_jack_cb_called = 0;
851   cras_alsa_jack_list_report(jack_list);
852   EXPECT_EQ(1, fake_jack_cb_plugged);
853   EXPECT_EQ(1, fake_jack_cb_called);
854 
855   ucm_section_free_list(section);
856   cras_alsa_jack_list_destroy(jack_list);
857 }
858 
TEST(AlsaJacks,CreateGPIOHeadphoneJackFromUCM)859 TEST(AlsaJacks, CreateGPIOHeadphoneJackFromUCM) {
860   struct cras_alsa_jack_list *jack_list;
861   struct cras_alsa_jack *jack;
862   struct ucm_section *section;
863 
864   section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
865                                "c1 Headphone Jack", "gpio");
866 
867   ResetStubData();
868   gpio_switch_list_for_each_dev_names.push_back("some-other-device");
869   gpio_switch_list_for_each_dev_names.push_back("c1 Headphone Jack");
870   eviocbit_ret[LONG(SW_HEADPHONE_INSERT)] |= 1 << OFF(SW_HEADPHONE_INSERT);
871   gpio_switch_eviocgbit_fd = 2;
872   snd_hctl_first_elem_return_val = NULL;
873   jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
874                                          fake_mixer,
875                                          NULL, fake_hctl,
876                                          CRAS_STREAM_OUTPUT,
877                                          fake_jack_cb,
878                                          fake_jack_cb_arg);
879   ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
880   EXPECT_EQ(0, cras_alsa_jack_list_add_jack_for_section(
881                    jack_list, section, &jack));
882   EXPECT_EQ(1, gpio_switch_list_for_each_called);
883   EXPECT_GT(gpio_switch_open_called, 1);
884   EXPECT_EQ(1, gpio_switch_eviocgsw_called);
885   EXPECT_GT(gpio_switch_eviocgbit_called, 1);
886   EXPECT_EQ(1, cras_system_add_select_fd_called);
887   EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called);
888 
889   fake_jack_cb_called = 0;
890   ucm_get_dev_for_jack_return = true;
891   cras_alsa_jack_list_report(jack_list);
892   EXPECT_EQ(1, fake_jack_cb_plugged);
893   EXPECT_EQ(1, fake_jack_cb_called);
894   EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
895 
896   ucm_section_free_list(section);
897   cras_alsa_jack_list_destroy(jack_list);
898   EXPECT_EQ(1, cras_system_rm_select_fd_called);
899 }
900 
TEST(AlsaJacks,BadJackTypeFromUCM)901 TEST(AlsaJacks, BadJackTypeFromUCM) {
902   std::string elem_names[] = {
903     "HP/DP,pcm=5 Jack",
904     "Headphone Jack",
905   };
906   struct cras_alsa_jack_list *jack_list;
907   struct ucm_section *section;
908 
909   section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
910                                "Headphone Jack", "badtype");
911 
912   ResetStubData();
913   ucm_get_dev_for_jack_return = true;
914 
915   jack_list = run_test_with_section(
916       CRAS_STREAM_OUTPUT,
917       elem_names,
918       ARRAY_SIZE(elem_names),
919       5,
920       reinterpret_cast<struct cras_use_case_mgr *>(0x55),
921       section,
922       -22,
923       1);
924   EXPECT_EQ(reinterpret_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
925 
926   ucm_section_free_list(section);
927 }
928 
TEST(AlsaJacks,NoJackTypeFromUCM)929 TEST(AlsaJacks, NoJackTypeFromUCM) {
930   std::string elem_names[] = {
931     "HP/DP,pcm=5 Jack",
932     "Headphone Jack",
933   };
934   struct cras_alsa_jack_list *jack_list;
935   struct ucm_section *section;
936 
937   section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
938                                "Headphone Jack", NULL);
939 
940   ResetStubData();
941   ucm_get_dev_for_jack_return = true;
942 
943   jack_list = run_test_with_section(
944       CRAS_STREAM_OUTPUT,
945       elem_names,
946       ARRAY_SIZE(elem_names),
947       5,
948       reinterpret_cast<struct cras_use_case_mgr *>(0x55),
949       section,
950       -22,
951       1);
952   EXPECT_EQ(reinterpret_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
953 
954   ucm_section_free_list(section);
955 }
956 
957 /* Stubs */
958 
959 extern "C" {
960 
961 // From cras_system_state
cras_system_add_select_fd(int fd,void (* callback)(void * data),void * callback_data)962 int cras_system_add_select_fd(int fd,
963 			      void (*callback)(void *data),
964 			      void *callback_data)
965 {
966   cras_system_add_select_fd_called++;
967   cras_system_add_select_fd_values.push_back(fd);
968   return 0;
969 }
cras_system_rm_select_fd(int fd)970 void cras_system_rm_select_fd(int fd)
971 {
972   cras_system_rm_select_fd_called++;
973   cras_system_rm_select_fd_values.push_back(fd);
974 }
975 
976 // From alsa-lib hcontrol.c
snd_hctl_elem_get_device(const snd_hctl_elem_t * obj)977 unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj) {
978   snd_hctl_elem_get_device_called = 1;
979   return snd_hctl_elem_get_device_return_val;
980 }
snd_hctl_first_elem(snd_hctl_t * hctl)981 snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl) {
982   snd_hctl_first_elem_called++;
983 
984   /* When first elem is called, restored the poped ret values */
985   while (!snd_hctl_elem_next_ret_vals_poped.empty()) {
986     snd_hctl_elem_t *tmp = snd_hctl_elem_next_ret_vals_poped.back();
987     snd_hctl_elem_next_ret_vals_poped.pop_back();
988     snd_hctl_elem_next_ret_vals.push_back(tmp);
989   }
990   return snd_hctl_first_elem_return_val;
991 }
snd_hctl_elem_next(snd_hctl_elem_t * elem)992 snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem) {
993   snd_hctl_elem_next_called++;
994   if (snd_hctl_elem_next_ret_vals.empty())
995     return NULL;
996   snd_hctl_elem_t *ret_elem = snd_hctl_elem_next_ret_vals.back();
997   snd_hctl_elem_next_ret_vals.pop_back();
998   snd_hctl_elem_next_ret_vals_poped.push_back(ret_elem);
999   return ret_elem;
1000 }
snd_hctl_elem_get_name(const snd_hctl_elem_t * obj)1001 const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj) {
1002   snd_hctl_elem_get_name_called++;
1003   const std::string *name = reinterpret_cast<const std::string *>(obj);
1004   return name->c_str();
1005 }
snd_hctl_elem_get_interface(const snd_hctl_elem_t * obj)1006 snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj) {
1007   return SND_CTL_ELEM_IFACE_CARD;
1008 }
snd_hctl_elem_set_callback(snd_hctl_elem_t * obj,snd_hctl_elem_callback_t val)1009 void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj,
1010                                 snd_hctl_elem_callback_t val) {
1011   snd_hctl_elem_set_callback_called++;
1012   snd_hctl_elem_set_callback_obj = obj;
1013   snd_hctl_elem_set_callback_value = val;
1014 }
snd_hctl_elem_set_callback_private(snd_hctl_elem_t * obj,void * val)1015 void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val) {
1016   snd_hctl_elem_set_callback_private_called++;
1017   snd_hctl_elem_set_callback_private_value = val;
1018 }
snd_hctl_elem_get_callback_private(const snd_hctl_elem_t * obj)1019 void *snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj) {
1020   return snd_hctl_elem_set_callback_private_value;
1021 }
snd_hctl_elem_get_hctl(snd_hctl_elem_t * elem)1022 snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem) {
1023   snd_hctl_elem_get_hctl_called++;
1024   return snd_hctl_elem_get_hctl_return_value;
1025 }
snd_hctl_elem_read(snd_hctl_elem_t * elem,snd_ctl_elem_value_t * value)1026 int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value) {
1027   return 0;
1028 }
snd_hctl_find_elem(snd_hctl_t * hctl,const snd_ctl_elem_id_t * id)1029 snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl,
1030                                     const snd_ctl_elem_id_t *id) {
1031   const size_t* index = reinterpret_cast<const size_t*>(id);
1032   snd_hctl_find_elem_called++;
1033   if (*index < snd_hctl_find_elem_return_vals.size())
1034     return snd_hctl_find_elem_return_vals[*index];
1035   return NULL;
1036 }
snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t * obj,snd_ctl_elem_iface_t val)1037 void snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t *obj,
1038                                    snd_ctl_elem_iface_t val) {
1039 }
snd_ctl_elem_id_set_device(snd_ctl_elem_id_t * obj,unsigned int val)1040 void snd_ctl_elem_id_set_device(snd_ctl_elem_id_t *obj, unsigned int val) {
1041 }
snd_ctl_elem_id_set_name(snd_ctl_elem_id_t * obj,const char * val)1042 void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val) {
1043   size_t *obj_id = reinterpret_cast<size_t*>(obj);
1044   std::map<std::string, size_t>::iterator id_name_it =
1045       snd_ctl_elem_id_set_name_map.find(val);
1046   if (id_name_it != snd_ctl_elem_id_set_name_map.end())
1047     *obj_id = id_name_it->second;
1048   else
1049     *obj_id = INT_MAX;
1050 }
1051 
1052 // From alsa-lib control.c
snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t * obj,unsigned int idx)1053 int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj,
1054                                    unsigned int idx) {
1055   snd_ctl_elem_value_get_boolean_called++;
1056   return snd_ctl_elem_value_get_boolean_return_value;
1057 }
1058 
1059 // From cras_alsa_mixer
cras_alsa_mixer_get_output_matching_name(const struct cras_alsa_mixer * cras_mixer,size_t device_index,const char * const name)1060 struct mixer_control *cras_alsa_mixer_get_output_matching_name(
1061     const struct cras_alsa_mixer *cras_mixer,
1062     size_t device_index,
1063     const char * const name)
1064 {
1065   cras_alsa_mixer_get_output_matching_name_called++;
1066   return cras_alsa_mixer_get_output_matching_name_return_value;
1067 }
1068 
cras_alsa_mixer_get_input_matching_name(struct cras_alsa_mixer * cras_mixer,const char * control_name)1069 struct mixer_control *cras_alsa_mixer_get_input_matching_name(
1070     struct cras_alsa_mixer *cras_mixer,
1071     const char *control_name)
1072 {
1073   cras_alsa_mixer_get_input_matching_name_called++;
1074   return cras_alsa_mixer_get_input_matching_name_return_value;
1075 }
1076 
cras_alsa_mixer_get_control_for_section(struct cras_alsa_mixer * cras_mixer,struct ucm_section * section)1077 struct mixer_control *cras_alsa_mixer_get_control_for_section(
1078     struct cras_alsa_mixer *cras_mixer,
1079     struct ucm_section *section)
1080 {
1081   cras_alsa_mixer_get_control_for_section_called++;
1082   return cras_alsa_mixer_get_control_for_section_return_value;
1083 }
1084 
gpio_switch_eviocgbit(int fd,void * buf,size_t n_bytes)1085 int gpio_switch_eviocgbit(int fd, void *buf, size_t n_bytes)
1086 {
1087   unsigned char *p = (unsigned char *)buf;
1088 
1089   /* Returns >= 0 if 'sw' is supported, negative if not.
1090    *
1091    *  Set the bit corresponding to 'sw' in 'buf'.  'buf' must have
1092    *  been allocated by the caller to accommodate this.
1093    */
1094   if (fd  == gpio_switch_eviocgbit_fd)
1095     memcpy(p, eviocbit_ret, n_bytes);
1096   else
1097     memset(p, 0, n_bytes);
1098 
1099   gpio_switch_eviocgbit_called++;
1100   return 1;
1101 }
1102 
gpio_switch_eviocgsw(int fd,void * bits,size_t n_bytes)1103 int gpio_switch_eviocgsw(int fd, void *bits, size_t n_bytes)
1104 {
1105   /* Bits set to '1' indicate a switch is enabled.
1106    * Bits set to '0' indicate a switch is disabled
1107    */
1108   gpio_switch_eviocgsw_called++;
1109   memset(bits, 0xff, n_bytes);
1110   return 1;
1111 }
1112 
gpio_switch_read(int fd,void * buf,size_t n_bytes)1113 int gpio_switch_read(int fd, void *buf, size_t n_bytes)
1114 {
1115   /* This function is only invoked when the 'switch has changed'
1116    * callback is invoked.  That code is not exercised by this
1117    * unittest.
1118    */
1119   assert(0);
1120   return 0;
1121 }
1122 
gpio_switch_open(const char * pathname)1123 int gpio_switch_open(const char *pathname)
1124 {
1125   ++gpio_switch_open_called;
1126   if (strstr(pathname, "event2"))
1127 	  return 2;
1128   if (strstr(pathname, "event3"))
1129 	  return 3;
1130   return 0;
1131 }
1132 
gpio_switch_list_for_each(gpio_switch_list_callback callback,void * arg)1133 void gpio_switch_list_for_each(gpio_switch_list_callback callback, void *arg)
1134 {
1135   size_t i = 0;
1136 
1137   ++gpio_switch_list_for_each_called;
1138 
1139   while (i < gpio_switch_list_for_each_dev_names.size() &&
1140          i < gpio_switch_list_for_each_dev_paths.size()) {
1141     callback(gpio_switch_list_for_each_dev_paths[i].c_str(),
1142              gpio_switch_list_for_each_dev_names[i].c_str(),
1143              arg);
1144     i++;
1145   }
1146 }
1147 
ucm_set_enabled(struct cras_use_case_mgr * mgr,const char * dev,int enable)1148 int ucm_set_enabled(
1149     struct cras_use_case_mgr *mgr, const char *dev, int enable) {
1150   ucm_set_enabled_value = enable;
1151   return 0;
1152 }
1153 
ucm_get_cap_control(struct cras_use_case_mgr * mgr,const char * ucm_dev)1154 char *ucm_get_cap_control(struct cras_use_case_mgr *mgr, const char *ucm_dev) {
1155   ++ucm_get_cap_control_called;
1156   return ucm_get_cap_control_value;
1157 }
1158 
ucm_get_dev_for_jack(struct cras_use_case_mgr * mgr,const char * jack,CRAS_STREAM_DIRECTION direction)1159 char *ucm_get_dev_for_jack(struct cras_use_case_mgr *mgr, const char *jack,
1160                            CRAS_STREAM_DIRECTION direction) {
1161   ++ucm_get_dev_for_jack_called;
1162   if (ucm_get_dev_for_jack_return)
1163     return static_cast<char*>(malloc(1)); // Will be freed in jack_list_destroy.
1164   return NULL;
1165 }
1166 
ucm_get_dsp_name(struct cras_use_case_mgr * mgr,const char * ucm_dev,int direction)1167 const char *ucm_get_dsp_name(struct cras_use_case_mgr *mgr, const char *ucm_dev,
1168                        int direction) {
1169   ++ucm_get_dsp_name_called;
1170   return NULL;
1171 }
1172 
ucm_get_edid_file_for_dev(struct cras_use_case_mgr * mgr,const char * dev)1173 const char *ucm_get_edid_file_for_dev(struct cras_use_case_mgr *mgr,
1174 				      const char *dev) {
1175   return edid_file_ret;
1176 }
1177 
ucm_get_override_type_name(struct cras_use_case_mgr * mgr,const char * ucm_dev)1178 const char *ucm_get_override_type_name(struct cras_use_case_mgr *mgr,
1179                                        const char *ucm_dev)
1180 {
1181   ++ucm_get_override_type_name_called;
1182   return NULL;
1183 }
1184 
ucm_get_device_name_for_dev(struct cras_use_case_mgr * mgr,const char * dev,enum CRAS_STREAM_DIRECTION direction)1185 const char *ucm_get_device_name_for_dev(struct cras_use_case_mgr *mgr,
1186                                         const char *dev,
1187                                         enum CRAS_STREAM_DIRECTION direction)
1188 {
1189   return ucm_get_device_name_for_dev_value;
1190 }
1191 
cras_tm_create_timer(cras_tm * tm,unsigned int ms,void (* cb)(cras_timer * t,void * data),void * cb_data)1192 cras_timer *cras_tm_create_timer(
1193     cras_tm *tm,
1194     unsigned int ms,
1195     void (*cb)(cras_timer *t, void *data),
1196     void *cb_data) {
1197   return reinterpret_cast<cras_timer*>(0x55);
1198 }
1199 
cras_tm_cancel_timer(cras_tm * tm,cras_timer * t)1200 void cras_tm_cancel_timer(cras_tm *tm, cras_timer *t) {
1201 }
1202 
cras_system_state_get_tm()1203 cras_tm *cras_system_state_get_tm() {
1204   return reinterpret_cast<cras_tm*>(0x66);
1205 }
1206 
edid_valid(const unsigned char * edid_data)1207 int edid_valid(const unsigned char *edid_data) {
1208   return 0;
1209 }
1210 
edid_lpcm_support(const unsigned char * edid_data,int ext)1211 int edid_lpcm_support(const unsigned char *edid_data, int ext) {
1212   return 0;
1213 }
1214 
edid_get_monitor_name(const unsigned char * edid_data,char * buf,unsigned int buf_size)1215 int edid_get_monitor_name(const unsigned char *edid_data,
1216                           char *buf,
1217                           unsigned int buf_size) {
1218   return 0;
1219 }
1220 
1221 // Overwrite this function so unittest can run without 2 seconds of wait
1222 // in find_gpio_jacks.
wait_for_dev_input_access()1223 int wait_for_dev_input_access() {
1224   return 0;
1225 }
1226 
1227 } /* extern "C" */
1228 
1229 }  //  namespace
1230 
main(int argc,char ** argv)1231 int main(int argc, char **argv) {
1232   ::testing::InitGoogleTest(&argc, argv);
1233   openlog(NULL, LOG_PERROR, LOG_USER);
1234   return RUN_ALL_TESTS();
1235 }
1236