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,
29                                    StreamCallbacks stream_cb,
30                                    PcmParameters pcm_config)
31     : flush_(std::move(flush)),
32       stream_cb_(std::move(stream_cb)),
33       remote_delay_report_ms_(0),
34       total_bytes_processed_(0),
35       data_position_({}),
36       pcm_config_(std::move(pcm_config)),
37       start_request_state_(StartRequestState::IDLE){};
38 
StartRequest()39 bool LeAudioTransport::StartRequest() {
40   SetStartRequestState(StartRequestState::PENDING_BEFORE_RESUME);
41   if (stream_cb_.on_resume_(true)) {
42     if (start_request_state_ == StartRequestState::CONFIRMED) {
43       log::info("Start completed.");
44       SetStartRequestState(StartRequestState::IDLE);
45       return true;
46     }
47 
48     if (start_request_state_ == StartRequestState::CANCELED) {
49       log::info("Start request failed.");
50       SetStartRequestState(StartRequestState::IDLE);
51       return false;
52     }
53 
54     log::info("Start pending.");
55     SetStartRequestState(StartRequestState::PENDING_AFTER_RESUME);
56     return true;
57   }
58 
59   log::error("Start request failed.");
60   SetStartRequestState(StartRequestState::IDLE);
61   return false;
62 }
63 
SuspendRequest()64 bool LeAudioTransport::SuspendRequest() {
65   log::info("");
66   if (stream_cb_.on_suspend_()) {
67     flush_();
68     return true;
69   } else {
70     return false;
71   }
72 }
73 
StopRequest()74 void LeAudioTransport::StopRequest() {
75   log::info("");
76   if (stream_cb_.on_suspend_()) {
77     flush_();
78   }
79 }
80 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_processed,timespec * data_position)81 bool LeAudioTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
82                                                uint64_t* total_bytes_processed,
83                                                timespec* data_position) {
84   log::verbose("data={} byte(s), timestamp={}.{}s, delay report={} msec.",
85                total_bytes_processed_, data_position_.tv_sec,
86                data_position_.tv_nsec, remote_delay_report_ms_);
87   if (remote_delay_report_ns != nullptr) {
88     *remote_delay_report_ns = remote_delay_report_ms_ * 1000000u;
89   }
90   if (total_bytes_processed != nullptr)
91     *total_bytes_processed = total_bytes_processed_;
92   if (data_position != nullptr) *data_position = data_position_;
93 
94   return true;
95 }
96 
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)97 void LeAudioTransport::SourceMetadataChanged(
98     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,
107                                  ::bluetooth::le_audio::DsaMode::DISABLED);
108 }
109 
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)110 void LeAudioTransport::SinkMetadataChanged(
111     const sink_metadata_v7_t& sink_metadata) {
112   auto track_count = sink_metadata.track_count;
113 
114   if (track_count == 0) {
115     log::warn(", invalid number of metadata changed tracks");
116     return;
117   }
118 
119   stream_cb_.on_sink_metadata_update_(sink_metadata);
120 }
121 
ResetPresentationPosition()122 void LeAudioTransport::ResetPresentationPosition() {
123   log::verbose("called.");
124   remote_delay_report_ms_ = 0;
125   total_bytes_processed_ = 0;
126   data_position_ = {};
127 }
128 
LogBytesProcessed(size_t bytes_processed)129 void LeAudioTransport::LogBytesProcessed(size_t bytes_processed) {
130   if (bytes_processed) {
131     total_bytes_processed_ += bytes_processed;
132     clock_gettime(CLOCK_MONOTONIC, &data_position_);
133   }
134 }
135 
SetRemoteDelay(uint16_t delay_report_ms)136 void LeAudioTransport::SetRemoteDelay(uint16_t delay_report_ms) {
137   log::info("delay_report={} msec", delay_report_ms);
138   remote_delay_report_ms_ = delay_report_ms;
139 }
140 
LeAudioGetSelectedHalPcmConfig()141 const PcmParameters& LeAudioTransport::LeAudioGetSelectedHalPcmConfig() {
142   return pcm_config_;
143 }
144 
LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,uint8_t bit_rate,uint8_t channels_count,uint32_t data_interval)145 void LeAudioTransport::LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,
146                                                       uint8_t bit_rate,
147                                                       uint8_t channels_count,
148                                                       uint32_t data_interval) {
149   pcm_config_.sample_rate = sample_rate_hz;
150   pcm_config_.bits_per_sample = bit_rate;
151   pcm_config_.channels_count = channels_count;
152   pcm_config_.data_interval_us = data_interval;
153 }
154 
GetStartRequestState(void)155 StartRequestState LeAudioTransport::GetStartRequestState(void) {
156   return start_request_state_;
157 }
158 
ClearStartRequestState(void)159 void LeAudioTransport::ClearStartRequestState(void) {
160   log::verbose("");
161   start_request_state_ = StartRequestState::IDLE;
162   remote_delay_report_ms_ = 0;
163 }
164 
SetStartRequestState(StartRequestState state)165 void LeAudioTransport::SetStartRequestState(StartRequestState state) {
166   start_request_state_ = state;
167 }
168 
get_source_default_pcm_parameters()169 static PcmParameters get_source_default_pcm_parameters() {
170   return PcmParameters{
171       .data_interval_us = 0,
172       .sample_rate = 16000,
173       .bits_per_sample = 16,
174       .channels_count = 1,
175   };
176 }
177 
get_sink_default_pcm_parameters()178 static PcmParameters get_sink_default_pcm_parameters() {
179   return PcmParameters{
180       .data_interval_us = 0,
181       .sample_rate = 16000,
182       .bits_per_sample = 16,
183       .channels_count = 2,
184   };
185 }
186 
LeAudioSinkTransport(StreamCallbacks stream_cb)187 LeAudioSinkTransport::LeAudioSinkTransport(StreamCallbacks stream_cb) {
188   std::function<void()> flush_sink = [&]() {
189     // TODO(b/331315361): investigate the effect of flushing the buffer
190   };
191 
192   transport_ = new LeAudioTransport(flush_sink, std::move(stream_cb),
193                                     get_sink_default_pcm_parameters());
194 };
195 
~LeAudioSinkTransport()196 LeAudioSinkTransport::~LeAudioSinkTransport() { delete transport_; }
197 
StartRequest()198 bool LeAudioSinkTransport::StartRequest() { return transport_->StartRequest(); }
199 
SuspendRequest()200 bool LeAudioSinkTransport::SuspendRequest() {
201   return transport_->SuspendRequest();
202 }
203 
StopRequest()204 void LeAudioSinkTransport::StopRequest() { transport_->StopRequest(); }
205 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_read,timespec * data_position)206 bool LeAudioSinkTransport::GetPresentationPosition(
207     uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read,
208     timespec* data_position) {
209   return transport_->GetPresentationPosition(remote_delay_report_ns,
210                                              total_bytes_read, data_position);
211 }
212 
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)213 void LeAudioSinkTransport::SourceMetadataChanged(
214     const source_metadata_v7_t& source_metadata) {
215   transport_->SourceMetadataChanged(source_metadata);
216 }
217 
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)218 void LeAudioSinkTransport::SinkMetadataChanged(
219     const sink_metadata_v7_t& sink_metadata) {
220   transport_->SinkMetadataChanged(sink_metadata);
221 }
222 
ResetPresentationPosition()223 void LeAudioSinkTransport::ResetPresentationPosition() {
224   transport_->ResetPresentationPosition();
225 }
226 
LogBytesRead(size_t bytes_read)227 void LeAudioSinkTransport::LogBytesRead(size_t bytes_read) {
228   transport_->LogBytesProcessed(bytes_read);
229 }
230 
SetRemoteDelay(uint16_t delay_report_ms)231 void LeAudioSinkTransport::SetRemoteDelay(uint16_t delay_report_ms) {
232   transport_->SetRemoteDelay(delay_report_ms);
233 }
234 
LeAudioGetSelectedHalPcmConfig()235 const PcmParameters& LeAudioSinkTransport::LeAudioGetSelectedHalPcmConfig() {
236   return transport_->LeAudioGetSelectedHalPcmConfig();
237 }
238 
LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,uint8_t bit_rate,uint8_t channels_count,uint32_t data_interval)239 void LeAudioSinkTransport::LeAudioSetSelectedHalPcmConfig(
240     uint32_t sample_rate_hz, uint8_t bit_rate, uint8_t channels_count,
241     uint32_t data_interval) {
242   transport_->LeAudioSetSelectedHalPcmConfig(sample_rate_hz, bit_rate,
243                                              channels_count, data_interval);
244 }
245 
GetStartRequestState(void)246 StartRequestState LeAudioSinkTransport::GetStartRequestState(void) {
247   return transport_->GetStartRequestState();
248 }
249 
ClearStartRequestState(void)250 void LeAudioSinkTransport::ClearStartRequestState(void) {
251   log::verbose("");
252   transport_->ClearStartRequestState();
253 }
254 
SetStartRequestState(StartRequestState state)255 void LeAudioSinkTransport::SetStartRequestState(StartRequestState state) {
256   transport_->SetStartRequestState(state);
257 }
258 
LeAudioSourceTransport(StreamCallbacks stream_cb)259 LeAudioSourceTransport::LeAudioSourceTransport(StreamCallbacks stream_cb) {
260   std::function<void()> flush_source = [&]() {
261     // TODO(b/331315361): investigate the effect of flushing the buffer
262   };
263 
264   transport_ = new LeAudioTransport(flush_source, std::move(stream_cb),
265                                     get_source_default_pcm_parameters());
266 };
267 
~LeAudioSourceTransport()268 LeAudioSourceTransport::~LeAudioSourceTransport() { delete transport_; }
269 
StartRequest()270 bool LeAudioSourceTransport::StartRequest() {
271   return transport_->StartRequest();
272 }
273 
SuspendRequest()274 bool LeAudioSourceTransport::SuspendRequest() {
275   return transport_->SuspendRequest();
276 }
277 
StopRequest()278 void LeAudioSourceTransport::StopRequest() { transport_->StopRequest(); }
279 
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_written,timespec * data_position)280 bool LeAudioSourceTransport::GetPresentationPosition(
281     uint64_t* remote_delay_report_ns, uint64_t* total_bytes_written,
282     timespec* data_position) {
283   return transport_->GetPresentationPosition(
284       remote_delay_report_ns, total_bytes_written, data_position);
285 }
286 
SourceMetadataChanged(const source_metadata_v7_t & source_metadata)287 void LeAudioSourceTransport::SourceMetadataChanged(
288     const source_metadata_v7_t& source_metadata) {}
289 
SinkMetadataChanged(const sink_metadata_v7_t & sink_metadata)290 void LeAudioSourceTransport::SinkMetadataChanged(
291     const sink_metadata_v7_t& sink_metadata) {
292   transport_->SinkMetadataChanged(sink_metadata);
293 }
294 
ResetPresentationPosition()295 void LeAudioSourceTransport::ResetPresentationPosition() {
296   transport_->ResetPresentationPosition();
297 }
298 
LogBytesWritten(size_t bytes_written)299 void LeAudioSourceTransport::LogBytesWritten(size_t bytes_written) {
300   transport_->LogBytesProcessed(bytes_written);
301 }
302 
SetRemoteDelay(uint16_t delay_report_ms)303 void LeAudioSourceTransport::SetRemoteDelay(uint16_t delay_report_ms) {
304   transport_->SetRemoteDelay(delay_report_ms);
305 }
306 
LeAudioGetSelectedHalPcmConfig()307 const PcmParameters& LeAudioSourceTransport::LeAudioGetSelectedHalPcmConfig() {
308   return transport_->LeAudioGetSelectedHalPcmConfig();
309 }
310 
LeAudioSetSelectedHalPcmConfig(uint32_t sample_rate_hz,uint8_t bit_rate,uint8_t channels_count,uint32_t data_interval)311 void LeAudioSourceTransport::LeAudioSetSelectedHalPcmConfig(
312     uint32_t sample_rate_hz, uint8_t bit_rate, uint8_t channels_count,
313     uint32_t data_interval) {
314   transport_->LeAudioSetSelectedHalPcmConfig(sample_rate_hz, bit_rate,
315                                              channels_count, data_interval);
316 }
317 
GetStartRequestState(void)318 StartRequestState LeAudioSourceTransport::GetStartRequestState(void) {
319   return transport_->GetStartRequestState();
320 }
321 
ClearStartRequestState(void)322 void LeAudioSourceTransport::ClearStartRequestState(void) {
323   log::verbose("");
324   transport_->ClearStartRequestState();
325 }
326 
SetStartRequestState(StartRequestState state)327 void LeAudioSourceTransport::SetStartRequestState(StartRequestState state) {
328   transport_->SetStartRequestState(state);
329 }
330 }  // namespace le_audio
331 }  // namespace host
332 }  // namespace audio
333 }  // namespace bluetooth
334