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 <gtest/gtest.h>
18 
19 #include <chrono>
20 #include <cstdint>
21 #include <future>
22 #include <string>
23 
24 #include "common/init_flags.h"
25 #include "common/time_util.h"
26 #include "os/log.h"
27 #include "osi/include/allocator.h"
28 #include "stack/include/a2dp_vendor_opus.h"
29 #include "stack/include/a2dp_vendor_opus_constants.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 kA2dpTickUs = 23 * 1000;
36 constexpr char kWavFile[] = "test/a2dp/raw_data/pcm1644s.wav";
37 const uint8_t kCodecInfoOpusCapability[AVDT_CODEC_SIZE] = {
38   A2DP_OPUS_CODEC_LEN,         // Length
39   AVDT_MEDIA_TYPE_AUDIO << 4,  // Media Type
40   A2DP_MEDIA_CT_NON_A2DP,      // Media Codec Type Vendor
41   (A2DP_OPUS_VENDOR_ID & 0x000000FF),
42   (A2DP_OPUS_VENDOR_ID & 0x0000FF00) >> 8,
43   (A2DP_OPUS_VENDOR_ID & 0x00FF0000) >> 16,
44   (A2DP_OPUS_VENDOR_ID & 0xFF000000) >> 24,
45   (A2DP_OPUS_CODEC_ID & 0x00FF),
46   (A2DP_OPUS_CODEC_ID & 0xFF00) >> 8,
47   A2DP_OPUS_CHANNEL_MODE_STEREO | A2DP_OPUS_20MS_FRAMESIZE |
48       A2DP_OPUS_SAMPLING_FREQ_48000
49 };
Data(BT_HDR * packet)50 uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
51 
GetReadSize()52 uint32_t GetReadSize() {
53   return A2DP_VendorGetFrameSizeOpus(kCodecInfoOpusCapability) * A2DP_VendorGetTrackChannelCountOpus(kCodecInfoOpusCapability) * (A2DP_VendorGetTrackBitsPerSampleOpus(kCodecInfoOpusCapability) / 8);
54 }
55 }  // namespace
56 
57 namespace bluetooth {
58 namespace testing {
59 
60 static BT_HDR* packet = nullptr;
61 static WavReader wav_reader = WavReader(GetWavFilePath(kWavFile).c_str());
62 static std::promise<void> promise;
63 
64 class A2dpOpusTest : public ::testing::Test {
65  protected:
SetUp()66   void SetUp() override {
67     common::InitFlags::SetAllForTesting();
68     SetCodecConfig();
69     encoder_iface_ = const_cast<tA2DP_ENCODER_INTERFACE*>(
70         A2DP_VendorGetEncoderInterfaceOpus(kCodecInfoOpusCapability));
71     ASSERT_NE(encoder_iface_, nullptr);
72     decoder_iface_ = const_cast<tA2DP_DECODER_INTERFACE*>(
73         A2DP_VendorGetDecoderInterfaceOpus(kCodecInfoOpusCapability));
74     ASSERT_NE(decoder_iface_, nullptr);
75   }
76 
TearDown()77   void TearDown() override {
78     if (a2dp_codecs_ != nullptr) {
79       delete a2dp_codecs_;
80     }
81     if (encoder_iface_ != nullptr) {
82       encoder_iface_->encoder_cleanup();
83     }
84     if (decoder_iface_ != nullptr) {
85       decoder_iface_->decoder_cleanup();
86     }
87   }
88 
SetCodecConfig()89   void SetCodecConfig() {
90     uint8_t codec_info_result[AVDT_CODEC_SIZE];
91     btav_a2dp_codec_index_t peer_codec_index;
92     a2dp_codecs_ = new A2dpCodecs(std::vector<btav_a2dp_codec_config_t>());
93 
94     ASSERT_TRUE(a2dp_codecs_->init());
95 
96     // Create the codec capability - SBC Sink
97     memset(codec_info_result, 0, sizeof(codec_info_result));
98     peer_codec_index = A2DP_SinkCodecIndex(kCodecInfoOpusCapability);
99     ASSERT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
100     codec_config_ = a2dp_codecs_->findSinkCodecConfig(kCodecInfoOpusCapability);
101     ASSERT_NE(codec_config_, nullptr);
102     ASSERT_TRUE(a2dp_codecs_->setSinkCodecConfig(kCodecInfoOpusCapability, true,
103                                                  codec_info_result, true));
104     ASSERT_EQ(a2dp_codecs_->getCurrentCodecConfig(), codec_config_);
105     // Compare the result codec with the local test codec info
106     for (size_t i = 0; i < kCodecInfoOpusCapability[0] + 1; i++) {
107       ASSERT_EQ(codec_info_result[i], kCodecInfoOpusCapability[i]);
108     }
109     ASSERT_EQ(codec_config_->getAudioBitsPerSample(), 16);
110   }
111 
InitializeEncoder(a2dp_source_read_callback_t read_cb,a2dp_source_enqueue_callback_t enqueue_cb)112   void InitializeEncoder(a2dp_source_read_callback_t read_cb,
113                          a2dp_source_enqueue_callback_t enqueue_cb) {
114     tA2DP_ENCODER_INIT_PEER_PARAMS peer_params = {true, true, 1000};
115     encoder_iface_->encoder_init(&peer_params, codec_config_, read_cb,
116                                  enqueue_cb);
117   }
118 
InitializeDecoder(decoded_data_callback_t data_cb)119   void InitializeDecoder(decoded_data_callback_t data_cb) {
120     decoder_iface_->decoder_init(data_cb);
121   }
122 
AllocateL2capPacket(const std::vector<uint8_t> data) const123   BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
124     auto packet = AllocatePacket(data.size());
125     std::copy(data.cbegin(), data.cend(), Data(packet));
126     return packet;
127   }
128 
AllocatePacket(size_t packet_length) const129   BT_HDR* AllocatePacket(size_t packet_length) const {
130     BT_HDR* packet =
131         static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
132     packet->len = packet_length;
133     return packet;
134   }
135   A2dpCodecConfig* codec_config_;
136   A2dpCodecs* a2dp_codecs_;
137   tA2DP_ENCODER_INTERFACE* encoder_iface_;
138   tA2DP_DECODER_INTERFACE* decoder_iface_;
139 };
140 
TEST_F(A2dpOpusTest,a2dp_source_read_underflow)141 TEST_F(A2dpOpusTest, a2dp_source_read_underflow) {
142   promise = {};
143   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
144     // underflow
145     return 0;
146   };
147   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
148     promise.set_value();
149     osi_free(p_buf);
150     return false;
151   };
152   InitializeEncoder(read_cb, enqueue_cb);
153   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
154   encoder_iface_->send_frames(timestamp_us);
155   usleep(kA2dpTickUs);
156   timestamp_us = bluetooth::common::time_gettimeofday_us();
157   encoder_iface_->send_frames(timestamp_us);
158   ASSERT_EQ(promise.get_future().wait_for(std::chrono::milliseconds(10)),
159             std::future_status::timeout);
160 }
161 
TEST_F(A2dpOpusTest,a2dp_enqueue_cb_is_invoked)162 TEST_F(A2dpOpusTest, a2dp_enqueue_cb_is_invoked) {
163   promise = {};
164   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
165     log::assert_that(GetReadSize() == len,
166                      "assert failed: GetReadSize() == len");
167     return len;
168   };
169   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
170     static bool first_invocation = true;
171     if (first_invocation) {
172       promise.set_value();
173     }
174     first_invocation = false;
175     osi_free(p_buf);
176     return false;
177   };
178   InitializeEncoder(read_cb, enqueue_cb);
179   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
180   encoder_iface_->send_frames(timestamp_us);
181   usleep(kA2dpTickUs);
182   timestamp_us = bluetooth::common::time_gettimeofday_us();
183   encoder_iface_->send_frames(timestamp_us);
184   promise.get_future().wait();
185 }
186 
TEST_F(A2dpOpusTest,decoded_data_cb_not_invoked_when_empty_packet)187 TEST_F(A2dpOpusTest, decoded_data_cb_not_invoked_when_empty_packet) {
188   auto data_cb = +[](uint8_t* p_buf, uint32_t len) { FAIL(); };
189   InitializeDecoder(data_cb);
190   std::vector<uint8_t> data;
191   BT_HDR* packet = AllocateL2capPacket(data);
192   decoder_iface_->decode_packet(packet);
193   osi_free(packet);
194 }
195 
TEST_F(A2dpOpusTest,decoded_data_cb_invoked)196 TEST_F(A2dpOpusTest, decoded_data_cb_invoked) {
197   promise = {};
198   auto data_cb = +[](uint8_t* p_buf, uint32_t len) {};
199   InitializeDecoder(data_cb);
200 
201   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
202     static uint32_t counter = 0;
203     memcpy(p_buf, wav_reader.GetSamples() + counter, len);
204     counter += len;
205     return len;
206   };
207   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
208     static bool first_invocation = true;
209     if (first_invocation) {
210       packet = reinterpret_cast<BT_HDR*>(
211           osi_malloc(sizeof(*p_buf) + p_buf->len + 1));
212       memcpy(packet, p_buf, sizeof(*p_buf));
213       packet->offset = 0;
214       memcpy(packet->data + 1, p_buf->data + p_buf->offset, p_buf->len);
215       packet->data[0] = frames_n;
216       p_buf->len += 1;
217       promise.set_value();
218     }
219     first_invocation = false;
220     osi_free(p_buf);
221     return false;
222   };
223   InitializeEncoder(read_cb, enqueue_cb);
224 
225   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
226   encoder_iface_->send_frames(timestamp_us);
227 
228   promise.get_future().wait();
229   decoder_iface_->decode_packet(packet);
230   osi_free(packet);
231 }
232 
233 }  // namespace testing
234 }  // namespace bluetooth
235