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