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