• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>(&params));
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>(&params));
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