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