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