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