1 /*
2  * Copyright (C) 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 <set>
18 
19 #include "aidl/android/hardware/bluetooth/audio/ChannelMode.h"
20 #include "aidl/android/hardware/bluetooth/audio/CodecId.h"
21 #include "aidl_android_hardware_bluetooth_audio_setting_enums.h"
22 #define LOG_TAG "BTAudioCodecsProviderAidl"
23 
24 #include "BluetoothLeAudioCodecsProvider.h"
25 
26 namespace aidl {
27 namespace android {
28 namespace hardware {
29 namespace bluetooth {
30 namespace audio {
31 
32 static const char* kLeAudioCodecCapabilitiesFile =
33     "/vendor/etc/le_audio_codec_capabilities.xml";
34 
35 static const AudioLocation kStereoAudio = static_cast<AudioLocation>(
36     static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
37     static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
38 static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN;
39 
40 static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
41 
42 static bool isInvalidFileContent = false;
43 
44 std::optional<setting::LeAudioOffloadSetting>
ParseFromLeAudioOffloadSettingFile()45 BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() {
46   auto le_audio_offload_setting =
47       setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
48   if (!le_audio_offload_setting.has_value()) {
49     LOG(ERROR) << __func__ << ": Failed to read "
50                << kLeAudioCodecCapabilitiesFile;
51   }
52   return le_audio_offload_setting;
53 }
54 
55 std::unordered_map<SessionType, std::vector<CodecInfo>>
GetLeAudioCodecInfo(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)56 BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
57     const std::optional<setting::LeAudioOffloadSetting>&
58         le_audio_offload_setting) {
59   // Load from previous storage if present
60   if (!session_codecs_map_.empty()) return session_codecs_map_;
61 
62   isInvalidFileContent = true;
63   if (!le_audio_offload_setting.has_value()) return {};
64 
65   // Load scenario, configuration, codec configuration and strategy
66   LoadConfigurationToMap(le_audio_offload_setting);
67   if (supported_scenarios_.empty() || configuration_map_.empty() ||
68       codec_configuration_map_.empty() || strategy_configuration_map_.empty())
69     return {};
70 
71   // Map each configuration into a CodecInfo
72   std::unordered_map<std::string, CodecInfo> config_codec_info_map_;
73 
74   for (auto& p : configuration_map_) {
75     // Initialize new CodecInfo for the config
76     auto config_name = p.first;
77 
78     // Getting informations from codecConfig and strategyConfig
79     const auto codec_config_name = p.second.getCodecConfiguration();
80     const auto strategy_config_name = p.second.getStrategyConfiguration();
81     const auto codec_configuration_map_iter =
82         codec_configuration_map_.find(codec_config_name);
83     if (codec_configuration_map_iter == codec_configuration_map_.end())
84       continue;
85     const auto strategy_configuration_map_iter =
86         strategy_configuration_map_.find(strategy_config_name);
87     if (strategy_configuration_map_iter == strategy_configuration_map_.end())
88       continue;
89 
90     if (config_codec_info_map_.count(config_name) == 0)
91       config_codec_info_map_[config_name] = CodecInfo();
92 
93     const auto& codec_config = codec_configuration_map_iter->second;
94     const auto codec = codec_config.getCodec();
95     const auto& strategy_config = strategy_configuration_map_iter->second;
96     const auto strategy_config_channel_count =
97         strategy_config.getChannelCount();
98 
99     // Initiate information
100     auto& codec_info = config_codec_info_map_[config_name];
101     switch (codec) {
102       case setting::CodecType::LC3:
103         codec_info.name = "LC3";
104         codec_info.id = CodecId::Core::LC3;
105         break;
106       default:
107         codec_info.name = "UNDEFINE";
108         codec_info.id = CodecId::Vendor();
109         break;
110     }
111     codec_info.transport =
112         CodecInfo::Transport::make<CodecInfo::Transport::Tag::leAudio>();
113 
114     // Mapping codec configuration information
115     auto& transport =
116         codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
117     transport.samplingFrequencyHz.push_back(
118         codec_config.getSamplingFrequency());
119     // Mapping octetsPerCodecFrame to bitdepth for easier comparison.
120     transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
121     transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
122     if (strategy_config.hasAudioLocation()) {
123       switch (strategy_config.getAudioLocation()) {
124         case setting::AudioLocation::MONO:
125           if (strategy_config_channel_count == 1)
126             transport.channelMode.push_back(ChannelMode::MONO);
127           else
128             transport.channelMode.push_back(ChannelMode::DUALMONO);
129           break;
130         case setting::AudioLocation::STEREO:
131           transport.channelMode.push_back(ChannelMode::STEREO);
132           break;
133         default:
134           transport.channelMode.push_back(ChannelMode::UNKNOWN);
135           break;
136       }
137     } else if (strategy_config.hasAudioChannelAllocation()) {
138       auto count =
139           std::bitset<32>(strategy_config.getAudioChannelAllocation()).count();
140       if (count <= 1) {
141         if (strategy_config_channel_count == 1)
142           transport.channelMode.push_back(ChannelMode::MONO);
143         else
144           transport.channelMode.push_back(ChannelMode::DUALMONO);
145       } else if (count == 2) {
146         transport.channelMode.push_back(ChannelMode::STEREO);
147       } else {
148         transport.channelMode.push_back(ChannelMode::UNKNOWN);
149       }
150     } else {
151       transport.channelMode.push_back(ChannelMode::UNKNOWN);
152     }
153   }
154 
155   // Goes through every scenario, deduplicate configuration, skip the invalid
156   // config references (e.g. the "invalid" entries in the xml file).
157   std::set<std::string> encoding_config, decoding_config, broadcast_config;
158   for (auto& s : supported_scenarios_) {
159     if (s.hasEncode() && config_codec_info_map_.count(s.getEncode())) {
160       encoding_config.insert(s.getEncode());
161     }
162     if (s.hasDecode() && config_codec_info_map_.count(s.getDecode())) {
163       decoding_config.insert(s.getDecode());
164     }
165     if (s.hasBroadcast() && config_codec_info_map_.count(s.getBroadcast())) {
166       broadcast_config.insert(s.getBroadcast());
167     }
168   }
169 
170   // Split by session types and add results
171   const auto encoding_path =
172       SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
173   const auto decoding_path =
174       SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
175   const auto broadcast_path =
176       SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
177   session_codecs_map_ =
178       std::unordered_map<SessionType, std::vector<CodecInfo>>();
179   session_codecs_map_[encoding_path] = std::vector<CodecInfo>();
180   session_codecs_map_[decoding_path] = std::vector<CodecInfo>();
181   session_codecs_map_[broadcast_path] = std::vector<CodecInfo>();
182   session_codecs_map_[encoding_path].reserve(encoding_config.size());
183   session_codecs_map_[decoding_path].reserve(decoding_config.size());
184   session_codecs_map_[broadcast_path].reserve(broadcast_config.size());
185   for (auto& c : encoding_config)
186     session_codecs_map_[encoding_path].push_back(config_codec_info_map_[c]);
187   for (auto& c : decoding_config)
188     session_codecs_map_[decoding_path].push_back(config_codec_info_map_[c]);
189   for (auto& c : broadcast_config)
190     session_codecs_map_[broadcast_path].push_back(config_codec_info_map_[c]);
191 
192   isInvalidFileContent = session_codecs_map_.empty();
193 
194   return session_codecs_map_;
195 }
196 
197 std::vector<LeAudioCodecCapabilitiesSetting>
GetLeAudioCodecCapabilities(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)198 BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
199     const std::optional<setting::LeAudioOffloadSetting>&
200         le_audio_offload_setting) {
201   if (!leAudioCodecCapabilities.empty()) {
202     return leAudioCodecCapabilities;
203   }
204 
205   isInvalidFileContent = true;
206 
207   if (!le_audio_offload_setting.has_value()) {
208     LOG(ERROR)
209         << __func__
210         << ": input le_audio_offload_setting content need to be non empty";
211     return {};
212   }
213 
214   LoadConfigurationToMap(le_audio_offload_setting);
215   if (supported_scenarios_.empty() || configuration_map_.empty() ||
216       codec_configuration_map_.empty() || strategy_configuration_map_.empty())
217     return {};
218 
219   leAudioCodecCapabilities =
220       ComposeLeAudioCodecCapabilities(supported_scenarios_);
221   isInvalidFileContent = leAudioCodecCapabilities.empty();
222 
223   return leAudioCodecCapabilities;
224 }
225 
ClearLeAudioCodecCapabilities()226 void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() {
227   leAudioCodecCapabilities.clear();
228   configuration_map_.clear();
229   codec_configuration_map_.clear();
230   strategy_configuration_map_.clear();
231   session_codecs_map_.clear();
232   supported_scenarios_.clear();
233 }
234 
GetScenarios(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)235 std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
236     const std::optional<setting::LeAudioOffloadSetting>&
237         le_audio_offload_setting) {
238   std::vector<setting::Scenario> supported_scenarios;
239   if (le_audio_offload_setting->hasScenarioList()) {
240     for (const auto& scenario_list :
241          le_audio_offload_setting->getScenarioList()) {
242       if (!scenario_list.hasScenario()) {
243         continue;
244       }
245       for (const auto& scenario : scenario_list.getScenario()) {
246         if (scenario.hasEncode() && scenario.hasDecode()) {
247           supported_scenarios.push_back(scenario);
248         }
249       }
250     }
251   }
252   return supported_scenarios;
253 }
254 
UpdateConfigurationsToMap(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)255 void BluetoothLeAudioCodecsProvider::UpdateConfigurationsToMap(
256     const std::optional<setting::LeAudioOffloadSetting>&
257         le_audio_offload_setting) {
258   if (le_audio_offload_setting->hasConfigurationList()) {
259     for (const auto& configuration_list :
260          le_audio_offload_setting->getConfigurationList()) {
261       if (!configuration_list.hasConfiguration()) {
262         continue;
263       }
264       for (const auto& configuration : configuration_list.getConfiguration()) {
265         if (configuration.hasName() && configuration.hasCodecConfiguration() &&
266             configuration.hasStrategyConfiguration()) {
267           configuration_map_.insert(
268               make_pair(configuration.getName(), configuration));
269         }
270       }
271     }
272   }
273 }
274 
UpdateCodecConfigurationsToMap(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)275 void BluetoothLeAudioCodecsProvider::UpdateCodecConfigurationsToMap(
276     const std::optional<setting::LeAudioOffloadSetting>&
277         le_audio_offload_setting) {
278   if (le_audio_offload_setting->hasCodecConfigurationList()) {
279     for (const auto& codec_configuration_list :
280          le_audio_offload_setting->getCodecConfigurationList()) {
281       if (!codec_configuration_list.hasCodecConfiguration()) {
282         continue;
283       }
284       for (const auto& codec_configuration :
285            codec_configuration_list.getCodecConfiguration()) {
286         if (IsValidCodecConfiguration(codec_configuration)) {
287           codec_configuration_map_.insert(
288               make_pair(codec_configuration.getName(), codec_configuration));
289         }
290       }
291     }
292   }
293 }
294 
UpdateStrategyConfigurationsToMap(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)295 void BluetoothLeAudioCodecsProvider::UpdateStrategyConfigurationsToMap(
296     const std::optional<setting::LeAudioOffloadSetting>&
297         le_audio_offload_setting) {
298   if (le_audio_offload_setting->hasStrategyConfigurationList()) {
299     for (const auto& strategy_configuration_list :
300          le_audio_offload_setting->getStrategyConfigurationList()) {
301       if (!strategy_configuration_list.hasStrategyConfiguration()) {
302         continue;
303       }
304       for (const auto& strategy_configuration :
305            strategy_configuration_list.getStrategyConfiguration()) {
306         if (IsValidStrategyConfiguration(strategy_configuration)) {
307           strategy_configuration_map_.insert(make_pair(
308               strategy_configuration.getName(), strategy_configuration));
309         }
310       }
311     }
312   }
313 }
314 
LoadConfigurationToMap(const std::optional<setting::LeAudioOffloadSetting> & le_audio_offload_setting)315 void BluetoothLeAudioCodecsProvider::LoadConfigurationToMap(
316     const std::optional<setting::LeAudioOffloadSetting>&
317         le_audio_offload_setting) {
318   ClearLeAudioCodecCapabilities();
319 
320   supported_scenarios_ = GetScenarios(le_audio_offload_setting);
321   if (supported_scenarios_.empty()) {
322     LOG(ERROR) << __func__ << ": No scenarios in "
323                << kLeAudioCodecCapabilitiesFile;
324     return;
325   }
326 
327   UpdateConfigurationsToMap(le_audio_offload_setting);
328   if (configuration_map_.empty()) {
329     LOG(ERROR) << __func__ << ": No configurations in "
330                << kLeAudioCodecCapabilitiesFile;
331     return;
332   }
333 
334   UpdateCodecConfigurationsToMap(le_audio_offload_setting);
335   if (codec_configuration_map_.empty()) {
336     LOG(ERROR) << __func__ << ": No codec configurations in "
337                << kLeAudioCodecCapabilitiesFile;
338     return;
339   }
340 
341   UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
342   if (strategy_configuration_map_.empty()) {
343     LOG(ERROR) << __func__ << ": No strategy configurations in "
344                << kLeAudioCodecCapabilitiesFile;
345     return;
346   }
347 }
348 
349 std::vector<LeAudioCodecCapabilitiesSetting>
ComposeLeAudioCodecCapabilities(const std::vector<setting::Scenario> & supported_scenarios)350 BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
351     const std::vector<setting::Scenario>& supported_scenarios) {
352   std::vector<LeAudioCodecCapabilitiesSetting> le_audio_codec_capabilities;
353   for (const auto& scenario : supported_scenarios) {
354     UnicastCapability unicast_encode_capability =
355         GetUnicastCapability(scenario.getEncode());
356     LOG(INFO) << __func__ << ": Unicast capability encode = "
357               << unicast_encode_capability.toString();
358     UnicastCapability unicast_decode_capability =
359         GetUnicastCapability(scenario.getDecode());
360     LOG(INFO) << __func__ << ": Unicast capability decode = "
361               << unicast_decode_capability.toString();
362     BroadcastCapability broadcast_capability = {.codecType =
363                                                     CodecType::UNKNOWN};
364 
365     if (scenario.hasBroadcast()) {
366       broadcast_capability = GetBroadcastCapability(scenario.getBroadcast());
367     }
368 
369     // At least one capability should be valid
370     if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
371         unicast_decode_capability.codecType == CodecType::UNKNOWN &&
372         broadcast_capability.codecType == CodecType::UNKNOWN) {
373       LOG(ERROR) << __func__ << ": None of the capability is valid.";
374       continue;
375     }
376 
377     le_audio_codec_capabilities.push_back(
378         {.unicastEncodeCapability = unicast_encode_capability,
379          .unicastDecodeCapability = unicast_decode_capability,
380          .broadcastCapability = broadcast_capability});
381   }
382   return le_audio_codec_capabilities;
383 }
384 
GetUnicastCapability(const std::string & coding_direction)385 UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability(
386     const std::string& coding_direction) {
387   if (coding_direction == "invalid") {
388     return {.codecType = CodecType::UNKNOWN};
389   }
390 
391   auto configuration_iter = configuration_map_.find(coding_direction);
392   if (configuration_iter == configuration_map_.end()) {
393     return {.codecType = CodecType::UNKNOWN};
394   }
395 
396   auto codec_configuration_iter = codec_configuration_map_.find(
397       configuration_iter->second.getCodecConfiguration());
398   if (codec_configuration_iter == codec_configuration_map_.end()) {
399     return {.codecType = CodecType::UNKNOWN};
400   }
401 
402   auto strategy_configuration_iter = strategy_configuration_map_.find(
403       configuration_iter->second.getStrategyConfiguration());
404   if (strategy_configuration_iter == strategy_configuration_map_.end()) {
405     return {.codecType = CodecType::UNKNOWN};
406   }
407 
408   // Populate audio location
409   AudioLocation audio_location = AudioLocation::UNKNOWN;
410   if (strategy_configuration_iter->second.hasAudioLocation()) {
411     audio_location = GetAudioLocation(
412         strategy_configuration_iter->second.getAudioLocation());
413   }
414 
415   // Populate audio channel allocation
416   std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
417       audio_channel_allocation = std::nullopt;
418   if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
419     LOG(INFO) << __func__ << ": has allocation";
420     CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
421     tmp.bitmask =
422         strategy_configuration_iter->second.getAudioChannelAllocation();
423     audio_channel_allocation = tmp;
424   }
425 
426   CodecType codec_type =
427       GetCodecType(codec_configuration_iter->second.getCodec());
428   if (codec_type == CodecType::LC3) {
429     return ComposeUnicastCapability(
430         codec_type, audio_location, audio_channel_allocation,
431         strategy_configuration_iter->second.getConnectedDevice(),
432         strategy_configuration_iter->second.getChannelCount(),
433         ComposeLc3Capability(codec_configuration_iter->second));
434   } else if (codec_type == CodecType::APTX_ADAPTIVE_LE ||
435              codec_type == CodecType::APTX_ADAPTIVE_LEX) {
436     return ComposeUnicastCapability(
437         codec_type, audio_location, audio_channel_allocation,
438         strategy_configuration_iter->second.getConnectedDevice(),
439         strategy_configuration_iter->second.getChannelCount(),
440         ComposeAptxAdaptiveLeCapability(codec_configuration_iter->second));
441   }
442   return {.codecType = CodecType::UNKNOWN};
443 }
444 
GetBroadcastCapability(const std::string & coding_direction)445 BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
446     const std::string& coding_direction) {
447   if (coding_direction == "invalid") {
448     return {.codecType = CodecType::UNKNOWN};
449   }
450 
451   auto configuration_iter = configuration_map_.find(coding_direction);
452   if (configuration_iter == configuration_map_.end()) {
453     return {.codecType = CodecType::UNKNOWN};
454   }
455 
456   auto codec_configuration_iter = codec_configuration_map_.find(
457       configuration_iter->second.getCodecConfiguration());
458   if (codec_configuration_iter == codec_configuration_map_.end()) {
459     return {.codecType = CodecType::UNKNOWN};
460   }
461 
462   auto strategy_configuration_iter = strategy_configuration_map_.find(
463       configuration_iter->second.getStrategyConfiguration());
464   if (strategy_configuration_iter == strategy_configuration_map_.end()) {
465     return {.codecType = CodecType::UNKNOWN};
466   }
467 
468   CodecType codec_type =
469       GetCodecType(codec_configuration_iter->second.getCodec());
470   std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
471       1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
472 
473   // Populate audio location
474   AudioLocation audio_location = AudioLocation::UNKNOWN;
475   if (strategy_configuration_iter->second.hasAudioLocation()) {
476     audio_location = GetAudioLocation(
477         strategy_configuration_iter->second.getAudioLocation());
478   }
479 
480   // Populate audio channel allocation
481   std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
482       audio_channel_allocation = std::nullopt;
483   if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
484     LOG(INFO) << __func__ << ": has allocation";
485     CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
486     tmp.bitmask =
487         strategy_configuration_iter->second.getAudioChannelAllocation();
488     audio_channel_allocation = tmp;
489   }
490 
491   if (codec_type == CodecType::LC3) {
492     return ComposeBroadcastCapability(
493         codec_type, audio_location, audio_channel_allocation,
494         strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
495   }
496   return {.codecType = CodecType::UNKNOWN};
497 }
498 
499 template <class T>
ComposeBroadcastCapability(const CodecType & codec_type,const AudioLocation & audio_location,const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation> & audio_channel_allocation,const uint8_t & channel_count,const std::vector<T> & capability)500 BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
501     const CodecType& codec_type, const AudioLocation& audio_location,
502     const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
503         audio_channel_allocation,
504     const uint8_t& channel_count, const std::vector<T>& capability) {
505   return {.codecType = codec_type,
506           .supportedChannel = audio_location,
507           .channelCountPerStream = channel_count,
508           .leAudioCodecCapabilities = std::optional(capability),
509           .audioLocation = audio_channel_allocation};
510 }
511 
512 template <class T>
ComposeUnicastCapability(const CodecType & codec_type,const AudioLocation & audio_location,const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation> & audio_channel_allocation,const uint8_t & device_cnt,const uint8_t & channel_count,const T & capability)513 UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
514     const CodecType& codec_type, const AudioLocation& audio_location,
515     const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
516         audio_channel_allocation,
517     const uint8_t& device_cnt, const uint8_t& channel_count,
518     const T& capability) {
519   return {
520       .codecType = codec_type,
521       .supportedChannel = audio_location,
522       .deviceCount = device_cnt,
523       .channelCountPerDevice = channel_count,
524       .leAudioCodecCapabilities =
525           UnicastCapability::LeAudioCodecCapabilities(capability),
526       .audioLocation = audio_channel_allocation,
527   };
528 }
529 
ComposeLc3Capability(const setting::CodecConfiguration & codec_configuration)530 Lc3Capabilities BluetoothLeAudioCodecsProvider::ComposeLc3Capability(
531     const setting::CodecConfiguration& codec_configuration) {
532   return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
533           .frameDurationUs = {codec_configuration.getFrameDurationUs()},
534           .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
535 }
536 
537 AptxAdaptiveLeCapabilities
ComposeAptxAdaptiveLeCapability(const setting::CodecConfiguration & codec_configuration)538 BluetoothLeAudioCodecsProvider::ComposeAptxAdaptiveLeCapability(
539     const setting::CodecConfiguration& codec_configuration) {
540   return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
541           .frameDurationUs = {codec_configuration.getFrameDurationUs()},
542           .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
543 }
544 
GetAudioLocation(const setting::AudioLocation & audio_location)545 AudioLocation BluetoothLeAudioCodecsProvider::GetAudioLocation(
546     const setting::AudioLocation& audio_location) {
547   switch (audio_location) {
548     case setting::AudioLocation::MONO:
549       return kMonoAudio;
550     case setting::AudioLocation::STEREO:
551       return kStereoAudio;
552     default:
553       return AudioLocation::UNKNOWN;
554   }
555 }
556 
GetCodecType(const setting::CodecType & codec_type)557 CodecType BluetoothLeAudioCodecsProvider::GetCodecType(
558     const setting::CodecType& codec_type) {
559   switch (codec_type) {
560     case setting::CodecType::LC3:
561       return CodecType::LC3;
562     case setting::CodecType::APTX_ADAPTIVE_LE:
563       return CodecType::APTX_ADAPTIVE_LE;
564     case setting::CodecType::APTX_ADAPTIVE_LEX:
565       return CodecType::APTX_ADAPTIVE_LEX;
566     default:
567       return CodecType::UNKNOWN;
568   }
569 }
570 
IsValidCodecConfiguration(const setting::CodecConfiguration & codec_configuration)571 bool BluetoothLeAudioCodecsProvider::IsValidCodecConfiguration(
572     const setting::CodecConfiguration& codec_configuration) {
573   return codec_configuration.hasName() && codec_configuration.hasCodec() &&
574          codec_configuration.hasSamplingFrequency() &&
575          codec_configuration.hasFrameDurationUs() &&
576          codec_configuration.hasOctetsPerCodecFrame();
577 }
578 
IsValidStereoAudioLocation(const setting::StrategyConfiguration & strategy_configuration)579 bool IsValidStereoAudioLocation(
580     const setting::StrategyConfiguration& strategy_configuration) {
581   if ((strategy_configuration.getConnectedDevice() == 2 &&
582        strategy_configuration.getChannelCount() == 1) ||
583       (strategy_configuration.getConnectedDevice() == 1 &&
584        strategy_configuration.getChannelCount() == 2)) {
585     // Stereo
586     // 1. two connected device, one for L one for R
587     // 2. one connected device for both L and R
588     return true;
589   } else if (strategy_configuration.getConnectedDevice() == 0 &&
590              strategy_configuration.getChannelCount() == 2) {
591     // Broadcast
592     return true;
593   }
594   return false;
595 }
596 
IsValidMonoAudioLocation(const setting::StrategyConfiguration & strategy_configuration)597 bool IsValidMonoAudioLocation(
598     const setting::StrategyConfiguration& strategy_configuration) {
599   if (strategy_configuration.getConnectedDevice() == 1 &&
600       strategy_configuration.getChannelCount() == 1) {
601     return true;
602   }
603   return false;
604 }
605 
IsValidAudioLocation(const setting::StrategyConfiguration & strategy_configuration)606 bool IsValidAudioLocation(
607     const setting::StrategyConfiguration& strategy_configuration) {
608   if (strategy_configuration.getAudioLocation() ==
609       setting::AudioLocation::STEREO)
610     return IsValidStereoAudioLocation(strategy_configuration);
611   else if (strategy_configuration.getAudioLocation() ==
612            setting::AudioLocation::MONO)
613     return IsValidMonoAudioLocation(strategy_configuration);
614   return false;
615 }
616 
IsValidAudioChannelAllocation(const setting::StrategyConfiguration & strategy_configuration)617 bool IsValidAudioChannelAllocation(
618     const setting::StrategyConfiguration& strategy_configuration) {
619   // First, ensure that there's only 2 bitmask enabled
620   int audio_channel_allocation =
621       strategy_configuration.getAudioChannelAllocation();
622   int count = 0;
623   for (int bit = 0; bit < 32; ++bit)
624     if (audio_channel_allocation & (1 << bit)) ++count;
625   if (count > 2) {
626     LOG(WARNING) << "Cannot parse more than 2 audio location, input is "
627                  << audio_channel_allocation;
628     return false;
629   }
630 
631   if (count == 2)
632     return IsValidStereoAudioLocation(strategy_configuration);
633   else
634     return IsValidMonoAudioLocation(strategy_configuration);
635 }
636 
IsValidStrategyConfiguration(const setting::StrategyConfiguration & strategy_configuration)637 bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
638     const setting::StrategyConfiguration& strategy_configuration) {
639   if (!strategy_configuration.hasName() ||
640       !strategy_configuration.hasConnectedDevice() ||
641       !strategy_configuration.hasChannelCount()) {
642     return false;
643   }
644 
645   // Both audio location field cannot be empty
646   if (!strategy_configuration.hasAudioLocation() &&
647       !strategy_configuration.hasAudioChannelAllocation())
648     return false;
649 
650   // Any audio location field that presents must be valid
651   if (strategy_configuration.hasAudioLocation() &&
652       !IsValidAudioLocation(strategy_configuration))
653     return false;
654 
655   if (strategy_configuration.hasAudioChannelAllocation() &&
656       !IsValidAudioChannelAllocation(strategy_configuration))
657     return false;
658 
659   return true;
660 }
661 
662 }  // namespace audio
663 }  // namespace bluetooth
664 }  // namespace hardware
665 }  // namespace android
666 }  // namespace aidl
667