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_aac.h"
18 
19 #include <bluetooth/log.h>
20 #include <gtest/gtest.h>
21 
22 #include <cstdint>
23 #include <string>
24 
25 #include "common/init_flags.h"
26 #include "common/time_util.h"
27 #include "os/log.h"
28 #include "osi/include/allocator.h"
29 #include "stack/include/a2dp_aac_decoder.h"
30 #include "stack/include/a2dp_aac_encoder.h"
31 #include "stack/include/avdt_api.h"
32 #include "stack/include/bt_hdr.h"
33 #include "test_util.h"
34 #include "wav_reader.h"
35 
36 namespace {
37 constexpr uint32_t kAacReadSize = 1024 * 2 * 2;
38 constexpr uint32_t kA2dpTickUs = 23 * 1000;
39 constexpr uint16_t kPeerMtu = 1000;
40 constexpr char kWavFile[] = "test/a2dp/raw_data/pcm1644s.wav";
41 constexpr uint8_t kCodecInfoAacCapability[AVDT_CODEC_SIZE] = {
42     8,           // Length (A2DP_AAC_INFO_LEN)
43     0,           // Media Type: AVDT_MEDIA_TYPE_AUDIO
44     2,           // Media Codec Type: A2DP_MEDIA_CT_AAC
45     0x80,        // Object Type: A2DP_AAC_OBJECT_TYPE_MPEG2_LC
46     0x01,        // Sampling Frequency: A2DP_AAC_SAMPLING_FREQ_44100
47     0x04,        // Channels: A2DP_AAC_CHANNEL_MODE_STEREO
48     0x00 | 0x4,  // Variable Bit Rate:
49                  // A2DP_AAC_VARIABLE_BIT_RATE_DISABLED
50                  // Bit Rate: 320000 = 0x4e200
51     0xe2,        // Bit Rate: 320000 = 0x4e200
52     0x00,        // Bit Rate: 320000 = 0x4e200
53     7,           // Unused
54     8,           // Unused
55     9            // Unused
56 };
Data(BT_HDR * packet)57 uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
58 }  // namespace
59 
60 namespace bluetooth {
61 namespace testing {
62 
63 static BT_HDR* packet = nullptr;
64 static WavReader wav_reader = WavReader(GetWavFilePath(kWavFile).c_str());
65 
66 class A2dpAacTest : public ::testing::Test {
67  protected:
SetUp()68   void SetUp() override {
69     common::InitFlags::SetAllForTesting();
70     SetCodecConfig();
71     encoder_iface_ = const_cast<tA2DP_ENCODER_INTERFACE*>(
72         A2DP_GetEncoderInterfaceAac(kCodecInfoAacCapability));
73     ASSERT_NE(encoder_iface_, nullptr);
74     decoder_iface_ = const_cast<tA2DP_DECODER_INTERFACE*>(
75         A2DP_GetDecoderInterfaceAac(kCodecInfoAacCapability));
76     ASSERT_NE(decoder_iface_, nullptr);
77   }
78 
TearDown()79   void TearDown() override {
80     if (a2dp_codecs_ != nullptr) {
81       delete a2dp_codecs_;
82     }
83     if (encoder_iface_ != nullptr) {
84       encoder_iface_->encoder_cleanup();
85     }
86     A2DP_UnloadEncoderAac();
87     if (decoder_iface_ != nullptr) {
88       decoder_iface_->decoder_cleanup();
89     }
90     A2DP_UnloadDecoderAac();
91   }
92 
SetCodecConfig()93   void SetCodecConfig() {
94     uint8_t codec_info_result[AVDT_CODEC_SIZE];
95     btav_a2dp_codec_index_t peer_codec_index;
96     a2dp_codecs_ = new A2dpCodecs(std::vector<btav_a2dp_codec_config_t>());
97 
98     ASSERT_TRUE(a2dp_codecs_->init());
99 
100     // Create the codec capability - AAC Sink
101     memset(codec_info_result, 0, sizeof(codec_info_result));
102     ASSERT_TRUE(A2DP_IsSinkCodecSupportedAac(kCodecInfoAacCapability));
103     peer_codec_index = A2DP_SinkCodecIndex(kCodecInfoAacCapability);
104     ASSERT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
105     sink_codec_config_ = a2dp_codecs_->findSinkCodecConfig(kCodecInfoAacCapability);
106     ASSERT_NE(sink_codec_config_, nullptr);
107     ASSERT_TRUE(a2dp_codecs_->setSinkCodecConfig(kCodecInfoAacCapability, true,
108                                                  codec_info_result, true));
109     ASSERT_TRUE(a2dp_codecs_->setPeerSinkCodecCapabilities(kCodecInfoAacCapability));
110     // Compare the result codec with the local test codec info
111     for (size_t i = 0; i < kCodecInfoAacCapability[0] + 1; i++) {
112       ASSERT_EQ(codec_info_result[i], kCodecInfoAacCapability[i]);
113     }
114     ASSERT_TRUE(a2dp_codecs_->setCodecConfig(kCodecInfoAacCapability, true, codec_info_result, true));
115     source_codec_config_ = a2dp_codecs_->getCurrentCodecConfig();
116   }
117 
InitializeEncoder(bool peer_supports_3mbps,a2dp_source_read_callback_t read_cb,a2dp_source_enqueue_callback_t enqueue_cb)118   void InitializeEncoder(bool peer_supports_3mbps, a2dp_source_read_callback_t read_cb,
119                          a2dp_source_enqueue_callback_t enqueue_cb) {
120     tA2DP_ENCODER_INIT_PEER_PARAMS peer_params = {true, peer_supports_3mbps, kPeerMtu};
121     encoder_iface_->encoder_init(&peer_params, sink_codec_config_, read_cb,
122                                  enqueue_cb);
123   }
124 
InitializeDecoder(decoded_data_callback_t data_cb)125   void InitializeDecoder(decoded_data_callback_t data_cb) {
126     decoder_iface_->decoder_init(data_cb);
127   }
128 
AllocateL2capPacket(const std::vector<uint8_t> data) const129   BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
130     auto packet = AllocatePacket(data.size());
131     std::copy(data.cbegin(), data.cend(), Data(packet));
132     return packet;
133   }
134 
AllocatePacket(size_t packet_length) const135   BT_HDR* AllocatePacket(size_t packet_length) const {
136     BT_HDR* packet =
137         static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
138     packet->len = packet_length;
139     return packet;
140   }
141   A2dpCodecConfig* sink_codec_config_;
142   A2dpCodecConfig* source_codec_config_;
143   A2dpCodecs* a2dp_codecs_;
144   tA2DP_ENCODER_INTERFACE* encoder_iface_;
145   tA2DP_DECODER_INTERFACE* decoder_iface_;
146 };
147 
TEST_F(A2dpAacTest,a2dp_source_read_underflow)148 TEST_F(A2dpAacTest, a2dp_source_read_underflow) {
149   static int enqueue_cb_invoked = 0;
150 
151   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { return 0; };
152 
153   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
154     enqueue_cb_invoked += 1;
155     osi_free(p_buf);
156     return false;
157   };
158 
159   InitializeEncoder(true, read_cb, enqueue_cb);
160   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
161   encoder_iface_->send_frames(timestamp_us);
162   encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
163 
164   ASSERT_EQ(enqueue_cb_invoked, 0);
165 }
166 
TEST_F(A2dpAacTest,a2dp_enqueue_cb_is_invoked)167 TEST_F(A2dpAacTest, a2dp_enqueue_cb_is_invoked) {
168   static int enqueue_cb_invoked = 0;
169 
170   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t { return len; };
171 
172   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
173     enqueue_cb_invoked += 1;
174     osi_free(p_buf);
175     return false;
176   };
177 
178   InitializeEncoder(true, read_cb, enqueue_cb);
179   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
180   encoder_iface_->send_frames(timestamp_us);
181   encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
182 
183   ASSERT_EQ(enqueue_cb_invoked, 1);
184 }
185 
TEST_F(A2dpAacTest,decoded_data_cb_not_invoked_when_empty_packet)186 TEST_F(A2dpAacTest, decoded_data_cb_not_invoked_when_empty_packet) {
187   auto data_cb = +[](uint8_t* p_buf, uint32_t len) { FAIL(); };
188   InitializeDecoder(data_cb);
189   std::vector<uint8_t> data;
190   BT_HDR* packet = AllocateL2capPacket(data);
191   decoder_iface_->decode_packet(packet);
192   osi_free(packet);
193 }
194 
TEST_F(A2dpAacTest,decoded_data_cb_invoked)195 TEST_F(A2dpAacTest, decoded_data_cb_invoked) {
196   static int data_cb_invoked = 0;
197   static int enqueue_cb_invoked = 0;
198 
199   auto data_cb = +[](uint8_t* p_buf, uint32_t len) { data_cb_invoked += 1; };
200 
201   InitializeDecoder(data_cb);
202 
203   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
204     static uint32_t counter = 0;
205     memcpy(p_buf, wav_reader.GetSamples() + counter, len);
206     counter += len;
207     return len;
208   };
209 
210   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
211     enqueue_cb_invoked += 1;
212     packet = p_buf;
213     return false;
214   };
215 
216   InitializeEncoder(true, read_cb, enqueue_cb);
217 
218   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
219   encoder_iface_->send_frames(timestamp_us);
220   encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
221 
222   ASSERT_EQ(enqueue_cb_invoked, 1);
223   decoder_iface_->decode_packet(packet);
224   osi_free(packet);
225   ASSERT_EQ(data_cb_invoked, 1);
226 }
227 
TEST_F(A2dpAacTest,set_source_codec_config_works)228 TEST_F(A2dpAacTest, set_source_codec_config_works) {
229   uint8_t codec_info_result[AVDT_CODEC_SIZE];
230   ASSERT_TRUE(a2dp_codecs_->setCodecConfig(kCodecInfoAacCapability, true, codec_info_result, true));
231   ASSERT_TRUE(A2DP_CodecTypeEqualsAac(codec_info_result, kCodecInfoAacCapability));
232   ASSERT_TRUE(A2DP_CodecEqualsAac(codec_info_result, kCodecInfoAacCapability));
233   auto* codec_config = a2dp_codecs_->findSourceCodecConfig(kCodecInfoAacCapability);
234   ASSERT_EQ(codec_config->name(), source_codec_config_->name());
235   ASSERT_EQ(codec_config->getAudioBitsPerSample(), source_codec_config_->getAudioBitsPerSample());
236 }
237 
TEST_F(A2dpAacTest,sink_supports_aac)238 TEST_F(A2dpAacTest, sink_supports_aac) {
239   ASSERT_TRUE(A2DP_IsSinkCodecSupportedAac(kCodecInfoAacCapability));
240 }
241 
TEST_F(A2dpAacTest,effective_mtu_when_peer_supports_3mbps)242 TEST_F(A2dpAacTest, effective_mtu_when_peer_supports_3mbps) {
243   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
244     log::assert_that(kAacReadSize == len, "assert failed: kAacReadSize == len");
245     return len;
246   };
247   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
248     osi_free(p_buf);
249     return false;
250   };
251   InitializeEncoder(true, read_cb, enqueue_cb);
252   ASSERT_EQ(a2dp_aac_get_effective_frame_size(), kPeerMtu);
253 }
254 
TEST_F(A2dpAacTest,effective_mtu_when_peer_does_not_support_3mbps)255 TEST_F(A2dpAacTest, effective_mtu_when_peer_does_not_support_3mbps) {
256   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
257     log::assert_that(kAacReadSize == len, "assert failed: kAacReadSize == len");
258     return len;
259   };
260   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
261     osi_free(p_buf);
262     return false;
263   };
264   InitializeEncoder(false, read_cb, enqueue_cb);
265   ASSERT_EQ(a2dp_aac_get_effective_frame_size(), 663 /* MAX_2MBPS_AVDTP_MTU */);
266 }
267 
TEST_F(A2dpAacTest,codec_info_string)268 TEST_F(A2dpAacTest, codec_info_string) {
269   auto codec_info = A2DP_CodecInfoString(kCodecInfoAacCapability);
270   ASSERT_NE(codec_info.find("samp_freq: 44100"), std::string::npos);
271   ASSERT_NE(codec_info.find("ch_mode: Stereo"), std::string::npos);
272 }
273 
TEST_F(A2dpAacTest,get_track_bits_per_sample)274 TEST_F(A2dpAacTest, get_track_bits_per_sample) {
275   ASSERT_EQ(A2DP_GetTrackBitsPerSampleAac(kCodecInfoAacCapability), 16);
276 }
277 
278 }  // namespace testing
279 }  // namespace bluetooth
280