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