1 /******************************************************************************
2 *
3 * Copyright 2019 HIMSA II K/S - www.himsa.com.Represented by EHIMA -
4 * www.ehima.com
5 * Copyright (c) 2022 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at:
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20
21 #include <bluetooth/log.h>
22 #include <com_android_bluetooth_flags.h>
23 #include <stdio.h>
24
25 #include <chrono>
26 #include <cstddef>
27 #include <cstdint>
28 #include <functional>
29 #include <memory>
30 #include <mutex>
31 #include <optional>
32 #include <ostream>
33 #include <sstream>
34 #include <string>
35 #include <utility>
36 #include <vector>
37
38 #include "audio/asrc/asrc_resampler.h"
39 #include "audio_hal_client.h"
40 #include "audio_hal_interface/le_audio_software.h"
41 #include "bta/le_audio/codec_manager.h"
42 #include "common/message_loop_thread.h"
43 #include "common/repeating_timer.h"
44 #include "common/time_util.h"
45 #include "hardware/bluetooth.h"
46 #include "le_audio/broadcaster/broadcaster_types.h"
47 #include "le_audio/le_audio_types.h"
48 #include "osi/include/wakelock.h"
49 #include "stack/include/main_thread.h"
50
51 namespace bluetooth::le_audio {
52 namespace {
53 struct AudioHalStats {
54 size_t media_read_total_underflow_bytes;
55 size_t media_read_total_underflow_count;
56 uint64_t media_read_last_underflow_us;
57
AudioHalStatsbluetooth::le_audio::__anoncec690b60111::AudioHalStats58 AudioHalStats() { Reset(); }
59
Resetbluetooth::le_audio::__anoncec690b60111::AudioHalStats60 void Reset() {
61 media_read_total_underflow_bytes = 0;
62 media_read_total_underflow_count = 0;
63 media_read_last_underflow_us = 0;
64 }
65 } sStats;
66
67 class SourceImpl : public LeAudioSourceAudioHalClient {
68 enum LeAudioSinkHalState {
69 HAL_UNINITIALIZED,
70 HAL_STOPPED,
71 HAL_STARTED,
72 } le_audio_sink_hal_state_;
73
74 public:
75 // Interface implementation
76 bool Start(const LeAudioCodecConfiguration& codec_configuration,
77 LeAudioSourceAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes) override;
78 void Stop() override;
79 void ConfirmStreamingRequest() override;
80 void CancelStreamingRequest() override;
81 void UpdateRemoteDelay(uint16_t remote_delay_ms) override;
82 void UpdateAudioConfigToHal(const ::bluetooth::le_audio::offload_config& config) override;
83 std::optional<broadcaster::BroadcastConfiguration> GetBroadcastConfig(
84 const std::vector<std::pair<types::LeAudioContextType, uint8_t>>& subgroup_quality,
85 const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>& pacs)
86 const override;
87 std::optional<::bluetooth::le_audio::set_configurations::AudioSetConfiguration> GetUnicastConfig(
88 const CodecManager::UnicastConfigurationRequirements& requirements) const override;
89 void UpdateBroadcastAudioConfigToHal(
90 const ::bluetooth::le_audio::broadcast_offload_config& config) override;
91 void SuspendedForReconfiguration() override;
92 void ReconfigurationComplete() override;
93
94 // Internal functionality
SourceImpl(bool is_broadcaster)95 SourceImpl(bool is_broadcaster)
96 : le_audio_sink_hal_state_(HAL_UNINITIALIZED),
97 audio_timer_(
98 /* clock_tick_us= */ bluetooth::common::time_get_audio_server_tick_us),
99 is_broadcaster_(is_broadcaster) {}
~SourceImpl()100 ~SourceImpl() override {
101 if (le_audio_sink_hal_state_ != HAL_UNINITIALIZED) {
102 Release();
103 }
104 }
105
106 bool OnResumeReq(bool start_media_task);
107 bool OnSuspendReq();
108 bool OnMetadataUpdateReq(const source_metadata_v7_t& source_metadata, DsaMode latency_mode);
109 bool Acquire();
110 void Release();
111 bool InitAudioSinkThread();
112
113 bluetooth::common::MessageLoopThread* worker_thread_;
114 bluetooth::common::RepeatingTimer audio_timer_;
115 LeAudioCodecConfiguration source_codec_config_;
116 void StartAudioTicks();
117 void StopAudioTicks();
118 void SendAudioData();
119
120 bool is_broadcaster_;
121
122 bluetooth::audio::le_audio::LeAudioClientInterface::Sink* halSinkInterface_ = nullptr;
123 LeAudioSourceAudioHalClient::Callbacks* audioSourceCallbacks_ = nullptr;
124 std::mutex audioSourceCallbacksMutex_;
125 std::unique_ptr<bluetooth::audio::asrc::SourceAudioHalAsrc> asrc_;
126
127 base::WeakPtrFactory<SourceImpl> weak_factory_{this};
128 };
129
Acquire()130 bool SourceImpl::Acquire() {
131 auto sink_stream_cb = bluetooth::audio::le_audio::StreamCallbacks{
132 .on_resume_ = std::bind(&SourceImpl::OnResumeReq, this, std::placeholders::_1),
133 .on_suspend_ = std::bind(&SourceImpl::OnSuspendReq, this),
134 .on_metadata_update_ = std::bind(&SourceImpl::OnMetadataUpdateReq, this,
135 std::placeholders::_1, std::placeholders::_2),
136 .on_sink_metadata_update_ =
137 [](const sink_metadata_v7_t& /*sink_metadata*/) {
138 // TODO: update microphone configuration based on sink metadata
139 return true;
140 },
141 };
142
143 /* Get pointer to singleton LE audio client interface */
144 auto halInterface = audio::le_audio::LeAudioClientInterface::Get();
145 if (halInterface == nullptr) {
146 log::error("Can't get LE Audio HAL interface");
147 return false;
148 }
149
150 halSinkInterface_ = halInterface->GetSink(sink_stream_cb, get_main_thread(), is_broadcaster_);
151
152 if (halSinkInterface_ == nullptr) {
153 log::error("Can't get Audio HAL Audio sink interface");
154 return false;
155 }
156
157 log::info("");
158 le_audio_sink_hal_state_ = HAL_STOPPED;
159 return this->InitAudioSinkThread();
160 }
161
Release()162 void SourceImpl::Release() {
163 if (le_audio_sink_hal_state_ == HAL_UNINITIALIZED) {
164 log::warn("Audio HAL Audio sink is not running");
165 return;
166 }
167
168 log::info("");
169 worker_thread_->ShutDown();
170
171 if (halSinkInterface_) {
172 if (le_audio_sink_hal_state_ == HAL_STARTED) {
173 halSinkInterface_->StopSession();
174 le_audio_sink_hal_state_ = HAL_STOPPED;
175 }
176
177 halSinkInterface_->Cleanup();
178
179 auto halInterface = audio::le_audio::LeAudioClientInterface::Get();
180 if (halInterface != nullptr) {
181 halInterface->ReleaseSink(halSinkInterface_);
182 } else {
183 log::error("Can't get LE Audio HAL interface");
184 }
185
186 le_audio_sink_hal_state_ = HAL_UNINITIALIZED;
187 halSinkInterface_ = nullptr;
188 }
189 }
190
OnResumeReq(bool)191 bool SourceImpl::OnResumeReq(bool /*start_media_task*/) {
192 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
193 if (audioSourceCallbacks_ == nullptr) {
194 log::error("audioSourceCallbacks_ not set");
195 return false;
196 }
197 bt_status_t status =
198 do_in_main_thread(base::BindOnce(&LeAudioSourceAudioHalClient::Callbacks::OnAudioResume,
199 audioSourceCallbacks_->weak_factory_.GetWeakPtr()));
200 if (status == BT_STATUS_SUCCESS) {
201 return true;
202 }
203
204 log::error("do_in_main_thread err={}", status);
205 return false;
206 }
207
SendAudioData()208 void SourceImpl::SendAudioData() {
209 if (halSinkInterface_ == nullptr) {
210 log::error("Audio HAL Audio sink interface not acquired - aborting");
211 return;
212 }
213
214 // 24 bit audio is aligned to 32bit
215 int bytes_per_sample = (source_codec_config_.bits_per_sample == 24)
216 ? 4
217 : (source_codec_config_.bits_per_sample / 8);
218 uint32_t bytes_per_tick = (source_codec_config_.num_channels * source_codec_config_.sample_rate *
219 source_codec_config_.data_interval_us / 1000 * bytes_per_sample) /
220 1000;
221 std::vector<uint8_t> data(bytes_per_tick);
222
223 uint32_t bytes_read = halSinkInterface_->Read(data.data(), bytes_per_tick);
224 if (bytes_read < bytes_per_tick) {
225 sStats.media_read_total_underflow_bytes += bytes_per_tick - bytes_read;
226 sStats.media_read_total_underflow_count++;
227 sStats.media_read_last_underflow_us = bluetooth::common::time_get_os_boottime_us();
228 }
229
230 if (com::android::bluetooth::flags::leaudio_hal_client_asrc()) {
231 auto asrc_buffers = asrc_->Run(data);
232
233 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
234 for (auto buffer : asrc_buffers) {
235 if (audioSourceCallbacks_ != nullptr) {
236 audioSourceCallbacks_->OnAudioDataReady(*buffer);
237 }
238 }
239 } else {
240 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
241 if (audioSourceCallbacks_ != nullptr) {
242 audioSourceCallbacks_->OnAudioDataReady(data);
243 }
244 }
245 }
246
InitAudioSinkThread()247 bool SourceImpl::InitAudioSinkThread() {
248 const std::string thread_name = is_broadcaster_ ? "bt_le_audio_broadcast_sink_worker_thread"
249 : "bt_le_audio_unicast_sink_worker_thread";
250 worker_thread_ = new bluetooth::common::MessageLoopThread(thread_name);
251
252 worker_thread_->StartUp();
253 if (!worker_thread_->IsRunning()) {
254 log::error("Unable to start up the BLE audio sink worker thread");
255 return false;
256 }
257
258 /* Schedule the rest of the operations */
259 if (!worker_thread_->EnableRealTimeScheduling()) {
260 #if defined(__ANDROID__)
261 log::fatal("Failed to increase media thread priority");
262 #endif
263 }
264
265 return true;
266 }
267
StartAudioTicks()268 void SourceImpl::StartAudioTicks() {
269 wakelock_acquire();
270 if (com::android::bluetooth::flags::leaudio_hal_client_asrc()) {
271 asrc_ = std::make_unique<bluetooth::audio::asrc::SourceAudioHalAsrc>(
272 worker_thread_, source_codec_config_.num_channels, source_codec_config_.sample_rate,
273 source_codec_config_.bits_per_sample, source_codec_config_.data_interval_us);
274 }
275 audio_timer_.SchedulePeriodic(
276 worker_thread_->GetWeakPtr(), FROM_HERE,
277 base::BindRepeating(&SourceImpl::SendAudioData, weak_factory_.GetWeakPtr()),
278 std::chrono::microseconds(source_codec_config_.data_interval_us));
279 }
280
StopAudioTicks()281 void SourceImpl::StopAudioTicks() {
282 audio_timer_.CancelAndWait();
283 asrc_.reset(nullptr);
284 wakelock_release();
285 }
286
OnSuspendReq()287 bool SourceImpl::OnSuspendReq() {
288 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
289 if (CodecManager::GetInstance()->GetCodecLocation() == types::CodecLocation::HOST) {
290 if (com::android::bluetooth::flags::run_ble_audio_ticks_in_worker_thread()) {
291 worker_thread_->DoInThread(
292 FROM_HERE, base::BindOnce(&SourceImpl::StopAudioTicks, weak_factory_.GetWeakPtr()));
293 } else {
294 StopAudioTicks();
295 }
296 }
297
298 if (audioSourceCallbacks_ == nullptr) {
299 log::error("audioSourceCallbacks_ not set");
300 return false;
301 }
302
303 bt_status_t status =
304 do_in_main_thread(base::BindOnce(&LeAudioSourceAudioHalClient::Callbacks::OnAudioSuspend,
305 audioSourceCallbacks_->weak_factory_.GetWeakPtr()));
306 if (status == BT_STATUS_SUCCESS) {
307 return true;
308 }
309
310 log::error("do_in_main_thread err={}", status);
311 return false;
312 }
313
OnMetadataUpdateReq(const source_metadata_v7_t & source_metadata,DsaMode dsa_mode)314 bool SourceImpl::OnMetadataUpdateReq(const source_metadata_v7_t& source_metadata,
315 DsaMode dsa_mode) {
316 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
317 if (audioSourceCallbacks_ == nullptr) {
318 log::error("audio receiver not started");
319 return false;
320 }
321
322 std::vector<struct playback_track_metadata_v7> metadata(
323 source_metadata.tracks, source_metadata.tracks + source_metadata.track_count);
324
325 bt_status_t status = do_in_main_thread(base::BindOnce(
326 &LeAudioSourceAudioHalClient::Callbacks::OnAudioMetadataUpdate,
327 audioSourceCallbacks_->weak_factory_.GetWeakPtr(), std::move(metadata), dsa_mode));
328 if (status == BT_STATUS_SUCCESS) {
329 return true;
330 }
331
332 log::error("do_in_main_thread err={}", status);
333 return false;
334 }
335
Start(const LeAudioCodecConfiguration & codec_configuration,LeAudioSourceAudioHalClient::Callbacks * audioReceiver,DsaModes dsa_modes)336 bool SourceImpl::Start(const LeAudioCodecConfiguration& codec_configuration,
337 LeAudioSourceAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes) {
338 if (!halSinkInterface_) {
339 log::error("Audio HAL Audio sink interface not acquired");
340 return false;
341 }
342
343 if (le_audio_sink_hal_state_ == HAL_STARTED) {
344 log::error("Audio HAL Audio sink is already in use");
345 return false;
346 }
347
348 log::info("bit rate: {}, num channels: {}, sample rate: {}, data interval: {}",
349 codec_configuration.bits_per_sample, codec_configuration.num_channels,
350 codec_configuration.sample_rate, codec_configuration.data_interval_us);
351
352 sStats.Reset();
353
354 /* Global config for periodic audio data */
355 source_codec_config_ = codec_configuration;
356 audio::le_audio::LeAudioClientInterface::PcmParameters pcmParameters = {
357 .data_interval_us = codec_configuration.data_interval_us,
358 .sample_rate = codec_configuration.sample_rate,
359 .bits_per_sample = codec_configuration.bits_per_sample,
360 .channels_count = codec_configuration.num_channels};
361
362 halSinkInterface_->SetPcmParameters(pcmParameters);
363 audio::le_audio::LeAudioClientInterface::Get()->SetAllowedDsaModes(dsa_modes);
364 halSinkInterface_->StartSession();
365
366 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
367 audioSourceCallbacks_ = audioReceiver;
368 le_audio_sink_hal_state_ = HAL_STARTED;
369 return true;
370 }
371
Stop()372 void SourceImpl::Stop() {
373 if (!halSinkInterface_) {
374 log::error("Audio HAL Audio sink interface already stopped");
375 return;
376 }
377
378 if (le_audio_sink_hal_state_ != HAL_STARTED) {
379 log::error("Audio HAL Audio sink was not started!");
380 return;
381 }
382
383 log::info("");
384
385 halSinkInterface_->StopSession();
386 le_audio_sink_hal_state_ = HAL_STOPPED;
387
388 if (CodecManager::GetInstance()->GetCodecLocation() == types::CodecLocation::HOST) {
389 if (com::android::bluetooth::flags::run_ble_audio_ticks_in_worker_thread()) {
390 worker_thread_->DoInThread(
391 FROM_HERE, base::BindOnce(&SourceImpl::StopAudioTicks, weak_factory_.GetWeakPtr()));
392 } else {
393 StopAudioTicks();
394 }
395 }
396
397 std::lock_guard<std::mutex> guard(audioSourceCallbacksMutex_);
398 audioSourceCallbacks_ = nullptr;
399 }
400
ConfirmStreamingRequest()401 void SourceImpl::ConfirmStreamingRequest() {
402 if ((halSinkInterface_ == nullptr) || (le_audio_sink_hal_state_ != HAL_STARTED)) {
403 log::error("Audio HAL Audio sink was not started!");
404 return;
405 }
406
407 log::info("");
408 halSinkInterface_->ConfirmStreamingRequest();
409
410 if (CodecManager::GetInstance()->GetCodecLocation() != types::CodecLocation::HOST) {
411 return;
412 }
413
414 if (com::android::bluetooth::flags::run_ble_audio_ticks_in_worker_thread()) {
415 worker_thread_->DoInThread(
416 FROM_HERE, base::BindOnce(&SourceImpl::StartAudioTicks, weak_factory_.GetWeakPtr()));
417 } else {
418 StartAudioTicks();
419 }
420 }
421
SuspendedForReconfiguration()422 void SourceImpl::SuspendedForReconfiguration() {
423 if ((halSinkInterface_ == nullptr) || (le_audio_sink_hal_state_ != HAL_STARTED)) {
424 log::error("Audio HAL Audio sink was not started!");
425 return;
426 }
427
428 log::info("");
429 halSinkInterface_->SuspendedForReconfiguration();
430 }
431
ReconfigurationComplete()432 void SourceImpl::ReconfigurationComplete() {
433 if ((halSinkInterface_ == nullptr) || (le_audio_sink_hal_state_ != HAL_STARTED)) {
434 log::error("Audio HAL Audio sink was not started!");
435 return;
436 }
437
438 log::info("");
439 halSinkInterface_->ReconfigurationComplete();
440 }
441
CancelStreamingRequest()442 void SourceImpl::CancelStreamingRequest() {
443 if ((halSinkInterface_ == nullptr) || (le_audio_sink_hal_state_ != HAL_STARTED)) {
444 log::error("Audio HAL Audio sink was not started!");
445 return;
446 }
447
448 log::info("");
449 halSinkInterface_->CancelStreamingRequest();
450 }
451
UpdateRemoteDelay(uint16_t remote_delay_ms)452 void SourceImpl::UpdateRemoteDelay(uint16_t remote_delay_ms) {
453 if ((halSinkInterface_ == nullptr) || (le_audio_sink_hal_state_ != HAL_STARTED)) {
454 log::error("Audio HAL Audio sink was not started!");
455 return;
456 }
457
458 log::info("");
459 halSinkInterface_->SetRemoteDelay(remote_delay_ms);
460 }
461
UpdateAudioConfigToHal(const::bluetooth::le_audio::offload_config & config)462 void SourceImpl::UpdateAudioConfigToHal(const ::bluetooth::le_audio::offload_config& config) {
463 if ((halSinkInterface_ == nullptr) || (le_audio_sink_hal_state_ != HAL_STARTED)) {
464 log::error("Audio HAL Audio sink was not started!");
465 return;
466 }
467
468 log::info("");
469 halSinkInterface_->UpdateAudioConfigToHal(config);
470 }
471
GetBroadcastConfig(const std::vector<std::pair<types::LeAudioContextType,uint8_t>> & subgroup_quality,const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>> & pacs) const472 std::optional<broadcaster::BroadcastConfiguration> SourceImpl::GetBroadcastConfig(
473 const std::vector<std::pair<types::LeAudioContextType, uint8_t>>& subgroup_quality,
474 const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>& pacs) const {
475 if (halSinkInterface_ == nullptr) {
476 log::error("Audio HAL Audio sink is null!");
477 return std::nullopt;
478 }
479
480 log::info("");
481 return halSinkInterface_->GetBroadcastConfig(subgroup_quality, pacs);
482 }
483
484 std::optional<::bluetooth::le_audio::set_configurations::AudioSetConfiguration>
GetUnicastConfig(const CodecManager::UnicastConfigurationRequirements & requirements) const485 SourceImpl::GetUnicastConfig(
486 const CodecManager::UnicastConfigurationRequirements& requirements) const {
487 if (halSinkInterface_ == nullptr) {
488 log::error("Audio HAL Audio sink is null!");
489 return std::nullopt;
490 }
491
492 log::info("");
493 return halSinkInterface_->GetUnicastConfig(requirements);
494 }
495
UpdateBroadcastAudioConfigToHal(const::bluetooth::le_audio::broadcast_offload_config & config)496 void SourceImpl::UpdateBroadcastAudioConfigToHal(
497 const ::bluetooth::le_audio::broadcast_offload_config& config) {
498 if (halSinkInterface_ == nullptr) {
499 log::error("Audio HAL Audio sink interface not acquired");
500 return;
501 }
502
503 log::info("");
504 halSinkInterface_->UpdateBroadcastAudioConfigToHal(config);
505 }
506 } // namespace
507
AcquireUnicast()508 std::unique_ptr<LeAudioSourceAudioHalClient> LeAudioSourceAudioHalClient::AcquireUnicast() {
509 std::unique_ptr<SourceImpl> impl(new SourceImpl(false));
510 if (!impl->Acquire()) {
511 log::error("Could not acquire Unicast Source on LE Audio HAL enpoint");
512 impl.reset();
513 return nullptr;
514 }
515
516 log::info("");
517 return std::move(impl);
518 }
519
AcquireBroadcast()520 std::unique_ptr<LeAudioSourceAudioHalClient> LeAudioSourceAudioHalClient::AcquireBroadcast() {
521 std::unique_ptr<SourceImpl> impl(new SourceImpl(true));
522 if (!impl->Acquire()) {
523 log::error("Could not acquire Broadcast Source on LE Audio HAL endpoint");
524 impl.reset();
525 return nullptr;
526 }
527
528 log::info("");
529 return std::move(impl);
530 }
531
DebugDump(int fd)532 void LeAudioSourceAudioHalClient::DebugDump(int fd) {
533 uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
534 std::stringstream stream;
535 stream << " LE AudioHalClient:"
536 << "\n Counts (underflow) : "
537 << sStats.media_read_total_underflow_count
538 << "\n Bytes (underflow) : "
539 << sStats.media_read_total_underflow_bytes
540 << "\n Last update time ago in ms (underflow) : "
541 << (sStats.media_read_last_underflow_us > 0
542 ? (now_us - sStats.media_read_last_underflow_us) / 1000
543 : 0)
544 << std::endl;
545 dprintf(fd, "%s", stream.str().c_str());
546 }
547 } // namespace bluetooth::le_audio
548