1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "le_audio_utils.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include "common/strings.h"
22 #include "le_audio_types.h"
23 #include "os/log.h"
24 
25 using bluetooth::common::ToString;
26 using bluetooth::le_audio::types::AudioContexts;
27 using bluetooth::le_audio::types::LeAudioContextType;
28 
29 namespace fmt {
30 template <>
31 struct formatter<audio_usage_t> : enum_formatter<audio_usage_t> {};
32 template <>
33 struct formatter<audio_content_type_t> : enum_formatter<audio_content_type_t> {
34 };
35 template <>
36 struct formatter<audio_source_t> : enum_formatter<audio_source_t> {};
37 template <>
38 struct formatter<audio_devices_t> : enum_formatter<audio_devices_t> {};
39 }  // namespace fmt
40 
41 namespace bluetooth::le_audio {
42 namespace utils {
43 
44 /* The returned LeAudioContextType should have its entry in the
45  * AudioSetConfigurationProvider's ContextTypeToScenario mapping table.
46  * Otherwise the AudioSetConfigurationProvider will fall back
47  * to default scenario.
48  */
AudioContentToLeAudioContext(audio_content_type_t content_type,audio_usage_t usage)49 LeAudioContextType AudioContentToLeAudioContext(
50     audio_content_type_t content_type, audio_usage_t usage) {
51   /* Check audio attribute usage of stream */
52   switch (usage) {
53     case AUDIO_USAGE_MEDIA:
54       return LeAudioContextType::MEDIA;
55     case AUDIO_USAGE_ASSISTANT:
56       return LeAudioContextType::VOICEASSISTANTS;
57     case AUDIO_USAGE_VOICE_COMMUNICATION:
58     case AUDIO_USAGE_CALL_ASSISTANT:
59       return LeAudioContextType::CONVERSATIONAL;
60     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
61       if (content_type == AUDIO_CONTENT_TYPE_SPEECH) {
62         return LeAudioContextType::CONVERSATIONAL;
63       }
64 
65       if (content_type == AUDIO_CONTENT_TYPE_SONIFICATION) {
66         return LeAudioContextType::RINGTONE;
67       }
68 
69       return LeAudioContextType::MEDIA;
70     case AUDIO_USAGE_GAME:
71       return LeAudioContextType::GAME;
72     case AUDIO_USAGE_NOTIFICATION:
73       return LeAudioContextType::NOTIFICATIONS;
74     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
75       return LeAudioContextType::RINGTONE;
76     case AUDIO_USAGE_ALARM:
77       return LeAudioContextType::ALERTS;
78     case AUDIO_USAGE_EMERGENCY:
79       return LeAudioContextType::EMERGENCYALARM;
80     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
81       return LeAudioContextType::INSTRUCTIONAL;
82     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
83       return LeAudioContextType::SOUNDEFFECTS;
84     default:
85       break;
86   }
87 
88   return LeAudioContextType::MEDIA;
89 }
90 
usageToString(audio_usage_t usage)91 static std::string usageToString(audio_usage_t usage) {
92   switch (usage) {
93     case AUDIO_USAGE_UNKNOWN:
94       return "USAGE_UNKNOWN";
95     case AUDIO_USAGE_MEDIA:
96       return "USAGE_MEDIA";
97     case AUDIO_USAGE_VOICE_COMMUNICATION:
98       return "USAGE_VOICE_COMMUNICATION";
99     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
100       return "USAGE_VOICE_COMMUNICATION_SIGNALLING";
101     case AUDIO_USAGE_ALARM:
102       return "USAGE_ALARM";
103     case AUDIO_USAGE_NOTIFICATION:
104       return "USAGE_NOTIFICATION";
105     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
106       return "USAGE_NOTIFICATION_TELEPHONY_RINGTONE";
107     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
108       return "USAGE_NOTIFICATION_COMMUNICATION_REQUEST";
109     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
110       return "USAGE_NOTIFICATION_COMMUNICATION_INSTANT";
111     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
112       return "USAGE_NOTIFICATION_COMMUNICATION_DELAYED";
113     case AUDIO_USAGE_NOTIFICATION_EVENT:
114       return "USAGE_NOTIFICATION_EVENT";
115     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
116       return "USAGE_ASSISTANCE_ACCESSIBILITY";
117     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
118       return "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE";
119     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
120       return "USAGE_ASSISTANCE_SONIFICATION";
121     case AUDIO_USAGE_GAME:
122       return "USAGE_GAME";
123     case AUDIO_USAGE_ASSISTANT:
124       return "USAGE_ASSISTANT";
125     case AUDIO_USAGE_CALL_ASSISTANT:
126       return "USAGE_CALL_ASSISTANT";
127     case AUDIO_USAGE_EMERGENCY:
128       return "USAGE_EMERGENCY";
129     case AUDIO_USAGE_SAFETY:
130       return "USAGE_SAFETY";
131     case AUDIO_USAGE_VEHICLE_STATUS:
132       return "USAGE_VEHICLE_STATUS";
133     case AUDIO_USAGE_ANNOUNCEMENT:
134       return "USAGE_ANNOUNCEMENT";
135     default:
136       return "unknown usage ";
137   }
138 }
139 
contentTypeToString(audio_content_type_t content_type)140 static std::string contentTypeToString(audio_content_type_t content_type) {
141   switch (content_type) {
142     case AUDIO_CONTENT_TYPE_UNKNOWN:
143       return "CONTENT_TYPE_UNKNOWN";
144     case AUDIO_CONTENT_TYPE_SPEECH:
145       return "CONTENT_TYPE_SPEECH";
146     case AUDIO_CONTENT_TYPE_MUSIC:
147       return "CONTENT_TYPE_MUSIC";
148     case AUDIO_CONTENT_TYPE_MOVIE:
149       return "CONTENT_TYPE_MOVIE";
150     case AUDIO_CONTENT_TYPE_SONIFICATION:
151       return "CONTENT_TYPE_SONIFICATION";
152     default:
153       return "unknown content type ";
154   }
155 }
156 
audioSourceToStr(audio_source_t source)157 static const char* audioSourceToStr(audio_source_t source) {
158   const char* strArr[] = {
159       "AUDIO_SOURCE_DEFAULT",           "AUDIO_SOURCE_MIC",
160       "AUDIO_SOURCE_VOICE_UPLINK",      "AUDIO_SOURCE_VOICE_DOWNLINK",
161       "AUDIO_SOURCE_VOICE_CALL",        "AUDIO_SOURCE_CAMCORDER",
162       "AUDIO_SOURCE_VOICE_RECOGNITION", "AUDIO_SOURCE_VOICE_COMMUNICATION",
163       "AUDIO_SOURCE_REMOTE_SUBMIX",     "AUDIO_SOURCE_UNPROCESSED",
164       "AUDIO_SOURCE_VOICE_PERFORMANCE"};
165 
166   if (static_cast<uint32_t>(source) < (sizeof(strArr) / sizeof(strArr[0])))
167     return strArr[source];
168   return "UNKNOWN";
169 }
170 
isMetadataTagPresent(const char * tags,const char * tag)171 static bool isMetadataTagPresent(const char* tags, const char* tag) {
172   std::istringstream iss(tags);
173   std::string t;
174   while (std::getline(iss, t, AUDIO_ATTRIBUTES_TAGS_SEPARATOR)) {
175     log::verbose("Tag {}", t);
176     if (t.compare(tag) == 0) {
177       return true;
178     }
179   }
180   return false;
181 }
182 
GetAudioContextsFromSourceMetadata(const std::vector<struct playback_track_metadata_v7> & source_metadata)183 AudioContexts GetAudioContextsFromSourceMetadata(
184     const std::vector<struct playback_track_metadata_v7>& source_metadata) {
185   AudioContexts track_contexts;
186   for (const auto& entry : source_metadata) {
187     auto track = entry.base;
188     if (track.content_type == 0 && track.usage == 0) continue;
189 
190     log::info("usage={}({}), content_type={}({}), gain={:f}, tag:{}",
191               usageToString(track.usage), track.usage,
192               contentTypeToString(track.content_type),
193               track.content_type, track.gain, entry.tags);
194 
195     if (isMetadataTagPresent(entry.tags, "VX_AOSP_SAMPLESOUND")) {
196       track_contexts.set(LeAudioContextType::SOUNDEFFECTS);
197     } else {
198       track_contexts.set(
199           AudioContentToLeAudioContext(track.content_type, track.usage));
200     }
201   }
202   return track_contexts;
203 }
204 
GetAudioContextsFromSinkMetadata(const std::vector<struct record_track_metadata_v7> & sink_metadata)205 AudioContexts GetAudioContextsFromSinkMetadata(
206     const std::vector<struct record_track_metadata_v7>& sink_metadata) {
207   AudioContexts all_track_contexts;
208 
209   for (const auto& entry : sink_metadata) {
210     auto track = entry.base;
211     if (track.source == AUDIO_SOURCE_INVALID) continue;
212     LeAudioContextType track_context;
213 
214     log::debug(
215         "source={}(0x{:02x}), gain={:f}, destination device=0x{:08x}, "
216         "destination device address={:32s}",
217         audioSourceToStr(track.source), track.source, track.gain,
218         track.dest_device, track.dest_device_address);
219 
220     if (track.source == AUDIO_SOURCE_MIC) {
221       track_context = LeAudioContextType::LIVE;
222 
223     } else if (track.source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
224       track_context = LeAudioContextType::CONVERSATIONAL;
225 
226     } else {
227       /* Fallback to voice assistant
228        * This will handle also a case when the device is
229        * AUDIO_SOURCE_VOICE_RECOGNITION
230        */
231       track_context = LeAudioContextType::VOICEASSISTANTS;
232       log::warn(
233           "Could not match the recording track type to group available "
234           "context. Using context {}.",
235           ToString(track_context));
236     }
237 
238     all_track_contexts.set(track_context);
239   }
240 
241   if (all_track_contexts.none()) {
242     all_track_contexts = AudioContexts(
243         static_cast<std::underlying_type<LeAudioContextType>::type>(
244             LeAudioContextType::UNSPECIFIED));
245     log::debug(
246         "Unable to find supported audio source context for the remote audio "
247         "sink device. This may result in voice back channel malfunction.");
248   }
249 
250   log::info("Allowed contexts from sink metadata: {} (0x{:08x})",
251             bluetooth::common::ToString(all_track_contexts),
252             all_track_contexts.value());
253   return all_track_contexts;
254 }
255 
256 bluetooth::le_audio::btle_audio_codec_index_t
translateBluetoothCodecFormatToCodecType(uint8_t codec_format)257 translateBluetoothCodecFormatToCodecType(uint8_t codec_format) {
258   switch (codec_format) {
259     case types::kLeAudioCodingFormatLC3:
260       return bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3;
261   }
262   return bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_INVALID;
263 }
264 
265 bluetooth::le_audio::btle_audio_sample_rate_index_t
translateToBtLeAudioCodecConfigSampleRate(uint32_t sample_rate)266 translateToBtLeAudioCodecConfigSampleRate(uint32_t sample_rate) {
267   log::info("{}", sample_rate);
268   switch (sample_rate) {
269     case LeAudioCodecConfiguration::kSampleRate8000:
270       return LE_AUDIO_SAMPLE_RATE_INDEX_8000HZ;
271     case LeAudioCodecConfiguration::kSampleRate16000:
272       return LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ;
273     case LeAudioCodecConfiguration::kSampleRate24000:
274       return LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ;
275     case LeAudioCodecConfiguration::kSampleRate32000:
276       return LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ;
277     case LeAudioCodecConfiguration::kSampleRate44100:
278       return LE_AUDIO_SAMPLE_RATE_INDEX_44100HZ;
279     case LeAudioCodecConfiguration::kSampleRate48000:
280       return LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ;
281   }
282 
283   return LE_AUDIO_SAMPLE_RATE_INDEX_NONE;
284 }
285 
286 bluetooth::le_audio::btle_audio_bits_per_sample_index_t
translateToBtLeAudioCodecConfigBitPerSample(uint8_t bits_per_sample)287 translateToBtLeAudioCodecConfigBitPerSample(uint8_t bits_per_sample) {
288   switch (bits_per_sample) {
289     case 16:
290       return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_16;
291     case 24:
292       return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_24;
293     case 32:
294       return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_32;
295   }
296   return bluetooth::le_audio::LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE;
297 }
298 
299 bluetooth::le_audio::btle_audio_channel_count_index_t
translateToBtLeAudioCodecConfigChannelCount(uint8_t channel_count)300 translateToBtLeAudioCodecConfigChannelCount(uint8_t channel_count) {
301   switch (channel_count) {
302     case 1:
303       return bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_1;
304     case 2:
305       return bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_2;
306   }
307   return bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_NONE;
308 }
309 
310 bluetooth::le_audio::btle_audio_frame_duration_index_t
translateToBtLeAudioCodecConfigFrameDuration(int frame_duration)311 translateToBtLeAudioCodecConfigFrameDuration(int frame_duration) {
312   switch (frame_duration) {
313     case 7500:
314       return bluetooth::le_audio::LE_AUDIO_FRAME_DURATION_INDEX_7500US;
315     case 10000:
316       return bluetooth::le_audio::LE_AUDIO_FRAME_DURATION_INDEX_10000US;
317   }
318   return bluetooth::le_audio::LE_AUDIO_FRAME_DURATION_INDEX_NONE;
319 }
320 
fillStreamParamsToBtLeAudioCodecConfig(const std::vector<struct set_configurations::AseConfiguration> & confs,bluetooth::le_audio::btle_audio_codec_config_t & out_config)321 void fillStreamParamsToBtLeAudioCodecConfig(
322     const std::vector<struct set_configurations::AseConfiguration>& confs,
323     bluetooth::le_audio::btle_audio_codec_config_t& out_config) {
324   if (confs.size() == 0) {
325     log::warn("Stream params are null");
326     return;
327   }
328 
329   auto config = confs.at(0).codec;
330 
331   out_config.codec_type =
332       translateBluetoothCodecFormatToCodecType(config.id.coding_format);
333   if (out_config.codec_type !=
334       bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3) {
335     return;
336   }
337 
338   out_config.sample_rate = translateToBtLeAudioCodecConfigSampleRate(
339       config.GetSamplingFrequencyHz());
340   out_config.bits_per_sample = translateToBtLeAudioCodecConfigBitPerSample(16);
341   out_config.frame_duration =
342       translateToBtLeAudioCodecConfigFrameDuration(config.GetDataIntervalUs());
343   out_config.octets_per_frame = config.GetOctectsPerFrame();
344   out_config.channel_count = translateToBtLeAudioCodecConfigChannelCount(
345       config.GetChannelCountPerIsoStream());
346 }
347 
is_known_codec(const types::LeAudioCodecId & codec_id)348 static bool is_known_codec(const types::LeAudioCodecId& codec_id) {
349   switch (codec_id.coding_format) {
350     case types::kLeAudioCodingFormatLC3:
351       return true;
352   }
353   return false;
354 }
355 
fillRemotePacsCapabitiliesToBtLeAudioCodecConfig(const struct types::acs_ac_record & record,std::vector<bluetooth::le_audio::btle_audio_codec_config_t> & vec)356 static void fillRemotePacsCapabitiliesToBtLeAudioCodecConfig(
357     const struct types::acs_ac_record& record,
358     std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& vec) {
359   if (!utils::IsCodecUsingLtvFormat(record.codec_id)) {
360     log::warn(
361         "Unknown codec capability format. Unable to report known codec "
362         "parameters.");
363     return;
364   }
365   log::assert_that(!record.codec_spec_caps.IsEmpty(),
366                    "Codec specific capabilities are not parsed approprietly.");
367 
368   const struct types::LeAudioCoreCodecCapabilities capa =
369       record.codec_spec_caps.GetAsCoreCodecCapabilities();
370   for (uint8_t freq_bit = codec_spec_conf::kLeAudioSamplingFreq8000Hz;
371        freq_bit <= codec_spec_conf::kLeAudioSamplingFreq384000Hz; freq_bit++) {
372     if (!capa.IsSamplingFrequencyConfigSupported(freq_bit)) continue;
373     for (uint8_t fd_bit = codec_spec_conf::kLeAudioCodecFrameDur7500us;
374          fd_bit <= codec_spec_conf::kLeAudioCodecFrameDur10000us; fd_bit++) {
375       if (!capa.IsFrameDurationConfigSupported(fd_bit)) continue;
376       if (!capa.HasSupportedAudioChannelCounts()) {
377         bluetooth::le_audio::btle_audio_codec_config_t config = {
378             .codec_type = utils::translateBluetoothCodecFormatToCodecType(
379                 record.codec_id.coding_format),
380             .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate(
381                 types::LeAudioCoreCodecConfig::GetSamplingFrequencyHz(
382                     freq_bit)),
383             .bits_per_sample =
384                 utils::translateToBtLeAudioCodecConfigBitPerSample(16),
385             .channel_count =
386                 utils::translateToBtLeAudioCodecConfigChannelCount(1),
387             .frame_duration =
388                 utils::translateToBtLeAudioCodecConfigFrameDuration(
389                     types::LeAudioCoreCodecConfig::GetFrameDurationUs(fd_bit)),
390         };
391         vec.push_back(config);
392       } else {
393         for (int chan_bit = 1; chan_bit <= 2; chan_bit++) {
394           if (!capa.IsAudioChannelCountsSupported(chan_bit)) continue;
395 
396           bluetooth::le_audio::btle_audio_codec_config_t config = {
397               .codec_type = utils::translateBluetoothCodecFormatToCodecType(
398                   record.codec_id.coding_format),
399               .sample_rate = utils::translateToBtLeAudioCodecConfigSampleRate(
400                   types::LeAudioCoreCodecConfig::GetSamplingFrequencyHz(
401                       freq_bit)),
402               .bits_per_sample =
403                   utils::translateToBtLeAudioCodecConfigBitPerSample(16),
404               .channel_count =
405                   utils::translateToBtLeAudioCodecConfigChannelCount(chan_bit),
406               .frame_duration =
407                   utils::translateToBtLeAudioCodecConfigFrameDuration(
408                       types::LeAudioCoreCodecConfig::GetFrameDurationUs(
409                           fd_bit)),
410           };
411           vec.push_back(config);
412         }
413       }
414     }
415   }
416 }
417 
418 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
GetRemoteBtLeAudioCodecConfigFromPac(const types::PublishedAudioCapabilities & group_pacs)419 GetRemoteBtLeAudioCodecConfigFromPac(
420     const types::PublishedAudioCapabilities& group_pacs) {
421   std::vector<bluetooth::le_audio::btle_audio_codec_config_t> vec;
422 
423   for (auto& [handles, pacs_record] : group_pacs) {
424     for (auto& pac : pacs_record) {
425       if (!is_known_codec(pac.codec_id)) continue;
426 
427       fillRemotePacsCapabitiliesToBtLeAudioCodecConfig(pac, vec);
428     }
429   }
430   return vec;
431 }
432 
IsCodecUsingLtvFormat(const types::LeAudioCodecId & codec_id)433 bool IsCodecUsingLtvFormat(const types::LeAudioCodecId& codec_id) {
434   if (codec_id == set_configurations::LeAudioCodecIdLc3) {
435     return true;
436   }
437   return false;
438 }
439 
440 ::bluetooth::le_audio::LeAudioCodecConfiguration
GetAudioSessionCodecConfigFromAudioSetConfiguration(const bluetooth::le_audio::set_configurations::AudioSetConfiguration & audio_set_conf,uint8_t remote_direction)441 GetAudioSessionCodecConfigFromAudioSetConfiguration(
442     const bluetooth::le_audio::set_configurations::AudioSetConfiguration&
443         audio_set_conf,
444     uint8_t remote_direction) {
445   /* Note: For now we expect that each ASE in a particular direction needs
446    *       exactly the same audio codec parameters.
447    */
448 
449   LeAudioCodecConfiguration group_config = {0, 0, 0, 0};
450   for (const auto& conf : audio_set_conf.confs.get(remote_direction)) {
451     if (group_config.sample_rate != 0 &&
452         conf.codec.GetSamplingFrequencyHz() != group_config.sample_rate) {
453       log::warn(
454           "Stream configuration could not be determined (multiple, different "
455           "sampling frequencies) for remote_direction: {:#x}",
456           remote_direction);
457       break;
458     }
459     group_config.sample_rate = conf.codec.GetSamplingFrequencyHz();
460 
461     if (group_config.data_interval_us != 0 &&
462         conf.codec.GetDataIntervalUs() != group_config.data_interval_us) {
463       log::warn(
464           "Stream configuration could not be determined (multiple, different "
465           "data intervals) for remote_direction: {:#x}",
466           remote_direction);
467       break;
468     }
469     group_config.data_interval_us = conf.codec.GetDataIntervalUs();
470 
471     if (group_config.bits_per_sample != 0 &&
472         conf.codec.GetBitsPerSample() != group_config.bits_per_sample) {
473       log::warn(
474           "Stream configuration could not be determined (multiple, different "
475           "bits per sample) for remote_direction: {:#x}",
476           remote_direction);
477       break;
478     }
479     group_config.bits_per_sample = conf.codec.GetBitsPerSample();
480     group_config.num_channels += conf.codec.GetChannelCountPerIsoStream();
481   }
482   if (group_config.num_channels > 2) group_config.num_channels = 2;
483 
484   return group_config;
485 }
486 
GetStrategyForAseConfig(const std::vector<le_audio::set_configurations::AseConfiguration> & cfgs,uint8_t device_cnt)487 types::LeAudioConfigurationStrategy GetStrategyForAseConfig(
488     const std::vector<le_audio::set_configurations::AseConfiguration>& cfgs,
489     uint8_t device_cnt) {
490   if (cfgs.size() == 0) {
491     return types::LeAudioConfigurationStrategy::RFU;
492   }
493 
494   /* Banded headphones or the Classic TWS style topology (a single device) */
495   if (device_cnt == 1) {
496     if (cfgs.at(0).codec.GetChannelCountPerIsoStream() == 1) {
497       /* One mono ASE - could be a single channel microphone */
498       if (cfgs.size() == 1) {
499         return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
500       }
501 
502       /* Each channel on a dedicated ASE - TWS style split channel re-routing */
503       return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE;
504     }
505 
506     /* Banded headphones with 1 ASE - requires two channels per CIS */
507     return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE;
508   }
509 
510   // We need at least 2 ASEs in the group config to set up more than one device
511   if (cfgs.size() == 1) {
512     return types::LeAudioConfigurationStrategy::RFU;
513   }
514 
515   /* The common one channel per device topology */
516   return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
517 }
518 
IsCodecConfigSupported(const types::LeAudioLtvMap & pacs,const types::LeAudioLtvMap & reqs,uint8_t channel_cnt_per_ase)519 static bool IsCodecConfigSupported(const types::LeAudioLtvMap& pacs,
520                                    const types::LeAudioLtvMap& reqs,
521                                    uint8_t channel_cnt_per_ase) {
522   auto caps = pacs.GetAsCoreCodecCapabilities();
523   auto config = reqs.GetAsCoreCodecConfig();
524 
525   /* Sampling frequency */
526   if (!caps.HasSupportedSamplingFrequencies() || !config.sampling_frequency) {
527     log::debug("Missing supported sampling frequencies capability");
528     return false;
529   }
530   if (!caps.IsSamplingFrequencyConfigSupported(
531           config.sampling_frequency.value())) {
532     log::debug("Cfg: SamplingFrequency= {:#x}",
533                config.sampling_frequency.value());
534     log::debug("Cap: SupportedSamplingFrequencies= {:#x}",
535                caps.supported_sampling_frequencies.value());
536     log::debug("Sampling frequency not supported");
537     return false;
538   }
539 
540   /* Channel counts */
541   if (!caps.IsAudioChannelCountsSupported(channel_cnt_per_ase)) {
542     log::debug("Cfg: Allocated channel count= {:#x}", channel_cnt_per_ase);
543     log::debug("Cap: Supported channel counts= {:#x}",
544                caps.supported_audio_channel_counts.value_or(1));
545     log::debug("Channel count not supported");
546     return false;
547   }
548 
549   /* Frame duration */
550   if (!caps.HasSupportedFrameDurations() || !config.frame_duration) {
551     log::debug("Missing supported frame durations capability");
552     return false;
553   }
554   if (!caps.IsFrameDurationConfigSupported(config.frame_duration.value())) {
555     log::debug("Cfg: FrameDuration= {:#x}", config.frame_duration.value());
556     log::debug("Cap: SupportedFrameDurations= {:#x}",
557                caps.supported_frame_durations.value());
558     log::debug("Frame duration not supported");
559     return false;
560   }
561 
562   /* Octets per frame */
563   if (!caps.HasSupportedOctetsPerCodecFrame() ||
564       !config.octets_per_codec_frame) {
565     log::debug("Missing supported octets per codec frame");
566     return false;
567   }
568   if (!caps.IsOctetsPerCodecFrameConfigSupported(
569           config.octets_per_codec_frame.value())) {
570     log::debug("Cfg: Octets per frame={}",
571                config.octets_per_codec_frame.value());
572     log::debug("Cap: Min octets per frame={}",
573                caps.supported_min_octets_per_codec_frame.value());
574     log::debug("Cap: Max octets per frame={}",
575                caps.supported_max_octets_per_codec_frame.value());
576     log::debug("Octets per codec frame outside the capabilities");
577     return false;
578   }
579 
580   return true;
581 }
582 
IsCodecConfigSettingSupported(const types::acs_ac_record & pac,const set_configurations::CodecConfigSetting & codec_config_setting)583 static bool IsCodecConfigSettingSupported(
584     const types::acs_ac_record& pac,
585     const set_configurations::CodecConfigSetting& codec_config_setting) {
586   const auto& codec_id = codec_config_setting.id;
587   if (codec_id != pac.codec_id) return false;
588 
589   log::debug(": Settings for format: 0x{:#02x} ", codec_id.coding_format);
590 
591   if (utils::IsCodecUsingLtvFormat(codec_id)) {
592     log::assert_that(
593         !pac.codec_spec_caps.IsEmpty(),
594         "Codec specific capabilities are not parsed approprietly.");
595     return IsCodecConfigSupported(
596         pac.codec_spec_caps, codec_config_setting.params,
597         codec_config_setting.GetChannelCountPerIsoStream());
598   }
599 
600   log::error("Codec {}, seems to be not supported here.",
601              bluetooth::common::ToString(codec_id));
602   return false;
603 }
604 
GetConfigurationSupportedPac(const types::PublishedAudioCapabilities & pacs,const set_configurations::CodecConfigSetting & codec_config_setting)605 const struct types::acs_ac_record* GetConfigurationSupportedPac(
606     const types::PublishedAudioCapabilities& pacs,
607     const set_configurations::CodecConfigSetting& codec_config_setting) {
608   for (const auto& pac_tuple : pacs) {
609     for (const auto& pac : std::get<1>(pac_tuple)) {
610       if (utils::IsCodecConfigSettingSupported(pac, codec_config_setting))
611         return &pac;
612     };
613   }
614   /* Doesn't match required configuration with any PAC */
615   if (pacs.size() == 0) log::error("No PAC records");
616   return nullptr;
617 }
618 }  // namespace utils
619 }  // namespace bluetooth::le_audio
620