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