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/init_flags.h"
22 #include "common/time_util.h"
23 #include "osi/include/allocator.h"
24 #include "stack/include/a2dp_vendor_ldac_constants.h"
25 #include "stack/include/avdt_api.h"
26 #include "stack/include/bt_hdr.h"
27 #include "test_util.h"
28 #include "wav_reader.h"
29 
30 namespace {
31 constexpr uint32_t kA2dpTickUs = 23 * 1000;
32 constexpr char kWavFile[] = "test/a2dp/raw_data/pcm1644s.wav";
33 constexpr uint8_t kCodecInfoLdacCapability[AVDT_CODEC_SIZE] = {
34     A2DP_LDAC_CODEC_LEN,
35     AVDT_MEDIA_TYPE_AUDIO,
36     A2DP_MEDIA_CT_NON_A2DP,
37     0x2D,  // A2DP_LDAC_VENDOR_ID
38     0x01,  // A2DP_LDAC_VENDOR_ID
39     0x00,  // A2DP_LDAC_VENDOR_ID
40     0x00,  // A2DP_LDAC_VENDOR_ID
41     0xAA,  // A2DP_LDAC_CODEC_ID
42     0x00,  // A2DP_LDAC_CODEC_ID,
43     A2DP_LDAC_SAMPLING_FREQ_44100,
44     A2DP_LDAC_CHANNEL_MODE_STEREO,
45 };
Data(BT_HDR * packet)46 uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
47 }  // namespace
48 namespace bluetooth {
49 namespace testing {
50 
51 // static BT_HDR* packet = nullptr;
52 static WavReader wav_reader = WavReader(GetWavFilePath(kWavFile).c_str());
53 
54 class A2dpLdacTest : public ::testing::Test {
55  protected:
SetUp()56   void SetUp() override {
57     common::InitFlags::SetAllForTesting();
58     SetCodecConfig();
59     encoder_iface_ = const_cast<tA2DP_ENCODER_INTERFACE*>(
60         A2DP_VendorGetEncoderInterfaceLdac(kCodecInfoLdacCapability));
61     ASSERT_NE(encoder_iface_, nullptr);
62     decoder_iface_ = const_cast<tA2DP_DECODER_INTERFACE*>(
63         A2DP_VendorGetDecoderInterfaceLdac(kCodecInfoLdacCapability));
64     ASSERT_NE(decoder_iface_, nullptr);
65   }
66 
TearDown()67   void TearDown() override {
68     if (a2dp_codecs_ != nullptr) {
69       delete a2dp_codecs_;
70     }
71     if (encoder_iface_ != nullptr) {
72       encoder_iface_->encoder_cleanup();
73     }
74     if (decoder_iface_ != nullptr) {
75       decoder_iface_->decoder_cleanup();
76     }
77   }
78 
79 // NOTE: Make a super func for all codecs
SetCodecConfig()80   void SetCodecConfig() {
81     uint8_t source_codec_info_result[AVDT_CODEC_SIZE];
82     btav_a2dp_codec_index_t peer_codec_index;
83     a2dp_codecs_ = new A2dpCodecs(std::vector<btav_a2dp_codec_config_t>());
84 
85     ASSERT_TRUE(a2dp_codecs_->init());
86 
87     peer_codec_index = A2DP_SinkCodecIndex(kCodecInfoLdacCapability);
88     ASSERT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
89     ASSERT_EQ(peer_codec_index, BTAV_A2DP_CODEC_INDEX_SINK_LDAC);
90     source_codec_config_ =
91         a2dp_codecs_->findSourceCodecConfig(kCodecInfoLdacCapability);
92     ASSERT_NE(source_codec_config_, nullptr);
93     ASSERT_TRUE(a2dp_codecs_->setCodecConfig(kCodecInfoLdacCapability, true,
94                                                 source_codec_info_result, true));
95     ASSERT_EQ(a2dp_codecs_->getCurrentCodecConfig(), source_codec_config_);
96     // Compare the result codec with the local test codec info
97     for (size_t i = 0; i < kCodecInfoLdacCapability[0] + 1; i++) {
98       ASSERT_EQ(source_codec_info_result[i], kCodecInfoLdacCapability[i]);
99     }
100     ASSERT_NE(source_codec_config_->getAudioBitsPerSample(), 0);
101   }
102 
InitializeEncoder(a2dp_source_read_callback_t read_cb,a2dp_source_enqueue_callback_t enqueue_cb)103   void InitializeEncoder(a2dp_source_read_callback_t read_cb,
104                          a2dp_source_enqueue_callback_t enqueue_cb) {
105     tA2DP_ENCODER_INIT_PEER_PARAMS peer_params = {true, true, 1000};
106     encoder_iface_->encoder_init(&peer_params, source_codec_config_, read_cb,
107                                  enqueue_cb);
108   }
109 
InitializeDecoder(decoded_data_callback_t data_cb)110   void InitializeDecoder(decoded_data_callback_t data_cb) {
111     decoder_iface_->decoder_init(data_cb);
112   }
AllocateL2capPacket(const std::vector<uint8_t> data) const113   BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
114     auto packet = AllocatePacket(data.size());
115     std::copy(data.cbegin(), data.cend(), Data(packet));
116     return packet;
117   }
118 
AllocatePacket(size_t packet_length) const119   BT_HDR* AllocatePacket(size_t packet_length) const {
120     BT_HDR* packet =
121         static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
122     packet->len = packet_length;
123     return packet;
124   }
125   A2dpCodecConfig* source_codec_config_;
126   A2dpCodecs* a2dp_codecs_;
127   tA2DP_ENCODER_INTERFACE* encoder_iface_;
128   tA2DP_DECODER_INTERFACE* decoder_iface_;
129 };
130 
TEST_F(A2dpLdacTest,a2dp_source_read_underflow)131 TEST_F(A2dpLdacTest, a2dp_source_read_underflow) {
132   static int enqueue_cb_invoked = 0;
133 
134   auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
135     return 0;
136   };
137 
138   auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t len) -> bool {
139     enqueue_cb_invoked += 1;
140     return false;
141   };
142 
143   InitializeEncoder(read_cb, enqueue_cb);
144   uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
145   encoder_iface_->send_frames(timestamp_us);
146   encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
147 
148   ASSERT_EQ(enqueue_cb_invoked, 0);
149 }
150 
151 }  // namespace testing
152 }  // namespace bluetooth
153