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
23 #include <cstddef>
24 #include <cstdint>
25 #include <functional>
26 #include <memory>
27 #include <utility>
28 #include <vector>
29
30 #include "audio_hal_client.h"
31 #include "audio_hal_interface/le_audio_software.h"
32 #include "bta/le_audio/codec_manager.h"
33 #include "bta_le_audio_api.h"
34 #include "hardware/bluetooth.h"
35 #include "le_audio/le_audio_types.h"
36 #include "stack/include/main_thread.h"
37
38 namespace bluetooth::le_audio {
39 namespace {
40 // TODO: HAL state should be in the HAL implementation
41 enum {
42 HAL_UNINITIALIZED,
43 HAL_STOPPED,
44 HAL_STARTED,
45 } le_audio_source_hal_state;
46
47 class SinkImpl : public LeAudioSinkAudioHalClient {
48 public:
49 // Interface implementation
50 bool Start(const LeAudioCodecConfiguration& codecConfiguration,
51 LeAudioSinkAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes) override;
52 void Stop();
53 size_t SendData(uint8_t* data, uint16_t size) override;
54 void ConfirmStreamingRequest() override;
55 void CancelStreamingRequest() override;
56 void UpdateRemoteDelay(uint16_t remote_delay_ms) override;
57 void UpdateAudioConfigToHal(const ::bluetooth::le_audio::offload_config& config) override;
58 void SuspendedForReconfiguration() override;
59 void ReconfigurationComplete() override;
60
61 // Internal functionality
62 SinkImpl() = default;
~SinkImpl()63 ~SinkImpl() override {
64 if (le_audio_source_hal_state != HAL_UNINITIALIZED) {
65 Release();
66 }
67 }
68
69 bool OnResumeReq(bool start_media_task);
70 bool OnSuspendReq();
71 bool OnMetadataUpdateReq(const sink_metadata_v7_t& sink_metadata);
72 bool Acquire();
73 void Release();
74
75 bluetooth::audio::le_audio::LeAudioClientInterface::Source* halSourceInterface_ = nullptr;
76 LeAudioSinkAudioHalClient::Callbacks* audioSinkCallbacks_ = nullptr;
77 };
78
Acquire()79 bool SinkImpl::Acquire() {
80 auto source_stream_cb = bluetooth::audio::le_audio::StreamCallbacks{
81 .on_resume_ = std::bind(&SinkImpl::OnResumeReq, this, std::placeholders::_1),
82 .on_suspend_ = std::bind(&SinkImpl::OnSuspendReq, this),
83 .on_sink_metadata_update_ =
84 std::bind(&SinkImpl::OnMetadataUpdateReq, this, std::placeholders::_1),
85 };
86
87 auto halInterface = audio::le_audio::LeAudioClientInterface::Get();
88 if (halInterface == nullptr) {
89 log::error("Can't get LE Audio HAL interface");
90 return false;
91 }
92
93 halSourceInterface_ = halInterface->GetSource(source_stream_cb, get_main_thread());
94
95 if (halSourceInterface_ == nullptr) {
96 log::error("Can't get Audio HAL Audio source interface");
97 return false;
98 }
99
100 log::info("");
101 le_audio_source_hal_state = HAL_STOPPED;
102 return true;
103 }
104
Release()105 void SinkImpl::Release() {
106 if (le_audio_source_hal_state == HAL_UNINITIALIZED) {
107 log::warn("Audio HAL Audio source is not running");
108 return;
109 }
110
111 log::info("");
112 if (halSourceInterface_) {
113 if (le_audio_source_hal_state == HAL_STARTED) {
114 halSourceInterface_->StopSession();
115 le_audio_source_hal_state = HAL_STOPPED;
116 }
117
118 halSourceInterface_->Cleanup();
119
120 auto halInterface = audio::le_audio::LeAudioClientInterface::Get();
121 if (halInterface != nullptr) {
122 halInterface->ReleaseSource(halSourceInterface_);
123 } else {
124 log::error("Can't get LE Audio HAL interface");
125 }
126
127 le_audio_source_hal_state = HAL_UNINITIALIZED;
128 halSourceInterface_ = nullptr;
129 }
130 }
131
OnResumeReq(bool)132 bool SinkImpl::OnResumeReq(bool /*start_media_task*/) {
133 if (audioSinkCallbacks_ == nullptr) {
134 log::error("audioSinkCallbacks_ not set");
135 return false;
136 }
137
138 bt_status_t status =
139 do_in_main_thread(base::BindOnce(&LeAudioSinkAudioHalClient::Callbacks::OnAudioResume,
140 audioSinkCallbacks_->weak_factory_.GetWeakPtr()));
141 if (status == BT_STATUS_SUCCESS) {
142 return true;
143 }
144
145 log::error("do_in_main_thread err={}", status);
146 return false;
147 }
148
OnSuspendReq()149 bool SinkImpl::OnSuspendReq() {
150 if (audioSinkCallbacks_ == nullptr) {
151 log::error("audioSinkCallbacks_ not set");
152 return false;
153 }
154
155 bt_status_t status =
156 do_in_main_thread(base::BindOnce(&LeAudioSinkAudioHalClient::Callbacks::OnAudioSuspend,
157 audioSinkCallbacks_->weak_factory_.GetWeakPtr()));
158 if (status == BT_STATUS_SUCCESS) {
159 return true;
160 }
161
162 log::error("do_in_main_thread err={}", status);
163 return false;
164 }
165
OnMetadataUpdateReq(const sink_metadata_v7_t & sink_metadata)166 bool SinkImpl::OnMetadataUpdateReq(const sink_metadata_v7_t& sink_metadata) {
167 if (audioSinkCallbacks_ == nullptr) {
168 log::error("audioSinkCallbacks_ not set");
169 return false;
170 }
171
172 std::vector<struct record_track_metadata_v7> metadata(
173 sink_metadata.tracks, sink_metadata.tracks + sink_metadata.track_count);
174
175 bt_status_t status = do_in_main_thread(
176 base::BindOnce(&LeAudioSinkAudioHalClient::Callbacks::OnAudioMetadataUpdate,
177 audioSinkCallbacks_->weak_factory_.GetWeakPtr(), std::move(metadata)));
178 if (status == BT_STATUS_SUCCESS) {
179 return true;
180 }
181
182 log::error("do_in_main_thread err={}", status);
183 return false;
184 }
185
Start(const LeAudioCodecConfiguration & codec_configuration,LeAudioSinkAudioHalClient::Callbacks * audioReceiver,DsaModes dsa_modes)186 bool SinkImpl::Start(const LeAudioCodecConfiguration& codec_configuration,
187 LeAudioSinkAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes) {
188 if (!halSourceInterface_) {
189 log::error("Audio HAL Audio source interface not acquired");
190 return false;
191 }
192
193 if (le_audio_source_hal_state == HAL_STARTED) {
194 log::error("Audio HAL Audio source is already in use");
195 return false;
196 }
197
198 log::info("bit rate: {}, num channels: {}, sample rate: {}, data interval: {}",
199 codec_configuration.bits_per_sample, codec_configuration.num_channels,
200 codec_configuration.sample_rate, codec_configuration.data_interval_us);
201
202 audio::le_audio::LeAudioClientInterface::PcmParameters pcmParameters = {
203 .data_interval_us = codec_configuration.data_interval_us,
204 .sample_rate = codec_configuration.sample_rate,
205 .bits_per_sample = codec_configuration.bits_per_sample,
206 .channels_count = codec_configuration.num_channels};
207
208 halSourceInterface_->SetPcmParameters(pcmParameters);
209 audio::le_audio::LeAudioClientInterface::Get()->SetAllowedDsaModes(dsa_modes);
210 halSourceInterface_->StartSession();
211
212 audioSinkCallbacks_ = audioReceiver;
213 le_audio_source_hal_state = HAL_STARTED;
214 return true;
215 }
216
Stop()217 void SinkImpl::Stop() {
218 if (!halSourceInterface_) {
219 log::error("Audio HAL Audio source interface already stopped");
220 return;
221 }
222
223 if (le_audio_source_hal_state != HAL_STARTED) {
224 log::error("Audio HAL Audio source was not started!");
225 return;
226 }
227
228 log::info("");
229
230 halSourceInterface_->StopSession();
231 le_audio_source_hal_state = HAL_STOPPED;
232 audioSinkCallbacks_ = nullptr;
233 }
234
SendData(uint8_t * data,uint16_t size)235 size_t SinkImpl::SendData(uint8_t* data, uint16_t size) {
236 size_t bytes_written;
237 if (!halSourceInterface_) {
238 log::error("Audio HAL Audio source interface not initialized");
239 return 0;
240 }
241
242 if (le_audio_source_hal_state != HAL_STARTED) {
243 log::error("Audio HAL Audio source was not started!");
244 return 0;
245 }
246
247 /* TODO: What to do if not all data is written ? */
248 bytes_written = halSourceInterface_->Write(data, size);
249 if (bytes_written != size) {
250 log::error("Not all data is written to source HAL. Bytes written: {}, total: {}", bytes_written,
251 size);
252 }
253
254 return bytes_written;
255 }
256
ConfirmStreamingRequest()257 void SinkImpl::ConfirmStreamingRequest() {
258 if ((halSourceInterface_ == nullptr) || (le_audio_source_hal_state != HAL_STARTED)) {
259 log::error("Audio HAL Audio source was not started!");
260 return;
261 }
262 log::info("");
263 halSourceInterface_->ConfirmStreamingRequest();
264 }
265
SuspendedForReconfiguration()266 void SinkImpl::SuspendedForReconfiguration() {
267 if ((halSourceInterface_ == nullptr) || (le_audio_source_hal_state != HAL_STARTED)) {
268 log::error("Audio HAL Audio source was not started!");
269 return;
270 }
271
272 log::info("");
273 halSourceInterface_->SuspendedForReconfiguration();
274 }
275
ReconfigurationComplete()276 void SinkImpl::ReconfigurationComplete() {
277 if ((halSourceInterface_ == nullptr) || (le_audio_source_hal_state != HAL_STARTED)) {
278 log::error("Audio HAL Audio source was not started!");
279 return;
280 }
281
282 log::info("");
283 halSourceInterface_->ReconfigurationComplete();
284 }
285
CancelStreamingRequest()286 void SinkImpl::CancelStreamingRequest() {
287 if ((halSourceInterface_ == nullptr) || (le_audio_source_hal_state != HAL_STARTED)) {
288 log::error("Audio HAL Audio source was not started!");
289 return;
290 }
291
292 log::info("");
293 halSourceInterface_->CancelStreamingRequest();
294 }
295
UpdateRemoteDelay(uint16_t remote_delay_ms)296 void SinkImpl::UpdateRemoteDelay(uint16_t remote_delay_ms) {
297 if ((halSourceInterface_ == nullptr) || (le_audio_source_hal_state != HAL_STARTED)) {
298 log::error("Audio HAL Audio source was not started!");
299 return;
300 }
301
302 log::info("");
303 halSourceInterface_->SetRemoteDelay(remote_delay_ms);
304 }
305
UpdateAudioConfigToHal(const::bluetooth::le_audio::offload_config & config)306 void SinkImpl::UpdateAudioConfigToHal(const ::bluetooth::le_audio::offload_config& config) {
307 if ((halSourceInterface_ == nullptr) || (le_audio_source_hal_state != HAL_STARTED)) {
308 log::error("Audio HAL Audio source was not started!");
309 return;
310 }
311
312 log::info("");
313 halSourceInterface_->UpdateAudioConfigToHal(config);
314 }
315 } // namespace
316
AcquireUnicast()317 std::unique_ptr<LeAudioSinkAudioHalClient> LeAudioSinkAudioHalClient::AcquireUnicast() {
318 std::unique_ptr<SinkImpl> impl(new SinkImpl());
319 if (!impl->Acquire()) {
320 log::error("Could not acquire Unicast Sink on LE Audio HAL enpoint");
321 impl.reset();
322 return nullptr;
323 }
324
325 log::info("");
326 return std::move(impl);
327 }
328
DebugDump(int)329 void LeAudioSinkAudioHalClient::DebugDump(int /*fd*/) {
330 /* TODO: Add some statistic for LeAudioSink Audio HAL interface */
331 }
332 } // namespace bluetooth::le_audio
333