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