• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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