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