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