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