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