1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "audio_hal_interface/le_audio_software_host_transport.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include <functional>
22 
23 namespace bluetooth {
24 namespace audio {
25 namespace host {
26 namespace le_audio {
27 
LeAudioTransport(std::function<void ()> flush,StreamCallbacks stream_cb,PcmParameters pcm_config)28 LeAudioTransport::LeAudioTransport(std::function<void()> flush, StreamCallbacks stream_cb,
29                                    PcmParameters pcm_config)
30     : flush_(std::move(flush)),
31       stream_cb_(std::move(stream_cb)),
32       remote_delay_report_ms_(0),
33       total_bytes_processed_(0),
34       data_position_({}),
35       pcm_config_(std::move(pcm_config)),
36       start_request_state_(StartRequestState::IDLE) {}
37 
StartRequest()38 bool LeAudioTransport::StartRequest() {
39   SetStartRequestState(StartRequestState::PENDING_BEFORE_RESUME);
40   if (stream_cb_.on_resume_(true)) {
41     if (start_request_state_ == StartRequestState::CONFIRMED) {
42       log::info("Start completed.");
43       SetStartRequestState(StartRequestState::IDLE);
44       return true;
45     }
46 
47     if (start_request_state_ == StartRequestState::CANCELED) {
48       log::info("Start request failed.");
49       SetStartRequestState(StartRequestState::IDLE);
50       return false;
51     }
52 
53     log::info("Start pending.");
54     SetStartRequestState(StartRequestState::PENDING_AFTER_RESUME);
55     return true;
56   }
57 
58   log::error("Start request failed.");
59   SetStartRequestState(StartRequestState::IDLE);
60   return false;
61 }
62 
SuspendRequest()63 bool LeAudioTransport::SuspendRequest() {
64   log::info("");
65   if (stream_cb_.on_suspend_()) {
66     flush_();
67     return true;
68   } else {
69     return false;
70   }
71 }
72 
StopRequest()73 void LeAudioTransport::StopRequest() {
74   log::info("");
75   if (stream_cb_.on_suspend_()) {
76     flush_();
77   }
78 }
79 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_processed,timespec * data_position)80 bool LeAudioTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
81                                                uint64_t* total_bytes_processed,
82                                                timespec* data_position) {
83   log::verbose("data={} byte(s), timestamp={}.{}s, delay report={} msec.", total_bytes_processed_,
84                data_position_.tv_sec, data_position_.tv_nsec, remote_delay_report_ms_);
85   if (remote_delay_report_ns != nullptr) {
86     *remote_delay_report_ns = remote_delay_report_ms_ * 1000000u;
87   }
88   if (total_bytes_processed != nullptr) {
89     *total_bytes_processed = total_bytes_processed_;
90   }
91   if (data_position != nullptr) {
92     *data_position = data_position_;
93   }
94 
95   return true;
96 }
97 
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)98 void LeAudioTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {
99   auto track_count = source_metadata.track_count;
100 
101   if (track_count == 0) {
102     log::warn(", invalid number of metadata changed tracks");
103     return;
104   }
105 
106   stream_cb_.on_metadata_update_(source_metadata, ::bluetooth::le_audio::DsaMode::DISABLED);
107 }
108 
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)109 void LeAudioTransport::SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) {
110   auto track_count = sink_metadata.track_count;
111 
112   if (track_count == 0) {
113     log::warn(", invalid number of metadata changed tracks");
114     return;
115   }
116 
117   stream_cb_.on_sink_metadata_update_(sink_metadata);
118 }
119 
ResetPresentationPosition()120 void LeAudioTransport::ResetPresentationPosition() {
121   log::verbose("called.");
122   remote_delay_report_ms_ = 0;
123   total_bytes_processed_ = 0;
124   data_position_ = {};
125 }
126 
LogBytesProcessed(size_t bytes_processed)127 void LeAudioTransport::LogBytesProcessed(size_t bytes_processed) {
128   if (bytes_processed) {
129     total_bytes_processed_ += bytes_processed;
130     clock_gettime(CLOCK_MONOTONIC, &data_position_);
131   }
132 }
133 
SetRemoteDelay(uint16_t delay_report_ms)134 void LeAudioTransport::SetRemoteDelay(uint16_t delay_report_ms) {
135   log::info("delay_report={} msec", delay_report_ms);
136   remote_delay_report_ms_ = delay_report_ms;
137 }
138 
LeAudioGetSelectedHalPcmConfig()139 const PcmParameters& LeAudioTransport::LeAudioGetSelectedHalPcmConfig() { return pcm_config_; }
140 
LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,uint8_t bit_rate,uint8_t channels_count,uint32_t data_interval)141 void LeAudioTransport::LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz, uint8_t bit_rate,
142                                                       uint8_t channels_count,
143                                                       uint32_t data_interval) {
144   pcm_config_.sample_rate = sample_rate_hz;
145   pcm_config_.bits_per_sample = bit_rate;
146   pcm_config_.channels_count = channels_count;
147   pcm_config_.data_interval_us = data_interval;
148 }
149 
GetStartRequestState(void)150 StartRequestState LeAudioTransport::GetStartRequestState(void) { return start_request_state_; }
151 
ClearStartRequestState(void)152 void LeAudioTransport::ClearStartRequestState(void) {
153   log::verbose("");
154   start_request_state_ = StartRequestState::IDLE;
155   remote_delay_report_ms_ = 0;
156 }
157 
SetStartRequestState(StartRequestState state)158 void LeAudioTransport::SetStartRequestState(StartRequestState state) {
159   start_request_state_ = state;
160 }
161 
get_source_default_pcm_parameters()162 static PcmParameters get_source_default_pcm_parameters() {
163   return PcmParameters{
164           .data_interval_us = 0,
165           .sample_rate = 16000,
166           .bits_per_sample = 16,
167           .channels_count = 1,
168   };
169 }
170 
get_sink_default_pcm_parameters()171 static PcmParameters get_sink_default_pcm_parameters() {
172   return PcmParameters{
173           .data_interval_us = 0,
174           .sample_rate = 16000,
175           .bits_per_sample = 16,
176           .channels_count = 2,
177   };
178 }
179 
LeAudioSinkTransport(StreamCallbacks stream_cb)180 LeAudioSinkTransport::LeAudioSinkTransport(StreamCallbacks stream_cb) {
181   std::function<void()> flush_sink = [&]() {
182     // TODO(b/331315361): investigate the effect of flushing the buffer
183   };
184 
185   transport_ =
186           new LeAudioTransport(flush_sink, std::move(stream_cb), get_sink_default_pcm_parameters());
187 }
188 
~LeAudioSinkTransport()189 LeAudioSinkTransport::~LeAudioSinkTransport() { delete transport_; }
190 
StartRequest()191 bool LeAudioSinkTransport::StartRequest() { return transport_->StartRequest(); }
192 
SuspendRequest()193 bool LeAudioSinkTransport::SuspendRequest() { return transport_->SuspendRequest(); }
194 
StopRequest()195 void LeAudioSinkTransport::StopRequest() { transport_->StopRequest(); }
196 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_read,timespec * data_position)197 bool LeAudioSinkTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
198                                                    uint64_t* total_bytes_read,
199                                                    timespec* data_position) {
200   return transport_->GetPresentationPosition(remote_delay_report_ns, total_bytes_read,
201                                              data_position);
202 }
203 
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)204 void LeAudioSinkTransport::SourceMetadataChanged(const source_metadata_v7_t& source_metadata) {
205   transport_->SourceMetadataChanged(source_metadata);
206 }
207 
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)208 void LeAudioSinkTransport::SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) {
209   transport_->SinkMetadataChanged(sink_metadata);
210 }
211 
ResetPresentationPosition()212 void LeAudioSinkTransport::ResetPresentationPosition() { transport_->ResetPresentationPosition(); }
213 
LogBytesRead(size_t bytes_read)214 void LeAudioSinkTransport::LogBytesRead(size_t bytes_read) {
215   transport_->LogBytesProcessed(bytes_read);
216 }
217 
SetRemoteDelay(uint16_t delay_report_ms)218 void LeAudioSinkTransport::SetRemoteDelay(uint16_t delay_report_ms) {
219   transport_->SetRemoteDelay(delay_report_ms);
220 }
221 
LeAudioGetSelectedHalPcmConfig()222 const PcmParameters& LeAudioSinkTransport::LeAudioGetSelectedHalPcmConfig() {
223   return transport_->LeAudioGetSelectedHalPcmConfig();
224 }
225 
LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,uint8_t bit_rate,uint8_t channels_count,uint32_t data_interval)226 void LeAudioSinkTransport::LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz, uint8_t bit_rate,
227                                                           uint8_t channels_count,
228                                                           uint32_t data_interval) {
229   transport_->LeAudioSetSelectedHalPcmConfig(sample_rate_hz, bit_rate, channels_count,
230                                              data_interval);
231 }
232 
GetStartRequestState(void)233 StartRequestState LeAudioSinkTransport::GetStartRequestState(void) {
234   return transport_->GetStartRequestState();
235 }
236 
ClearStartRequestState(void)237 void LeAudioSinkTransport::ClearStartRequestState(void) {
238   log::verbose("");
239   transport_->ClearStartRequestState();
240 }
241 
SetStartRequestState(StartRequestState state)242 void LeAudioSinkTransport::SetStartRequestState(StartRequestState state) {
243   transport_->SetStartRequestState(state);
244 }
245 
LeAudioSourceTransport(StreamCallbacks stream_cb)246 LeAudioSourceTransport::LeAudioSourceTransport(StreamCallbacks stream_cb) {
247   std::function<void()> flush_source = [&]() {
248     // TODO(b/331315361): investigate the effect of flushing the buffer
249   };
250 
251   transport_ = new LeAudioTransport(flush_source, std::move(stream_cb),
252                                     get_source_default_pcm_parameters());
253 }
254 
~LeAudioSourceTransport()255 LeAudioSourceTransport::~LeAudioSourceTransport() { delete transport_; }
256 
StartRequest()257 bool LeAudioSourceTransport::StartRequest() { return transport_->StartRequest(); }
258 
SuspendRequest()259 bool LeAudioSourceTransport::SuspendRequest() { return transport_->SuspendRequest(); }
260 
StopRequest()261 void LeAudioSourceTransport::StopRequest() { transport_->StopRequest(); }
262 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_written,timespec * data_position)263 bool LeAudioSourceTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
264                                                      uint64_t* total_bytes_written,
265                                                      timespec* data_position) {
266   return transport_->GetPresentationPosition(remote_delay_report_ns, total_bytes_written,
267                                              data_position);
268 }
269 
SourceMetadataChanged(const source_metadata_v7_t &)270 void LeAudioSourceTransport::SourceMetadataChanged(
271         const source_metadata_v7_t& /*source_metadata*/) {}
272 
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)273 void LeAudioSourceTransport::SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata) {
274   transport_->SinkMetadataChanged(sink_metadata);
275 }
276 
ResetPresentationPosition()277 void LeAudioSourceTransport::ResetPresentationPosition() {
278   transport_->ResetPresentationPosition();
279 }
280 
LogBytesWritten(size_t bytes_written)281 void LeAudioSourceTransport::LogBytesWritten(size_t bytes_written) {
282   transport_->LogBytesProcessed(bytes_written);
283 }
284 
SetRemoteDelay(uint16_t delay_report_ms)285 void LeAudioSourceTransport::SetRemoteDelay(uint16_t delay_report_ms) {
286   transport_->SetRemoteDelay(delay_report_ms);
287 }
288 
LeAudioGetSelectedHalPcmConfig()289 const PcmParameters& LeAudioSourceTransport::LeAudioGetSelectedHalPcmConfig() {
290   return transport_->LeAudioGetSelectedHalPcmConfig();
291 }
292 
LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,uint8_t bit_rate,uint8_t channels_count,uint32_t data_interval)293 void LeAudioSourceTransport::LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,
294                                                             uint8_t bit_rate,
295                                                             uint8_t channels_count,
296                                                             uint32_t data_interval) {
297   transport_->LeAudioSetSelectedHalPcmConfig(sample_rate_hz, bit_rate, channels_count,
298                                              data_interval);
299 }
300 
GetStartRequestState(void)301 StartRequestState LeAudioSourceTransport::GetStartRequestState(void) {
302   return transport_->GetStartRequestState();
303 }
304 
ClearStartRequestState(void)305 void LeAudioSourceTransport::ClearStartRequestState(void) {
306   log::verbose("");
307   transport_->ClearStartRequestState();
308 }
309 
SetStartRequestState(StartRequestState state)310 void LeAudioSourceTransport::SetStartRequestState(StartRequestState state) {
311   transport_->SetStartRequestState(state);
312 }
313 }  // namespace le_audio
314 }  // namespace host
315 }  // namespace audio
316 }  // namespace bluetooth
317