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