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