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