1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
3 * www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #define LOG_TAG "BTAudioClientLeAudio"
19
20 #include "le_audio_software.h"
21
22 #include "client_interface.h"
23 #include "osi/include/log.h"
24 #include "osi/include/properties.h"
25
26 namespace {
27
28 using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
29 using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
30 using ::android::hardware::bluetooth::audio::V2_0::CodecType;
31 using ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
32 using ::bluetooth::audio::BluetoothAudioCtrlAck;
33 using ::bluetooth::audio::SampleRate_2_1;
34 using ::bluetooth::audio::SessionType;
35 using ::bluetooth::audio::SessionType_2_1;
36 using ::bluetooth::audio::le_audio::LeAudioClientInterface;
37 using ::bluetooth::audio::le_audio::StreamCallbacks;
38
39 bluetooth::audio::BluetoothAudioSinkClientInterface*
40 le_audio_sink_hal_clientinterface = nullptr;
41 bluetooth::audio::BluetoothAudioSourceClientInterface*
42 le_audio_source_hal_clientinterface = nullptr;
43
is_source_hal_enabled()44 static bool is_source_hal_enabled() {
45 return le_audio_source_hal_clientinterface != nullptr;
46 }
47
is_sink_hal_enabled()48 static bool is_sink_hal_enabled() {
49 return le_audio_sink_hal_clientinterface != nullptr;
50 }
51
52 class LeAudioTransport {
53 public:
LeAudioTransport(void (* flush)(void),StreamCallbacks stream_cb,PcmParameters pcm_config)54 LeAudioTransport(void (*flush)(void), StreamCallbacks stream_cb,
55 PcmParameters pcm_config)
56 : flush_(std::move(flush)),
57 stream_cb_(std::move(stream_cb)),
58 remote_delay_report_ms_(0),
59 total_bytes_processed_(0),
60 data_position_({}),
61 pcm_config_(std::move(pcm_config)){};
62
StartRequest()63 BluetoothAudioCtrlAck StartRequest() {
64 LOG(INFO) << __func__;
65 if (stream_cb_.on_resume_(true)) {
66 return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
67 }
68 return BluetoothAudioCtrlAck::FAILURE;
69 }
70
SuspendRequest()71 BluetoothAudioCtrlAck SuspendRequest() {
72 LOG(INFO) << __func__;
73 if (stream_cb_.on_suspend_()) {
74 flush_();
75 return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
76 } else {
77 return BluetoothAudioCtrlAck::FAILURE;
78 }
79 }
80
StopRequest()81 void StopRequest() {
82 LOG(INFO) << __func__;
83 if (stream_cb_.on_suspend_()) {
84 flush_();
85 }
86 }
87
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_processed,timespec * data_position)88 bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
89 uint64_t* total_bytes_processed,
90 timespec* data_position) {
91 VLOG(2) << __func__ << ": data=" << total_bytes_processed_
92 << " byte(s), timestamp=" << data_position_.tv_sec << "."
93 << data_position_.tv_nsec
94 << "s, delay report=" << remote_delay_report_ms_ << " msec.";
95 if (remote_delay_report_ns != nullptr) {
96 *remote_delay_report_ns = remote_delay_report_ms_ * 1000000u;
97 }
98 if (total_bytes_processed != nullptr)
99 *total_bytes_processed = total_bytes_processed_;
100 if (data_position != nullptr) *data_position = data_position_;
101
102 return true;
103 }
104
MetadataChanged(const source_metadata_t & source_metadata)105 void MetadataChanged(const source_metadata_t& source_metadata) {
106 auto track_count = source_metadata.track_count;
107 auto tracks = source_metadata.tracks;
108 LOG(INFO) << __func__ << ": " << track_count << " track(s) received";
109 while (track_count) {
110 VLOG(1) << __func__ << ": usage=" << tracks->usage
111 << ", content_type=" << tracks->content_type
112 << ", gain=" << tracks->gain;
113 --track_count;
114 ++tracks;
115 }
116 }
117
ResetPresentationPosition()118 void ResetPresentationPosition() {
119 VLOG(2) << __func__ << ": called.";
120 remote_delay_report_ms_ = 0;
121 total_bytes_processed_ = 0;
122 data_position_ = {};
123 }
124
LogBytesProcessed(size_t bytes_processed)125 void LogBytesProcessed(size_t bytes_processed) {
126 if (bytes_processed) {
127 total_bytes_processed_ += bytes_processed;
128 clock_gettime(CLOCK_MONOTONIC, &data_position_);
129 }
130 }
131
SetRemoteDelay(uint16_t delay_report_ms)132 void SetRemoteDelay(uint16_t delay_report_ms) {
133 LOG(INFO) << __func__ << ": delay_report=" << delay_report_ms << " msec";
134 remote_delay_report_ms_ = delay_report_ms;
135 }
136
LeAudioGetSelectedHalPcmConfig()137 const PcmParameters& LeAudioGetSelectedHalPcmConfig() { return pcm_config_; }
138
LeAudioSetSelectedHalPcmConfig(SampleRate_2_1 sample_rate,BitsPerSample bit_rate,ChannelMode channel_mode,uint32_t data_interval)139 void LeAudioSetSelectedHalPcmConfig(SampleRate_2_1 sample_rate,
140 BitsPerSample bit_rate,
141 ChannelMode channel_mode,
142 uint32_t data_interval) {
143 pcm_config_.sampleRate = sample_rate;
144 pcm_config_.bitsPerSample = bit_rate;
145 pcm_config_.channelMode = channel_mode;
146 pcm_config_.dataIntervalUs = data_interval;
147 }
148
149 private:
150 void (*flush_)(void);
151 StreamCallbacks stream_cb_;
152 uint16_t remote_delay_report_ms_;
153 uint64_t total_bytes_processed_;
154 timespec data_position_;
155 PcmParameters pcm_config_;
156 };
157
flush_sink()158 static void flush_sink() {
159 if (!is_sink_hal_enabled()) return;
160
161 le_audio_sink_hal_clientinterface->FlushAudioData();
162 }
163
164 // Sink transport implementation for Le Audio
165 class LeAudioSinkTransport
166 : public bluetooth::audio::IBluetoothSinkTransportInstance {
167 public:
LeAudioSinkTransport(StreamCallbacks stream_cb)168 LeAudioSinkTransport(StreamCallbacks stream_cb)
169 : IBluetoothSinkTransportInstance(
170 SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH, {}) {
171 transport_ =
172 new LeAudioTransport(flush_sink, std::move(stream_cb),
173 {SampleRate_2_1::RATE_16000, ChannelMode::STEREO,
174 BitsPerSample::BITS_16, 0});
175 };
176
~LeAudioSinkTransport()177 ~LeAudioSinkTransport() { delete transport_; }
178
StartRequest()179 BluetoothAudioCtrlAck StartRequest() override {
180 return transport_->StartRequest();
181 }
182
SuspendRequest()183 BluetoothAudioCtrlAck SuspendRequest() override {
184 return transport_->SuspendRequest();
185 }
186
StopRequest()187 void StopRequest() override { transport_->StopRequest(); }
188
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_read,timespec * data_position)189 bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
190 uint64_t* total_bytes_read,
191 timespec* data_position) override {
192 return transport_->GetPresentationPosition(remote_delay_report_ns,
193 total_bytes_read, data_position);
194 }
195
MetadataChanged(const source_metadata_t & source_metadata)196 void MetadataChanged(const source_metadata_t& source_metadata) override {
197 transport_->MetadataChanged(source_metadata);
198 }
199
ResetPresentationPosition()200 void ResetPresentationPosition() override {
201 transport_->ResetPresentationPosition();
202 }
203
LogBytesRead(size_t bytes_read)204 void LogBytesRead(size_t bytes_read) override {
205 transport_->LogBytesProcessed(bytes_read);
206 }
207
SetRemoteDelay(uint16_t delay_report_ms)208 void SetRemoteDelay(uint16_t delay_report_ms) {
209 transport_->SetRemoteDelay(delay_report_ms);
210 }
211
LeAudioGetSelectedHalPcmConfig()212 const PcmParameters& LeAudioGetSelectedHalPcmConfig() {
213 return transport_->LeAudioGetSelectedHalPcmConfig();
214 }
215
LeAudioSetSelectedHalPcmConfig(SampleRate_2_1 sample_rate,BitsPerSample bit_rate,ChannelMode channel_mode,uint32_t data_interval)216 void LeAudioSetSelectedHalPcmConfig(SampleRate_2_1 sample_rate,
217 BitsPerSample bit_rate,
218 ChannelMode channel_mode,
219 uint32_t data_interval) {
220 transport_->LeAudioSetSelectedHalPcmConfig(sample_rate, bit_rate,
221 channel_mode, data_interval);
222 }
223
224 private:
225 LeAudioTransport* transport_;
226 };
227
flush_source()228 static void flush_source() {
229 if (le_audio_source_hal_clientinterface == nullptr) return;
230
231 le_audio_source_hal_clientinterface->FlushAudioData();
232 }
233
234 class LeAudioSourceTransport
235 : public bluetooth::audio::IBluetoothSourceTransportInstance {
236 public:
LeAudioSourceTransport(StreamCallbacks stream_cb)237 LeAudioSourceTransport(StreamCallbacks stream_cb)
238 : IBluetoothSourceTransportInstance(
239 SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH, {}) {
240 transport_ =
241 new LeAudioTransport(flush_source, std::move(stream_cb),
242 {SampleRate_2_1::RATE_16000, ChannelMode::MONO,
243 BitsPerSample::BITS_16, 0});
244 };
245
~LeAudioSourceTransport()246 ~LeAudioSourceTransport() { delete transport_; }
247
StartRequest()248 BluetoothAudioCtrlAck StartRequest() override {
249 return transport_->StartRequest();
250 }
251
SuspendRequest()252 BluetoothAudioCtrlAck SuspendRequest() override {
253 return transport_->SuspendRequest();
254 }
255
StopRequest()256 void StopRequest() override { transport_->StopRequest(); }
257
GetPresentationPosition(uint64_t * remote_delay_report_ns,uint64_t * total_bytes_written,timespec * data_position)258 bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
259 uint64_t* total_bytes_written,
260 timespec* data_position) override {
261 return transport_->GetPresentationPosition(
262 remote_delay_report_ns, total_bytes_written, data_position);
263 }
264
MetadataChanged(const source_metadata_t & source_metadata)265 void MetadataChanged(const source_metadata_t& source_metadata) override {
266 transport_->MetadataChanged(source_metadata);
267 }
268
ResetPresentationPosition()269 void ResetPresentationPosition() override {
270 transport_->ResetPresentationPosition();
271 }
272
LogBytesWritten(size_t bytes_written)273 void LogBytesWritten(size_t bytes_written) override {
274 transport_->LogBytesProcessed(bytes_written);
275 }
276
SetRemoteDelay(uint16_t delay_report_ms)277 void SetRemoteDelay(uint16_t delay_report_ms) {
278 transport_->SetRemoteDelay(delay_report_ms);
279 }
280
LeAudioGetSelectedHalPcmConfig()281 const PcmParameters& LeAudioGetSelectedHalPcmConfig() {
282 return transport_->LeAudioGetSelectedHalPcmConfig();
283 }
284
LeAudioSetSelectedHalPcmConfig(SampleRate_2_1 sample_rate,BitsPerSample bit_rate,ChannelMode channel_mode,uint32_t data_interval)285 void LeAudioSetSelectedHalPcmConfig(SampleRate_2_1 sample_rate,
286 BitsPerSample bit_rate,
287 ChannelMode channel_mode,
288 uint32_t data_interval) {
289 transport_->LeAudioSetSelectedHalPcmConfig(sample_rate, bit_rate,
290 channel_mode, data_interval);
291 }
292
293 private:
294 LeAudioTransport* transport_;
295 };
296
297 // Instance of Le Audio to provide call-in APIs for Bluetooth Audio Hal
298 LeAudioSinkTransport* le_audio_sink = nullptr;
299 LeAudioSourceTransport* le_audio_source = nullptr;
300 } // namespace
301
302 namespace bluetooth {
303 namespace audio {
304 namespace le_audio {
305
306 LeAudioClientInterface* LeAudioClientInterface::interface = nullptr;
Get()307 LeAudioClientInterface* LeAudioClientInterface::Get() {
308 if (osi_property_get_bool(BLUETOOTH_AUDIO_HAL_PROP_DISABLED, false)) {
309 LOG(ERROR) << __func__ << ": BluetoothAudio HAL is disabled";
310 return nullptr;
311 }
312
313 if (LeAudioClientInterface::interface == nullptr)
314 LeAudioClientInterface::interface = new LeAudioClientInterface();
315
316 return LeAudioClientInterface::interface;
317 }
318
le_audio_sample_rate2audio_hal(uint32_t sample_rate_2_1)319 static SampleRate_2_1 le_audio_sample_rate2audio_hal(uint32_t sample_rate_2_1) {
320 switch (sample_rate_2_1) {
321 case 8000:
322 return SampleRate_2_1::RATE_8000;
323 case 16000:
324 return SampleRate_2_1::RATE_16000;
325 case 24000:
326 return SampleRate_2_1::RATE_24000;
327 case 32000:
328 return SampleRate_2_1::RATE_32000;
329 case 44100:
330 return SampleRate_2_1::RATE_44100;
331 case 48000:
332 return SampleRate_2_1::RATE_48000;
333 case 88200:
334 return SampleRate_2_1::RATE_88200;
335 case 96000:
336 return SampleRate_2_1::RATE_96000;
337 case 176400:
338 return SampleRate_2_1::RATE_176400;
339 case 192000:
340 return SampleRate_2_1::RATE_192000;
341 };
342 return SampleRate_2_1::RATE_UNKNOWN;
343 }
344
le_audio_bit_rate2audio_hal(uint8_t bits_per_sample)345 static BitsPerSample le_audio_bit_rate2audio_hal(uint8_t bits_per_sample) {
346 switch (bits_per_sample) {
347 case 16:
348 return BitsPerSample::BITS_16;
349 case 24:
350 return BitsPerSample::BITS_24;
351 case 32:
352 return BitsPerSample::BITS_32;
353 };
354 return BitsPerSample::BITS_UNKNOWN;
355 }
356
le_audio_channel_mode2audio_hal(uint8_t channels_count)357 static ChannelMode le_audio_channel_mode2audio_hal(uint8_t channels_count) {
358 switch (channels_count) {
359 case 1:
360 return ChannelMode::MONO;
361 case 2:
362 return ChannelMode::STEREO;
363 }
364 return ChannelMode::UNKNOWN;
365 }
366
Cleanup()367 void LeAudioClientInterface::Sink::Cleanup() {
368 LOG(INFO) << __func__;
369 StopSession();
370 delete le_audio_sink_hal_clientinterface;
371 le_audio_sink_hal_clientinterface = nullptr;
372 delete le_audio_sink;
373 le_audio_sink = nullptr;
374 }
375
SetPcmParameters(const PcmParameters & params)376 void LeAudioClientInterface::Sink::SetPcmParameters(
377 const PcmParameters& params) {
378 le_audio_sink->LeAudioSetSelectedHalPcmConfig(
379 le_audio_sample_rate2audio_hal(params.sample_rate),
380 le_audio_bit_rate2audio_hal(params.bits_per_sample),
381 le_audio_channel_mode2audio_hal(params.channels_count),
382 params.data_interval_us);
383 }
384
385 // Update Le Audio delay report to BluetoothAudio HAL
SetRemoteDelay(uint16_t delay_report_ms)386 void LeAudioClientInterface::Sink::SetRemoteDelay(uint16_t delay_report_ms) {
387 LOG(INFO) << __func__ << ": delay_report_ms=" << delay_report_ms << " ms";
388 le_audio_sink->SetRemoteDelay(delay_report_ms);
389 }
390
StartSession()391 void LeAudioClientInterface::Sink::StartSession() {
392 LOG(INFO) << __func__;
393 AudioConfiguration_2_1 audio_config;
394 audio_config.pcmConfig(le_audio_sink->LeAudioGetSelectedHalPcmConfig());
395 if (!le_audio_sink_hal_clientinterface->UpdateAudioConfig_2_1(audio_config)) {
396 LOG(ERROR) << __func__ << ": cannot update audio config to HAL";
397 return;
398 }
399 le_audio_sink_hal_clientinterface->StartSession_2_1();
400 }
401
StopSession()402 void LeAudioClientInterface::Sink::StopSession() {
403 LOG(INFO) << __func__;
404 le_audio_sink_hal_clientinterface->EndSession();
405 }
406
Read(uint8_t * p_buf,uint32_t len)407 size_t LeAudioClientInterface::Sink::Read(uint8_t* p_buf, uint32_t len) {
408 return le_audio_sink_hal_clientinterface->ReadAudioData(p_buf, len);
409 }
410
Cleanup()411 void LeAudioClientInterface::Source::Cleanup() {
412 LOG(INFO) << __func__;
413 StopSession();
414 delete le_audio_source_hal_clientinterface;
415 le_audio_source_hal_clientinterface = nullptr;
416 delete le_audio_source;
417 le_audio_source = nullptr;
418 }
419
SetPcmParameters(const PcmParameters & params)420 void LeAudioClientInterface::Source::SetPcmParameters(
421 const PcmParameters& params) {
422 le_audio_source->LeAudioSetSelectedHalPcmConfig(
423 le_audio_sample_rate2audio_hal(params.sample_rate),
424 le_audio_bit_rate2audio_hal(params.bits_per_sample),
425 le_audio_channel_mode2audio_hal(params.channels_count),
426 params.data_interval_us);
427 }
428
SetRemoteDelay(uint16_t delay_report_ms)429 void LeAudioClientInterface::Source::SetRemoteDelay(uint16_t delay_report_ms) {
430 LOG(INFO) << __func__ << ": delay_report_ms=" << delay_report_ms << " ms";
431 le_audio_source->SetRemoteDelay(delay_report_ms);
432 }
433
StartSession()434 void LeAudioClientInterface::Source::StartSession() {
435 LOG(INFO) << __func__;
436 if (!is_source_hal_enabled()) return;
437 AudioConfiguration_2_1 audio_config;
438 audio_config.pcmConfig(le_audio_source->LeAudioGetSelectedHalPcmConfig());
439 if (!le_audio_source_hal_clientinterface->UpdateAudioConfig_2_1(
440 audio_config)) {
441 LOG(ERROR) << __func__ << ": cannot update audio config to HAL";
442 return;
443 }
444 le_audio_source_hal_clientinterface->StartSession_2_1();
445 }
446
StopSession()447 void LeAudioClientInterface::Source::StopSession() {
448 LOG(INFO) << __func__;
449 le_audio_source_hal_clientinterface->EndSession();
450 }
451
Write(const uint8_t * p_buf,uint32_t len)452 size_t LeAudioClientInterface::Source::Write(const uint8_t* p_buf,
453 uint32_t len) {
454 return le_audio_source_hal_clientinterface->WriteAudioData(p_buf, len);
455 }
456
GetSink(StreamCallbacks stream_cb,bluetooth::common::MessageLoopThread * message_loop)457 LeAudioClientInterface::Sink* LeAudioClientInterface::GetSink(
458 StreamCallbacks stream_cb,
459 bluetooth::common::MessageLoopThread* message_loop) {
460 if (sink_ == nullptr) {
461 sink_ = new Sink();
462 } else {
463 LOG(WARNING) << __func__ << ", Sink is already acquired";
464 return nullptr;
465 }
466
467 LOG(INFO) << __func__;
468
469 le_audio_sink = new LeAudioSinkTransport(std::move(stream_cb));
470 le_audio_sink_hal_clientinterface =
471 new bluetooth::audio::BluetoothAudioSinkClientInterface(le_audio_sink,
472 message_loop);
473 if (!le_audio_sink_hal_clientinterface->IsValid()) {
474 LOG(WARNING) << __func__
475 << ": BluetoothAudio HAL for Le Audio is invalid?!";
476 delete le_audio_sink_hal_clientinterface;
477 le_audio_sink_hal_clientinterface = nullptr;
478 delete le_audio_sink;
479 le_audio_sink = nullptr;
480 delete sink_;
481 sink_ = nullptr;
482
483 return nullptr;
484 }
485
486 return sink_;
487 }
488
IsSinkAcquired()489 bool LeAudioClientInterface::IsSinkAcquired() { return sink_ != nullptr; }
490
ReleaseSink(LeAudioClientInterface::Sink * sink)491 bool LeAudioClientInterface::ReleaseSink(LeAudioClientInterface::Sink* sink) {
492 if (sink != sink_) {
493 LOG(WARNING) << __func__ << ", can't release not acquired sink";
494 return false;
495 }
496
497 if (le_audio_sink_hal_clientinterface && le_audio_sink) sink->Cleanup();
498
499 delete (sink_);
500 sink_ = nullptr;
501
502 return true;
503 }
504
GetSource(StreamCallbacks stream_cb,bluetooth::common::MessageLoopThread * message_loop)505 LeAudioClientInterface::Source* LeAudioClientInterface::GetSource(
506 StreamCallbacks stream_cb,
507 bluetooth::common::MessageLoopThread* message_loop) {
508 if (source_ == nullptr) {
509 source_ = new Source();
510 } else {
511 LOG(WARNING) << __func__ << ", Source is already acquired";
512 return nullptr;
513 }
514
515 LOG(INFO) << __func__;
516
517 le_audio_source = new LeAudioSourceTransport(std::move(stream_cb));
518 le_audio_source_hal_clientinterface =
519 new bluetooth::audio::BluetoothAudioSourceClientInterface(le_audio_source,
520 message_loop);
521 if (!le_audio_source_hal_clientinterface->IsValid()) {
522 LOG(WARNING) << __func__
523 << ": BluetoothAudio HAL for Le Audio is invalid?!";
524 delete le_audio_source_hal_clientinterface;
525 le_audio_source_hal_clientinterface = nullptr;
526 delete le_audio_source;
527 le_audio_source = nullptr;
528 delete source_;
529 source_ = nullptr;
530
531 return nullptr;
532 }
533
534 return source_;
535 }
536
IsSourceAcquired()537 bool LeAudioClientInterface::IsSourceAcquired() { return source_ != nullptr; }
538
ReleaseSource(LeAudioClientInterface::Source * source)539 bool LeAudioClientInterface::ReleaseSource(
540 LeAudioClientInterface::Source* source) {
541 if (source != source_) {
542 LOG(WARNING) << __func__ << ", can't release not acquired source";
543 return false;
544 }
545
546 if (le_audio_source_hal_clientinterface && le_audio_source) source->Cleanup();
547
548 delete (source_);
549 source_ = nullptr;
550
551 return true;
552 }
553
554 } // namespace le_audio
555 } // namespace audio
556 } // namespace bluetooth
557