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