1 /*
2  * Copyright 2024 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 "hfp_client_interface.h"
18 
19 #include <gtest/gtest.h>
20 #include <hardware/audio.h>
21 #include <log/log.h>
22 
23 #include <cerrno>
24 
25 #include "aidl/hfp_client_interface_aidl.h"
26 #include "aidl/transport_instance.h"
27 #include "audio_hal_interface/hal_version_manager.h"
28 
29 #pragma GCC diagnostic ignored "-Wunused-private-field"
30 
31 using testing::Test;
32 
33 using bluetooth::audio::hfp::HfpClientInterface;
34 
35 // Mock
bta_ag_get_sco_offload_enabled()36 bool bta_ag_get_sco_offload_enabled() { return true; }
37 
38 bool sink_client_read_called = false;
39 bool source_client_write_called = false;
40 
41 namespace bluetooth::audio {
42 const BluetoothAudioHalVersion BluetoothAudioHalVersion::VERSION_AIDL_V4 =
43         BluetoothAudioHalVersion(BluetoothAudioHalTransport::AIDL, 4, 0);
44 
GetHalTransport()45 BluetoothAudioHalTransport HalVersionManager::GetHalTransport() {
46   return BluetoothAudioHalTransport::AIDL;
47 }
GetHalVersion()48 BluetoothAudioHalVersion HalVersionManager::GetHalVersion() {
49   return BluetoothAudioHalVersion::VERSION_AIDL_V4;
50 }
51 
52 namespace aidl {
BluetoothAudioClientInterface(IBluetoothTransportInstance * instance)53 BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* instance)
54     : provider_(nullptr),
55       provider_factory_(nullptr),
56       session_started_(false),
57       data_mq_(nullptr),
58       transport_(instance),
59       latency_modes_({LatencyMode::FREE}) {}
60 
BluetoothAudioSinkClientInterface(IBluetoothSinkTransportInstance * sink)61 BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface(
62         IBluetoothSinkTransportInstance* sink)
63     : BluetoothAudioClientInterface{sink}, sink_(sink) {}
~BluetoothAudioSinkClientInterface()64 BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() {}
65 
ReadAudioData(uint8_t *,uint32_t len)66 size_t BluetoothAudioSinkClientInterface::ReadAudioData(uint8_t* /*p_buf*/, uint32_t len) {
67   sink_client_read_called = true;
68   return len;
69 }
70 
BluetoothAudioSourceClientInterface(IBluetoothSourceTransportInstance * source)71 BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface(
72         IBluetoothSourceTransportInstance* source)
73     : BluetoothAudioClientInterface{source}, source_(source) {}
~BluetoothAudioSourceClientInterface()74 BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() {}
75 
WriteAudioData(const uint8_t *,uint32_t len)76 size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* /*p_buf*/, uint32_t len) {
77   source_client_write_called = true;
78   return len;
79 }
80 
IsValid() const81 bool BluetoothAudioClientInterface::IsValid() const { return true; }
82 
SetAllowedLatencyModes(std::vector<LatencyMode>)83 bool BluetoothAudioClientInterface::SetAllowedLatencyModes(
84         std::vector<LatencyMode> /*latency_modes*/) {
85   return false;
86 }
87 
FlushAudioData()88 void BluetoothAudioClientInterface::FlushAudioData() {}
89 
UpdateAudioConfig(const AudioConfiguration &)90 bool BluetoothAudioClientInterface::UpdateAudioConfig(const AudioConfiguration& /*audio_config*/) {
91   return false;
92 }
93 
StartSession()94 int BluetoothAudioClientInterface::StartSession() { return -EINVAL; }
95 
StreamStarted(const BluetoothAudioCtrlAck &)96 void BluetoothAudioClientInterface::StreamStarted(const BluetoothAudioCtrlAck& /*ack*/) {}
97 
EndSession()98 int BluetoothAudioClientInterface::EndSession() { return -EINVAL; }
99 
StreamSuspended(const BluetoothAudioCtrlAck &)100 void BluetoothAudioClientInterface::StreamSuspended(const BluetoothAudioCtrlAck& /*ack*/) {}
101 
GetAudioCapabilities(SessionType)102 std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities(
103         SessionType /*session_type*/) {
104   return std::vector<AudioCapabilities>(0);
105 }
106 
107 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
GetLeAudioAseConfiguration(std::optional<std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>> &,std::optional<std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>> &,std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement> &)108 BluetoothAudioClientInterface::GetLeAudioAseConfiguration(
109         std::optional<
110                 std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
111         /*remoteSinkAudioCapabilities*/,
112         std::optional<
113                 std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
114         /*remoteSourceAudioCapabilities*/,
115         std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>& /*requirements*/) {
116   return std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>();
117 }
118 
119 IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting
getLeAudioBroadcastConfiguration(const std::optional<std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>> &,const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement &)120 BluetoothAudioClientInterface::getLeAudioBroadcastConfiguration(
121         const std::optional<
122                 std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
123         /*remoteSinkAudioCapabilities*/,
124         const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement& /*requirement*/) {
125   return IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting();
126 }
127 
operator <<(std::ostream & os,const BluetoothAudioCtrlAck &)128 std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& /*ack*/) { return os; }
129 
130 namespace hfp {
131 
132 static bool encoding_transport_is_stream_active_ret;
133 static bool decoding_transport_is_stream_active_ret;
134 
HfpTransport()135 HfpTransport::HfpTransport() {}
StartRequest()136 BluetoothAudioCtrlAck HfpTransport::StartRequest() {
137   return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
138 }
StopRequest()139 void HfpTransport::StopRequest() {}
ResetPendingCmd()140 void HfpTransport::ResetPendingCmd() {}
GetPendingCmd() const141 uint8_t HfpTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; }
LogBytesProcessed(size_t)142 void HfpTransport::LogBytesProcessed(size_t /*bytes_read*/) {}
SuspendRequest()143 BluetoothAudioCtrlAck HfpTransport::SuspendRequest() {
144   return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
145 }
SetLatencyMode(LatencyMode)146 void HfpTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {}
SourceMetadataChanged(const source_metadata_v7_t &)147 void HfpTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {}
SinkMetadataChanged(const sink_metadata_v7_t &)148 void HfpTransport::SinkMetadataChanged(const sink_metadata_v7_t&) {}
ResetPresentationPosition()149 void HfpTransport::ResetPresentationPosition() {}
GetPresentationPosition(uint64_t *,uint64_t *,timespec *)150 bool HfpTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/,
151                                            uint64_t* /*total_bytes_read*/,
152                                            timespec* /*data_position*/) {
153   return false;
154 }
155 
GetHfpScoConfig(SessionType)156 std::unordered_map<tBTA_AG_UUID_CODEC, ::hfp::sco_config> HfpTransport::GetHfpScoConfig(
157         SessionType /*sessionType*/) {
158   return std::unordered_map<tBTA_AG_UUID_CODEC, ::hfp::sco_config>{};
159 }
160 
161 // Source / sink functions
HfpDecodingTransport(SessionType session_type)162 HfpDecodingTransport::HfpDecodingTransport(SessionType session_type)
163     : IBluetoothSourceTransportInstance(session_type, (AudioConfiguration){}) {}
164 
~HfpDecodingTransport()165 HfpDecodingTransport::~HfpDecodingTransport() {}
StartRequest(bool)166 BluetoothAudioCtrlAck HfpDecodingTransport::StartRequest(bool /*is_low_latency*/) {
167   return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
168 }
SuspendRequest()169 BluetoothAudioCtrlAck HfpDecodingTransport::SuspendRequest() {
170   return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
171 }
SetLatencyMode(LatencyMode)172 void HfpDecodingTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {}
GetPresentationPosition(uint64_t *,uint64_t *,timespec *)173 bool HfpDecodingTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/,
174                                                    uint64_t* /*total_bytes_written*/,
175                                                    timespec* /*data_position*/) {
176   return false;
177 }
SourceMetadataChanged(const source_metadata_v7_t &)178 void HfpDecodingTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {}
SinkMetadataChanged(const sink_metadata_v7_t &)179 void HfpDecodingTransport::SinkMetadataChanged(const sink_metadata_v7_t& /*sink_metadata*/) {}
ResetPresentationPosition()180 void HfpDecodingTransport::ResetPresentationPosition() {}
LogBytesWritten(size_t)181 void HfpDecodingTransport::LogBytesWritten(size_t /*bytes_written*/) {}
GetPendingCmd() const182 uint8_t HfpDecodingTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; }
ResetPendingCmd()183 void HfpDecodingTransport::ResetPendingCmd() {}
StopRequest()184 void HfpDecodingTransport::StopRequest() {}
IsStreamActive()185 bool HfpDecodingTransport::IsStreamActive() { return decoding_transport_is_stream_active_ret; }
186 
HfpEncodingTransport(SessionType session_type)187 HfpEncodingTransport::HfpEncodingTransport(SessionType session_type)
188     : IBluetoothSinkTransportInstance(session_type, (AudioConfiguration){}) {}
~HfpEncodingTransport()189 HfpEncodingTransport::~HfpEncodingTransport() {}
StartRequest(bool)190 BluetoothAudioCtrlAck HfpEncodingTransport::StartRequest(bool /*is_low_latency*/) {
191   return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
192 }
SuspendRequest()193 BluetoothAudioCtrlAck HfpEncodingTransport::SuspendRequest() {
194   return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
195 }
StopRequest()196 void HfpEncodingTransport::StopRequest() {}
SetLatencyMode(LatencyMode)197 void HfpEncodingTransport::SetLatencyMode(LatencyMode /*latency_mode*/) {}
GetPresentationPosition(uint64_t *,uint64_t *,timespec *)198 bool HfpEncodingTransport::GetPresentationPosition(uint64_t* /*remote_delay_report_ns*/,
199                                                    uint64_t* /*total_bytes_written*/,
200                                                    timespec* /*data_position*/) {
201   return false;
202 }
203 
SourceMetadataChanged(const source_metadata_v7_t &)204 void HfpEncodingTransport::SourceMetadataChanged(const source_metadata_v7_t& /*source_metadata*/) {}
SinkMetadataChanged(const sink_metadata_v7_t &)205 void HfpEncodingTransport::SinkMetadataChanged(const sink_metadata_v7_t& /*sink_metadata*/) {}
ResetPresentationPosition()206 void HfpEncodingTransport::ResetPresentationPosition() {}
LogBytesRead(size_t)207 void HfpEncodingTransport::LogBytesRead(size_t /*bytes_written*/) {}
GetPendingCmd() const208 uint8_t HfpEncodingTransport::GetPendingCmd() const { return HFP_CTRL_CMD_NONE; }
ResetPendingCmd()209 void HfpEncodingTransport::ResetPendingCmd() {}
IsStreamActive()210 bool HfpEncodingTransport::IsStreamActive() { return encoding_transport_is_stream_active_ret; }
211 
212 }  // namespace hfp
213 }  // namespace aidl
214 }  // namespace bluetooth::audio
215 
216 namespace {
217 
218 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
219 static base::MessageLoop* message_loop_;
220 
init_message_loop_thread()221 static void init_message_loop_thread() {
222   message_loop_thread.StartUp();
223   if (!message_loop_thread.IsRunning()) {
224     FAIL() << "unable to create message loop thread.";
225   }
226 
227   if (!message_loop_thread.EnableRealTimeScheduling()) {
228     bluetooth::log::warn("Unable to set real time scheduling");
229   }
230 
231   message_loop_ = message_loop_thread.message_loop();
232   if (message_loop_ == nullptr) {
233     FAIL() << "unable to get message loop.";
234   }
235 }
236 
cleanup_message_loop_thread()237 static void cleanup_message_loop_thread() {
238   message_loop_ = nullptr;
239   message_loop_thread.ShutDown();
240 }
241 
242 class HfpClientInterfaceTest : public Test {
243 protected:
SetUp()244   virtual void SetUp() override {
245     init_message_loop_thread();
246     sink_client_read_called = false;
247     source_client_write_called = false;
248     bluetooth::audio::aidl::hfp::encoding_transport_is_stream_active_ret = true;
249     bluetooth::audio::aidl::hfp::decoding_transport_is_stream_active_ret = true;
250   }
251 
TearDown()252   virtual void TearDown() override { cleanup_message_loop_thread(); }
253 };
254 
TEST_F(HfpClientInterfaceTest,InitEncodeInterfaceAndRead)255 TEST_F(HfpClientInterfaceTest, InitEncodeInterfaceAndRead) {
256   uint8_t data[48];
257   HfpClientInterface::Encode* encode_ = nullptr;
258 
259   encode_ = HfpClientInterface::Get()->GetEncode(&message_loop_thread);
260   ASSERT_NE(nullptr, encode_);
261 
262   encode_->Read(data, 48);
263   ASSERT_EQ(1, sink_client_read_called);
264 
265   HfpClientInterface::Get()->ReleaseEncode(encode_);
266 }
267 
TEST_F(HfpClientInterfaceTest,InitEncodeInterfaceAndReadWhenStreamInactive)268 TEST_F(HfpClientInterfaceTest, InitEncodeInterfaceAndReadWhenStreamInactive) {
269   uint8_t data[48];
270   data[0] = 0xab;
271 
272   HfpClientInterface::Encode* encode_ = nullptr;
273 
274   bluetooth::audio::aidl::hfp::encoding_transport_is_stream_active_ret = false;
275 
276   encode_ = HfpClientInterface::Get()->GetEncode(&message_loop_thread);
277   ASSERT_NE(nullptr, encode_);
278 
279   encode_->Read(data, 48);
280   ASSERT_EQ(0, sink_client_read_called);
281   ASSERT_EQ(0x00, data[0]);
282 
283   HfpClientInterface::Get()->ReleaseEncode(encode_);
284 }
285 
TEST_F(HfpClientInterfaceTest,InitDecodeInterfaceAndWrite)286 TEST_F(HfpClientInterfaceTest, InitDecodeInterfaceAndWrite) {
287   uint8_t data[48];
288   HfpClientInterface::Decode* decode_ = nullptr;
289 
290   decode_ = HfpClientInterface::Get()->GetDecode(&message_loop_thread);
291   ASSERT_NE(nullptr, decode_);
292 
293   decode_->Write(data, 48);
294   ASSERT_EQ(1, source_client_write_called);
295 
296   HfpClientInterface::Get()->ReleaseDecode(decode_);
297 }
298 
TEST_F(HfpClientInterfaceTest,InitDecodeInterfaceAndWriteWhenStreamInactive)299 TEST_F(HfpClientInterfaceTest, InitDecodeInterfaceAndWriteWhenStreamInactive) {
300   uint8_t data[48];
301 
302   HfpClientInterface::Decode* decode_ = nullptr;
303 
304   bluetooth::audio::aidl::hfp::decoding_transport_is_stream_active_ret = false;
305 
306   decode_ = HfpClientInterface::Get()->GetDecode(&message_loop_thread);
307   ASSERT_NE(nullptr, decode_);
308 
309   decode_->Write(data, 48);
310   ASSERT_EQ(0, source_client_write_called);
311 
312   HfpClientInterface::Get()->ReleaseDecode(decode_);
313 }
314 }  // namespace
315