1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "stack/include/a2dp_vendor_ldac.h"
18
19 #include <gtest/gtest.h>
20
21 #include "common/time_util.h"
22 #include "osi/include/allocator.h"
23 #include "stack/include/a2dp_vendor_ldac_constants.h"
24 #include "stack/include/avdt_api.h"
25 #include "stack/include/bt_hdr.h"
26 #include "test_util.h"
27 #include "wav_reader.h"
28
29 namespace {
30 constexpr uint32_t kA2dpTickUs = 23 * 1000;
31 constexpr char kWavFile[] = "test/a2dp/raw_data/pcm1644s.wav";
32 constexpr uint8_t kCodecInfoLdacCapability[AVDT_CODEC_SIZE] = {
33 A2DP_LDAC_CODEC_LEN,
34 AVDT_MEDIA_TYPE_AUDIO,
35 A2DP_MEDIA_CT_NON_A2DP,
36 0x2D, // A2DP_LDAC_VENDOR_ID
37 0x01, // A2DP_LDAC_VENDOR_ID
38 0x00, // A2DP_LDAC_VENDOR_ID
39 0x00, // A2DP_LDAC_VENDOR_ID
40 0xAA, // A2DP_LDAC_CODEC_ID
41 0x00, // A2DP_LDAC_CODEC_ID,
42 A2DP_LDAC_SAMPLING_FREQ_44100,
43 A2DP_LDAC_CHANNEL_MODE_STEREO,
44 };
Data(BT_HDR * packet)45 uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
46 } // namespace
47 namespace bluetooth {
48 namespace testing {
49
50 // static BT_HDR* packet = nullptr;
51 static WavReader wav_reader = WavReader(GetWavFilePath(kWavFile).c_str());
52
53 class A2dpLdacTest : public ::testing::Test {
54 protected:
SetUp()55 void SetUp() override {
56 SetCodecConfig();
57 encoder_iface_ = const_cast<tA2DP_ENCODER_INTERFACE*>(
58 A2DP_VendorGetEncoderInterfaceLdac(kCodecInfoLdacCapability));
59 ASSERT_NE(encoder_iface_, nullptr);
60 decoder_iface_ = const_cast<tA2DP_DECODER_INTERFACE*>(
61 A2DP_VendorGetDecoderInterfaceLdac(kCodecInfoLdacCapability));
62 ASSERT_NE(decoder_iface_, nullptr);
63 }
64
TearDown()65 void TearDown() override {
66 if (a2dp_codecs_ != nullptr) {
67 delete a2dp_codecs_;
68 }
69 if (encoder_iface_ != nullptr) {
70 encoder_iface_->encoder_cleanup();
71 }
72 if (decoder_iface_ != nullptr) {
73 decoder_iface_->decoder_cleanup();
74 }
75 }
76
77 // NOTE: Make a super func for all codecs
SetCodecConfig()78 void SetCodecConfig() {
79 uint8_t source_codec_info_result[AVDT_CODEC_SIZE];
80 btav_a2dp_codec_index_t peer_codec_index;
81 a2dp_codecs_ = new A2dpCodecs(std::vector<btav_a2dp_codec_config_t>());
82
83 ASSERT_TRUE(a2dp_codecs_->init());
84
85 peer_codec_index = A2DP_SinkCodecIndex(kCodecInfoLdacCapability);
86 ASSERT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
87 ASSERT_EQ(peer_codec_index, BTAV_A2DP_CODEC_INDEX_SINK_LDAC);
88 source_codec_config_ = a2dp_codecs_->findSourceCodecConfig(kCodecInfoLdacCapability);
89 ASSERT_NE(source_codec_config_, nullptr);
90 ASSERT_TRUE(a2dp_codecs_->setCodecConfig(kCodecInfoLdacCapability, true,
91 source_codec_info_result, true));
92 ASSERT_EQ(a2dp_codecs_->getCurrentCodecConfig(), source_codec_config_);
93 // Compare the result codec with the local test codec info
94 for (size_t i = 0; i < kCodecInfoLdacCapability[0] + 1; i++) {
95 ASSERT_EQ(source_codec_info_result[i], kCodecInfoLdacCapability[i]);
96 }
97 ASSERT_NE(source_codec_config_->getAudioBitsPerSample(), 0);
98 }
99
InitializeEncoder(a2dp_source_read_callback_t read_cb,a2dp_source_enqueue_callback_t enqueue_cb)100 void InitializeEncoder(a2dp_source_read_callback_t read_cb,
101 a2dp_source_enqueue_callback_t enqueue_cb) {
102 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params = {true, true, 1000};
103 encoder_iface_->encoder_init(&peer_params, source_codec_config_, read_cb, enqueue_cb);
104 }
105
InitializeDecoder(decoded_data_callback_t data_cb)106 void InitializeDecoder(decoded_data_callback_t data_cb) { decoder_iface_->decoder_init(data_cb); }
AllocateL2capPacket(const std::vector<uint8_t> data) const107 BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
108 auto packet = AllocatePacket(data.size());
109 std::copy(data.cbegin(), data.cend(), Data(packet));
110 return packet;
111 }
112
AllocatePacket(size_t packet_length) const113 BT_HDR* AllocatePacket(size_t packet_length) const {
114 BT_HDR* packet = static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
115 packet->len = packet_length;
116 return packet;
117 }
118 A2dpCodecConfig* source_codec_config_;
119 A2dpCodecs* a2dp_codecs_;
120 tA2DP_ENCODER_INTERFACE* encoder_iface_;
121 tA2DP_DECODER_INTERFACE* decoder_iface_;
122 };
123
TEST_F(A2dpLdacTest,a2dp_source_read_underflow)124 TEST_F(A2dpLdacTest, a2dp_source_read_underflow) {
125 static int enqueue_cb_invoked = 0;
126
127 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t { return 0; };
128
129 auto enqueue_cb = +[](BT_HDR* /*p_buf*/, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
130 enqueue_cb_invoked += 1;
131 return false;
132 };
133
134 InitializeEncoder(read_cb, enqueue_cb);
135 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
136 encoder_iface_->send_frames(timestamp_us);
137 encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
138
139 ASSERT_EQ(enqueue_cb_invoked, 0);
140 }
141
142 } // namespace testing
143 } // namespace bluetooth
144