1 /*
2  * Copyright 2024 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 "le_audio_utils.h"
18 
19 #include <com_android_bluetooth_flags.h>
20 
21 #include <optional>
22 
23 #include "hardware/bt_le_audio.h"
24 
25 namespace bluetooth {
26 namespace audio {
27 namespace aidl {
28 
GetAidlCodecIdFromStackFormat(const::bluetooth::le_audio::types::LeAudioCodecId & codec_id)29 ::aidl::android::hardware::bluetooth::audio::CodecId GetAidlCodecIdFromStackFormat(
30         const ::bluetooth::le_audio::types::LeAudioCodecId& codec_id) {
31   ::aidl::android::hardware::bluetooth::audio::CodecId codec;
32 
33   if (codec_id.coding_format == 0x06) {
34     codec = ::aidl::android::hardware::bluetooth::audio::CodecId::Core::LC3;
35   } else if (codec_id.coding_format == 0x02) {
36     codec = ::aidl::android::hardware::bluetooth::audio::CodecId::Core::CVSD;
37   } else if (codec_id.coding_format == 0x05) {
38     codec = ::aidl::android::hardware::bluetooth::audio::CodecId::Core::MSBC;
39   } else if (codec_id.coding_format == 0xFF) {
40     auto vc = ::aidl::android::hardware::bluetooth::audio::CodecId::Vendor();
41     vc.id = codec_id.vendor_company_id;
42     vc.codecId = codec_id.vendor_codec_id;
43     codec = vc;
44   } else {
45     log::error("Invalid coding format: {:02x}", codec_id.coding_format);
46   }
47   return codec;
48 }
49 
GetStackCodecIdFromAidlFormat(const::aidl::android::hardware::bluetooth::audio::CodecId & codec_id)50 ::bluetooth::le_audio::types::LeAudioCodecId GetStackCodecIdFromAidlFormat(
51         const ::aidl::android::hardware::bluetooth::audio::CodecId& codec_id) {
52   ::bluetooth::le_audio::types::LeAudioCodecId codec;
53   switch (codec_id.getTag()) {
54     case ::aidl::android::hardware::bluetooth::audio::CodecId::core: {
55       codec.vendor_codec_id = 0x00;
56       codec.vendor_company_id = 0x00;
57 
58       if (codec_id == ::aidl::android::hardware::bluetooth::audio::CodecId::Core::LC3) {
59         codec.coding_format = 0x06;
60       } else if (codec_id == ::aidl::android::hardware::bluetooth::audio::CodecId::Core::CVSD) {
61         codec.coding_format = 0x02;
62       } else if (codec_id == ::aidl::android::hardware::bluetooth::audio::CodecId::Core::MSBC) {
63         codec.coding_format = 0x05;
64       }
65     } break;
66     case ::aidl::android::hardware::bluetooth::audio::CodecId::vendor: {
67       auto vendor = codec_id.get<::aidl::android::hardware::bluetooth::audio::CodecId::vendor>();
68       codec.coding_format = 0xFF;
69       codec.vendor_company_id = vendor.id;
70       codec.vendor_codec_id = vendor.codecId;
71     } break;
72     case ::aidl::android::hardware::bluetooth::audio::CodecId::a2dp:
73       log::error("A2DP codecs are not supported here");
74       break;
75     default:
76       break;
77   }
78   return codec;
79 }
80 
81 static std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv>
GetAidlCodecCapabilitiesFromStack(const::bluetooth::le_audio::types::LeAudioLtvMap & in)82 GetAidlCodecCapabilitiesFromStack(const ::bluetooth::le_audio::types::LeAudioLtvMap& in) {
83   std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv> ltvs;
84   auto stack_caps = in.GetAsCoreCodecCapabilities();
85 
86   if (stack_caps.supported_sampling_frequencies) {
87     /* Note: The values match exactly */
88     ::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv::
89             SupportedSamplingFrequencies freqs{.bitmask =
90                                                        *stack_caps.supported_sampling_frequencies};
91     if (freqs.bitmask) {
92       ltvs.push_back(freqs);
93     }
94   }
95 
96   if (stack_caps.supported_frame_durations) {
97     /* Note: The values match exactly */
98     ::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv::
99             SupportedFrameDurations durations{.bitmask = *stack_caps.supported_frame_durations};
100     if (durations.bitmask) {
101       ltvs.push_back(durations);
102     }
103   }
104 
105   if (stack_caps.supported_audio_channel_counts) {
106     /* Note: The values match exactly */
107     ::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv::
108             SupportedAudioChannelCounts counts{.bitmask =
109                                                        *stack_caps.supported_audio_channel_counts};
110     if (counts.bitmask) {
111       ltvs.push_back(counts);
112     }
113   }
114 
115   if (stack_caps.supported_min_octets_per_codec_frame &&
116       stack_caps.supported_max_octets_per_codec_frame) {
117     ::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv::
118             SupportedOctetsPerCodecFrame octets_per_frame{
119                     .min = *stack_caps.supported_min_octets_per_codec_frame,
120                     .max = *stack_caps.supported_max_octets_per_codec_frame,
121             };
122     ltvs.push_back(octets_per_frame);
123   }
124 
125   if (stack_caps.supported_max_codec_frames_per_sdu) {
126     ::aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv::
127             SupportedMaxCodecFramesPerSDU codec_frames{
128                     .value = *stack_caps.supported_max_codec_frames_per_sdu};
129     ltvs.push_back(codec_frames);
130   }
131 
132   return ltvs;
133 }
134 
135 static std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv>
GetAidlCodecSpecificConfigurationFromStack(const::bluetooth::le_audio::types::LeAudioLtvMap & stack_ltvs)136 GetAidlCodecSpecificConfigurationFromStack(
137         const ::bluetooth::le_audio::types::LeAudioLtvMap& stack_ltvs) {
138   std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv> aidl_ltvs;
139   auto stack_config = stack_ltvs.GetAsCoreCodecConfig();
140 
141   if (stack_config.sampling_frequency.has_value()) {
142     // The frequency values match exactly
143     aidl_ltvs.push_back(
144             static_cast<::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::
145                                 SamplingFrequency>(stack_config.sampling_frequency.value()));
146   }
147   if (stack_config.frame_duration.has_value()) {
148     // The frame duration values match exactly
149     aidl_ltvs.push_back(
150             static_cast<::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::
151                                 FrameDuration>(stack_config.frame_duration.value()));
152   }
153   if (stack_config.audio_channel_allocation.has_value()) {
154     // The frequency values match exactly
155     auto aidl_location = static_cast<int32_t>(stack_config.audio_channel_allocation.value());
156     aidl_ltvs.push_back(::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::
157                                 AudioChannelAllocation{.bitmask = aidl_location});
158   }
159   if (stack_config.octets_per_codec_frame.has_value()) {
160     // The octetes per codec frame values match exactly
161     aidl_ltvs.push_back(
162             ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::
163                     OctetsPerCodecFrame{.value = stack_config.octets_per_codec_frame.value()});
164   }
165 
166   if (stack_config.codec_frames_blocks_per_sdu.has_value()) {
167     // The codec frame blocks per sdu values match exactly
168     aidl_ltvs.push_back(::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::
169                                 CodecFrameBlocksPerSDU{
170                                         .value = stack_config.codec_frames_blocks_per_sdu.value()});
171   }
172 
173   return aidl_ltvs;
174 }
175 
176 std::optional<std::vector<std::optional<::aidl::android::hardware::bluetooth::audio::MetadataLtv>>>
GetAidlMetadataFromStackFormat(const std::vector<uint8_t> & vec)177 GetAidlMetadataFromStackFormat(const std::vector<uint8_t>& vec) {
178   if (vec.empty()) {
179     return std::nullopt;
180   }
181   std::vector<std::optional<::aidl::android::hardware::bluetooth::audio::MetadataLtv>> out_ltvs;
182 
183   auto ltvs = ::bluetooth::le_audio::types::LeAudioLtvMap();
184   if (ltvs.Parse(vec.data(), vec.size())) {
185     auto stackMetadata = ltvs.GetAsLeAudioMetadata();
186 
187     if (stackMetadata.preferred_audio_context) {
188       out_ltvs.push_back(
189               ::aidl::android::hardware::bluetooth::audio::MetadataLtv::PreferredAudioContexts{
190                       .values = ::aidl::android::hardware::bluetooth::audio::AudioContext{
191                               .bitmask = stackMetadata.preferred_audio_context.value()}});
192     }
193     if (stackMetadata.streaming_audio_context) {
194       out_ltvs.push_back(
195               ::aidl::android::hardware::bluetooth::audio::MetadataLtv::StreamingAudioContexts{
196                       .values = ::aidl::android::hardware::bluetooth::audio::AudioContext{
197                               .bitmask = stackMetadata.streaming_audio_context.value()}});
198     }
199     if (stackMetadata.vendor_specific) {
200       if (stackMetadata.vendor_specific->size() >= 2) {
201         out_ltvs.push_back(::aidl::android::hardware::bluetooth::audio::MetadataLtv::VendorSpecific{
202                 /* Two octets for the company identifier */
203                 stackMetadata.vendor_specific->at(0) | (stackMetadata.vendor_specific->at(1) << 8),
204                 /* The rest is a payload */
205                 .opaqueValue = std::vector<uint8_t>(stackMetadata.vendor_specific->begin() + 2,
206                                                     stackMetadata.vendor_specific->end())});
207       }
208     }
209     /* Note: stackMetadata.program_info
210      *       stackMetadata.language
211      *       stackMetadata.ccid_list
212      *       stackMetadata.parental_rating
213      *       stackMetadata.program_info_uri
214      *       stackMetadata.extended_metadata
215      *       stackMetadata.audio_active_state
216      *       stackMetadata.broadcast_audio_immediate_rendering
217      *       are not sent over the AIDL interface as they are considered as
218      *       irrelevant for the configuration process.
219      */
220   }
221   return out_ltvs;
222 }
223 
GetStackMetadataFromAidlFormat(const std::vector<std::optional<::aidl::android::hardware::bluetooth::audio::MetadataLtv>> & source)224 bluetooth::le_audio::types::LeAudioLtvMap GetStackMetadataFromAidlFormat(
225         const std::vector<std::optional<::aidl::android::hardware::bluetooth::audio::MetadataLtv>>&
226                 source) {
227   bluetooth::le_audio::types::LeAudioLtvMap cfg;
228   (void)source;
229   for (auto const& entry : source) {
230     if (!entry.has_value()) {
231       continue;
232     }
233 
234     if (entry->getTag() ==
235         ::aidl::android::hardware::bluetooth::audio::MetadataLtv::preferredAudioContexts) {
236       auto aidl_contexts = entry->get<
237               ::aidl::android::hardware::bluetooth::audio::MetadataLtv::preferredAudioContexts>();
238       cfg.Add(bluetooth::le_audio::types::kLeAudioMetadataTypePreferredAudioContext,
239               (uint16_t)aidl_contexts.values.bitmask);
240 
241     } else if (entry->getTag() ==
242                ::aidl::android::hardware::bluetooth::audio::MetadataLtv::streamingAudioContexts) {
243       auto aidl_contexts = entry->get<
244               ::aidl::android::hardware::bluetooth::audio::MetadataLtv::streamingAudioContexts>();
245       cfg.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
246               (uint16_t)aidl_contexts.values.bitmask);
247 
248     } else if (entry->getTag() ==
249                ::aidl::android::hardware::bluetooth::audio::MetadataLtv::vendorSpecific) {
250       auto aidl_vendor_data = entry->get<
251               ::aidl::android::hardware::bluetooth::audio::MetadataLtv::vendorSpecific>();
252       cfg.Add(bluetooth::le_audio::types::kLeAudioMetadataTypeVendorSpecific,
253               aidl_vendor_data.companyId, aidl_vendor_data.opaqueValue);
254     }
255   }
256   return cfg;
257 }
258 
259 std::optional<
260         std::vector<std::optional<::aidl::android::hardware::bluetooth::audio::
261                                           IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>
GetAidlLeAudioDeviceCapabilitiesFromStackFormat(const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>> & pacs)262 GetAidlLeAudioDeviceCapabilitiesFromStackFormat(
263         const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>& pacs) {
264   std::vector<std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
265                                     LeAudioDeviceCapabilities>>
266           caps;
267 
268   if (pacs.has_value()) {
269     for (auto const& rec : pacs.value()) {
270       ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
271               LeAudioDeviceCapabilities cap;
272       cap.codecId = GetAidlCodecIdFromStackFormat(rec.codec_id);
273 
274       cap.codecSpecificCapabilities = GetAidlCodecCapabilitiesFromStack(rec.codec_spec_caps);
275 
276       cap.vendorCodecSpecificCapabilities =
277               (rec.codec_spec_caps_raw.empty()
278                        ? std::nullopt
279                        : std::optional<std::vector<uint8_t>>(rec.codec_spec_caps_raw));
280       cap.metadata = GetAidlMetadataFromStackFormat(rec.metadata);
281       caps.push_back(cap);
282     }
283   }
284   return caps.empty() ? std::nullopt
285                       : std::optional<std::vector<std::optional<
286                                 ::aidl::android::hardware::bluetooth::audio::
287                                         IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>(caps);
288 }
289 
GetStackLeAudioLtvMapFromAidlFormat(const std::vector<::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv> & aidl_config_ltvs)290 ::bluetooth::le_audio::types::LeAudioLtvMap GetStackLeAudioLtvMapFromAidlFormat(
291         const std::vector<
292                 ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv>&
293                 aidl_config_ltvs) {
294   ::bluetooth::le_audio::types::LeAudioLtvMap stack_ltv;
295   for (auto const& ltv : aidl_config_ltvs) {
296     switch (ltv.getTag()) {
297       case ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::Tag::
298               codecFrameBlocksPerSDU:
299         stack_ltv.Add(
300                 ::bluetooth::le_audio::codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
301                 (uint8_t)ltv
302                         .get<::aidl::android::hardware::bluetooth::audio::
303                                      CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU>()
304                         .value);
305         break;
306       case ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::Tag::
307               samplingFrequency:
308         stack_ltv.Add(
309                 ::bluetooth::le_audio::codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
310                 (uint8_t)ltv.get<::aidl::android::hardware::bluetooth::audio::
311                                          CodecSpecificConfigurationLtv::Tag::samplingFrequency>());
312         break;
313       case ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::Tag::
314               frameDuration:
315         stack_ltv.Add(
316                 ::bluetooth::le_audio::codec_spec_conf::kLeAudioLtvTypeFrameDuration,
317                 (uint8_t)ltv.get<::aidl::android::hardware::bluetooth::audio::
318                                          CodecSpecificConfigurationLtv::Tag::frameDuration>());
319         break;
320       case ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::Tag::
321               audioChannelAllocation:
322         stack_ltv.Add(
323                 ::bluetooth::le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
324                 (uint32_t)ltv
325                         .get<::aidl::android::hardware::bluetooth::audio::
326                                      CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
327                         .bitmask);
328         break;
329       case ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv::Tag::
330               octetsPerCodecFrame:
331         stack_ltv.Add(
332                 ::bluetooth::le_audio::codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
333                 (uint16_t)ltv
334                         .get<::aidl::android::hardware::bluetooth::audio::
335                                      CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>()
336                         .value);
337         break;
338       default:
339         break;
340     }
341   }
342   return stack_ltv;
343 }
344 
GetStackBisConfigFromAidlFormat(const::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration & aidl_cfg,::bluetooth::le_audio::types::LeAudioCodecId & out_codec_id)345 ::bluetooth::le_audio::broadcaster::BroadcastSubgroupBisCodecConfig GetStackBisConfigFromAidlFormat(
346         const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
347                 LeAudioSubgroupBisConfiguration& aidl_cfg,
348         ::bluetooth::le_audio::types::LeAudioCodecId& out_codec_id) {
349   out_codec_id = GetStackCodecIdFromAidlFormat(aidl_cfg.bisConfiguration.codecId);
350 
351   // Note: Using the hardcoded value for now - the BIS allocated channel
352   uint8_t bis_channel_cnt = 1;
353 
354   // Note: No support for the metadata at the BIS level in the BT stack yet.
355 
356   return ::bluetooth::le_audio::broadcaster::BroadcastSubgroupBisCodecConfig(
357           aidl_cfg.numBis, bis_channel_cnt,
358           GetStackLeAudioLtvMapFromAidlFormat(aidl_cfg.bisConfiguration.codecConfiguration),
359           aidl_cfg.bisConfiguration.vendorCodecConfiguration.empty()
360                   ? std::nullopt
361                   : std::optional<std::vector<uint8_t>>(
362                             aidl_cfg.bisConfiguration.vendorCodecConfiguration));
363 }
364 
365 std::vector<::bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig>
GetStackSubgroupsFromAidlFormat(const std::vector<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration> & aidl_subgroups)366 GetStackSubgroupsFromAidlFormat(
367         const std::vector<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
368                                   LeAudioBroadcastSubgroupConfiguration>& aidl_subgroups) {
369   std::vector<::bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig> vec;
370   for (const auto& subgroup : aidl_subgroups) {
371     std::vector<::bluetooth::le_audio::broadcaster::BroadcastSubgroupBisCodecConfig>
372             bis_codec_configs;
373     ::bluetooth::le_audio::types::LeAudioCodecId codec_id;
374     for (auto const& bis_cfg : subgroup.bisConfigurations) {
375       bis_codec_configs.push_back(GetStackBisConfigFromAidlFormat(bis_cfg, codec_id));
376     }
377 
378     uint8_t bits_per_sample = 16;  // Note: Irrelevant for the offloader
379     ::bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig stack_subgroup(
380             codec_id, bis_codec_configs, bits_per_sample, subgroup.vendorCodecConfiguration);
381     vec.push_back(stack_subgroup);
382   }
383   return vec;
384 }
385 
386 std::optional<::bluetooth::le_audio::broadcaster::BroadcastConfiguration>
GetStackBroadcastConfigurationFromAidlFormat(const::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting & setting)387 GetStackBroadcastConfigurationFromAidlFormat(
388         const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
389                 LeAudioBroadcastConfigurationSetting& setting) {
390   ::bluetooth::le_audio::broadcaster::BroadcastConfiguration cfg{
391           .subgroups = GetStackSubgroupsFromAidlFormat(setting.subgroupsConfigurations),
392           .qos = ::bluetooth::le_audio::broadcaster::BroadcastQosConfig(
393                   setting.retransmitionNum, setting.maxTransportLatencyMs),
394           .data_path = GetStackDataPathFromAidlFormat(*setting.dataPathConfiguration),
395           .sduIntervalUs = (uint32_t)setting.sduIntervalUs,
396           .maxSduOctets = (uint16_t)setting.maxSduOctets,
397           .phy = 0,  // recomputed later on
398           .packing = (uint8_t)setting.packing,
399           .framing = (uint8_t)setting.framing,
400   };
401 
402   for (auto phy : setting.phy) {
403     cfg.phy |= static_cast<int8_t>(phy);
404   }
405 
406   return std::move(cfg);
407 }
408 
GetStackQosConfigSettingFromAidl(const std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioAseQosConfiguration> & aidl_qos,::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration::TargetLatency target_latency)409 static ::bluetooth::le_audio::set_configurations::QosConfigSetting GetStackQosConfigSettingFromAidl(
410         const std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
411                                     LeAudioAseQosConfiguration>& aidl_qos,
412         ::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration::TargetLatency
413                 target_latency) {
414   auto config = ::bluetooth::le_audio::set_configurations::QosConfigSetting();
415   if (aidl_qos.has_value()) {
416     config.sduIntervalUs = aidl_qos->sduIntervalUs;
417     config.max_transport_latency = aidl_qos->maxTransportLatencyMs;
418     config.maxSdu = aidl_qos->maxSdu;
419     config.retransmission_number = aidl_qos->retransmissionNum;
420   }
421   config.target_latency = (uint8_t)target_latency;
422 
423   return config;
424 }
425 
GetCodecConfigSettingFromAidl(const std::optional<::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration> & ase_config)426 static ::bluetooth::le_audio::set_configurations::CodecConfigSetting GetCodecConfigSettingFromAidl(
427         const std::optional<::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration>&
428                 ase_config) {
429   auto stack_config = ::bluetooth::le_audio::set_configurations::CodecConfigSetting();
430 
431   if (ase_config.has_value()) {
432     if (ase_config->codecId.has_value()) {
433       stack_config.id = GetStackCodecIdFromAidlFormat(ase_config->codecId.value());
434     }
435     if (ase_config->vendorCodecConfiguration.has_value()) {
436       stack_config.vendor_params = ase_config->vendorCodecConfiguration.value();
437     }
438 
439     if (!ase_config->codecConfiguration.empty()) {
440       stack_config.params = GetStackLeAudioLtvMapFromAidlFormat(ase_config->codecConfiguration);
441       auto cfg = stack_config.params.GetAsCoreCodecConfig();
442       if (cfg.audio_channel_allocation.has_value()) {
443         auto allocation_bitset = std::bitset<32>(cfg.audio_channel_allocation.value());
444         // Value of 0x00000000 means MonoAudio - one channel per iso stream
445         stack_config.channel_count_per_iso_stream =
446                 allocation_bitset.any() ? allocation_bitset.count() : 1;
447       }
448     }
449   }
450 
451   return stack_config;
452 }
453 
GetStackDataPathFromAidlFormat(const::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioDataPathConfiguration & dp)454 ::bluetooth::le_audio::types::DataPathConfiguration GetStackDataPathFromAidlFormat(
455         const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
456                 LeAudioDataPathConfiguration& dp) {
457   auto config = ::bluetooth::le_audio::types::DataPathConfiguration{
458           .dataPathId = static_cast<uint8_t>(dp.dataPathId),
459           .dataPathConfig = {},
460           .isoDataPathConfig = {
461                   .codecId = GetStackCodecIdFromAidlFormat(dp.isoDataPathConfiguration.codecId),
462                   .isTransparent = dp.isoDataPathConfiguration.isTransparent,
463                   .controllerDelayUs = (uint32_t)dp.isoDataPathConfiguration.controllerDelayUs,
464                   .configuration = {},
465           }};
466 
467   // Due to AIDL not having the Transparent codec type, it uses the boolean and
468   // we should manually align the codecId.
469   if (config.isoDataPathConfig.isTransparent) {
470     config.isoDataPathConfig.codecId.coding_format = 0x03;  // Transparent
471     config.isoDataPathConfig.codecId.vendor_codec_id = 0x00;
472     config.isoDataPathConfig.codecId.vendor_company_id = 0x00;
473   }
474 
475   if (dp.dataPathConfiguration.configuration) {
476     config.dataPathConfig = *dp.dataPathConfiguration.configuration;
477   }
478 
479   // Due to AIDL not having the Transparent codec type, it uses the boolean and
480   // we should manually align the codecId.
481   if (config.isoDataPathConfig.isTransparent) {
482     config.isoDataPathConfig.codecId.coding_format = bluetooth::hci::kIsoCodingFormatTransparent;
483     config.isoDataPathConfig.codecId.vendor_codec_id = 0x00;
484     config.isoDataPathConfig.codecId.vendor_company_id = 0x00;
485   }
486 
487   if (dp.isoDataPathConfiguration.configuration) {
488     config.isoDataPathConfig.configuration = *dp.isoDataPathConfiguration.configuration;
489   }
490 
491   return config;
492 }
493 
494 // The number of source entries is the total count of ASEs within the group to
495 // be configured
GetStackAseConfigurationFromAidl(const::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioAseConfigurationSetting::AseDirectionConfiguration & source)496 static ::bluetooth::le_audio::set_configurations::AseConfiguration GetStackAseConfigurationFromAidl(
497         const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
498                 LeAudioAseConfigurationSetting::AseDirectionConfiguration& source) {
499   auto stack_qos = GetStackQosConfigSettingFromAidl(source.qosConfiguration,
500                                                     source.aseConfiguration.targetLatency);
501 
502   auto config = ::bluetooth::le_audio::set_configurations::AseConfiguration(
503           GetCodecConfigSettingFromAidl(source.aseConfiguration), stack_qos);
504   if (source.dataPathConfiguration.has_value()) {
505     config.data_path_configuration = GetStackDataPathFromAidlFormat(*source.dataPathConfiguration);
506   }
507   return config;
508 }
509 
GenerateNameForConfig(const::bluetooth::le_audio::set_configurations::AudioSetConfiguration & config)510 static std::string GenerateNameForConfig(
511         const ::bluetooth::le_audio::set_configurations::AudioSetConfiguration& config) {
512   auto namegen = [](const std::vector<::bluetooth::le_audio::set_configurations::AseConfiguration>&
513                             configs,
514                     const char* dir_str) {
515     std::stringstream cfg_str;
516     if (configs.size() > 0) {
517       auto current_config = configs.begin();
518       while (current_config != configs.end()) {
519         uint8_t cfg_multiplier = 1;
520         auto last_equal_config = current_config;
521         auto current_codec = current_config->codec;
522         while (++last_equal_config != configs.end()) {
523           // For the purpose of name generation, ignore the audio channel allocation
524           auto current_codec_no_channels = current_codec;
525           auto last_codec_no_channels = last_equal_config->codec;
526           current_codec_no_channels.params.Add(
527                   le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, (uint32_t)0);
528           last_codec_no_channels.params.Add(
529                   le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation, (uint32_t)0);
530 
531           if (current_codec_no_channels != last_codec_no_channels) {
532             break;
533           }
534           ++cfg_multiplier;
535           current_config = last_equal_config;
536         }
537 
538         // Channel configuration
539         cfg_str << +cfg_multiplier << "-" << +current_codec.GetChannelCountPerIsoStream() << "chan";
540         cfg_str << "-" << dir_str << "Ase-";
541         // Codec Id
542         cfg_str << "CodecId_" << +current_codec.id.coding_format << "_"
543                 << +current_codec.id.vendor_company_id << "_" << +current_codec.id.vendor_codec_id
544                 << "-";
545         // Codec parameters
546         cfg_str << current_codec.GetSamplingFrequencyHz() << "hz";
547         if (current_codec.id.coding_format ==
548             ::bluetooth::le_audio::types::kLeAudioCodingFormatLC3) {
549           cfg_str << "_" << current_codec.GetOctetsPerFrame() << "oct";
550           cfg_str << "_" << current_codec.GetDataIntervalUs() << "us";
551         }
552         // QoS
553         cfg_str << "-TargetLatency_" << +current_config->qos.target_latency;
554 
555         if (last_equal_config == configs.end()) {
556           break;
557         }
558 
559         // Check if there are some different configs left
560         ++current_config;
561       }
562     }
563     return cfg_str.str();
564   };
565 
566   std::stringstream name;
567   name << "AIDL";
568   if (!config.confs.sink.empty()) {
569     name << "-" << namegen(config.confs.sink, "Sink");
570   }
571   if (!config.confs.source.empty()) {
572     name << "-" << namegen(config.confs.source, "Source");
573   }
574   return name.str();
575 }
576 
577 static ::bluetooth::le_audio::set_configurations::AudioSetConfiguration
GetStackConfigSettingFromAidl(::bluetooth::le_audio::types::LeAudioContextType ctx_type,const::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioAseConfigurationSetting & aidl_ase_config)578 GetStackConfigSettingFromAidl(
579         ::bluetooth::le_audio::types::LeAudioContextType ctx_type,
580         const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
581                 LeAudioAseConfigurationSetting& aidl_ase_config) {
582   /* Verify the returned audio context and report if not matching */
583   if (aidl_ase_config.audioContext.bitmask != (uint16_t)ctx_type) {
584     log::error("Audio Context mismatch. Expected {}, but received: {}", (int)ctx_type,
585                aidl_ase_config.audioContext.bitmask);
586   }
587 
588   ::bluetooth::le_audio::set_configurations::AudioSetConfiguration cig_config{
589           .name = "AIDL codec provider configuration",
590           .packing = (uint8_t)aidl_ase_config.packing,
591           .confs = {.sink = {}, .source = {}},
592   };
593 
594   if (aidl_ase_config.sinkAseConfiguration) {
595     for (auto const& entry : *aidl_ase_config.sinkAseConfiguration) {
596       if (entry) {
597         cig_config.confs.sink.push_back(GetStackAseConfigurationFromAidl(*entry));
598       }
599     }
600   }
601 
602   if (aidl_ase_config.sourceAseConfiguration) {
603     for (auto const& entry : *aidl_ase_config.sourceAseConfiguration) {
604       if (entry) {
605         cig_config.confs.source.push_back(GetStackAseConfigurationFromAidl(*entry));
606       }
607     }
608   }
609 
610   cig_config.name = GenerateNameForConfig(cig_config);
611   return cig_config;
612 }
613 
614 std::optional<::bluetooth::le_audio::set_configurations::AudioSetConfiguration>
GetStackUnicastConfigurationFromAidlFormat(::bluetooth::le_audio::types::LeAudioContextType ctx_type,const::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::LeAudioAseConfigurationSetting & config)615 GetStackUnicastConfigurationFromAidlFormat(
616         ::bluetooth::le_audio::types::LeAudioContextType ctx_type,
617         const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
618                 LeAudioAseConfigurationSetting& config) {
619   auto stack_config = GetStackConfigSettingFromAidl(ctx_type, config);
620 
621   if (stack_config.confs.sink.empty() && stack_config.confs.source.empty()) {
622     log::error("Unexpected empty sink and source configurations!");
623     return std::nullopt;
624   }
625   return stack_config;
626 }
627 
628 ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
629         LeAudioBroadcastConfigurationRequirement
GetAidlLeAudioBroadcastConfigurationRequirementFromStackFormat(const std::vector<std::pair<::bluetooth::le_audio::types::LeAudioContextType,uint8_t>> & subgroup_quality)630         GetAidlLeAudioBroadcastConfigurationRequirementFromStackFormat(
631                 const std::vector<std::pair<::bluetooth::le_audio::types::LeAudioContextType,
632                                             uint8_t>>& subgroup_quality) {
633   auto aidl_requirements = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
634           LeAudioBroadcastConfigurationRequirement();
635 
636   for (auto const& [context, quality] : subgroup_quality) {
637     ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
638             LeAudioBroadcastSubgroupConfigurationRequirement req;
639     req.audioContext.bitmask = static_cast<uint16_t>(context);
640 
641     // Note: Currently there is no equivalent of this in the stack data format
642     req.bisNumPerSubgroup = 2;
643 
644     if (quality == le_audio::QUALITY_STANDARD) {
645       req.quality = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
646               BroadcastQuality::STANDARD;
647     } else if (quality == le_audio::QUALITY_HIGH) {
648       req.quality = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
649               BroadcastQuality::HIGH;
650     }
651 
652     aidl_requirements.subgroupConfigurationRequirements.push_back(req);
653   }
654 
655   return aidl_requirements;
656 }
657 
658 ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
659         LeAudioConfigurationRequirement
GetAidlLeAudioUnicastConfigurationRequirementsFromStackFormat(::bluetooth::le_audio::types::LeAudioContextType context_type,const std::optional<std::vector<::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements::DeviceDirectionRequirements>> & sink_reqs,const std::optional<std::vector<::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements::DeviceDirectionRequirements>> & source_reqs)660         GetAidlLeAudioUnicastConfigurationRequirementsFromStackFormat(
661                 ::bluetooth::le_audio::types::LeAudioContextType context_type,
662                 const std::optional<std::vector<
663                         ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements::
664                                 DeviceDirectionRequirements>>& sink_reqs,
665                 const std::optional<std::vector<
666                         ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements::
667                                 DeviceDirectionRequirements>>& source_reqs) {
668   auto aidl_reqs = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
669           LeAudioConfigurationRequirement();
670 
671   if (sink_reqs) {
672     aidl_reqs.sinkAseRequirement = std::make_optional<std::vector<
673             std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
674                                   LeAudioConfigurationRequirement::AseDirectionRequirement>>>();
675 
676     for (auto const& stack_req : *sink_reqs) {
677       auto aidl_req = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
678               LeAudioConfigurationRequirement::AseDirectionRequirement();
679       aidl_req.aseConfiguration.targetLatency = static_cast<
680               ::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration::TargetLatency>(
681               stack_req.target_latency);
682       aidl_req.aseConfiguration.targetPhy =
683               static_cast<::aidl::android::hardware::bluetooth::audio::Phy>(stack_req.target_Phy);
684 
685       // TODO(b/341936031): Add the codec enforcement mechanism in the stack
686       // aidl_req.aseConfiguration.codecId =
687       // GetAidlCodecIdFromStackFormat(stack_req.codecId);
688       aidl_req.aseConfiguration.codecConfiguration =
689               GetAidlCodecSpecificConfigurationFromStack(stack_req.params);
690 
691       aidl_reqs.sinkAseRequirement->push_back(aidl_req);
692     }
693   }
694 
695   if (source_reqs) {
696     aidl_reqs.sourceAseRequirement = std::make_optional<std::vector<
697             std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
698                                   LeAudioConfigurationRequirement::AseDirectionRequirement>>>();
699 
700     for (auto const& stack_req : *source_reqs) {
701       auto aidl_req = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
702               LeAudioConfigurationRequirement::AseDirectionRequirement();
703       aidl_req.aseConfiguration.targetLatency = static_cast<
704               ::aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration::TargetLatency>(
705               stack_req.target_latency);
706       aidl_req.aseConfiguration.targetPhy =
707               static_cast<::aidl::android::hardware::bluetooth::audio::Phy>(stack_req.target_Phy);
708 
709       // TODO(b/341936031): Add the codec enforcement mechanism in the stack
710       // aidl_req.aseConfiguration.codecId =
711       // GetAidlCodecIdFromStackFormat(stack_req.codecId);
712       aidl_req.aseConfiguration.codecConfiguration =
713               GetAidlCodecSpecificConfigurationFromStack(stack_req.params);
714 
715       aidl_reqs.sourceAseRequirement->push_back(aidl_req);
716     }
717   }
718 
719   // Context type values match exactly
720   aidl_reqs.audioContext.bitmask = (uint32_t)context_type;
721 
722   // TODO(b/341935895): Add the feature flags mechanism in the stack
723   // aidl_reqs.flags
724 
725   return aidl_reqs;
726 }
727 
728 }  // namespace aidl
729 }  // namespace audio
730 }  // namespace bluetooth
731