summaryrefslogtreecommitdiff
path: root/cras/src/tests/a2dp_iodev_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/tests/a2dp_iodev_unittest.cc')
-rw-r--r--cras/src/tests/a2dp_iodev_unittest.cc962
1 files changed, 0 insertions, 962 deletions
diff --git a/cras/src/tests/a2dp_iodev_unittest.cc b/cras/src/tests/a2dp_iodev_unittest.cc
deleted file mode 100644
index 06c1cd3c..00000000
--- a/cras/src/tests/a2dp_iodev_unittest.cc
+++ /dev/null
@@ -1,962 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <gtest/gtest.h>
-#include <stdint.h>
-#include <stdio.h>
-
-extern "C" {
-#include "cras_a2dp_iodev.c"
-
-#include "audio_thread.h"
-#include "audio_thread_log.h"
-#include "cras_audio_area.h"
-#include "cras_bt_transport.h"
-#include "cras_iodev.h"
-}
-
-#define FAKE_OBJECT_PATH "/fake/obj/path"
-
-#define MAX_A2DP_ENCODE_CALLS 8
-#define MAX_A2DP_WRITE_CALLS 4
-
-/* Fake the codec to encode (512/4) frames into 128 bytes. */
-#define FAKE_A2DP_CODE_SIZE 512
-#define FAKE_A2DP_FRAME_LENGTH 128
-
-static struct cras_bt_transport* fake_transport;
-static cras_audio_format format;
-static size_t cras_bt_device_append_iodev_called;
-static size_t cras_bt_device_rm_iodev_called;
-static size_t cras_iodev_add_node_called;
-static size_t cras_iodev_rm_node_called;
-static size_t cras_iodev_set_active_node_called;
-static size_t cras_bt_transport_acquire_called;
-static size_t cras_bt_transport_configuration_called;
-static size_t cras_bt_transport_release_called;
-static size_t init_a2dp_called;
-static int init_a2dp_return_val;
-static size_t destroy_a2dp_called;
-static size_t a2dp_reset_called;
-static size_t cras_iodev_free_format_called;
-static size_t cras_iodev_free_resources_called;
-static int a2dp_write_return_val[MAX_A2DP_WRITE_CALLS];
-static unsigned int a2dp_write_index;
-static int a2dp_encode_called;
-static cras_audio_area* mock_audio_area;
-static thread_callback write_callback;
-static void* write_callback_data;
-static const char* fake_device_name = "fake device name";
-static const char* cras_bt_device_name_ret;
-static unsigned int cras_bt_transport_write_mtu_ret;
-static int cras_iodev_fill_odev_zeros_called;
-static unsigned int cras_iodev_fill_odev_zeros_frames;
-static int audio_thread_config_events_callback_called;
-static enum AUDIO_THREAD_EVENTS_CB_TRIGGER
- audio_thread_config_events_callback_trigger;
-
-void ResetStubData() {
- cras_bt_device_append_iodev_called = 0;
- cras_bt_device_rm_iodev_called = 0;
- cras_iodev_add_node_called = 0;
- cras_iodev_rm_node_called = 0;
- cras_iodev_set_active_node_called = 0;
- cras_bt_transport_acquire_called = 0;
- cras_bt_transport_configuration_called = 0;
- cras_bt_transport_release_called = 0;
- init_a2dp_called = 0;
- init_a2dp_return_val = 0;
- destroy_a2dp_called = 0;
- a2dp_reset_called = 0;
- cras_iodev_free_format_called = 0;
- cras_iodev_free_resources_called = 0;
- a2dp_write_index = 0;
- a2dp_encode_called = 0;
- /* Fake the MTU value. min_buffer_level will be derived from this value. */
- cras_bt_transport_write_mtu_ret = 950;
- cras_iodev_fill_odev_zeros_called = 0;
-
- fake_transport = reinterpret_cast<struct cras_bt_transport*>(0x123);
-
- if (!mock_audio_area) {
- mock_audio_area = (cras_audio_area*)calloc(
- 1, sizeof(*mock_audio_area) + sizeof(cras_channel_area) * 2);
- }
-
- write_callback = NULL;
-}
-
-int iodev_set_format(struct cras_iodev* iodev, struct cras_audio_format* fmt) {
- fmt->format = SND_PCM_FORMAT_S16_LE;
- fmt->num_channels = 2;
- fmt->frame_rate = 44100;
- iodev->format = fmt;
- return 0;
-}
-
-namespace {
-
-static struct timespec time_now;
-class A2dpIodev : public testing::Test {
- protected:
- virtual void SetUp() {
- ResetStubData();
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- atlog = (audio_thread_event_log*)calloc(1, sizeof(audio_thread_event_log));
- }
-
- virtual void TearDown() {
- free(mock_audio_area);
- mock_audio_area = NULL;
- free(atlog);
- }
-};
-
-TEST_F(A2dpIodev, InitializeA2dpIodev) {
- struct cras_iodev* iodev;
-
- cras_bt_device_name_ret = NULL;
- iodev = a2dp_iodev_create(fake_transport);
-
- ASSERT_NE(iodev, (void*)NULL);
- ASSERT_EQ(iodev->direction, CRAS_STREAM_OUTPUT);
- ASSERT_EQ(1, cras_bt_transport_configuration_called);
- ASSERT_EQ(1, init_a2dp_called);
- ASSERT_EQ(1, cras_bt_device_append_iodev_called);
- ASSERT_EQ(1, cras_iodev_add_node_called);
- ASSERT_EQ(1, cras_iodev_set_active_node_called);
-
- /* Assert iodev name matches the object path when bt device doesn't
- * have its readable name populated. */
- ASSERT_STREQ(FAKE_OBJECT_PATH, iodev->info.name);
-
- a2dp_iodev_destroy(iodev);
-
- ASSERT_EQ(1, cras_bt_device_rm_iodev_called);
- ASSERT_EQ(1, cras_iodev_rm_node_called);
- ASSERT_EQ(1, destroy_a2dp_called);
- ASSERT_EQ(1, cras_iodev_free_resources_called);
-
- cras_bt_device_name_ret = fake_device_name;
- /* Assert iodev name matches the bt device's name */
- iodev = a2dp_iodev_create(fake_transport);
- ASSERT_STREQ(fake_device_name, iodev->info.name);
-
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, InitializeFail) {
- struct cras_iodev* iodev;
-
- init_a2dp_return_val = -1;
- iodev = a2dp_iodev_create(fake_transport);
-
- ASSERT_EQ(iodev, (void*)NULL);
- ASSERT_EQ(1, cras_bt_transport_configuration_called);
- ASSERT_EQ(1, init_a2dp_called);
- ASSERT_EQ(0, cras_bt_device_append_iodev_called);
- ASSERT_EQ(0, cras_iodev_add_node_called);
- ASSERT_EQ(0, cras_iodev_set_active_node_called);
- ASSERT_EQ(0, cras_iodev_rm_node_called);
-}
-
-TEST_F(A2dpIodev, OpenIodev) {
- struct cras_iodev* iodev;
-
- iodev = a2dp_iodev_create(fake_transport);
-
- iodev_set_format(iodev, &format);
- iodev->configure_dev(iodev);
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- ASSERT_EQ(1, cras_bt_transport_acquire_called);
-
- iodev->close_dev(iodev);
- ASSERT_EQ(1, cras_bt_transport_release_called);
- ASSERT_EQ(1, a2dp_reset_called);
- ASSERT_EQ(1, cras_iodev_free_format_called);
-
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, GetPutBuffer) {
- struct cras_iodev* iodev;
- struct cras_audio_area *area1, *area2, *area3;
- uint8_t* last_buf_head;
- unsigned frames;
- struct timespec tstamp;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- /* (950 - 13) / 128 * 512 / 4 */
- ASSERT_EQ(iodev->min_buffer_level, 896);
-
- frames = 1500;
- iodev->get_buffer(iodev, &area1, &frames);
- ASSERT_EQ(1500, frames);
- ASSERT_EQ(1500, area1->frames);
- last_buf_head = area1->channels[0].buf;
- iodev->put_buffer(iodev, 1000);
- /* 1000 frames takes 8 encode call, FAKE_A2DP_CODE_SIZE / 4 = 128
- * and 7 * 128 < 1000 < 8 * 128
- */
- EXPECT_EQ(8, a2dp_encode_called);
- /* Expect flushed one block, leaving 1000 - 896 = 104 queued and
- * next_flush_time has shifted. */
- EXPECT_EQ(1, a2dp_write_index);
- EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp));
- EXPECT_GT(a2dpio->next_flush_time.tv_nsec, 0);
-
- /* Assert buffer possition shifted 1000 * 4 bytes */
- frames = 1000;
- iodev->get_buffer(iodev, &area2, &frames);
- ASSERT_EQ(1000, frames);
- ASSERT_EQ(1000, area2->frames);
- ASSERT_EQ(4000, area2->channels[0].buf - last_buf_head);
- last_buf_head = area2->channels[0].buf;
-
- iodev->put_buffer(iodev, 700);
- EXPECT_EQ(804, iodev->frames_queued(iodev, &tstamp));
- /* Assert that even next_flush_time is not met, pcm data still processed.
- * Expect to takes 7 more encode calls to process the 804 frames of data.
- * and 6 * 128 < 804 < 7 * 128
- */
- EXPECT_EQ(15, a2dp_encode_called);
- EXPECT_EQ(768, a2dpio->a2dp.samples);
-
- time_now.tv_nsec = 25000000;
- frames = 50;
- iodev->get_buffer(iodev, &area3, &frames);
- ASSERT_EQ(50, frames);
- /* Assert buffer possition shifted 700 * 4 bytes */
- EXPECT_EQ(2800, area3->channels[0].buf - last_buf_head);
-
- iodev->put_buffer(iodev, 50);
- /* 804 + 50 = 854 queued, 768 of them are encoded. */
- EXPECT_EQ(854, iodev->frames_queued(iodev, &tstamp));
- EXPECT_EQ(768, a2dpio->a2dp.samples);
- /* Expect one a2dp encode call was executed for the left un-encoded frames.
- * 854 - 768 = 86 < 128 */
- EXPECT_EQ(16, a2dp_encode_called);
- /* Even time now has passed next_flush_time, no a2dp write gets called
- * because the number of encoded samples is not sufficient for a flush. */
- EXPECT_EQ(1, a2dp_write_index);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, FramesQueued) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
- /* a2dp_block_size(mtu) / format_bytes
- * (950 - 13) / 128 * 512 / 4 = 896 */
- EXPECT_EQ(896, a2dpio->write_block);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- frames = 256;
- iodev->get_buffer(iodev, &area, &frames);
- ASSERT_EQ(256, frames);
- ASSERT_EQ(256, area->frames);
-
- /* Data less than write_block hence not written. */
- iodev->put_buffer(iodev, 200);
- EXPECT_EQ(200, iodev->frames_queued(iodev, &tstamp));
- EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec);
- EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec);
-
- /* 200 + 800 - 896 = 104 */
- a2dp_write_return_val[0] = 0;
- frames = 800;
- iodev->get_buffer(iodev, &area, &frames);
- iodev->put_buffer(iodev, 800);
- EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp));
-
- /* Some time has passed, same amount of frames are queued. */
- time_now.tv_nsec = 15000000;
- write_callback(write_callback_data, POLLOUT);
- EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp));
-
- /* Put 900 more frames. next_flush_time not yet passed so expect
- * total 900 + 104 = 1004 are queued. */
- frames = 900;
- iodev->get_buffer(iodev, &area, &frames);
- iodev->put_buffer(iodev, 900);
- EXPECT_EQ(1004, iodev->frames_queued(iodev, &tstamp));
-
- /* Time passes next_flush_time, 1004 + 300 - 896 = 408 */
- time_now.tv_nsec = 25000000;
- frames = 300;
- iodev->get_buffer(iodev, &area, &frames);
- iodev->put_buffer(iodev, 300);
- EXPECT_EQ(408, iodev->frames_queued(iodev, &tstamp));
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, SleepTimeWithWriteThrottle) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- unsigned frames;
- unsigned int level;
- unsigned long target;
- struct timespec tstamp;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
- /* a2dp_block_size(mtu) / format_bytes
- * 900 / 128 * 512 / 4 = 896 */
- EXPECT_EQ(896, a2dpio->write_block);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- /* Both time now and next_flush_time are at 0. Expect write_block of
- * time to sleep */
- EXPECT_EQ(a2dpio->write_block,
- iodev->frames_to_play_in_sleep(iodev, &level, &tstamp));
-
- /* Fake that 1000 frames are put and one block got flushed.
- * Expect next_wake_time be fast forward by one flush_period. */
- frames = 1000;
- iodev->get_buffer(iodev, &area, &frames);
- ASSERT_EQ(1000, frames);
- ASSERT_EQ(1000, area->frames);
-
- /* Expect the first block be flushed at time 0. */
- time_now.tv_nsec = 0;
- a2dp_write_return_val[0] = 0;
- EXPECT_EQ(0, iodev->put_buffer(iodev, 1000));
- EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp)); /* 1000 - 896 */
-
- /* Same amount of frames are queued after some time has passed. */
- time_now.tv_nsec = 10000000;
- EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp));
-
- /* Expect to sleep the time between now(10ms) and next_flush_time(~20.3ms). */
- frames = iodev->frames_to_play_in_sleep(iodev, &level, &tstamp);
- target =
- a2dpio->write_block - time_now.tv_nsec * format.frame_rate / 1000000000;
- EXPECT_GE(frames + 1, target);
- EXPECT_GE(target + 1, frames);
-
- /* Time now has passed the next flush time(~20.3ms), expect to return
- * write_block of time to sleep. */
- time_now.tv_nsec = 25000000;
- EXPECT_EQ(a2dpio->write_block,
- iodev->frames_to_play_in_sleep(iodev, &level, &tstamp));
-
- a2dp_write_return_val[1] = 0;
- frames = 1000;
- iodev->get_buffer(iodev, &area, &frames);
- EXPECT_EQ(0, iodev->put_buffer(iodev, 1000));
- EXPECT_EQ(208, iodev->frames_queued(iodev, &tstamp)); /* 104 + 1000 - 896 */
-
- /* Flush another write_block of data, next_wake_time fast forward by
- * another flush_period. Expect to sleep the time between now(25ms)
- * and next_flush_time(~40.6ms). */
- frames = iodev->frames_to_play_in_sleep(iodev, &level, &tstamp);
- target = a2dpio->write_block * 2 -
- time_now.tv_nsec * format.frame_rate / 1000000000;
- EXPECT_GE(frames + 1, target);
- EXPECT_GE(target + 1, frames);
-
- /* Put 1000 more frames, and make a fake failure to this flush. */
- time_now.tv_nsec = 45000000;
- a2dp_write_return_val[2] = -EAGAIN;
- frames = 1000;
- iodev->get_buffer(iodev, &area, &frames);
- EXPECT_EQ(0, iodev->put_buffer(iodev, 1000));
-
- /* Last a2dp write call failed with -EAGAIN, time now(45ms) is after
- * next_flush_time. Expect to return exact |write_block| equivalant
- * of time to sleep. */
- EXPECT_EQ(1208, iodev->frames_queued(iodev, &tstamp)); /* 208 + 1000 */
- EXPECT_EQ(a2dpio->write_block,
- iodev->frames_to_play_in_sleep(iodev, &level, &tstamp));
-
- /* Fake the event that socket becomes writable so data continues to flush.
- * next_flush_time fast forwards by another flush_period. */
- a2dp_write_return_val[3] = 0;
- write_callback(write_callback_data, POLLOUT);
- EXPECT_EQ(312, iodev->frames_queued(iodev, &tstamp)); /* 1208 - 896 */
-
- /* Expect to sleep the time between now and next_flush_time(~60.9ms). */
- frames = iodev->frames_to_play_in_sleep(iodev, &level, &tstamp);
- target = a2dpio->write_block * 3 -
- time_now.tv_nsec * format.frame_rate / 1000000000;
- EXPECT_GE(frames + 1, target);
- EXPECT_GE(target + 1, frames);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, EnableThreadCallbackAtBufferFull) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- audio_thread_config_events_callback_called = 0;
- a2dp_write_return_val[0] = 0;
- frames = iodev->buffer_size;
- iodev->get_buffer(iodev, &area, &frames);
- EXPECT_LE(frames, iodev->buffer_size);
- EXPECT_EQ(0, iodev->put_buffer(iodev, frames));
- EXPECT_EQ(1, a2dp_write_index);
- EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec);
- EXPECT_EQ(1, audio_thread_config_events_callback_called);
- EXPECT_EQ(TRIGGER_NONE, audio_thread_config_events_callback_trigger);
-
- /* Fastfoward time 1ms, not yet reaches the next flush time. */
- time_now.tv_nsec = 1000000;
-
- /* Cram into iodev as much data as possible. Expect its buffer to
- * be full because flush time does not yet met. */
- frames = iodev->buffer_size;
- iodev->get_buffer(iodev, &area, &frames);
- EXPECT_LE(frames, iodev->buffer_size);
- EXPECT_EQ(0, iodev->put_buffer(iodev, frames));
- frames = iodev->frames_queued(iodev, &tstamp);
- EXPECT_EQ(frames, iodev->buffer_size);
-
- /* Expect a2dp_write didn't get called in last get/put buffer. And
- * audio thread callback has been enabled. */
- EXPECT_EQ(1, a2dp_write_index);
- EXPECT_EQ(2, audio_thread_config_events_callback_called);
- EXPECT_EQ(TRIGGER_WAKEUP, audio_thread_config_events_callback_trigger);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, FlushAtLowBufferLevel) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames;
-
- iodev = a2dp_iodev_create(fake_transport);
-
- iodev_set_format(iodev, &format);
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
-
- /* (950 - 13)/ 128 * 512 / 4 */
- ASSERT_EQ(iodev->min_buffer_level, 896);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- frames = 1500;
- iodev->get_buffer(iodev, &area, &frames);
- ASSERT_EQ(1500, frames);
- ASSERT_EQ(1500, area->frames);
-
- /*
- * Assert put_buffer shouldn't trigger the 2nd call to a2dp_encode()
- * because buffer is low: 896 < 1500 < 896 * 2
- */
- a2dp_write_return_val[0] = 0;
- EXPECT_EQ(0, iodev->put_buffer(iodev, 1500));
- EXPECT_EQ(1, a2dp_write_index);
-
- /* 1500 - 896 */
- time_now.tv_nsec = 25000000;
- EXPECT_EQ(604, iodev->frames_queued(iodev, &tstamp));
- EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec);
- EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec);
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, HandleUnderrun) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames;
-
- iodev = a2dp_iodev_create(fake_transport);
-
- iodev_set_format(iodev, &format);
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- iodev->configure_dev(iodev);
- /* (950 - 13) / 128 * 512 / 4 */
- EXPECT_EQ(896, iodev->min_buffer_level);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- frames = 300;
- iodev->get_buffer(iodev, &area, &frames);
- ASSERT_EQ(300, frames);
- ASSERT_EQ(300, area->frames);
- a2dp_write_return_val[0] = -EAGAIN;
-
- time_now.tv_nsec = 10000000;
- iodev->put_buffer(iodev, 300);
-
- time_now.tv_nsec = 20000000;
- EXPECT_EQ(300, iodev->frames_queued(iodev, &tstamp));
-
- /* Frames queued below min_buffer_level, which is derived from transport MTU.
- * Assert min_cb_level of zero frames are filled. */
- iodev->min_cb_level = 150;
- iodev->output_underrun(iodev);
- ASSERT_EQ(1, cras_iodev_fill_odev_zeros_called);
- EXPECT_EQ(150, cras_iodev_fill_odev_zeros_frames);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, LeavingNoStreamStateWithSmallStreamDoesntUnderrun) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
- /* (950 - 13)/ 128 * 512 / 4 */
- ASSERT_EQ(896, iodev->min_buffer_level);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- /* Put iodev in no_stream state. Verify it doesn't underrun after each
- * call of no_stream ops. */
- a2dp_write_return_val[0] = 0;
- iodev->no_stream(iodev, 1);
- EXPECT_EQ(1, a2dp_write_index);
- EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec);
- frames = iodev->frames_queued(iodev, &tstamp);
- EXPECT_LE(iodev->min_buffer_level, frames);
-
- /* Some time has passed and a small stream of 200 frames block is added.
- * Verify leaving no_stream state doesn't underrun immediately. */
- time_now.tv_nsec = 20000000;
- iodev->no_stream(iodev, 1);
- frames = 200;
- iodev->get_buffer(iodev, &area, &frames);
- iodev->put_buffer(iodev, 200);
- frames = iodev->frames_queued(iodev, &tstamp);
- EXPECT_LE(iodev->min_buffer_level, frames);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, NoStreamStateFillZerosToTargetLevel) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
- /* (950 - 13)/ 128 * 512 / 4 */
- ASSERT_EQ(896, iodev->min_buffer_level);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- iodev->min_cb_level = 480;
- frames = 200;
- iodev->get_buffer(iodev, &area, &frames);
- iodev->put_buffer(iodev, 200);
-
- a2dp_write_return_val[0] = 0;
- iodev->no_stream(iodev, 1);
- EXPECT_EQ(1, a2dp_write_index);
- EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec);
-
- /* Some time has passed but not yet reach next flush. Entering no_stream
- * fills buffer to 3 times of min_buffer_level. */
- time_now.tv_nsec = 10000000;
- iodev->no_stream(iodev, 1);
- frames = iodev->frames_queued(iodev, &tstamp);
- EXPECT_EQ(3 * iodev->min_buffer_level, frames);
-
- /* Time has passed next flush time, expect one block is flushed. */
- a2dp_write_return_val[1] = 0;
- time_now.tv_nsec = 25000000;
- iodev->no_stream(iodev, 1);
- frames = iodev->frames_queued(iodev, &tstamp);
- ASSERT_EQ(2 * iodev->min_buffer_level, frames);
- EXPECT_EQ(2, a2dp_write_index);
-
- /* Leaving no_stream state fills buffer level back to 2 * min_buffer_level.
- */
- a2dp_write_return_val[2] = 0;
- time_now.tv_nsec = 30000000;
- iodev->no_stream(iodev, 0);
- frames = iodev->frames_queued(iodev, &tstamp);
- ASSERT_EQ(2 * iodev->min_buffer_level, frames);
- EXPECT_EQ(2, a2dp_write_index);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-
-TEST_F(A2dpIodev, EnterNoStreamStateAtHighBufferLevelDoesntFillMore) {
- struct cras_iodev* iodev;
- struct cras_audio_area* area;
- struct timespec tstamp;
- unsigned frames, start_level;
- struct a2dp_io* a2dpio;
-
- iodev = a2dp_iodev_create(fake_transport);
- a2dpio = (struct a2dp_io*)iodev;
-
- iodev_set_format(iodev, &format);
- time_now.tv_sec = 0;
- time_now.tv_nsec = 0;
- iodev->configure_dev(iodev);
- ASSERT_NE(write_callback, (void*)NULL);
- /* (950 - 13)/ 128 * 512 / 4 */
- ASSERT_EQ(896, iodev->min_buffer_level);
-
- iodev->start(iodev);
- iodev->state = CRAS_IODEV_STATE_NORMAL_RUN;
-
- a2dp_write_return_val[0] = 0;
- start_level = 6000;
- frames = start_level;
- iodev->get_buffer(iodev, &area, &frames);
- iodev->put_buffer(iodev, frames);
- frames = iodev->frames_queued(iodev, &tstamp);
- /* Assert one block has fluxhed */
- EXPECT_EQ(start_level - iodev->min_buffer_level, frames);
- EXPECT_EQ(1, a2dp_write_index);
- EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec);
-
- a2dp_write_return_val[1] = 0;
- time_now.tv_nsec = 25000000;
- iodev->no_stream(iodev, 1);
- frames = iodev->frames_queued(iodev, &tstamp);
- /* Next flush time meets requirement so another block is flushed. */
- ASSERT_EQ(start_level - 2 * iodev->min_buffer_level, frames);
-
- a2dp_write_return_val[2] = 0;
- time_now.tv_nsec = 50000000;
- iodev->no_stream(iodev, 1);
- frames = iodev->frames_queued(iodev, &tstamp);
- /* Another block flushed at leaving no stream state. No more data
- * filled because level is high. */
- ASSERT_EQ(start_level - 3 * iodev->min_buffer_level, frames);
-
- iodev->close_dev(iodev);
- a2dp_iodev_destroy(iodev);
-}
-} // namespace
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-
-extern "C" {
-
-int cras_bt_transport_configuration(const struct cras_bt_transport* transport,
- void* configuration,
- int len) {
- memset(configuration, 0, len);
- cras_bt_transport_configuration_called++;
- return 0;
-}
-
-int cras_bt_transport_acquire(struct cras_bt_transport* transport) {
- cras_bt_transport_acquire_called++;
- return 0;
-}
-
-int cras_bt_transport_release(struct cras_bt_transport* transport,
- unsigned int blocking) {
- cras_bt_transport_release_called++;
- return 0;
-}
-
-int cras_bt_transport_fd(const struct cras_bt_transport* transport) {
- return 0;
-}
-
-const char* cras_bt_transport_object_path(
- const struct cras_bt_transport* transport) {
- return FAKE_OBJECT_PATH;
-}
-
-uint16_t cras_bt_transport_write_mtu(
- const struct cras_bt_transport* transport) {
- return cras_bt_transport_write_mtu_ret;
-}
-
-int cras_bt_transport_set_volume(struct cras_bt_transport* transport,
- uint16_t volume) {
- return 0;
-}
-
-void cras_iodev_free_format(struct cras_iodev* iodev) {
- cras_iodev_free_format_called++;
-}
-
-void cras_iodev_free_resources(struct cras_iodev* iodev) {
- cras_iodev_free_resources_called++;
-}
-
-// Cras iodev
-void cras_iodev_add_node(struct cras_iodev* iodev, struct cras_ionode* node) {
- cras_iodev_add_node_called++;
- iodev->nodes = node;
-}
-
-void cras_iodev_rm_node(struct cras_iodev* iodev, struct cras_ionode* node) {
- cras_iodev_rm_node_called++;
- iodev->nodes = NULL;
-}
-
-void cras_iodev_set_active_node(struct cras_iodev* iodev,
- struct cras_ionode* node) {
- cras_iodev_set_active_node_called++;
- iodev->active_node = node;
-}
-
-// From cras_bt_transport
-struct cras_bt_device* cras_bt_transport_device(
- const struct cras_bt_transport* transport) {
- return reinterpret_cast<struct cras_bt_device*>(0x456);
- ;
-}
-
-enum cras_bt_device_profile cras_bt_transport_profile(
- const struct cras_bt_transport* transport) {
- return CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE;
-}
-
-// From cras_bt_device
-const char* cras_bt_device_name(const struct cras_bt_device* device) {
- return cras_bt_device_name_ret;
-}
-
-const char* cras_bt_device_object_path(const struct cras_bt_device* device) {
- return "/org/bluez/hci0/dev_1A_2B_3C_4D_5E_6F";
-}
-
-int cras_bt_device_get_stable_id(const struct cras_bt_device* device) {
- return 123;
-}
-
-void cras_bt_device_append_iodev(struct cras_bt_device* device,
- struct cras_iodev* iodev,
- enum cras_bt_device_profile profile) {
- cras_bt_device_append_iodev_called++;
-}
-
-void cras_bt_device_rm_iodev(struct cras_bt_device* device,
- struct cras_iodev* iodev) {
- cras_bt_device_rm_iodev_called++;
-}
-
-int cras_bt_device_get_use_hardware_volume(struct cras_bt_device* device) {
- return 0;
-}
-
-int cras_bt_device_cancel_suspend(struct cras_bt_device* device) {
- return 0;
-}
-
-int cras_bt_device_schedule_suspend(
- struct cras_bt_device* device,
- unsigned int msec,
- enum cras_bt_device_suspend_reason suspend_reason) {
- return 0;
-}
-
-int init_a2dp(struct a2dp_info* a2dp, a2dp_sbc_t* sbc) {
- init_a2dp_called++;
- memset(a2dp, 0, sizeof(*a2dp));
- a2dp->frame_length = FAKE_A2DP_FRAME_LENGTH;
- a2dp->codesize = FAKE_A2DP_CODE_SIZE;
- return init_a2dp_return_val;
-}
-
-void destroy_a2dp(struct a2dp_info* a2dp) {
- destroy_a2dp_called++;
-}
-
-int a2dp_codesize(struct a2dp_info* a2dp) {
- return a2dp->codesize;
-}
-
-int a2dp_block_size(struct a2dp_info* a2dp, int encoded_bytes) {
- return encoded_bytes / a2dp->frame_length * a2dp->codesize;
-}
-
-int a2dp_queued_frames(const struct a2dp_info* a2dp) {
- return a2dp->samples;
-}
-
-void a2dp_reset(struct a2dp_info* a2dp) {
- a2dp_reset_called++;
- a2dp->samples = 0;
-}
-
-int a2dp_encode(struct a2dp_info* a2dp,
- const void* pcm_buf,
- int pcm_buf_size,
- int format_bytes,
- size_t link_mtu) {
- int processed = 0;
- a2dp_encode_called++;
-
- if (a2dp->a2dp_buf_used + a2dp->frame_length > link_mtu)
- return 0;
- if (pcm_buf_size < a2dp->codesize)
- return 0;
-
- processed += a2dp->codesize;
- a2dp->a2dp_buf_used += a2dp->frame_length;
- a2dp->samples += processed / format_bytes;
-
- return processed;
-}
-
-int a2dp_write(struct a2dp_info* a2dp, int stream_fd, size_t link_mtu) {
- int ret, samples;
- if (a2dp->frame_length + a2dp->a2dp_buf_used < link_mtu)
- return 0;
-
- ret = a2dp_write_return_val[a2dp_write_index++];
- if (ret < 0)
- return ret;
-
- samples = a2dp->samples;
- a2dp->samples = 0;
- a2dp->a2dp_buf_used = 0;
- return samples;
-}
-
-int clock_gettime(clockid_t clk_id, struct timespec* tp) {
- *tp = time_now;
- return 0;
-}
-
-void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) {
- iodev->area = mock_audio_area;
-}
-
-void cras_iodev_free_audio_area(struct cras_iodev* iodev) {}
-
-int cras_iodev_fill_odev_zeros(struct cras_iodev* odev, unsigned int frames) {
- struct cras_audio_area* area;
- cras_iodev_fill_odev_zeros_called++;
- cras_iodev_fill_odev_zeros_frames = frames;
-
- odev->get_buffer(odev, &area, &frames);
- odev->put_buffer(odev, frames);
- return 0;
-}
-
-void cras_audio_area_config_buf_pointers(struct cras_audio_area* area,
- const struct cras_audio_format* fmt,
- uint8_t* base_buffer) {
- mock_audio_area->channels[0].buf = base_buffer;
-}
-
-struct audio_thread* cras_iodev_list_get_audio_thread() {
- return NULL;
-}
-// From ewma_power
-void ewma_power_disable(struct ewma_power* ewma) {}
-
-// From audio_thread
-struct audio_thread_event_log* atlog;
-
-void audio_thread_add_events_callback(int fd,
- thread_callback cb,
- void* data,
- int events) {
- write_callback = cb;
- write_callback_data = data;
-}
-
-int audio_thread_rm_callback_sync(struct audio_thread* thread, int fd) {
- return 0;
-}
-
-void audio_thread_config_events_callback(
- int fd,
- enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger) {
- audio_thread_config_events_callback_called++;
- audio_thread_config_events_callback_trigger = trigger;
-}
-}
-
-int cras_audio_thread_event_a2dp_overrun() {
- return 0;
-}
-
-int cras_audio_thread_event_a2dp_throttle() {
- return 0;
-}