1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 * Copyright (c) 2022 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "audio_hal_client.h"
20
21 #include <bluetooth/log.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24
25 #include <chrono>
26 #include <future>
27
28 #include "audio_hal_interface/le_audio_software.h"
29 #include "base/bind_helpers.h"
30 #include "common/message_loop_thread.h"
31 #include "hardware/bluetooth.h"
32 #include "osi/include/wakelock.h"
33
34 // TODO(b/369381361) Enfore -Wmissing-prototypes
35 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
36
37 using ::testing::_;
38 using ::testing::Assign;
39 using ::testing::AtLeast;
40 using ::testing::DoAll;
41 using ::testing::DoDefault;
42 using ::testing::Invoke;
43 using ::testing::Mock;
44 using ::testing::Return;
45 using ::testing::ReturnPointee;
46 using ::testing::SaveArg;
47 using std::chrono_literals::operator""ms;
48
49 using bluetooth::le_audio::DsaMode;
50 using bluetooth::le_audio::DsaModes;
51 using bluetooth::le_audio::LeAudioCodecConfiguration;
52 using bluetooth::le_audio::LeAudioSinkAudioHalClient;
53 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
54
55 using namespace bluetooth;
56
57 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()58 bluetooth::common::MessageLoopThread* get_main_thread() { return &message_loop_thread; }
do_in_main_thread(base::OnceClosure task)59 bt_status_t do_in_main_thread(base::OnceClosure task) {
60 if (!message_loop_thread.DoInThread(FROM_HERE, std::move(task))) {
61 log::error("failed to post task to task runner!");
62 return BT_STATUS_FAIL;
63 }
64 return BT_STATUS_SUCCESS;
65 }
66
67 static base::MessageLoop* message_loop_;
get_main_message_loop()68 base::MessageLoop* get_main_message_loop() { return message_loop_; }
69
init_message_loop_thread()70 static void init_message_loop_thread() {
71 message_loop_thread.StartUp();
72 if (!message_loop_thread.IsRunning()) {
73 FAIL() << "unable to create message loop thread.";
74 }
75
76 if (!message_loop_thread.EnableRealTimeScheduling()) {
77 log::error("Unable to set real time scheduling");
78 }
79
80 message_loop_ = message_loop_thread.message_loop();
81 if (message_loop_ == nullptr) {
82 FAIL() << "unable to get message loop.";
83 }
84 }
85
cleanup_message_loop_thread()86 static void cleanup_message_loop_thread() {
87 message_loop_ = nullptr;
88 message_loop_thread.ShutDown();
89 }
90
91 using bluetooth::audio::le_audio::LeAudioClientInterface;
92
93 class MockLeAudioClientInterfaceSink : public LeAudioClientInterface::Sink {
94 public:
95 MOCK_METHOD((void), Cleanup, (), (override));
96 MOCK_METHOD((void), SetPcmParameters, (const LeAudioClientInterface::PcmParameters& params),
97 (override));
98 MOCK_METHOD((void), SetRemoteDelay, (uint16_t delay_report_ms), (override));
99 MOCK_METHOD((void), StartSession, (), (override));
100 MOCK_METHOD((void), StopSession, (), (override));
101 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
102 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
103 MOCK_METHOD((void), UpdateAudioConfigToHal, (const ::bluetooth::le_audio::offload_config&));
104 MOCK_METHOD((std::optional<::le_audio::broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
105 ((const std::vector<std::pair<::le_audio::types::LeAudioContextType, uint8_t>>&),
106 (const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
107 (const));
108 MOCK_METHOD((std::optional<::le_audio::set_configurations::AudioSetConfiguration>),
109 GetUnicastConfig,
110 (const ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements&),
111 (const));
112 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
113 (const ::bluetooth::le_audio::broadcast_offload_config&));
114 MOCK_METHOD((size_t), Read, (uint8_t* p_buf, uint32_t len));
115 };
116
117 class MockLeAudioClientInterfaceSource : public LeAudioClientInterface::Source {
118 public:
119 MOCK_METHOD((void), Cleanup, (), (override));
120 MOCK_METHOD((void), SetPcmParameters, (const LeAudioClientInterface::PcmParameters& params),
121 (override));
122 MOCK_METHOD((void), SetRemoteDelay, (uint16_t delay_report_ms), (override));
123 MOCK_METHOD((void), StartSession, (), (override));
124 MOCK_METHOD((void), StopSession, (), (override));
125 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
126 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
127 MOCK_METHOD((void), UpdateAudioConfigToHal, (const ::bluetooth::le_audio::offload_config&));
128 MOCK_METHOD((size_t), Write, (const uint8_t* p_buf, uint32_t len));
129 };
130
131 class MockLeAudioClientInterface : public LeAudioClientInterface {
132 public:
133 MockLeAudioClientInterface() = default;
134 ~MockLeAudioClientInterface() = default;
135
136 MOCK_METHOD((Sink*), GetSink,
137 (bluetooth::audio::le_audio::StreamCallbacks stream_cb,
138 bluetooth::common::MessageLoopThread* message_loop,
139 bool is_broadcasting_session_type));
140 MOCK_METHOD((Source*), GetSource,
141 (bluetooth::audio::le_audio::StreamCallbacks stream_cb,
142 bluetooth::common::MessageLoopThread* message_loop));
143
144 MOCK_METHOD((void), SetAllowedDsaModes, (DsaModes dsa_modes));
145 };
146
147 LeAudioClientInterface* mockInterface;
148
149 namespace bluetooth {
150 namespace audio {
151 namespace le_audio {
152 MockLeAudioClientInterface* interface_mock;
153 MockLeAudioClientInterfaceSink* sink_mock;
154 MockLeAudioClientInterfaceSource* source_mock;
155
Get()156 LeAudioClientInterface* LeAudioClientInterface::Get() { return interface_mock; }
157
GetSink(StreamCallbacks stream_cb,bluetooth::common::MessageLoopThread * message_loop,bool is_broadcasting_session_type)158 LeAudioClientInterface::Sink* LeAudioClientInterface::GetSink(
159 StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* message_loop,
160 bool is_broadcasting_session_type) {
161 return interface_mock->GetSink(stream_cb, message_loop, is_broadcasting_session_type);
162 }
163
GetSource(StreamCallbacks stream_cb,bluetooth::common::MessageLoopThread * message_loop)164 LeAudioClientInterface::Source* LeAudioClientInterface::GetSource(
165 StreamCallbacks stream_cb, bluetooth::common::MessageLoopThread* message_loop) {
166 return interface_mock->GetSource(stream_cb, message_loop);
167 }
168
ReleaseSink(LeAudioClientInterface::Sink *)169 bool LeAudioClientInterface::ReleaseSink(LeAudioClientInterface::Sink* /*sink*/) { return true; }
ReleaseSource(LeAudioClientInterface::Source *)170 bool LeAudioClientInterface::ReleaseSource(LeAudioClientInterface::Source* /*source*/) {
171 return true;
172 }
173
SetAllowedDsaModes(DsaModes)174 void LeAudioClientInterface::SetAllowedDsaModes(DsaModes /*dsa_modes*/) { return; }
175
Cleanup()176 void LeAudioClientInterface::Sink::Cleanup() {}
SetPcmParameters(const PcmParameters &)177 void LeAudioClientInterface::Sink::SetPcmParameters(const PcmParameters& /*params*/) {}
SetRemoteDelay(uint16_t)178 void LeAudioClientInterface::Sink::SetRemoteDelay(uint16_t /*delay_report_ms*/) {}
StartSession()179 void LeAudioClientInterface::Sink::StartSession() {}
StopSession()180 void LeAudioClientInterface::Sink::StopSession() {}
ConfirmStreamingRequest()181 void LeAudioClientInterface::Sink::ConfirmStreamingRequest() {}
CancelStreamingRequest()182 void LeAudioClientInterface::Sink::CancelStreamingRequest() {}
UpdateAudioConfigToHal(const::bluetooth::le_audio::offload_config &)183 void LeAudioClientInterface::Sink::UpdateAudioConfigToHal(
184 const ::bluetooth::le_audio::offload_config& /*config*/) {}
UpdateBroadcastAudioConfigToHal(const::bluetooth::le_audio::broadcast_offload_config &)185 void LeAudioClientInterface::Sink::UpdateBroadcastAudioConfigToHal(
186 const ::bluetooth::le_audio::broadcast_offload_config& /*config*/) {}
187 std::optional<::le_audio::broadcaster::BroadcastConfiguration>
GetBroadcastConfig(const std::vector<std::pair<::le_audio::types::LeAudioContextType,uint8_t>> & quality,const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>> & pacs) const188 LeAudioClientInterface::Sink::GetBroadcastConfig(
189 const std::vector<std::pair<::le_audio::types::LeAudioContextType, uint8_t>>& quality,
190 const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>& pacs) const {
191 return sink_mock->GetBroadcastConfig(quality, pacs);
192 }
193 std::optional<::le_audio::set_configurations::AudioSetConfiguration>
GetUnicastConfig(const::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements & requirements) const194 LeAudioClientInterface::Sink::GetUnicastConfig(
195 const ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements& requirements)
196 const {
197 return sink_mock->GetUnicastConfig(requirements);
198 }
SuspendedForReconfiguration()199 void LeAudioClientInterface::Sink::SuspendedForReconfiguration() {}
ReconfigurationComplete()200 void LeAudioClientInterface::Sink::ReconfigurationComplete() {}
201
Cleanup()202 void LeAudioClientInterface::Source::Cleanup() {}
SetPcmParameters(const PcmParameters &)203 void LeAudioClientInterface::Source::SetPcmParameters(const PcmParameters& /*params*/) {}
SetRemoteDelay(uint16_t)204 void LeAudioClientInterface::Source::SetRemoteDelay(uint16_t /*delay_report_ms*/) {}
StartSession()205 void LeAudioClientInterface::Source::StartSession() {}
StopSession()206 void LeAudioClientInterface::Source::StopSession() {}
ConfirmStreamingRequest()207 void LeAudioClientInterface::Source::ConfirmStreamingRequest() {}
CancelStreamingRequest()208 void LeAudioClientInterface::Source::CancelStreamingRequest() {}
UpdateAudioConfigToHal(const::bluetooth::le_audio::offload_config &)209 void LeAudioClientInterface::Source::UpdateAudioConfigToHal(
210 const ::bluetooth::le_audio::offload_config& /*config*/) {}
SuspendedForReconfiguration()211 void LeAudioClientInterface::Source::SuspendedForReconfiguration() {}
ReconfigurationComplete()212 void LeAudioClientInterface::Source::ReconfigurationComplete() {}
213
Write(const uint8_t * p_buf,uint32_t len)214 size_t LeAudioClientInterface::Source::Write(const uint8_t* p_buf, uint32_t len) {
215 return source_mock->Write(p_buf, len);
216 }
217
Read(uint8_t * p_buf,uint32_t len)218 size_t LeAudioClientInterface::Sink::Read(uint8_t* p_buf, uint32_t len) {
219 return sink_mock->Read(p_buf, len);
220 }
221 } // namespace le_audio
222 } // namespace audio
223 } // namespace bluetooth
224
225 class MockLeAudioClientAudioSinkEventReceiver : public LeAudioSourceAudioHalClient::Callbacks {
226 public:
227 MOCK_METHOD((void), OnAudioDataReady, (const std::vector<uint8_t>& data), (override));
228 MOCK_METHOD((void), OnAudioSuspend, (), (override));
229 MOCK_METHOD((void), OnAudioResume, (), (override));
230 MOCK_METHOD((void), OnAudioMetadataUpdate,
231 (const std::vector<struct playback_track_metadata_v7> source_metadata,
232 DsaMode dsa_mode),
233 (override));
234 };
235
236 class MockAudioHalClientEventReceiver : public LeAudioSinkAudioHalClient::Callbacks {
237 public:
238 MOCK_METHOD((void), OnAudioSuspend, (), (override));
239 MOCK_METHOD((void), OnAudioResume, (), (override));
240 MOCK_METHOD((void), OnAudioMetadataUpdate,
241 (const std::vector<struct record_track_metadata_v7> sink_metadata), (override));
242 };
243
244 class LeAudioClientAudioTest : public ::testing::Test {
245 protected:
SetUp(void)246 void SetUp(void) override {
247 init_message_loop_thread();
248 bluetooth::audio::le_audio::interface_mock = &mock_client_interface_;
249 bluetooth::audio::le_audio::sink_mock = &mock_hal_interface_audio_sink_;
250 bluetooth::audio::le_audio::source_mock = &mock_hal_interface_audio_source_;
251
252 // Init sink Audio HAL mock
253 is_sink_audio_hal_acquired = false;
254 sink_audio_hal_stream_cb = {.on_resume_ = nullptr, .on_suspend_ = nullptr};
255
256 ON_CALL(mock_client_interface_, GetSink(_, _, _))
257 .WillByDefault(DoAll(SaveArg<0>(&sink_audio_hal_stream_cb),
258 Assign(&is_sink_audio_hal_acquired, true),
259 Return(bluetooth::audio::le_audio::sink_mock)));
260 ON_CALL(mock_hal_interface_audio_sink_, Cleanup())
261 .WillByDefault(Assign(&is_sink_audio_hal_acquired, false));
262
263 // Init source Audio HAL mock
264 is_source_audio_hal_acquired = false;
265 source_audio_hal_stream_cb = {.on_resume_ = nullptr, .on_suspend_ = nullptr};
266
267 ON_CALL(mock_client_interface_, GetSource(_, _))
268 .WillByDefault(DoAll(SaveArg<0>(&source_audio_hal_stream_cb),
269 Assign(&is_source_audio_hal_acquired, true),
270 Return(bluetooth::audio::le_audio::source_mock)));
271 ON_CALL(mock_hal_interface_audio_source_, Cleanup())
272 .WillByDefault(Assign(&is_source_audio_hal_acquired, false));
273 }
274
AcquireLeAudioSinkHalClient(void)275 bool AcquireLeAudioSinkHalClient(void) {
276 audio_sink_instance_ = LeAudioSinkAudioHalClient::AcquireUnicast();
277 return is_source_audio_hal_acquired;
278 }
279
ReleaseLeAudioSinkHalClient(void)280 bool ReleaseLeAudioSinkHalClient(void) {
281 audio_sink_instance_.reset();
282 return !is_source_audio_hal_acquired;
283 }
284
AcquireLeAudioSourceHalClient(void)285 bool AcquireLeAudioSourceHalClient(void) {
286 audio_source_instance_ = LeAudioSourceAudioHalClient::AcquireUnicast();
287 return is_sink_audio_hal_acquired;
288 }
289
ReleaseLeAudioSourceHalClient(void)290 bool ReleaseLeAudioSourceHalClient(void) {
291 audio_source_instance_.reset();
292 return !is_sink_audio_hal_acquired;
293 }
294
TearDown(void)295 void TearDown(void) override {
296 com::android::bluetooth::flags::provider_->reset_flags();
297
298 /* We have to call Cleanup to tidy up some static variables.
299 * If on the HAL end Source is running it means we are running the Sink
300 * on our end, and vice versa.
301 */
302 if (is_source_audio_hal_acquired == true) {
303 ReleaseLeAudioSinkHalClient();
304 }
305 if (is_sink_audio_hal_acquired == true) {
306 ReleaseLeAudioSourceHalClient();
307 }
308
309 cleanup_message_loop_thread();
310
311 bluetooth::audio::le_audio::sink_mock = nullptr;
312 bluetooth::audio::le_audio::source_mock = nullptr;
313 }
314
315 MockLeAudioClientInterface mock_client_interface_;
316 MockLeAudioClientInterfaceSink mock_hal_interface_audio_sink_;
317 MockLeAudioClientInterfaceSource mock_hal_interface_audio_source_;
318
319 MockLeAudioClientAudioSinkEventReceiver mock_hal_sink_event_receiver_;
320 MockAudioHalClientEventReceiver mock_hal_source_event_receiver_;
321
322 bool is_source_audio_hal_acquired = false;
323 bool is_sink_audio_hal_acquired = false;
324 std::unique_ptr<LeAudioSinkAudioHalClient> audio_sink_instance_;
325 std::unique_ptr<LeAudioSourceAudioHalClient> audio_source_instance_;
326
327 bluetooth::audio::le_audio::StreamCallbacks source_audio_hal_stream_cb;
328 bluetooth::audio::le_audio::StreamCallbacks sink_audio_hal_stream_cb;
329
330 const LeAudioCodecConfiguration default_codec_conf{
331 .num_channels = LeAudioCodecConfiguration::kChannelNumberMono,
332 .sample_rate = LeAudioCodecConfiguration::kSampleRate44100,
333 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample24,
334 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
335 };
336 };
337
TEST_F(LeAudioClientAudioTest,testLeAudioClientAudioSinkInitializeCleanup)338 TEST_F(LeAudioClientAudioTest, testLeAudioClientAudioSinkInitializeCleanup) {
339 EXPECT_CALL(mock_client_interface_, GetSource(_, _));
340 ASSERT_TRUE(AcquireLeAudioSinkHalClient());
341
342 EXPECT_CALL(mock_hal_interface_audio_source_, Cleanup());
343 ASSERT_TRUE(ReleaseLeAudioSinkHalClient());
344 }
345
TEST_F(LeAudioClientAudioTest,testAudioHalClientInitializeCleanup)346 TEST_F(LeAudioClientAudioTest, testAudioHalClientInitializeCleanup) {
347 EXPECT_CALL(mock_client_interface_, GetSink(_, _, _));
348 ASSERT_TRUE(AcquireLeAudioSourceHalClient());
349
350 EXPECT_CALL(mock_hal_interface_audio_sink_, Cleanup());
351 ASSERT_TRUE(ReleaseLeAudioSourceHalClient());
352 }
353
TEST_F(LeAudioClientAudioTest,testLeAudioClientAudioSinkStartStop)354 TEST_F(LeAudioClientAudioTest, testLeAudioClientAudioSinkStartStop) {
355 LeAudioClientInterface::PcmParameters params;
356 EXPECT_CALL(mock_hal_interface_audio_source_, SetPcmParameters(_))
357 .Times(1)
358 .WillOnce(SaveArg<0>(¶ms));
359 EXPECT_CALL(mock_hal_interface_audio_source_, StartSession()).Times(1);
360
361 ASSERT_TRUE(AcquireLeAudioSinkHalClient());
362 ASSERT_TRUE(audio_sink_instance_->Start(default_codec_conf, &mock_hal_source_event_receiver_));
363
364 ASSERT_EQ(params.channels_count, bluetooth::audio::le_audio::kChannelNumberMono);
365 ASSERT_EQ(params.sample_rate, bluetooth::audio::le_audio::kSampleRate44100);
366 ASSERT_EQ(params.bits_per_sample, bluetooth::audio::le_audio::kBitsPerSample24);
367 ASSERT_EQ(params.data_interval_us, 10000u);
368
369 EXPECT_CALL(mock_hal_interface_audio_source_, StopSession()).Times(1);
370
371 audio_sink_instance_->Stop();
372 }
373
TEST_F(LeAudioClientAudioTest,testAudioHalClientStartStop)374 TEST_F(LeAudioClientAudioTest, testAudioHalClientStartStop) {
375 LeAudioClientInterface::PcmParameters params;
376 EXPECT_CALL(mock_hal_interface_audio_sink_, SetPcmParameters(_))
377 .Times(1)
378 .WillOnce(SaveArg<0>(¶ms));
379 EXPECT_CALL(mock_hal_interface_audio_sink_, StartSession()).Times(1);
380
381 ASSERT_TRUE(AcquireLeAudioSourceHalClient());
382 ASSERT_TRUE(audio_source_instance_->Start(default_codec_conf, &mock_hal_sink_event_receiver_));
383
384 ASSERT_EQ(params.channels_count, bluetooth::audio::le_audio::kChannelNumberMono);
385 ASSERT_EQ(params.sample_rate, bluetooth::audio::le_audio::kSampleRate44100);
386 ASSERT_EQ(params.bits_per_sample, bluetooth::audio::le_audio::kBitsPerSample24);
387 ASSERT_EQ(params.data_interval_us, 10000u);
388
389 EXPECT_CALL(mock_hal_interface_audio_sink_, StopSession()).Times(1);
390
391 audio_source_instance_->Stop();
392 }
393
TEST_F(LeAudioClientAudioTest,testLeAudioClientAudioSinkSendData)394 TEST_F(LeAudioClientAudioTest, testLeAudioClientAudioSinkSendData) {
395 ASSERT_TRUE(AcquireLeAudioSinkHalClient());
396 ASSERT_TRUE(audio_sink_instance_->Start(default_codec_conf, &mock_hal_source_event_receiver_));
397
398 const uint8_t* exp_p = nullptr;
399 uint32_t exp_len = 0;
400 uint8_t input_buf[] = {
401 0x02,
402 0x03,
403 0x05,
404 0x19,
405 };
406 ON_CALL(mock_hal_interface_audio_source_, Write(_, _))
407 .WillByDefault(DoAll(SaveArg<0>(&exp_p), SaveArg<1>(&exp_len), ReturnPointee(&exp_len)));
408
409 ASSERT_EQ(audio_sink_instance_->SendData(input_buf, sizeof(input_buf)), sizeof(input_buf));
410 ASSERT_EQ(exp_len, sizeof(input_buf));
411 ASSERT_EQ(exp_p, input_buf);
412
413 audio_sink_instance_->Stop();
414 }
415
TEST_F(LeAudioClientAudioTest,testLeAudioClientAudioSinkSuspend)416 TEST_F(LeAudioClientAudioTest, testLeAudioClientAudioSinkSuspend) {
417 ASSERT_TRUE(AcquireLeAudioSinkHalClient());
418 ASSERT_TRUE(audio_sink_instance_->Start(default_codec_conf, &mock_hal_source_event_receiver_));
419
420 ASSERT_NE(source_audio_hal_stream_cb.on_suspend_, nullptr);
421
422 /* Expect LeAudio registered event listener to get called when HAL calls the
423 * audio_hal_client's internal suspend callback.
424 */
425 EXPECT_CALL(mock_hal_source_event_receiver_, OnAudioSuspend()).Times(1);
426 ASSERT_TRUE(source_audio_hal_stream_cb.on_suspend_());
427 }
428
TEST_F(LeAudioClientAudioTest,testAudioHalClientSuspend)429 TEST_F(LeAudioClientAudioTest, testAudioHalClientSuspend) {
430 ASSERT_TRUE(AcquireLeAudioSourceHalClient());
431 ASSERT_TRUE(audio_source_instance_->Start(default_codec_conf, &mock_hal_sink_event_receiver_));
432
433 ASSERT_NE(sink_audio_hal_stream_cb.on_suspend_, nullptr);
434
435 /* Expect LeAudio registered event listener to get called when HAL calls the
436 * audio_hal_client's internal suspend callback.
437 */
438 EXPECT_CALL(mock_hal_sink_event_receiver_, OnAudioSuspend()).Times(1);
439 ASSERT_TRUE(sink_audio_hal_stream_cb.on_suspend_());
440 }
441
TEST_F(LeAudioClientAudioTest,testLeAudioClientAudioSinkResume)442 TEST_F(LeAudioClientAudioTest, testLeAudioClientAudioSinkResume) {
443 ASSERT_TRUE(AcquireLeAudioSinkHalClient());
444 ASSERT_TRUE(audio_sink_instance_->Start(default_codec_conf, &mock_hal_source_event_receiver_));
445
446 ASSERT_NE(source_audio_hal_stream_cb.on_resume_, nullptr);
447
448 /* Expect LeAudio registered event listener to get called when HAL calls the
449 * audio_hal_client's internal resume callback.
450 */
451 EXPECT_CALL(mock_hal_source_event_receiver_, OnAudioResume()).Times(1);
452 bool start_media_task = false;
453 ASSERT_TRUE(source_audio_hal_stream_cb.on_resume_(start_media_task));
454 }
455
TEST_F(LeAudioClientAudioTest,testAudioHalClientResumeStartSourceTask_workerEnabled)456 TEST_F(LeAudioClientAudioTest, testAudioHalClientResumeStartSourceTask_workerEnabled) {
457 com::android::bluetooth::flags::provider_->run_ble_audio_ticks_in_worker_thread(true);
458
459 const LeAudioCodecConfiguration codec_conf{
460 .num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
461 .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
462 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample24,
463 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
464 };
465 ASSERT_TRUE(AcquireLeAudioSourceHalClient());
466 ASSERT_TRUE(audio_source_instance_->Start(codec_conf, &mock_hal_sink_event_receiver_));
467
468 std::promise<void> promise;
469 auto future = promise.get_future();
470
471 uint32_t calculated_bytes_per_tick = 0;
472 EXPECT_CALL(mock_hal_interface_audio_sink_, Read(_, _))
473 .Times(AtLeast(1))
474 .WillOnce(Invoke([&](uint8_t* p_buf, uint32_t len) -> uint32_t {
475 calculated_bytes_per_tick = len;
476
477 // fake some data from audio framework
478 for (uint32_t i = 0u; i < len; ++i) {
479 p_buf[i] = i;
480 }
481
482 // Return exactly as much data as requested
483 promise.set_value();
484 return len;
485 }))
486 .WillRepeatedly(Invoke([](uint8_t* p_buf, uint32_t len) -> uint32_t {
487 // fake some data from audio framework
488 for (uint32_t i = 0u; i < len; ++i) {
489 p_buf[i] = i;
490 }
491 return len;
492 }));
493
494 std::promise<void> data_promise;
495 auto data_future = data_promise.get_future();
496
497 /* Expect this callback to be called to Client by the HAL glue layer */
498 std::vector<uint8_t> media_data_to_send;
499 EXPECT_CALL(mock_hal_sink_event_receiver_, OnAudioDataReady(_))
500 .Times(AtLeast(1))
501 .WillOnce(Invoke([&](const std::vector<uint8_t>& data) -> void {
502 media_data_to_send = std::move(data);
503 data_promise.set_value();
504 }))
505 .WillRepeatedly(DoDefault());
506
507 /* Expect LeAudio registered event listener to get called when HAL calls the
508 * audio_hal_client's internal resume callback.
509 */
510 ASSERT_NE(sink_audio_hal_stream_cb.on_resume_, nullptr);
511 EXPECT_CALL(mock_hal_sink_event_receiver_, OnAudioResume()).Times(1);
512 bool start_media_task = true;
513 ASSERT_TRUE(sink_audio_hal_stream_cb.on_resume_(start_media_task));
514 audio_source_instance_->ConfirmStreamingRequest();
515
516 ASSERT_EQ(future.wait_for(std::chrono::seconds(1)), std::future_status::ready);
517
518 ASSERT_EQ(data_future.wait_for(std::chrono::seconds(1)), std::future_status::ready);
519
520 // Check against expected payload size
521 // 24 bit audio stream is sent as unpacked, each sample takes 4 bytes.
522 const uint32_t channel_bytes_per_sample = 4;
523 const uint32_t channel_bytes_per_10ms_at_16000Hz =
524 ((10ms).count() * channel_bytes_per_sample * 16000 /*Hz*/) / (1000ms).count();
525
526 // Expect 2 channel (stereo) data
527 ASSERT_EQ(calculated_bytes_per_tick, 2 * channel_bytes_per_10ms_at_16000Hz);
528
529 // Verify if we got just right amount of data in the callback call
530 ASSERT_EQ(media_data_to_send.size(), calculated_bytes_per_tick);
531 }
532
TEST_F(LeAudioClientAudioTest,testAudioHalClientResumeStartSourceTask)533 TEST_F(LeAudioClientAudioTest, testAudioHalClientResumeStartSourceTask) {
534 const LeAudioCodecConfiguration codec_conf{
535 .num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
536 .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
537 .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample24,
538 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
539 };
540 ASSERT_TRUE(AcquireLeAudioSourceHalClient());
541 ASSERT_TRUE(audio_source_instance_->Start(codec_conf, &mock_hal_sink_event_receiver_));
542
543 std::promise<void> promise;
544 auto future = promise.get_future();
545
546 uint32_t calculated_bytes_per_tick = 0;
547 EXPECT_CALL(mock_hal_interface_audio_sink_, Read(_, _))
548 .Times(AtLeast(1))
549 .WillOnce(Invoke([&](uint8_t* p_buf, uint32_t len) -> uint32_t {
550 calculated_bytes_per_tick = len;
551
552 // fake some data from audio framework
553 for (uint32_t i = 0u; i < len; ++i) {
554 p_buf[i] = i;
555 }
556
557 // Return exactly as much data as requested
558 promise.set_value();
559 return len;
560 }))
561 .WillRepeatedly(Invoke([](uint8_t* p_buf, uint32_t len) -> uint32_t {
562 // fake some data from audio framework
563 for (uint32_t i = 0u; i < len; ++i) {
564 p_buf[i] = i;
565 }
566 return len;
567 }));
568
569 std::promise<void> data_promise;
570 auto data_future = data_promise.get_future();
571
572 /* Expect this callback to be called to Client by the HAL glue layer */
573 std::vector<uint8_t> media_data_to_send;
574 EXPECT_CALL(mock_hal_sink_event_receiver_, OnAudioDataReady(_))
575 .Times(AtLeast(1))
576 .WillOnce(Invoke([&](const std::vector<uint8_t>& data) -> void {
577 media_data_to_send = std::move(data);
578 data_promise.set_value();
579 }))
580 .WillRepeatedly(DoDefault());
581
582 /* Expect LeAudio registered event listener to get called when HAL calls the
583 * audio_hal_client's internal resume callback.
584 */
585 ASSERT_NE(sink_audio_hal_stream_cb.on_resume_, nullptr);
586 EXPECT_CALL(mock_hal_sink_event_receiver_, OnAudioResume()).Times(1);
587 bool start_media_task = true;
588 ASSERT_TRUE(sink_audio_hal_stream_cb.on_resume_(start_media_task));
589 audio_source_instance_->ConfirmStreamingRequest();
590
591 ASSERT_EQ(future.wait_for(std::chrono::seconds(1)), std::future_status::ready);
592
593 ASSERT_EQ(data_future.wait_for(std::chrono::seconds(1)), std::future_status::ready);
594
595 // Check agains expected payload size
596 // 24 bit audio stream is sent as unpacked, each sample takes 4 bytes.
597 const uint32_t channel_bytes_per_sample = 4;
598 const uint32_t channel_bytes_per_10ms_at_16000Hz =
599 ((10ms).count() * channel_bytes_per_sample * 16000 /*Hz*/) / (1000ms).count();
600
601 // Expect 2 channel (stereo) data
602 ASSERT_EQ(calculated_bytes_per_tick, 2 * channel_bytes_per_10ms_at_16000Hz);
603
604 // Verify if we got just right amount of data in the callback call
605 ASSERT_EQ(media_data_to_send.size(), calculated_bytes_per_tick);
606 }
607
TEST_F(LeAudioClientAudioTest,testAudioHalClientResume)608 TEST_F(LeAudioClientAudioTest, testAudioHalClientResume) {
609 ASSERT_TRUE(AcquireLeAudioSourceHalClient());
610 ASSERT_TRUE(audio_source_instance_->Start(default_codec_conf, &mock_hal_sink_event_receiver_));
611
612 ASSERT_NE(sink_audio_hal_stream_cb.on_resume_, nullptr);
613
614 /* Expect LeAudio registered event listener to get called when HAL calls the
615 * audio_hal_client's internal resume callback.
616 */
617 EXPECT_CALL(mock_hal_sink_event_receiver_, OnAudioResume()).Times(1);
618 bool start_media_task = false;
619 ASSERT_TRUE(sink_audio_hal_stream_cb.on_resume_(start_media_task));
620 }
621