1 // Copyright (c) 2013 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 <stdint.h>
7 #include <stdio.h>
8
9 extern "C" {
10
11 #include "a2dp-codecs.h"
12 #include "audio_thread.h"
13 #include "audio_thread_log.h"
14 #include "cras_a2dp_iodev.h"
15 #include "cras_audio_area.h"
16 #include "cras_bt_transport.h"
17 #include "cras_iodev.h"
18 }
19
20 #define FAKE_OBJECT_PATH "/fake/obj/path"
21
22 #define MAX_A2DP_ENCODE_CALLS 8
23 #define MAX_A2DP_WRITE_CALLS 4
24
25 static struct cras_bt_transport* fake_transport;
26 static cras_audio_format format;
27 static size_t cras_bt_device_append_iodev_called;
28 static size_t cras_bt_device_rm_iodev_called;
29 static size_t cras_iodev_add_node_called;
30 static int cras_iodev_frames_queued_called;
31 static size_t cras_iodev_rm_node_called;
32 static size_t cras_iodev_set_active_node_called;
33 static size_t cras_bt_transport_acquire_called;
34 static size_t cras_bt_transport_configuration_called;
35 static size_t cras_bt_transport_release_called;
36 static size_t init_a2dp_called;
37 static int init_a2dp_return_val;
38 static size_t destroy_a2dp_called;
39 static size_t drain_a2dp_called;
40 static size_t a2dp_block_size_called;
41 static size_t a2dp_queued_frames_val;
42 static size_t cras_iodev_free_format_called;
43 static size_t cras_iodev_free_resources_called;
44 static int pcm_buf_size_val[MAX_A2DP_ENCODE_CALLS];
45 static unsigned int a2dp_encode_processed_bytes_val[MAX_A2DP_ENCODE_CALLS];
46 static unsigned int a2dp_encode_index;
47 static int a2dp_write_return_val[MAX_A2DP_WRITE_CALLS];
48 static unsigned int a2dp_write_index;
49 static cras_audio_area* dummy_audio_area;
50 static thread_callback write_callback;
51 static void* write_callback_data;
52 static const char* fake_device_name = "fake device name";
53 static const char* cras_bt_device_name_ret;
54 static unsigned int cras_bt_transport_write_mtu_ret;
55
ResetStubData()56 void ResetStubData() {
57 cras_bt_device_append_iodev_called = 0;
58 cras_bt_device_rm_iodev_called = 0;
59 cras_iodev_add_node_called = 0;
60 cras_iodev_frames_queued_called = 0;
61 cras_iodev_rm_node_called = 0;
62 cras_iodev_set_active_node_called = 0;
63 cras_bt_transport_acquire_called = 0;
64 cras_bt_transport_configuration_called = 0;
65 cras_bt_transport_release_called = 0;
66 init_a2dp_called = 0;
67 init_a2dp_return_val = 0;
68 destroy_a2dp_called = 0;
69 drain_a2dp_called = 0;
70 a2dp_block_size_called = 0;
71 a2dp_queued_frames_val = 0;
72 cras_iodev_free_format_called = 0;
73 cras_iodev_free_resources_called = 0;
74 memset(a2dp_encode_processed_bytes_val, 0,
75 sizeof(a2dp_encode_processed_bytes_val));
76 a2dp_encode_index = 0;
77 a2dp_write_index = 0;
78 cras_bt_transport_write_mtu_ret = 800;
79
80 fake_transport = reinterpret_cast<struct cras_bt_transport*>(0x123);
81
82 if (!dummy_audio_area) {
83 dummy_audio_area = (cras_audio_area*)calloc(
84 1, sizeof(*dummy_audio_area) + sizeof(cras_channel_area) * 2);
85 }
86
87 write_callback = NULL;
88 }
89
iodev_set_format(struct cras_iodev * iodev,struct cras_audio_format * fmt)90 int iodev_set_format(struct cras_iodev* iodev, struct cras_audio_format* fmt) {
91 fmt->format = SND_PCM_FORMAT_S16_LE;
92 fmt->num_channels = 2;
93 fmt->frame_rate = 44100;
94 iodev->format = fmt;
95 return 0;
96 }
97
98 namespace {
99
100 static struct timespec time_now;
101 class A2dpIodev : public testing::Test {
102 protected:
SetUp()103 virtual void SetUp() {
104 ResetStubData();
105 atlog = (audio_thread_event_log*)calloc(1, sizeof(audio_thread_event_log));
106 }
107
TearDown()108 virtual void TearDown() {
109 free(dummy_audio_area);
110 dummy_audio_area = NULL;
111 free(atlog);
112 }
113 };
114
TEST_F(A2dpIodev,InitializeA2dpIodev)115 TEST_F(A2dpIodev, InitializeA2dpIodev) {
116 struct cras_iodev* iodev;
117
118 cras_bt_device_name_ret = NULL;
119 iodev = a2dp_iodev_create(fake_transport);
120
121 ASSERT_NE(iodev, (void*)NULL);
122 ASSERT_EQ(iodev->direction, CRAS_STREAM_OUTPUT);
123 ASSERT_EQ(1, cras_bt_transport_configuration_called);
124 ASSERT_EQ(1, init_a2dp_called);
125 ASSERT_EQ(1, cras_bt_device_append_iodev_called);
126 ASSERT_EQ(1, cras_iodev_add_node_called);
127 ASSERT_EQ(1, cras_iodev_set_active_node_called);
128
129 /* Assert iodev name matches the object path when bt device doesn't
130 * have its readable name populated. */
131 ASSERT_STREQ(FAKE_OBJECT_PATH, iodev->info.name);
132
133 a2dp_iodev_destroy(iodev);
134
135 ASSERT_EQ(1, cras_bt_device_rm_iodev_called);
136 ASSERT_EQ(1, cras_iodev_rm_node_called);
137 ASSERT_EQ(1, destroy_a2dp_called);
138 ASSERT_EQ(1, cras_iodev_free_resources_called);
139
140 cras_bt_device_name_ret = fake_device_name;
141 /* Assert iodev name matches the bt device's name */
142 iodev = a2dp_iodev_create(fake_transport);
143 ASSERT_STREQ(fake_device_name, iodev->info.name);
144
145 a2dp_iodev_destroy(iodev);
146 }
147
TEST_F(A2dpIodev,InitializeFail)148 TEST_F(A2dpIodev, InitializeFail) {
149 struct cras_iodev* iodev;
150
151 init_a2dp_return_val = -1;
152 iodev = a2dp_iodev_create(fake_transport);
153
154 ASSERT_EQ(iodev, (void*)NULL);
155 ASSERT_EQ(1, cras_bt_transport_configuration_called);
156 ASSERT_EQ(1, init_a2dp_called);
157 ASSERT_EQ(0, cras_bt_device_append_iodev_called);
158 ASSERT_EQ(0, cras_iodev_add_node_called);
159 ASSERT_EQ(0, cras_iodev_set_active_node_called);
160 ASSERT_EQ(0, cras_iodev_rm_node_called);
161 }
162
TEST_F(A2dpIodev,OpenIodev)163 TEST_F(A2dpIodev, OpenIodev) {
164 struct cras_iodev* iodev;
165
166 iodev = a2dp_iodev_create(fake_transport);
167
168 iodev_set_format(iodev, &format);
169 iodev->configure_dev(iodev);
170
171 ASSERT_EQ(1, cras_bt_transport_acquire_called);
172
173 iodev->close_dev(iodev);
174 ASSERT_EQ(1, cras_bt_transport_release_called);
175 ASSERT_EQ(1, drain_a2dp_called);
176 ASSERT_EQ(1, cras_iodev_free_format_called);
177
178 a2dp_iodev_destroy(iodev);
179 }
180
TEST_F(A2dpIodev,GetPutBuffer)181 TEST_F(A2dpIodev, GetPutBuffer) {
182 struct cras_iodev* iodev;
183 struct cras_audio_area *area1, *area2, *area3;
184 uint8_t* area1_buf;
185 unsigned frames;
186
187 iodev = a2dp_iodev_create(fake_transport);
188
189 iodev_set_format(iodev, &format);
190 iodev->configure_dev(iodev);
191 ASSERT_NE(write_callback, (void*)NULL);
192
193 frames = 256;
194 iodev->get_buffer(iodev, &area1, &frames);
195 ASSERT_EQ(256, frames);
196 ASSERT_EQ(256, area1->frames);
197 area1_buf = area1->channels[0].buf;
198
199 /* Test 100 frames(400 bytes) put and all processed. */
200 a2dp_encode_processed_bytes_val[0] = 400;
201 a2dp_write_index = 0;
202 a2dp_write_return_val[0] = 400;
203 iodev->put_buffer(iodev, 100);
204 write_callback(write_callback_data);
205 // Start with 4k frames.
206 EXPECT_EQ(400, pcm_buf_size_val[0]);
207
208 iodev->get_buffer(iodev, &area2, &frames);
209 ASSERT_EQ(256, frames);
210 ASSERT_EQ(256, area2->frames);
211
212 /* Assert buf2 points to the same position as buf1 */
213 ASSERT_EQ(400, area2->channels[0].buf - area1_buf);
214
215 /* Test 100 frames(400 bytes) put, only 360 bytes processed,
216 * 40 bytes left in pcm buffer.
217 */
218 a2dp_encode_index = 0;
219 a2dp_encode_processed_bytes_val[0] = 360;
220 a2dp_encode_processed_bytes_val[1] = 0;
221 a2dp_write_index = 0;
222 a2dp_write_return_val[0] = 360;
223 a2dp_write_return_val[1] = 0;
224 iodev->put_buffer(iodev, 100);
225 write_callback(write_callback_data);
226 EXPECT_EQ(400, pcm_buf_size_val[0]);
227 ASSERT_EQ(40, pcm_buf_size_val[1]);
228
229 iodev->get_buffer(iodev, &area3, &frames);
230
231 /* Existing buffer not completed processed, assert new buffer starts from
232 * current write pointer.
233 */
234 ASSERT_EQ(256, frames);
235 EXPECT_EQ(800, area3->channels[0].buf - area1_buf);
236
237 iodev->close_dev(iodev);
238 a2dp_iodev_destroy(iodev);
239 }
240
TEST_F(A2dpIodev,FramesQueued)241 TEST_F(A2dpIodev, FramesQueued) {
242 struct cras_iodev* iodev;
243 struct cras_audio_area* area;
244 struct timespec tstamp;
245 unsigned frames;
246
247 iodev = a2dp_iodev_create(fake_transport);
248
249 iodev_set_format(iodev, &format);
250 time_now.tv_sec = 0;
251 time_now.tv_nsec = 0;
252 iodev->configure_dev(iodev);
253 ASSERT_NE(write_callback, (void*)NULL);
254
255 frames = 256;
256 iodev->get_buffer(iodev, &area, &frames);
257 ASSERT_EQ(256, frames);
258 ASSERT_EQ(256, area->frames);
259
260 /* Put 100 frames, proccessed 400 bytes to a2dp buffer.
261 * Assume 200 bytes written out, queued 50 frames in a2dp buffer.
262 */
263 a2dp_encode_processed_bytes_val[0] = 400;
264 a2dp_write_return_val[0] = 50;
265 a2dp_queued_frames_val = 50;
266 time_now.tv_sec = 0;
267 time_now.tv_nsec = 1000000;
268 iodev->put_buffer(iodev, 200);
269 write_callback(write_callback_data);
270 EXPECT_EQ(200, iodev->frames_queued(iodev, &tstamp));
271 EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec);
272 EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec);
273
274 /* After writing another 200 frames, check for correct buffer level. */
275 time_now.tv_sec = 0;
276 time_now.tv_nsec = 2000000;
277 a2dp_encode_index = 0;
278 a2dp_write_index = 0;
279 a2dp_encode_processed_bytes_val[0] = 400;
280 write_callback(write_callback_data);
281 /* 1000000 nsec has passed, estimated queued frames adjusted by 44 */
282 EXPECT_EQ(156, iodev->frames_queued(iodev, &tstamp));
283 EXPECT_EQ(400, pcm_buf_size_val[0]);
284 EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec);
285 EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec);
286
287 /* Queued frames and new put buffer are all written */
288 a2dp_encode_processed_bytes_val[0] = 400;
289 a2dp_encode_processed_bytes_val[1] = 0;
290 a2dp_encode_index = 0;
291 a2dp_write_return_val[0] = 400;
292 a2dp_write_return_val[1] = -EAGAIN;
293 a2dp_write_index = 0;
294
295 /* Add wnother 200 samples, get back to the original level. */
296 time_now.tv_sec = 0;
297 time_now.tv_nsec = 50000000;
298 a2dp_encode_processed_bytes_val[0] = 600;
299 a2dp_queued_frames_val = 50;
300 iodev->put_buffer(iodev, 200);
301 EXPECT_EQ(800, pcm_buf_size_val[0]);
302 EXPECT_EQ(100, iodev->frames_queued(iodev, &tstamp));
303 EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec);
304 EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec);
305 iodev->close_dev(iodev);
306 a2dp_iodev_destroy(iodev);
307 }
308
TEST_F(A2dpIodev,FlushAtLowBufferLevel)309 TEST_F(A2dpIodev, FlushAtLowBufferLevel) {
310 struct cras_iodev* iodev;
311 struct cras_audio_area* area;
312 struct timespec tstamp;
313 unsigned frames;
314
315 iodev = a2dp_iodev_create(fake_transport);
316
317 iodev_set_format(iodev, &format);
318 time_now.tv_sec = 0;
319 time_now.tv_nsec = 0;
320 iodev->configure_dev(iodev);
321 ASSERT_NE(write_callback, (void*)NULL);
322
323 ASSERT_EQ(iodev->min_buffer_level, 400);
324
325 frames = 700;
326 iodev->get_buffer(iodev, &area, &frames);
327 ASSERT_EQ(700, frames);
328 ASSERT_EQ(700, area->frames);
329
330 /* First call to a2dp_encode() processed 800 bytes. */
331 a2dp_encode_processed_bytes_val[0] = 800;
332 a2dp_encode_processed_bytes_val[1] = 0;
333 a2dp_write_return_val[0] = 200;
334
335 /* put_buffer shouldn't trigger the 2nd call to a2dp_encode() because
336 * buffer is low. Fake some data to make sure this test case will fail
337 * when a2dp_encode() called twice.
338 */
339 a2dp_encode_processed_bytes_val[2] = 800;
340 a2dp_encode_processed_bytes_val[3] = 0;
341 a2dp_write_return_val[1] = -EAGAIN;
342
343 time_now.tv_nsec = 10000000;
344 iodev->put_buffer(iodev, 700);
345
346 time_now.tv_nsec = 20000000;
347 EXPECT_EQ(500, iodev->frames_queued(iodev, &tstamp));
348 EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec);
349 EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec);
350 iodev->close_dev(iodev);
351 a2dp_iodev_destroy(iodev);
352 }
353
TEST_F(A2dpIodev,NoStreamState)354 TEST_F(A2dpIodev, NoStreamState) {
355 struct cras_iodev* iodev;
356 struct cras_audio_area* area;
357 struct timespec tstamp;
358 unsigned frames;
359
360 iodev = a2dp_iodev_create(fake_transport);
361 iodev_set_format(iodev, &format);
362 time_now.tv_sec = 0;
363 time_now.tv_nsec = 0;
364 iodev->configure_dev(iodev);
365 ASSERT_NE(write_callback, (void*)NULL);
366 ASSERT_EQ(400, iodev->min_buffer_level);
367
368 iodev->min_cb_level = 480;
369 frames = 200;
370 iodev->get_buffer(iodev, &area, &frames);
371 iodev->put_buffer(iodev, 200);
372
373 iodev->no_stream(iodev, 1);
374 EXPECT_EQ(1, cras_iodev_frames_queued_called);
375
376 /* no_stream will fill the buffer to hw_level = (441 (44100 * 0.01)) * 2
377 * frames, but 200 < min_buffer_level so cras_iodev_frames_queued will return
378 * 0 in no_stream and no_stream will fill 882 frames to device buffer.
379 */
380 frames = iodev->frames_queued(iodev, &tstamp);
381 ASSERT_EQ(1082, frames);
382
383 /* After leaving no stream state, output buffer won't be adjusted */
384 iodev->no_stream(iodev, 0);
385 frames = iodev->frames_queued(iodev, &tstamp);
386 ASSERT_EQ(1082, frames);
387 }
388
389 } // namespace
390
main(int argc,char ** argv)391 int main(int argc, char** argv) {
392 ::testing::InitGoogleTest(&argc, argv);
393 return RUN_ALL_TESTS();
394 }
395
396 extern "C" {
397
cras_bt_transport_configuration(const struct cras_bt_transport * transport,void * configuration,int len)398 int cras_bt_transport_configuration(const struct cras_bt_transport* transport,
399 void* configuration,
400 int len) {
401 cras_bt_transport_configuration_called++;
402 return 0;
403 }
404
cras_bt_transport_acquire(struct cras_bt_transport * transport)405 int cras_bt_transport_acquire(struct cras_bt_transport* transport) {
406 cras_bt_transport_acquire_called++;
407 return 0;
408 }
409
cras_bt_transport_release(struct cras_bt_transport * transport,unsigned int blocking)410 int cras_bt_transport_release(struct cras_bt_transport* transport,
411 unsigned int blocking) {
412 cras_bt_transport_release_called++;
413 return 0;
414 }
415
cras_bt_transport_fd(const struct cras_bt_transport * transport)416 int cras_bt_transport_fd(const struct cras_bt_transport* transport) {
417 return 0;
418 }
419
cras_bt_transport_object_path(const struct cras_bt_transport * transport)420 const char* cras_bt_transport_object_path(
421 const struct cras_bt_transport* transport) {
422 return FAKE_OBJECT_PATH;
423 }
424
cras_bt_transport_write_mtu(const struct cras_bt_transport * transport)425 uint16_t cras_bt_transport_write_mtu(
426 const struct cras_bt_transport* transport) {
427 return cras_bt_transport_write_mtu_ret;
428 }
429
cras_bt_transport_set_volume(struct cras_bt_transport * transport,uint16_t volume)430 int cras_bt_transport_set_volume(struct cras_bt_transport* transport,
431 uint16_t volume) {
432 return 0;
433 }
434
cras_iodev_free_format(struct cras_iodev * iodev)435 void cras_iodev_free_format(struct cras_iodev* iodev) {
436 cras_iodev_free_format_called++;
437 }
438
cras_iodev_free_resources(struct cras_iodev * iodev)439 void cras_iodev_free_resources(struct cras_iodev* iodev) {
440 cras_iodev_free_resources_called++;
441 }
442
443 // Cras iodev
cras_iodev_add_node(struct cras_iodev * iodev,struct cras_ionode * node)444 void cras_iodev_add_node(struct cras_iodev* iodev, struct cras_ionode* node) {
445 cras_iodev_add_node_called++;
446 iodev->nodes = node;
447 }
448
cras_iodev_rm_node(struct cras_iodev * iodev,struct cras_ionode * node)449 void cras_iodev_rm_node(struct cras_iodev* iodev, struct cras_ionode* node) {
450 cras_iodev_rm_node_called++;
451 iodev->nodes = NULL;
452 }
453
cras_iodev_set_active_node(struct cras_iodev * iodev,struct cras_ionode * node)454 void cras_iodev_set_active_node(struct cras_iodev* iodev,
455 struct cras_ionode* node) {
456 cras_iodev_set_active_node_called++;
457 iodev->active_node = node;
458 }
459
460 // From cras_bt_transport
cras_bt_transport_device(const struct cras_bt_transport * transport)461 struct cras_bt_device* cras_bt_transport_device(
462 const struct cras_bt_transport* transport) {
463 return reinterpret_cast<struct cras_bt_device*>(0x456);
464 ;
465 }
466
cras_bt_transport_profile(const struct cras_bt_transport * transport)467 enum cras_bt_device_profile cras_bt_transport_profile(
468 const struct cras_bt_transport* transport) {
469 return CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE;
470 }
471
472 // From cras_bt_device
cras_bt_device_name(const struct cras_bt_device * device)473 const char* cras_bt_device_name(const struct cras_bt_device* device) {
474 return cras_bt_device_name_ret;
475 }
476
cras_bt_device_object_path(const struct cras_bt_device * device)477 const char* cras_bt_device_object_path(const struct cras_bt_device* device) {
478 return "/org/bluez/hci0/dev_1A_2B_3C_4D_5E_6F";
479 }
480
cras_bt_device_append_iodev(struct cras_bt_device * device,struct cras_iodev * iodev,enum cras_bt_device_profile profile)481 void cras_bt_device_append_iodev(struct cras_bt_device* device,
482 struct cras_iodev* iodev,
483 enum cras_bt_device_profile profile) {
484 cras_bt_device_append_iodev_called++;
485 }
486
cras_bt_device_rm_iodev(struct cras_bt_device * device,struct cras_iodev * iodev)487 void cras_bt_device_rm_iodev(struct cras_bt_device* device,
488 struct cras_iodev* iodev) {
489 cras_bt_device_rm_iodev_called++;
490 }
491
cras_bt_device_get_use_hardware_volume(struct cras_bt_device * device)492 int cras_bt_device_get_use_hardware_volume(struct cras_bt_device* device) {
493 return 0;
494 }
495
cras_bt_device_cancel_suspend(struct cras_bt_device * device)496 int cras_bt_device_cancel_suspend(struct cras_bt_device* device) {
497 return 0;
498 }
499
cras_bt_device_schedule_suspend(struct cras_bt_device * device,unsigned int msec)500 int cras_bt_device_schedule_suspend(struct cras_bt_device* device,
501 unsigned int msec) {
502 return 0;
503 }
504
init_a2dp(struct a2dp_info * a2dp,a2dp_sbc_t * sbc)505 int init_a2dp(struct a2dp_info* a2dp, a2dp_sbc_t* sbc) {
506 init_a2dp_called++;
507 return init_a2dp_return_val;
508 }
509
destroy_a2dp(struct a2dp_info * a2dp)510 void destroy_a2dp(struct a2dp_info* a2dp) {
511 destroy_a2dp_called++;
512 }
513
a2dp_codesize(struct a2dp_info * a2dp)514 int a2dp_codesize(struct a2dp_info* a2dp) {
515 return 512;
516 }
517
a2dp_block_size(struct a2dp_info * a2dp,int encoded_bytes)518 int a2dp_block_size(struct a2dp_info* a2dp, int encoded_bytes) {
519 a2dp_block_size_called++;
520
521 // Assumes a2dp block size is 1:1 before/after encode.
522 return encoded_bytes;
523 }
524
a2dp_queued_frames(struct a2dp_info * a2dp)525 int a2dp_queued_frames(struct a2dp_info* a2dp) {
526 return a2dp_queued_frames_val;
527 }
528
a2dp_drain(struct a2dp_info * a2dp)529 void a2dp_drain(struct a2dp_info* a2dp) {
530 drain_a2dp_called++;
531 }
532
a2dp_encode(struct a2dp_info * a2dp,const void * pcm_buf,int pcm_buf_size,int format_bytes,size_t link_mtu)533 int a2dp_encode(struct a2dp_info* a2dp,
534 const void* pcm_buf,
535 int pcm_buf_size,
536 int format_bytes,
537 size_t link_mtu) {
538 unsigned int processed;
539
540 if (a2dp_encode_index == MAX_A2DP_ENCODE_CALLS)
541 return 0;
542 processed = a2dp_encode_processed_bytes_val[a2dp_encode_index];
543 pcm_buf_size_val[a2dp_encode_index] = pcm_buf_size;
544 a2dp_encode_index++;
545 return processed;
546 }
547
a2dp_write(struct a2dp_info * a2dp,int stream_fd,size_t link_mtu)548 int a2dp_write(struct a2dp_info* a2dp, int stream_fd, size_t link_mtu) {
549 return a2dp_write_return_val[a2dp_write_index++];
550 ;
551 }
552
clock_gettime(clockid_t clk_id,struct timespec * tp)553 int clock_gettime(clockid_t clk_id, struct timespec* tp) {
554 *tp = time_now;
555 return 0;
556 }
557
cras_iodev_init_audio_area(struct cras_iodev * iodev,int num_channels)558 void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) {
559 iodev->area = dummy_audio_area;
560 }
561
cras_iodev_free_audio_area(struct cras_iodev * iodev)562 void cras_iodev_free_audio_area(struct cras_iodev* iodev) {}
563
cras_iodev_frames_queued(struct cras_iodev * iodev,struct timespec * hw_tstamp)564 int cras_iodev_frames_queued(struct cras_iodev* iodev,
565 struct timespec* hw_tstamp) {
566 int rc;
567 cras_iodev_frames_queued_called++;
568 rc = iodev->frames_queued(iodev, hw_tstamp);
569 if (rc < 0)
570 return 0;
571 unsigned int num_queued = (unsigned int)rc;
572 if (num_queued < iodev->min_buffer_level)
573 return 0;
574
575 return num_queued - iodev->min_buffer_level;
576 }
577
cras_audio_area_config_buf_pointers(struct cras_audio_area * area,const struct cras_audio_format * fmt,uint8_t * base_buffer)578 void cras_audio_area_config_buf_pointers(struct cras_audio_area* area,
579 const struct cras_audio_format* fmt,
580 uint8_t* base_buffer) {
581 dummy_audio_area->channels[0].buf = base_buffer;
582 }
583
cras_iodev_list_get_audio_thread()584 struct audio_thread* cras_iodev_list_get_audio_thread() {
585 return NULL;
586 }
587 // From audio_thread
588 struct audio_thread_event_log* atlog;
589
audio_thread_add_write_callback(int fd,thread_callback cb,void * data)590 void audio_thread_add_write_callback(int fd, thread_callback cb, void* data) {
591 write_callback = cb;
592 write_callback_data = data;
593 }
594
audio_thread_rm_callback_sync(struct audio_thread * thread,int fd)595 int audio_thread_rm_callback_sync(struct audio_thread* thread, int fd) {
596 return 0;
597 }
598
audio_thread_enable_callback(int fd,int enabled)599 void audio_thread_enable_callback(int fd, int enabled) {}
600 }
601