1 /*
2 * Copyright 2022 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 "codec_manager.h"
18
19 #include <bluetooth/log.h>
20 #include <com_android_bluetooth_flags.h>
21
22 #include <bitset>
23 #include <sstream>
24 #include <vector>
25
26 #include "audio_hal_client/audio_hal_client.h"
27 #include "broadcaster/broadcast_configuration_provider.h"
28 #include "broadcaster/broadcaster_types.h"
29 #include "hci/controller_interface.h"
30 #include "le_audio/le_audio_types.h"
31 #include "le_audio_set_configuration_provider.h"
32 #include "le_audio_utils.h"
33 #include "main/shim/entry.h"
34 #include "os/log.h"
35 #include "osi/include/properties.h"
36 #include "stack/include/hcimsgs.h"
37
38 namespace {
39
40 using bluetooth::hci::iso_manager::kIsoDataPathHci;
41 using bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
42 using bluetooth::le_audio::CodecManager;
43 using bluetooth::le_audio::types::CodecLocation;
44 using bluetooth::legacy::hci::GetInterface;
45
46 using bluetooth::le_audio::AudioSetConfigurationProvider;
47 using bluetooth::le_audio::btle_audio_codec_config_t;
48 using bluetooth::le_audio::btle_audio_codec_index_t;
49 using bluetooth::le_audio::set_configurations::AseConfiguration;
50 using bluetooth::le_audio::set_configurations::AudioSetConfiguration;
51 using bluetooth::le_audio::set_configurations::AudioSetConfigurations;
52
53 typedef struct offloader_stream_maps {
54 std::vector<bluetooth::le_audio::stream_map_info> streams_map_target;
55 std::vector<bluetooth::le_audio::stream_map_info> streams_map_current;
56 bool has_changed;
57 bool is_initial;
58 } offloader_stream_maps_t;
59 } // namespace
60
61 namespace bluetooth::le_audio {
62 template <>
get(uint8_t direction)63 offloader_stream_maps_t& types::BidirectionalPair<offloader_stream_maps_t>::get(
64 uint8_t direction) {
65 log::assert_that(direction < types::kLeAudioDirectionBoth,
66 "Unsupported complex direction. Reference to a single "
67 "complex direction value is not supported.");
68 return (direction == types::kLeAudioDirectionSink) ? sink : source;
69 }
70
71 // The mapping for sampling rate, frame duration, and the QoS config
72 static std::unordered_map<
73 int, std::unordered_map<
74 int, bluetooth::le_audio::broadcaster::BroadcastQosConfig>>
75 bcast_high_reliability_qos = {
76 {LeAudioCodecConfiguration::kSampleRate16000,
77 {{LeAudioCodecConfiguration::kInterval7500Us,
78 bluetooth::le_audio::broadcaster::qos_config_4_45},
79 {LeAudioCodecConfiguration::kInterval10000Us,
80 bluetooth::le_audio::broadcaster::qos_config_4_60}}},
81 {LeAudioCodecConfiguration::kSampleRate24000,
82 {{LeAudioCodecConfiguration::kInterval7500Us,
83 bluetooth::le_audio::broadcaster::qos_config_4_45},
84 {LeAudioCodecConfiguration::kInterval10000Us,
85 bluetooth::le_audio::broadcaster::qos_config_4_60}}},
86 {LeAudioCodecConfiguration::kSampleRate32000,
87 {{LeAudioCodecConfiguration::kInterval7500Us,
88 bluetooth::le_audio::broadcaster::qos_config_4_45},
89 {LeAudioCodecConfiguration::kInterval10000Us,
90 bluetooth::le_audio::broadcaster::qos_config_4_60}}},
91 {LeAudioCodecConfiguration::kSampleRate48000,
92 {{LeAudioCodecConfiguration::kInterval7500Us,
93 bluetooth::le_audio::broadcaster::qos_config_4_50},
94 {LeAudioCodecConfiguration::kInterval10000Us,
95 bluetooth::le_audio::broadcaster::qos_config_4_65}}}};
96
97 struct codec_manager_impl {
98 public:
codec_manager_implbluetooth::le_audio::codec_manager_impl99 codec_manager_impl() {
100 offload_enable_ = osi_property_get_bool(
101 "ro.bluetooth.leaudio_offload.supported", false) &&
102 !osi_property_get_bool(
103 "persist.bluetooth.leaudio_offload.disabled", true);
104 if (offload_enable_ == false) {
105 log::info("offload disabled");
106 return;
107 }
108
109 if (!LeAudioHalVerifier::SupportsLeAudioHardwareOffload()) {
110 log::warn("HAL not support hardware offload");
111 return;
112 }
113
114 if (!bluetooth::shim::GetController()->IsSupported(
115 bluetooth::hci::OpCode::CONFIGURE_DATA_PATH)) {
116 log::warn("Controller does not support config data path command");
117 return;
118 }
119
120 log::info("LeAudioCodecManagerImpl: configure_data_path for encode");
121 GetInterface().ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
122 kIsoDataPathPlatformDefault, {});
123 GetInterface().ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
124 kIsoDataPathPlatformDefault, {});
125 SetCodecLocation(CodecLocation::ADSP);
126 }
startbluetooth::le_audio::codec_manager_impl127 void start(
128 const std::vector<btle_audio_codec_config_t>& offloading_preference) {
129 dual_bidirection_swb_supported_ = osi_property_get_bool(
130 "bluetooth.leaudio.dual_bidirection_swb.supported", false);
131 bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(
132 GetCodecLocation());
133 UpdateOffloadCapability(offloading_preference);
134 }
~codec_manager_implbluetooth::le_audio::codec_manager_impl135 ~codec_manager_impl() {
136 if (GetCodecLocation() != CodecLocation::HOST) {
137 GetInterface().ConfigureDataPath(hci_data_direction_t::HOST_TO_CONTROLLER,
138 kIsoDataPathHci, {});
139 GetInterface().ConfigureDataPath(hci_data_direction_t::CONTROLLER_TO_HOST,
140 kIsoDataPathHci, {});
141 }
142 bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
143 }
GetCodecLocationbluetooth::le_audio::codec_manager_impl144 CodecLocation GetCodecLocation(void) const { return codec_location_; }
145
IsDualBiDirSwbSupportedbluetooth::le_audio::codec_manager_impl146 bool IsDualBiDirSwbSupported(void) const {
147 if (GetCodecLocation() == CodecLocation::ADSP) {
148 // Whether dual bidirection swb is supported by property and for offload
149 return offload_dual_bidirection_swb_supported_;
150 } else if (GetCodecLocation() == CodecLocation::HOST) {
151 // Whether dual bidirection swb is supported for software
152 return dual_bidirection_swb_supported_;
153 }
154
155 return false;
156 }
157
158 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
GetLocalAudioOutputCodecCapabluetooth::le_audio::codec_manager_impl159 GetLocalAudioOutputCodecCapa() {
160 return codec_output_capa;
161 }
162
163 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
GetLocalAudioInputCodecCapabluetooth::le_audio::codec_manager_impl164 GetLocalAudioInputCodecCapa() {
165 return codec_input_capa;
166 }
167
UpdateActiveAudioConfigbluetooth::le_audio::codec_manager_impl168 void UpdateActiveAudioConfig(
169 const types::BidirectionalPair<stream_parameters>& stream_params,
170 types::BidirectionalPair<uint16_t> delays_ms,
171 std::function<void(const offload_config& config, uint8_t direction)>
172 update_receiver) {
173 if (GetCodecLocation() != bluetooth::le_audio::types::CodecLocation::ADSP) {
174 return;
175 }
176
177 for (auto direction :
178 {bluetooth::le_audio::types::kLeAudioDirectionSink,
179 bluetooth::le_audio::types::kLeAudioDirectionSource}) {
180 auto& stream_map = offloader_stream_maps.get(direction);
181 if (!stream_map.has_changed && !stream_map.is_initial) {
182 continue;
183 }
184 if (stream_params.get(direction).stream_locations.empty()) {
185 continue;
186 }
187
188 bluetooth::le_audio::offload_config unicast_cfg = {
189 .stream_map = (stream_map.is_initial ||
190 LeAudioHalVerifier::SupportsStreamActiveApi())
191 ? stream_map.streams_map_target
192 : stream_map.streams_map_current,
193 // TODO: set the default value 16 for now, would change it if we
194 // support mode bits_per_sample
195 .bits_per_sample = 16,
196 .sampling_rate = stream_params.get(direction).sample_frequency_hz,
197 .frame_duration = stream_params.get(direction).frame_duration_us,
198 .octets_per_frame =
199 stream_params.get(direction).octets_per_codec_frame,
200 .blocks_per_sdu =
201 stream_params.get(direction).codec_frames_blocks_per_sdu,
202 .peer_delay_ms = delays_ms.get(direction),
203 };
204 update_receiver(unicast_cfg, direction);
205 stream_map.is_initial = false;
206 }
207 }
208
UpdateActiveUnicastAudioHalClientbluetooth::le_audio::codec_manager_impl209 bool UpdateActiveUnicastAudioHalClient(
210 LeAudioSourceAudioHalClient* source_unicast_client,
211 LeAudioSinkAudioHalClient* sink_unicast_client, bool is_active) {
212 log::debug("local_source: {}, local_sink: {}, is_active: {}",
213 fmt::ptr(source_unicast_client), fmt::ptr(sink_unicast_client),
214 is_active);
215
216 if (source_unicast_client == nullptr && sink_unicast_client == nullptr) {
217 return false;
218 }
219
220 if (is_active) {
221 if (source_unicast_client && unicast_local_source_hal_client != nullptr) {
222 log::error("Trying to override previous source hal client {}",
223 fmt::ptr(unicast_local_source_hal_client));
224 return false;
225 }
226
227 if (sink_unicast_client && unicast_local_sink_hal_client != nullptr) {
228 log::error("Trying to override previous sink hal client {}",
229 fmt::ptr(unicast_local_sink_hal_client));
230 return false;
231 }
232
233 if (source_unicast_client) {
234 unicast_local_source_hal_client = source_unicast_client;
235 }
236
237 if (sink_unicast_client) {
238 unicast_local_sink_hal_client = sink_unicast_client;
239 }
240
241 return true;
242 }
243
244 if (source_unicast_client &&
245 source_unicast_client != unicast_local_source_hal_client) {
246 log::error("local source session does not match {} != {}",
247 fmt::ptr(source_unicast_client),
248 fmt::ptr(unicast_local_source_hal_client));
249 return false;
250 }
251
252 if (sink_unicast_client &&
253 sink_unicast_client != unicast_local_sink_hal_client) {
254 log::error("local source session does not match {} != {}",
255 fmt::ptr(sink_unicast_client),
256 fmt::ptr(unicast_local_sink_hal_client));
257 return false;
258 }
259
260 if (source_unicast_client) {
261 unicast_local_source_hal_client = nullptr;
262 }
263
264 if (sink_unicast_client) {
265 unicast_local_sink_hal_client = nullptr;
266 }
267
268 return true;
269 }
270
UpdateActiveBroadcastAudioHalClientbluetooth::le_audio::codec_manager_impl271 bool UpdateActiveBroadcastAudioHalClient(
272 LeAudioSourceAudioHalClient* source_broadcast_client, bool is_active) {
273 log::debug("local_source: {},is_active: {}",
274 fmt::ptr(source_broadcast_client), is_active);
275
276 if (source_broadcast_client == nullptr) {
277 return false;
278 }
279
280 if (is_active) {
281 if (broadcast_local_source_hal_client != nullptr) {
282 log::error("Trying to override previous source hal client {}",
283 fmt::ptr(broadcast_local_source_hal_client));
284 return false;
285 }
286 broadcast_local_source_hal_client = source_broadcast_client;
287 return true;
288 }
289
290 if (source_broadcast_client != broadcast_local_source_hal_client) {
291 log::error("local source session does not match {} != {}",
292 fmt::ptr(source_broadcast_client),
293 fmt::ptr(broadcast_local_source_hal_client));
294 return false;
295 }
296
297 broadcast_local_source_hal_client = nullptr;
298
299 return true;
300 }
301
GetSupportedCodecConfigurationsbluetooth::le_audio::codec_manager_impl302 AudioSetConfigurations GetSupportedCodecConfigurations(
303 const CodecManager::UnicastConfigurationRequirements& requirements)
304 const {
305 if (GetCodecLocation() == le_audio::types::CodecLocation::ADSP) {
306 log::verbose("Get offload config for the context type: {}",
307 (int)requirements.audio_context_type);
308
309 // TODO: Need to have a mechanism to switch to software session if offload
310 // doesn't support.
311 return context_type_offload_config_map_.count(
312 requirements.audio_context_type)
313 ? context_type_offload_config_map_.at(
314 requirements.audio_context_type)
315 : AudioSetConfigurations();
316 }
317
318 log::verbose("Get software config for the context type: {}",
319 (int)requirements.audio_context_type);
320 return *AudioSetConfigurationProvider::Get()->GetConfigurations(
321 requirements.audio_context_type);
322 }
323
PrintDebugStatebluetooth::le_audio::codec_manager_impl324 void PrintDebugState() const {
325 for (types::LeAudioContextType ctx_type :
326 types::kLeAudioContextAllTypesArray) {
327 std::stringstream os;
328 os << ctx_type << ": ";
329 if (context_type_offload_config_map_.count(ctx_type) == 0) {
330 os << "{empty}";
331 } else {
332 os << "{";
333 for (const auto& conf : context_type_offload_config_map_.at(ctx_type)) {
334 os << conf->name << ", ";
335 }
336 os << "}";
337 }
338 log::info("Offload configs for {}", os.str());
339 }
340 }
341
IsUsingCodecExtensibilitybluetooth::le_audio::codec_manager_impl342 bool IsUsingCodecExtensibility() const {
343 auto codec_ext_status =
344 osi_property_get_bool(
345 "bluetooth.core.le_audio.codec_extension_aidl.enabled", false) &&
346 com::android::bluetooth::flags::leaudio_multicodec_aidl_support();
347
348 log::debug("Using codec extensibility AIDL: {}", codec_ext_status);
349 return codec_ext_status;
350 }
351
GetCodecConfigbluetooth::le_audio::codec_manager_impl352 std::unique_ptr<AudioSetConfiguration> GetCodecConfig(
353 const CodecManager::UnicastConfigurationRequirements& requirements,
354 CodecManager::UnicastConfigurationVerifier verifier) {
355 if (IsUsingCodecExtensibility()) {
356 auto hal_config =
357 unicast_local_source_hal_client->GetUnicastConfig(requirements);
358 if (hal_config) {
359 return std::make_unique<AudioSetConfiguration>(*hal_config);
360 }
361 log::debug(
362 "No configuration received from AIDL, fall back to static "
363 "configuration.");
364 }
365
366 auto configs = GetSupportedCodecConfigurations(requirements);
367 if (configs.empty()) {
368 log::error("No valid configuration matching the requirements: {}",
369 requirements);
370 PrintDebugState();
371 return nullptr;
372 }
373
374 // Remove the dual bidir SWB config if not supported
375 if (!IsDualBiDirSwbSupported()) {
376 configs.erase(
377 std::remove_if(configs.begin(), configs.end(),
378 [](auto const& el) {
379 if (el->confs.source.empty()) return false;
380 return AudioSetConfigurationProvider::Get()
381 ->CheckConfigurationIsDualBiDirSwb(*el);
382 }),
383 configs.end());
384 }
385
386 // Note: For the only supported right now legacy software configuration
387 // provider, we use the device group logic to match the proper
388 // configuration with group capabilities. Note that this path only
389 // supports the LC3 codec format. For the multicodec support we should
390 // rely on the configuration matcher behind the AIDL interface.
391 auto conf = verifier(requirements, &configs);
392 return conf ? std::make_unique<AudioSetConfiguration>(*conf) : nullptr;
393 }
394
CheckCodecConfigIsBiDirSwbbluetooth::le_audio::codec_manager_impl395 bool CheckCodecConfigIsBiDirSwb(const AudioSetConfiguration& config) {
396 return AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb(
397 config);
398 }
399
CheckCodecConfigIsDualBiDirSwbbluetooth::le_audio::codec_manager_impl400 bool CheckCodecConfigIsDualBiDirSwb(const AudioSetConfiguration& config) {
401 return AudioSetConfigurationProvider::Get()
402 ->CheckConfigurationIsDualBiDirSwb(config);
403 }
404
UpdateSupportedBroadcastConfigbluetooth::le_audio::codec_manager_impl405 void UpdateSupportedBroadcastConfig(
406 const std::vector<AudioSetConfiguration>& adsp_capabilities) {
407 log::info("UpdateSupportedBroadcastConfig");
408
409 for (const auto& adsp_audio_set_conf : adsp_capabilities) {
410 if (adsp_audio_set_conf.confs.sink.empty() ||
411 !adsp_audio_set_conf.confs.source.empty()) {
412 continue;
413 }
414
415 auto& adsp_config = adsp_audio_set_conf.confs.sink[0];
416
417 const types::LeAudioCoreCodecConfig core_config =
418 adsp_config.codec.params.GetAsCoreCodecConfig();
419 bluetooth::le_audio::broadcast_offload_config broadcast_config;
420 broadcast_config.stream_map.resize(adsp_audio_set_conf.confs.sink.size());
421
422 // Enable the individual channels per BIS in the stream map
423 auto all_channels = adsp_config.codec.channel_count_per_iso_stream;
424 uint8_t channel_alloc_idx = 0;
425 for (auto& [_, channels] : broadcast_config.stream_map) {
426 if (all_channels) {
427 channels |= (0b1 << channel_alloc_idx++);
428 --all_channels;
429 }
430 }
431
432 broadcast_config.bits_per_sample =
433 LeAudioCodecConfiguration::kBitsPerSample16;
434 broadcast_config.sampling_rate = core_config.GetSamplingFrequencyHz();
435 broadcast_config.frame_duration = core_config.GetFrameDurationUs();
436 broadcast_config.octets_per_frame = *(core_config.octets_per_codec_frame);
437 broadcast_config.blocks_per_sdu = 1;
438
439 int sample_rate = broadcast_config.sampling_rate;
440 int frame_duration = broadcast_config.frame_duration;
441
442 if (bcast_high_reliability_qos.find(sample_rate) !=
443 bcast_high_reliability_qos.end() &&
444 bcast_high_reliability_qos[sample_rate].find(frame_duration) !=
445 bcast_high_reliability_qos[sample_rate].end()) {
446 auto qos = bcast_high_reliability_qos[sample_rate].at(frame_duration);
447 broadcast_config.retransmission_number = qos.getRetransmissionNumber();
448 broadcast_config.max_transport_latency = qos.getMaxTransportLatency();
449 supported_broadcast_config.push_back(broadcast_config);
450 } else {
451 log::error(
452 "Cannot find the correspoding QoS config for the sampling_rate: "
453 "{}, frame_duration: {}",
454 sample_rate, frame_duration);
455 }
456
457 log::info("broadcast_config sampling_rate: {}",
458 broadcast_config.sampling_rate);
459 }
460 }
461
GetBroadcastOffloadConfigbluetooth::le_audio::codec_manager_impl462 const broadcast_offload_config* GetBroadcastOffloadConfig(
463 uint8_t preferred_quality) {
464 if (supported_broadcast_config.empty()) {
465 log::error("There is no valid broadcast offload config");
466 return nullptr;
467 }
468 /* Broadcast audio config selection based on source broadcast capability
469 *
470 * If the preferred_quality is HIGH, the configs ranking is
471 * 48_4 > 48_2 > 24_2(sink mandatory) > 16_2(source & sink mandatory)
472 *
473 * If the preferred_quality is STANDARD, the configs ranking is
474 * 24_2(sink mandatory) > 16_2(source & sink mandatory)
475 */
476 broadcast_target_config = -1;
477 for (int i = 0; i < (int)supported_broadcast_config.size(); i++) {
478 if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) {
479 if (supported_broadcast_config[i].sampling_rate == 24000u &&
480 supported_broadcast_config[i].octets_per_frame == 60) { // 24_2
481 broadcast_target_config = i;
482 break;
483 }
484
485 if (supported_broadcast_config[i].sampling_rate == 16000u &&
486 supported_broadcast_config[i].octets_per_frame == 40) { // 16_2
487 broadcast_target_config = i;
488 }
489
490 continue;
491 }
492
493 // perferred_quality = bluetooth::le_audio::QUALITY_HIGH
494 if (supported_broadcast_config[i].sampling_rate == 48000u &&
495 supported_broadcast_config[i].octets_per_frame == 120) { // 48_4
496 broadcast_target_config = i;
497 break;
498 }
499
500 if ((supported_broadcast_config[i].sampling_rate == 48000u &&
501 supported_broadcast_config[i].octets_per_frame == 100) || // 48_2
502 (supported_broadcast_config[i].sampling_rate == 24000u &&
503 supported_broadcast_config[i].octets_per_frame == 60) || // 24_2
504 (supported_broadcast_config[i].sampling_rate == 16000u &&
505 supported_broadcast_config[i].octets_per_frame == 40)) { // 16_2
506 if (broadcast_target_config == -1 ||
507 (supported_broadcast_config[i].sampling_rate >
508 supported_broadcast_config[broadcast_target_config].sampling_rate))
509 broadcast_target_config = i;
510 }
511 }
512
513 if (broadcast_target_config == -1) {
514 log::error(
515 "There is no valid broadcast offload config with preferred_quality");
516 return nullptr;
517 }
518
519 log::info(
520 "stream_map.size(): {}, sampling_rate: {}, frame_duration(us): {}, "
521 "octets_per_frame: {}, blocks_per_sdu {}, retransmission_number: {}, "
522 "max_transport_latency: {}",
523 supported_broadcast_config[broadcast_target_config].stream_map.size(),
524 supported_broadcast_config[broadcast_target_config].sampling_rate,
525 supported_broadcast_config[broadcast_target_config].frame_duration,
526 supported_broadcast_config[broadcast_target_config].octets_per_frame,
527 (int)supported_broadcast_config[broadcast_target_config].blocks_per_sdu,
528 (int)supported_broadcast_config[broadcast_target_config]
529 .retransmission_number,
530 supported_broadcast_config[broadcast_target_config]
531 .max_transport_latency);
532
533 return &supported_broadcast_config[broadcast_target_config];
534 }
535
UpdateBroadcastOffloadConfigbluetooth::le_audio::codec_manager_impl536 void UpdateBroadcastOffloadConfig(
537 const broadcaster::BroadcastConfiguration& config) {
538 if (config.subgroups.empty()) {
539 broadcast_target_config = -1;
540 return;
541 }
542
543 // Use the first configuration slot
544 broadcast_target_config = 0;
545 auto& offload_cfg = supported_broadcast_config[broadcast_target_config];
546
547 // Note: Currently only a single subgroup offloading is supported
548 auto const& subgroup = config.subgroups.at(0);
549 auto subgroup_config =
550 subgroup.GetCommonBisCodecSpecData().GetAsCoreCodecConfig();
551
552 offload_cfg.sampling_rate = subgroup_config.GetSamplingFrequencyHz();
553 offload_cfg.frame_duration = subgroup_config.GetFrameDurationUs();
554 offload_cfg.octets_per_frame = subgroup_config.GetOctectsPerFrame();
555 offload_cfg.blocks_per_sdu = 1;
556 offload_cfg.stream_map.resize(subgroup.GetNumBis());
557
558 log::info(
559 "stream_map.size(): {}, sampling_rate: {}, frame_duration(us): {}, "
560 "octets_per_frame: {}, blocks_per_sdu {}, retransmission_number: {}, "
561 "max_transport_latency: {}",
562 supported_broadcast_config[broadcast_target_config].stream_map.size(),
563 supported_broadcast_config[broadcast_target_config].sampling_rate,
564 supported_broadcast_config[broadcast_target_config].frame_duration,
565 supported_broadcast_config[broadcast_target_config].octets_per_frame,
566 (int)supported_broadcast_config[broadcast_target_config].blocks_per_sdu,
567 (int)supported_broadcast_config[broadcast_target_config]
568 .retransmission_number,
569 supported_broadcast_config[broadcast_target_config]
570 .max_transport_latency);
571 }
572
GetBroadcastConfigbluetooth::le_audio::codec_manager_impl573 std::unique_ptr<broadcaster::BroadcastConfiguration> GetBroadcastConfig(
574 const CodecManager::BroadcastConfigurationRequirements& requirements) {
575 if (GetCodecLocation() != types::CodecLocation::ADSP) {
576 // Get the software supported broadcast configuration
577 return std::make_unique<broadcaster::BroadcastConfiguration>(
578 ::bluetooth::le_audio::broadcaster::GetBroadcastConfig(
579 requirements.subgroup_quality));
580 }
581
582 /* Subgroups with different audio qualities is not being supported now,
583 * if any subgroup preferred to use standard audio config, choose
584 * the standard audio config instead
585 */
586 uint8_t BIG_audio_quality = bluetooth::le_audio::QUALITY_HIGH;
587 for (const auto& [_, quality] : requirements.subgroup_quality) {
588 if (quality == bluetooth::le_audio::QUALITY_STANDARD) {
589 BIG_audio_quality = bluetooth::le_audio::QUALITY_STANDARD;
590 }
591 }
592
593 if (IsUsingCodecExtensibility()) {
594 log::assert_that(broadcast_local_source_hal_client != nullptr,
595 "audio source hal client is NULL");
596 auto hal_config = broadcast_local_source_hal_client->GetBroadcastConfig(
597 requirements.subgroup_quality, requirements.sink_pacs);
598 if (hal_config.has_value()) {
599 UpdateBroadcastOffloadConfig(hal_config.value());
600 return std::make_unique<broadcaster::BroadcastConfiguration>(
601 hal_config.value());
602 }
603
604 log::debug(
605 "No configuration received from AIDL, fall back to static "
606 "configuration.");
607 }
608
609 auto offload_config = GetBroadcastOffloadConfig(BIG_audio_quality);
610 if (offload_config == nullptr) {
611 log::error("No Offload configuration supported for quality index: {}.",
612 BIG_audio_quality);
613 return nullptr;
614 }
615
616 types::LeAudioLtvMap codec_params;
617 // Map sample freq. value to LE Audio codec specific config value
618 if (types::LeAudioCoreCodecConfig::sample_rate_map.count(
619 offload_config->sampling_rate)) {
620 codec_params.Add(codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
621 types::LeAudioCoreCodecConfig::sample_rate_map.at(
622 offload_config->sampling_rate));
623 }
624 // Map data interval value to LE Audio codec specific config value
625 if (types::LeAudioCoreCodecConfig::data_interval_map.count(
626 offload_config->frame_duration)) {
627 codec_params.Add(codec_spec_conf::kLeAudioLtvTypeFrameDuration,
628 types::LeAudioCoreCodecConfig::data_interval_map.at(
629 offload_config->frame_duration));
630 }
631 codec_params.Add(codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
632 offload_config->octets_per_frame);
633
634 // Note: We do not support a different channel count on each BIS within the
635 // same subgroup.
636 uint8_t allocated_channel_count =
637 offload_config->stream_map.size()
638 ? std::bitset<32>{offload_config->stream_map.at(0).second}.count()
639 : 1;
640 bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig codec_config(
641 bluetooth::le_audio::broadcaster::kLeAudioCodecIdLc3,
642 {bluetooth::le_audio::broadcaster::BroadcastSubgroupBisCodecConfig(
643 static_cast<uint8_t>(offload_config->stream_map.size()),
644 allocated_channel_count, codec_params)},
645 offload_config->bits_per_sample);
646
647 bluetooth::le_audio::broadcaster::BroadcastQosConfig qos_config(
648 offload_config->retransmission_number,
649 offload_config->max_transport_latency);
650
651 // Change the default software encoder config data path ID
652 auto data_path = broadcaster::lc3_data_path;
653 data_path.dataPathId =
654 bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
655
656 uint16_t max_sdu_octets = 0;
657 for (auto [_, allocation] : offload_config->stream_map) {
658 auto alloc_channels_per_bis = std::bitset<32>{allocation}.count() ?: 1;
659 auto sdu_octets = offload_config->octets_per_frame *
660 offload_config->blocks_per_sdu * alloc_channels_per_bis;
661 if (max_sdu_octets < sdu_octets) max_sdu_octets = sdu_octets;
662 }
663
664 if (requirements.subgroup_quality.size() > 1) {
665 log::error("More than one subgroup is not supported!");
666 }
667
668 return std::make_unique<broadcaster::BroadcastConfiguration>(
669 broadcaster::BroadcastConfiguration({
670 .subgroups = {codec_config},
671 .qos = qos_config,
672 .data_path = data_path,
673 .sduIntervalUs = offload_config->frame_duration,
674 .maxSduOctets = max_sdu_octets,
675 .phy = 0x02, // PHY_LE_2M
676 .packing = 0, // Sequential
677 .framing = 0 // Unframed,
678 }));
679 }
680
UpdateBroadcastConnHandlebluetooth::le_audio::codec_manager_impl681 void UpdateBroadcastConnHandle(
682 const std::vector<uint16_t>& conn_handle,
683 std::function<
684 void(const ::bluetooth::le_audio::broadcast_offload_config& config)>
685 update_receiver) {
686 if (GetCodecLocation() != le_audio::types::CodecLocation::ADSP) {
687 return;
688 }
689
690 if (broadcast_target_config == -1 ||
691 broadcast_target_config >= (int)supported_broadcast_config.size()) {
692 log::error("There is no valid broadcast offload config");
693 return;
694 }
695
696 auto broadcast_config = supported_broadcast_config[broadcast_target_config];
697 log::assert_that(conn_handle.size() == broadcast_config.stream_map.size(),
698 "assert failed: conn_handle.size() == "
699 "broadcast_config.stream_map.size()");
700
701 if (broadcast_config.stream_map.size() ==
702 LeAudioCodecConfiguration::kChannelNumberStereo) {
703 broadcast_config.stream_map[0] = std::pair<uint16_t, uint32_t>{
704 conn_handle[0], codec_spec_conf::kLeAudioLocationFrontLeft};
705 broadcast_config.stream_map[1] = std::pair<uint16_t, uint32_t>{
706 conn_handle[1], codec_spec_conf::kLeAudioLocationFrontRight};
707 } else if (broadcast_config.stream_map.size() ==
708 LeAudioCodecConfiguration::kChannelNumberMono) {
709 broadcast_config.stream_map[0] = std::pair<uint16_t, uint32_t>{
710 conn_handle[0], codec_spec_conf::kLeAudioLocationFrontCenter};
711 }
712
713 update_receiver(broadcast_config);
714 }
715
ClearCisConfigurationbluetooth::le_audio::codec_manager_impl716 void ClearCisConfiguration(uint8_t direction) {
717 if (GetCodecLocation() != bluetooth::le_audio::types::CodecLocation::ADSP) {
718 return;
719 }
720
721 auto& stream_map = offloader_stream_maps.get(direction);
722 stream_map.streams_map_target.clear();
723 stream_map.streams_map_current.clear();
724 }
725
AdjustAllocationForOffloaderbluetooth::le_audio::codec_manager_impl726 static uint32_t AdjustAllocationForOffloader(uint32_t allocation) {
727 if ((allocation & codec_spec_conf::kLeAudioLocationAnyLeft) &&
728 (allocation & codec_spec_conf::kLeAudioLocationAnyRight)) {
729 return codec_spec_conf::kLeAudioLocationStereo;
730 }
731 if (allocation & codec_spec_conf::kLeAudioLocationAnyLeft) {
732 return codec_spec_conf::kLeAudioLocationFrontLeft;
733 }
734 if (allocation & codec_spec_conf::kLeAudioLocationAnyRight) {
735 return codec_spec_conf::kLeAudioLocationFrontRight;
736 }
737 return 0;
738 }
739
UpdateCisConfigurationbluetooth::le_audio::codec_manager_impl740 void UpdateCisConfiguration(const std::vector<struct types::cis>& cises,
741 const stream_parameters& stream_params,
742 uint8_t direction) {
743 if (GetCodecLocation() != bluetooth::le_audio::types::CodecLocation::ADSP) {
744 return;
745 }
746
747 auto available_allocations =
748 AdjustAllocationForOffloader(stream_params.audio_channel_allocation);
749 if (available_allocations == 0) {
750 log::error("There is no CIS connected");
751 return;
752 }
753
754 auto& stream_map = offloader_stream_maps.get(direction);
755 if (stream_map.streams_map_target.empty()) {
756 stream_map.is_initial = true;
757 } else if (stream_map.is_initial ||
758 LeAudioHalVerifier::SupportsStreamActiveApi()) {
759 /* As multiple CISes phone call case, the target_allocation already have
760 * the previous data, but the is_initial flag not be cleared. We need to
761 * clear here to avoid make duplicated target allocation stream map. */
762 stream_map.streams_map_target.clear();
763 }
764
765 stream_map.streams_map_current.clear();
766 stream_map.has_changed = true;
767 bool all_cises_connected =
768 (available_allocations == codec_spec_conf::kLeAudioLocationStereo);
769
770 /* If all the cises are connected as stream started, reset changed_flag that
771 * the bt stack wouldn't send another audio configuration for the connection
772 * status. */
773 if (stream_map.is_initial && all_cises_connected) {
774 stream_map.has_changed = false;
775 }
776
777 const std::string tag = types::BidirectionalPair<std::string>(
778 {.sink = "Sink", .source = "Source"})
779 .get(direction);
780
781 constexpr types::BidirectionalPair<types::CisType> cis_types = {
782 .sink = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SINK,
783 .source = types::CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE};
784 auto cis_type = cis_types.get(direction);
785
786 for (auto const& cis_entry : cises) {
787 if ((cis_entry.type == types::CisType::CIS_TYPE_BIDIRECTIONAL ||
788 cis_entry.type == cis_type) &&
789 cis_entry.conn_handle != 0) {
790 uint32_t target_allocation = 0;
791 uint32_t current_allocation = 0;
792 bool is_active = false;
793 for (const auto& s : stream_params.stream_locations) {
794 if (s.first == cis_entry.conn_handle) {
795 is_active = true;
796 target_allocation = AdjustAllocationForOffloader(s.second);
797 current_allocation = target_allocation;
798 if (!all_cises_connected) {
799 /* Tell offloader to mix on this CIS.*/
800 current_allocation = codec_spec_conf::kLeAudioLocationStereo;
801 }
802 break;
803 }
804 }
805
806 if (target_allocation == 0) {
807 /* Take missing allocation for that one .*/
808 target_allocation =
809 codec_spec_conf::kLeAudioLocationStereo & ~available_allocations;
810 }
811
812 log::info(
813 "{}: Cis handle 0x{:04x}, target allocation 0x{:08x}, current "
814 "allocation 0x{:08x}, active: {}",
815 tag, cis_entry.conn_handle, target_allocation, current_allocation,
816 is_active);
817
818 if (stream_map.is_initial ||
819 LeAudioHalVerifier::SupportsStreamActiveApi()) {
820 stream_map.streams_map_target.emplace_back(stream_map_info(
821 cis_entry.conn_handle, target_allocation, is_active));
822 }
823 stream_map.streams_map_current.emplace_back(stream_map_info(
824 cis_entry.conn_handle, current_allocation, is_active));
825 }
826 }
827 }
828
829 private:
SetCodecLocationbluetooth::le_audio::codec_manager_impl830 void SetCodecLocation(CodecLocation location) {
831 if (offload_enable_ == false) return;
832 codec_location_ = location;
833 }
834
IsLc3ConfigMatchedbluetooth::le_audio::codec_manager_impl835 bool IsLc3ConfigMatched(
836 const set_configurations::CodecConfigSetting& target_config,
837 const set_configurations::CodecConfigSetting& adsp_config) {
838 if (adsp_config.id.coding_format != types::kLeAudioCodingFormatLC3 ||
839 target_config.id.coding_format != types::kLeAudioCodingFormatLC3) {
840 return false;
841 }
842
843 const types::LeAudioCoreCodecConfig adsp_lc3_config =
844 adsp_config.params.GetAsCoreCodecConfig();
845 const types::LeAudioCoreCodecConfig target_lc3_config =
846 target_config.params.GetAsCoreCodecConfig();
847
848 if (adsp_lc3_config.sampling_frequency !=
849 target_lc3_config.sampling_frequency ||
850 adsp_lc3_config.frame_duration != target_lc3_config.frame_duration ||
851 adsp_config.GetChannelCountPerIsoStream() !=
852 target_config.GetChannelCountPerIsoStream() ||
853 adsp_lc3_config.octets_per_codec_frame !=
854 target_lc3_config.octets_per_codec_frame) {
855 return false;
856 }
857
858 return true;
859 }
860
IsAseConfigurationMatchedbluetooth::le_audio::codec_manager_impl861 bool IsAseConfigurationMatched(const AseConfiguration& software_ase_config,
862 const AseConfiguration& adsp_ase_config) {
863 // Skip the check of strategy due to ADSP doesn't have the info
864 return IsLc3ConfigMatched(software_ase_config.codec, adsp_ase_config.codec);
865 }
866
IsAudioSetConfigurationMatchedbluetooth::le_audio::codec_manager_impl867 bool IsAudioSetConfigurationMatched(
868 const AudioSetConfiguration* software_audio_set_conf,
869 std::unordered_set<uint8_t>& offload_preference_set,
870 const std::vector<AudioSetConfiguration>& adsp_capabilities) {
871 if (software_audio_set_conf->confs.sink.empty() &&
872 software_audio_set_conf->confs.source.empty()) {
873 return false;
874 }
875
876 // No match if the codec is not on the preference list
877 for (auto direction : {le_audio::types::kLeAudioDirectionSink,
878 le_audio::types::kLeAudioDirectionSource}) {
879 for (auto const& conf : software_audio_set_conf->confs.get(direction)) {
880 if (offload_preference_set.find(conf.codec.id.coding_format) ==
881 offload_preference_set.end()) {
882 return false;
883 }
884 }
885 }
886
887 // Checks any of offload config matches the input audio set config
888 for (const auto& adsp_audio_set_conf : adsp_capabilities) {
889 size_t match_cnt = 0;
890 size_t expected_match_cnt = 0;
891
892 for (auto direction : {le_audio::types::kLeAudioDirectionSink,
893 le_audio::types::kLeAudioDirectionSource}) {
894 auto const& software_set_ase_confs =
895 software_audio_set_conf->confs.get(direction);
896 auto const& adsp_set_ase_confs =
897 adsp_audio_set_conf.confs.get(direction);
898
899 if (!software_set_ase_confs.size() || !adsp_set_ase_confs.size()) {
900 continue;
901 }
902
903 // Check for number of ASEs mismatch
904 if (adsp_set_ase_confs.size() != software_set_ase_confs.size()) {
905 log::error(
906 "{}: ADSP config size mismatches the software: {} != {}",
907 direction == types::kLeAudioDirectionSink ? "Sink" : "Source",
908 adsp_set_ase_confs.size(), software_set_ase_confs.size());
909 continue;
910 }
911
912 // The expected number of ASE configs, the ADSP config needs to match
913 expected_match_cnt += software_set_ase_confs.size();
914 if (expected_match_cnt == 0) {
915 continue;
916 }
917
918 // Check for matching configs
919 for (auto const& adsp_set_conf : adsp_set_ase_confs) {
920 for (auto const& software_set_conf : software_set_ase_confs) {
921 if (IsAseConfigurationMatched(software_set_conf, adsp_set_conf)) {
922 match_cnt++;
923 // Check the next adsp config if the first software config matches
924 break;
925 }
926 }
927 }
928 if (match_cnt != expected_match_cnt) {
929 break;
930 }
931 }
932
933 // Check the match count
934 if (match_cnt == expected_match_cnt) {
935 return true;
936 }
937 }
938
939 return false;
940 }
941
getStrategyStringbluetooth::le_audio::codec_manager_impl942 std::string getStrategyString(types::LeAudioConfigurationStrategy strategy) {
943 switch (strategy) {
944 case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
945 return "MONO_ONE_CIS_PER_DEVICE";
946 case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
947 return "STEREO_TWO_CISES_PER_DEVICE";
948 case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
949 return "STEREO_ONE_CIS_PER_DEVICE";
950 default:
951 return "RFU";
952 }
953 }
954
sampleFreqToBluetoothSigBitMaskbluetooth::le_audio::codec_manager_impl955 uint8_t sampleFreqToBluetoothSigBitMask(int sample_freq) {
956 switch (sample_freq) {
957 case 8000:
958 return bluetooth::le_audio::codec_spec_caps::kLeAudioSamplingFreq8000Hz;
959 case 16000:
960 return bluetooth::le_audio::codec_spec_caps::
961 kLeAudioSamplingFreq16000Hz;
962 case 24000:
963 return bluetooth::le_audio::codec_spec_caps::
964 kLeAudioSamplingFreq24000Hz;
965 case 32000:
966 return bluetooth::le_audio::codec_spec_caps::
967 kLeAudioSamplingFreq32000Hz;
968 case 44100:
969 return bluetooth::le_audio::codec_spec_caps::
970 kLeAudioSamplingFreq44100Hz;
971 case 48000:
972 return bluetooth::le_audio::codec_spec_caps::
973 kLeAudioSamplingFreq48000Hz;
974 }
975 return bluetooth::le_audio::codec_spec_caps::kLeAudioSamplingFreq8000Hz;
976 }
977
storeLocalCapabluetooth::le_audio::codec_manager_impl978 void storeLocalCapa(
979 std::vector<
980 ::bluetooth::le_audio::set_configurations::AudioSetConfiguration>&
981 adsp_capabilities,
982 const std::vector<btle_audio_codec_config_t>& offload_preference_set) {
983 log::debug("Print adsp_capabilities:");
984
985 for (auto& adsp : adsp_capabilities) {
986 log::debug("'{}':", adsp.name);
987 for (auto direction : {le_audio::types::kLeAudioDirectionSink,
988 le_audio::types::kLeAudioDirectionSource}) {
989 log::debug(
990 "dir: {}: number of confs {}:",
991 direction == types::kLeAudioDirectionSink ? "sink" : "source",
992 (int)(adsp.confs.get(direction).size()));
993 for (auto conf : adsp.confs.sink) {
994 log::debug(
995 "codecId: {}, sample_freq: {}, interval {}, channel_cnt: {}",
996 conf.codec.id.coding_format, conf.codec.GetSamplingFrequencyHz(),
997 conf.codec.GetDataIntervalUs(),
998 conf.codec.GetChannelCountPerIsoStream());
999
1000 /* TODO: How to get bits_per_sample ? */
1001 btle_audio_codec_config_t capa_to_add = {
1002 .codec_type = (conf.codec.id.coding_format ==
1003 types::kLeAudioCodingFormatLC3)
1004 ? btle_audio_codec_index_t::
1005 LE_AUDIO_CODEC_INDEX_SOURCE_LC3
1006 : btle_audio_codec_index_t::
1007 LE_AUDIO_CODEC_INDEX_SOURCE_INVALID,
1008 .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate(
1009 conf.codec.GetSamplingFrequencyHz()),
1010 .bits_per_sample =
1011 utils::translateToBtLeAudioCodecConfigBitPerSample(16),
1012 .channel_count =
1013 utils::translateToBtLeAudioCodecConfigChannelCount(
1014 conf.codec.GetChannelCountPerIsoStream()),
1015 .frame_duration =
1016 utils::translateToBtLeAudioCodecConfigFrameDuration(
1017 conf.codec.GetDataIntervalUs()),
1018 };
1019
1020 auto& capa_container = (direction == types::kLeAudioDirectionSink)
1021 ? codec_output_capa
1022 : codec_input_capa;
1023 if (std::find(capa_container.begin(), capa_container.end(),
1024 capa_to_add) == capa_container.end()) {
1025 log::debug("Adding {} capa {}",
1026 (direction == types::kLeAudioDirectionSink) ? "output"
1027 : "input",
1028 static_cast<int>(capa_container.size()));
1029 capa_container.push_back(capa_to_add);
1030 }
1031 }
1032 }
1033 }
1034
1035 log::debug("Output capa: {}, Input capa: {}",
1036 static_cast<int>(codec_output_capa.size()),
1037 static_cast<int>(codec_input_capa.size()));
1038
1039 log::debug("Print offload_preference_set: {}",
1040 (int)(offload_preference_set.size()));
1041
1042 int i = 0;
1043 for (auto set : offload_preference_set) {
1044 log::debug("set {}, {}", i++, set.ToString());
1045 }
1046 }
1047
UpdateOffloadCapabilitybluetooth::le_audio::codec_manager_impl1048 void UpdateOffloadCapability(
1049 const std::vector<btle_audio_codec_config_t>& offloading_preference) {
1050 log::info("");
1051 std::unordered_set<uint8_t> offload_preference_set;
1052
1053 if (AudioSetConfigurationProvider::Get() == nullptr) {
1054 log::error("Audio set configuration provider is not available.");
1055 return;
1056 }
1057
1058 auto adsp_capabilities =
1059 ::bluetooth::audio::le_audio::get_offload_capabilities();
1060
1061 storeLocalCapa(adsp_capabilities.unicast_offload_capabilities,
1062 offloading_preference);
1063
1064 for (auto codec : offloading_preference) {
1065 auto it = btle_audio_codec_type_map_.find(codec.codec_type);
1066
1067 if (it != btle_audio_codec_type_map_.end()) {
1068 offload_preference_set.insert(it->second);
1069 }
1070 }
1071
1072 for (types::LeAudioContextType ctx_type :
1073 types::kLeAudioContextAllTypesArray) {
1074 // Gets the software supported context type and the corresponding config
1075 // priority
1076 const AudioSetConfigurations* software_audio_set_confs =
1077 AudioSetConfigurationProvider::Get()->GetConfigurations(ctx_type);
1078
1079 for (const auto& software_audio_set_conf : *software_audio_set_confs) {
1080 if (IsAudioSetConfigurationMatched(
1081 software_audio_set_conf, offload_preference_set,
1082 adsp_capabilities.unicast_offload_capabilities)) {
1083 log::info("Offload supported conf, context type: {}, settings -> {}",
1084 (int)ctx_type, software_audio_set_conf->name);
1085 if (dual_bidirection_swb_supported_ &&
1086 AudioSetConfigurationProvider::Get()
1087 ->CheckConfigurationIsDualBiDirSwb(
1088 *software_audio_set_conf)) {
1089 offload_dual_bidirection_swb_supported_ = true;
1090 }
1091 context_type_offload_config_map_[ctx_type].push_back(
1092 software_audio_set_conf);
1093 }
1094 }
1095 }
1096 UpdateSupportedBroadcastConfig(
1097 adsp_capabilities.broadcast_offload_capabilities);
1098 }
1099
1100 CodecLocation codec_location_ = CodecLocation::HOST;
1101 bool offload_enable_ = false;
1102 bool offload_dual_bidirection_swb_supported_ = false;
1103 bool dual_bidirection_swb_supported_ = false;
1104 types::BidirectionalPair<offloader_stream_maps_t> offloader_stream_maps;
1105 std::vector<bluetooth::le_audio::broadcast_offload_config>
1106 supported_broadcast_config;
1107 std::unordered_map<types::LeAudioContextType, AudioSetConfigurations>
1108 context_type_offload_config_map_;
1109 std::unordered_map<btle_audio_codec_index_t, uint8_t>
1110 btle_audio_codec_type_map_ = {
1111 {::bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
1112 types::kLeAudioCodingFormatLC3}};
1113
1114 std::vector<btle_audio_codec_config_t> codec_input_capa = {};
1115 std::vector<btle_audio_codec_config_t> codec_output_capa = {};
1116 int broadcast_target_config = -1;
1117
1118 LeAudioSourceAudioHalClient* unicast_local_source_hal_client = nullptr;
1119 LeAudioSinkAudioHalClient* unicast_local_sink_hal_client = nullptr;
1120 LeAudioSourceAudioHalClient* broadcast_local_source_hal_client = nullptr;
1121 };
1122
operator <<(std::ostream & os,const CodecManager::UnicastConfigurationRequirements & req)1123 std::ostream& operator<<(
1124 std::ostream& os,
1125 const CodecManager::UnicastConfigurationRequirements& req) {
1126 os << "{audio context type: " << req.audio_context_type;
1127 if (req.sink_pacs.has_value()) {
1128 os << ", sink_pacs: [";
1129 for (auto const& pac : req.sink_pacs.value()) {
1130 os << "sink_pac: {";
1131 os << ", codec_id: " << pac.codec_id;
1132 os << ", caps size: " << pac.codec_spec_caps.Size();
1133 os << ", caps_raw size: " << pac.codec_spec_caps_raw.size();
1134 os << ", caps_raw size: " << pac.metadata.size();
1135 os << "}, ";
1136 }
1137 os << "\b\b]";
1138 } else {
1139 os << ", sink_pacs: "
1140 << "None";
1141 }
1142
1143 if (req.source_pacs.has_value()) {
1144 os << ", source_pacs: [";
1145 for (auto const& pac : req.source_pacs.value()) {
1146 os << "source_pac: {";
1147 os << ", codec_id: " << pac.codec_id;
1148 os << ", caps size: " << pac.codec_spec_caps.Size();
1149 os << ", caps_raw size: " << pac.codec_spec_caps_raw.size();
1150 os << ", caps_raw size: " << pac.metadata.size();
1151 os << "}, ";
1152 }
1153 os << "\b\b]";
1154 } else {
1155 os << ", source_pacs: "
1156 << "None";
1157 }
1158
1159 if (req.sink_requirements.has_value()) {
1160 for (auto const& sink_req : req.sink_requirements.value()) {
1161 os << "sink_req: {";
1162 os << ", target_latency: " << +sink_req.target_latency;
1163 os << ", target_Phy: " << +sink_req.target_Phy;
1164 // os << sink_req.params.GetAsCoreCodecCapabilities();
1165 os << "}";
1166 }
1167 } else {
1168 os << "sink_req: None";
1169 }
1170
1171 if (req.source_requirements.has_value()) {
1172 for (auto const& source_req : req.source_requirements.value()) {
1173 os << "source_req: {";
1174 os << ", target_latency: " << +source_req.target_latency;
1175 os << ", target_Phy: " << +source_req.target_Phy;
1176 // os << source_req.params.GetAsCoreCodecCapabilities();
1177 os << "}";
1178 }
1179 } else {
1180 os << "source_req: None";
1181 }
1182
1183 os << "}";
1184 return os;
1185 }
1186
1187 struct CodecManager::impl {
implbluetooth::le_audio::CodecManager::impl1188 impl(const CodecManager& codec_manager) : codec_manager_(codec_manager) {}
1189
Startbluetooth::le_audio::CodecManager::impl1190 void Start(
1191 const std::vector<btle_audio_codec_config_t>& offloading_preference) {
1192 log::assert_that(!codec_manager_impl_,
1193 "assert failed: !codec_manager_impl_");
1194 codec_manager_impl_ = std::make_unique<codec_manager_impl>();
1195 codec_manager_impl_->start(offloading_preference);
1196 }
1197
Stopbluetooth::le_audio::CodecManager::impl1198 void Stop() {
1199 log::assert_that(codec_manager_impl_ != nullptr,
1200 "assert failed: codec_manager_impl_ != nullptr");
1201 codec_manager_impl_.reset();
1202 }
1203
IsRunningbluetooth::le_audio::CodecManager::impl1204 bool IsRunning() { return codec_manager_impl_ ? true : false; }
1205
1206 const CodecManager& codec_manager_;
1207 std::unique_ptr<codec_manager_impl> codec_manager_impl_;
1208 };
1209
CodecManager()1210 CodecManager::CodecManager() : pimpl_(std::make_unique<impl>(*this)) {}
1211
Start(const std::vector<btle_audio_codec_config_t> & offloading_preference)1212 void CodecManager::Start(
1213 const std::vector<btle_audio_codec_config_t>& offloading_preference) {
1214 if (!pimpl_->IsRunning()) pimpl_->Start(offloading_preference);
1215 }
1216
Stop()1217 void CodecManager::Stop() {
1218 if (pimpl_->IsRunning()) pimpl_->Stop();
1219 }
1220
GetCodecLocation(void) const1221 types::CodecLocation CodecManager::GetCodecLocation(void) const {
1222 if (!pimpl_->IsRunning()) {
1223 return CodecLocation::HOST;
1224 }
1225
1226 return pimpl_->codec_manager_impl_->GetCodecLocation();
1227 }
1228
IsDualBiDirSwbSupported(void) const1229 bool CodecManager::IsDualBiDirSwbSupported(void) const {
1230 if (!pimpl_->IsRunning()) {
1231 return false;
1232 }
1233
1234 return pimpl_->codec_manager_impl_->IsDualBiDirSwbSupported();
1235 }
1236
1237 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
GetLocalAudioOutputCodecCapa()1238 CodecManager::GetLocalAudioOutputCodecCapa() {
1239 if (pimpl_->IsRunning()) {
1240 return pimpl_->codec_manager_impl_->GetLocalAudioOutputCodecCapa();
1241 }
1242
1243 std::vector<bluetooth::le_audio::btle_audio_codec_config_t> empty{};
1244 return empty;
1245 }
1246
1247 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
GetLocalAudioInputCodecCapa()1248 CodecManager::GetLocalAudioInputCodecCapa() {
1249 if (pimpl_->IsRunning()) {
1250 return pimpl_->codec_manager_impl_->GetLocalAudioOutputCodecCapa();
1251 }
1252 std::vector<bluetooth::le_audio::btle_audio_codec_config_t> empty{};
1253 return empty;
1254 }
1255
UpdateActiveAudioConfig(const types::BidirectionalPair<stream_parameters> & stream_params,types::BidirectionalPair<uint16_t> delays_ms,std::function<void (const offload_config & config,uint8_t direction)> update_receiver)1256 void CodecManager::UpdateActiveAudioConfig(
1257 const types::BidirectionalPair<stream_parameters>& stream_params,
1258 types::BidirectionalPair<uint16_t> delays_ms,
1259 std::function<void(const offload_config& config, uint8_t direction)>
1260 update_receiver) {
1261 if (pimpl_->IsRunning())
1262 pimpl_->codec_manager_impl_->UpdateActiveAudioConfig(
1263 stream_params, delays_ms, update_receiver);
1264 }
1265
UpdateActiveUnicastAudioHalClient(LeAudioSourceAudioHalClient * source_unicast_client,LeAudioSinkAudioHalClient * sink_unicast_client,bool is_active)1266 bool CodecManager::UpdateActiveUnicastAudioHalClient(
1267 LeAudioSourceAudioHalClient* source_unicast_client,
1268 LeAudioSinkAudioHalClient* sink_unicast_client, bool is_active) {
1269 if (pimpl_->IsRunning()) {
1270 return pimpl_->codec_manager_impl_->UpdateActiveUnicastAudioHalClient(
1271 source_unicast_client, sink_unicast_client, is_active);
1272 }
1273 return false;
1274 }
1275
UpdateActiveBroadcastAudioHalClient(LeAudioSourceAudioHalClient * source_broadcast_client,bool is_active)1276 bool CodecManager::UpdateActiveBroadcastAudioHalClient(
1277 LeAudioSourceAudioHalClient* source_broadcast_client, bool is_active) {
1278 if (pimpl_->IsRunning()) {
1279 return pimpl_->codec_manager_impl_->UpdateActiveBroadcastAudioHalClient(
1280 source_broadcast_client, is_active);
1281 }
1282 return false;
1283 }
1284
GetCodecConfig(const CodecManager::UnicastConfigurationRequirements & requirements,CodecManager::UnicastConfigurationVerifier verifier)1285 std::unique_ptr<AudioSetConfiguration> CodecManager::GetCodecConfig(
1286 const CodecManager::UnicastConfigurationRequirements& requirements,
1287 CodecManager::UnicastConfigurationVerifier verifier) {
1288 if (pimpl_->IsRunning()) {
1289 return pimpl_->codec_manager_impl_->GetCodecConfig(requirements, verifier);
1290 }
1291
1292 return nullptr;
1293 }
1294
CheckCodecConfigIsBiDirSwb(const set_configurations::AudioSetConfiguration & config) const1295 bool CodecManager::CheckCodecConfigIsBiDirSwb(
1296 const set_configurations::AudioSetConfiguration& config) const {
1297 if (pimpl_->IsRunning()) {
1298 return pimpl_->codec_manager_impl_->CheckCodecConfigIsBiDirSwb(config);
1299 }
1300 return false;
1301 }
1302
CheckCodecConfigIsDualBiDirSwb(const set_configurations::AudioSetConfiguration & config) const1303 bool CodecManager::CheckCodecConfigIsDualBiDirSwb(
1304 const set_configurations::AudioSetConfiguration& config) const {
1305 if (pimpl_->IsRunning()) {
1306 return pimpl_->codec_manager_impl_->CheckCodecConfigIsDualBiDirSwb(config);
1307 }
1308 return false;
1309 }
1310
1311 std::unique_ptr<broadcaster::BroadcastConfiguration>
GetBroadcastConfig(const CodecManager::BroadcastConfigurationRequirements & requirements) const1312 CodecManager::GetBroadcastConfig(
1313 const CodecManager::BroadcastConfigurationRequirements& requirements)
1314 const {
1315 if (pimpl_->IsRunning()) {
1316 return pimpl_->codec_manager_impl_->GetBroadcastConfig(requirements);
1317 }
1318
1319 return nullptr;
1320 }
1321
UpdateBroadcastConnHandle(const std::vector<uint16_t> & conn_handle,std::function<void (const::bluetooth::le_audio::broadcast_offload_config & config)> update_receiver)1322 void CodecManager::UpdateBroadcastConnHandle(
1323 const std::vector<uint16_t>& conn_handle,
1324 std::function<
1325 void(const ::bluetooth::le_audio::broadcast_offload_config& config)>
1326 update_receiver) {
1327 if (pimpl_->IsRunning()) {
1328 return pimpl_->codec_manager_impl_->UpdateBroadcastConnHandle(
1329 conn_handle, update_receiver);
1330 }
1331 }
1332
UpdateCisConfiguration(const std::vector<struct types::cis> & cises,const stream_parameters & stream_params,uint8_t direction)1333 void CodecManager::UpdateCisConfiguration(
1334 const std::vector<struct types::cis>& cises,
1335 const stream_parameters& stream_params, uint8_t direction) {
1336 if (pimpl_->IsRunning()) {
1337 return pimpl_->codec_manager_impl_->UpdateCisConfiguration(
1338 cises, stream_params, direction);
1339 }
1340 }
1341
ClearCisConfiguration(uint8_t direction)1342 void CodecManager::ClearCisConfiguration(uint8_t direction) {
1343 if (pimpl_->IsRunning()) {
1344 return pimpl_->codec_manager_impl_->ClearCisConfiguration(direction);
1345 }
1346 }
1347
IsUsingCodecExtensibility() const1348 bool CodecManager::IsUsingCodecExtensibility() const {
1349 if (pimpl_->IsRunning()) {
1350 return pimpl_->codec_manager_impl_->IsUsingCodecExtensibility();
1351 }
1352 return false;
1353 }
1354
1355 } // namespace bluetooth::le_audio
1356