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