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