blob: b6df67e133f4e841f00061b2175a03e8022c0676 [file] [log] [blame]
shihchienc8ed901a2022-09-06 08:44:44 +00001/*
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
Bao Do6aeb5d72023-12-11 10:53:18 +000017#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"
shihchienc8ed901a2022-09-06 08:44:44 +000022#define LOG_TAG "BTAudioCodecsProviderAidl"
23
24#include "BluetoothLeAudioCodecsProvider.h"
25
26namespace aidl {
27namespace android {
28namespace hardware {
29namespace bluetooth {
30namespace audio {
31
32static const char* kLeAudioCodecCapabilitiesFile =
33 "/vendor/etc/le_audio_codec_capabilities.xml";
34
35static const AudioLocation kStereoAudio = static_cast<AudioLocation>(
36 static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
37 static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
38static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN;
39
40static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
41
shihchiencd7f565a2022-10-14 13:45:37 +000042static bool isInvalidFileContent = false;
shihchienc8ed901a2022-09-06 08:44:44 +000043
shihchiencd7f565a2022-10-14 13:45:37 +000044std::optional<setting::LeAudioOffloadSetting>
45BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() {
46 if (!leAudioCodecCapabilities.empty() || isInvalidFileContent) {
47 return std::nullopt;
48 }
49 auto le_audio_offload_setting =
shihchienc8ed901a2022-09-06 08:44:44 +000050 setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
51 if (!le_audio_offload_setting.has_value()) {
52 LOG(ERROR) << __func__ << ": Failed to read "
53 << kLeAudioCodecCapabilitiesFile;
shihchiencd7f565a2022-10-14 13:45:37 +000054 }
55 return le_audio_offload_setting;
56}
57
Bao Do6aeb5d72023-12-11 10:53:18 +000058std::unordered_map<SessionType, std::vector<CodecInfo>>
59BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
60 const std::optional<setting::LeAudioOffloadSetting>&
61 le_audio_offload_setting) {
62 // Load from previous storage if present
63 if (!session_codecs_map_.empty()) return session_codecs_map_;
64
65 isInvalidFileContent = true;
66 if (!le_audio_offload_setting.has_value()) return {};
67
68 // Load scenario, configuration, codec configuration and strategy
69 LoadConfigurationToMap(le_audio_offload_setting);
70 if (supported_scenarios_.empty() || configuration_map_.empty() ||
71 codec_configuration_map_.empty() || strategy_configuration_map_.empty())
72 return {};
73
74 // Map each configuration into a CodecInfo
75 std::unordered_map<std::string, CodecInfo> config_codec_info_map_;
76
77 for (auto& p : configuration_map_) {
78 // Initialize new CodecInfo for the config
79 auto config_name = p.first;
80 if (config_codec_info_map_.count(config_name) == 0)
81 config_codec_info_map_[config_name] = CodecInfo();
82
83 // Getting informations from codecConfig and strategyConfig
84 const auto codec_config_name = p.second.getCodecConfiguration();
85 const auto strategy_config_name = p.second.getStrategyConfiguration();
86 const auto codec_configuration_map_iter =
87 codec_configuration_map_.find(codec_config_name);
88 if (codec_configuration_map_iter == codec_configuration_map_.end())
89 continue;
90 const auto strategy_configuration_map_iter =
91 strategy_configuration_map_.find(strategy_config_name);
92 if (strategy_configuration_map_iter == strategy_configuration_map_.end())
93 continue;
94
95 const auto& codec_config = codec_configuration_map_iter->second;
96 const auto codec = codec_config.getCodec();
97 const auto& strategy_config = strategy_configuration_map_iter->second;
98 const auto strategy_config_channel_count =
99 strategy_config.getChannelCount();
100
101 // Initiate information
102 auto& codec_info = config_codec_info_map_[config_name];
103 switch (codec) {
104 case setting::CodecType::LC3:
105 codec_info.name = "LC3";
106 codec_info.id = CodecId::Core::LC3;
107 break;
108 default:
109 codec_info.name = "UNDEFINE";
Bao Do5b2fdab2023-11-20 08:02:55 +0000110 codec_info.id = CodecId::Vendor();
Bao Do6aeb5d72023-12-11 10:53:18 +0000111 break;
112 }
113 codec_info.transport =
114 CodecInfo::Transport::make<CodecInfo::Transport::Tag::leAudio>();
115
116 // Mapping codec configuration information
117 auto& transport =
118 codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
119 transport.samplingFrequencyHz.push_back(
120 codec_config.getSamplingFrequency());
121 // Mapping octetsPerCodecFrame to bitdepth for easier comparison.
122 transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
123 transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
124 switch (strategy_config.getAudioLocation()) {
125 case setting::AudioLocation::MONO:
126 if (strategy_config_channel_count == 1)
127 transport.channelMode.push_back(ChannelMode::MONO);
128 else
129 transport.channelMode.push_back(ChannelMode::DUALMONO);
130 break;
131 case setting::AudioLocation::STEREO:
132 transport.channelMode.push_back(ChannelMode::STEREO);
133 break;
134 default:
135 transport.channelMode.push_back(ChannelMode::UNKNOWN);
136 break;
137 }
138 }
139
140 // Goes through every scenario, deduplicate configuration
141 std::set<std::string> encoding_config, decoding_config, broadcast_config;
142 for (auto& s : supported_scenarios_) {
143 if (s.hasEncode()) encoding_config.insert(s.getEncode());
144 if (s.hasDecode()) decoding_config.insert(s.getDecode());
145 if (s.hasBroadcast()) broadcast_config.insert(s.getBroadcast());
146 }
147
148 // Split by session types and add results
149 const auto encoding_path =
150 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
151 const auto decoding_path =
152 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
153 const auto broadcast_path =
154 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
155 session_codecs_map_ =
156 std::unordered_map<SessionType, std::vector<CodecInfo>>();
157 session_codecs_map_[encoding_path] = std::vector<CodecInfo>();
158 session_codecs_map_[decoding_path] = std::vector<CodecInfo>();
159 session_codecs_map_[broadcast_path] = std::vector<CodecInfo>();
160 session_codecs_map_[encoding_path].reserve(encoding_config.size());
161 session_codecs_map_[decoding_path].reserve(decoding_config.size());
162 session_codecs_map_[broadcast_path].reserve(broadcast_config.size());
163 for (auto& c : encoding_config)
164 session_codecs_map_[encoding_path].push_back(config_codec_info_map_[c]);
165 for (auto& c : decoding_config)
166 session_codecs_map_[decoding_path].push_back(config_codec_info_map_[c]);
167 for (auto& c : broadcast_config)
168 session_codecs_map_[broadcast_path].push_back(config_codec_info_map_[c]);
169
170 isInvalidFileContent = session_codecs_map_.empty();
171
172 return session_codecs_map_;
173}
174
shihchiencd7f565a2022-10-14 13:45:37 +0000175std::vector<LeAudioCodecCapabilitiesSetting>
176BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
177 const std::optional<setting::LeAudioOffloadSetting>&
178 le_audio_offload_setting) {
179 if (!leAudioCodecCapabilities.empty()) {
180 return leAudioCodecCapabilities;
181 }
182
Bao Do6aeb5d72023-12-11 10:53:18 +0000183 isInvalidFileContent = true;
184
shihchiencd7f565a2022-10-14 13:45:37 +0000185 if (!le_audio_offload_setting.has_value()) {
186 LOG(ERROR)
187 << __func__
188 << ": input le_audio_offload_setting content need to be non empty";
shihchienc8ed901a2022-09-06 08:44:44 +0000189 return {};
190 }
191
Bao Do6aeb5d72023-12-11 10:53:18 +0000192 LoadConfigurationToMap(le_audio_offload_setting);
193 if (supported_scenarios_.empty() || configuration_map_.empty() ||
194 codec_configuration_map_.empty() || strategy_configuration_map_.empty())
shihchienc8ed901a2022-09-06 08:44:44 +0000195 return {};
shihchienc8ed901a2022-09-06 08:44:44 +0000196
197 leAudioCodecCapabilities =
Bao Do6aeb5d72023-12-11 10:53:18 +0000198 ComposeLeAudioCodecCapabilities(supported_scenarios_);
shihchiencd7f565a2022-10-14 13:45:37 +0000199 isInvalidFileContent = leAudioCodecCapabilities.empty();
200
shihchienc8ed901a2022-09-06 08:44:44 +0000201 return leAudioCodecCapabilities;
202}
203
shihchiencd7f565a2022-10-14 13:45:37 +0000204void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() {
205 leAudioCodecCapabilities.clear();
206 configuration_map_.clear();
207 codec_configuration_map_.clear();
208 strategy_configuration_map_.clear();
Bao Do6aeb5d72023-12-11 10:53:18 +0000209 session_codecs_map_.clear();
210 supported_scenarios_.clear();
shihchiencd7f565a2022-10-14 13:45:37 +0000211}
212
shihchienc8ed901a2022-09-06 08:44:44 +0000213std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
214 const std::optional<setting::LeAudioOffloadSetting>&
215 le_audio_offload_setting) {
216 std::vector<setting::Scenario> supported_scenarios;
217 if (le_audio_offload_setting->hasScenarioList()) {
218 for (const auto& scenario_list :
219 le_audio_offload_setting->getScenarioList()) {
220 if (!scenario_list.hasScenario()) {
221 continue;
222 }
223 for (const auto& scenario : scenario_list.getScenario()) {
224 if (scenario.hasEncode() && scenario.hasDecode()) {
225 supported_scenarios.push_back(scenario);
226 }
227 }
228 }
229 }
230 return supported_scenarios;
231}
232
233void BluetoothLeAudioCodecsProvider::UpdateConfigurationsToMap(
234 const std::optional<setting::LeAudioOffloadSetting>&
235 le_audio_offload_setting) {
236 if (le_audio_offload_setting->hasConfigurationList()) {
237 for (const auto& configuration_list :
238 le_audio_offload_setting->getConfigurationList()) {
239 if (!configuration_list.hasConfiguration()) {
240 continue;
241 }
242 for (const auto& configuration : configuration_list.getConfiguration()) {
243 if (configuration.hasName() && configuration.hasCodecConfiguration() &&
244 configuration.hasStrategyConfiguration()) {
245 configuration_map_.insert(
246 make_pair(configuration.getName(), configuration));
247 }
248 }
249 }
250 }
251}
252
253void BluetoothLeAudioCodecsProvider::UpdateCodecConfigurationsToMap(
254 const std::optional<setting::LeAudioOffloadSetting>&
255 le_audio_offload_setting) {
256 if (le_audio_offload_setting->hasCodecConfigurationList()) {
257 for (const auto& codec_configuration_list :
258 le_audio_offload_setting->getCodecConfigurationList()) {
259 if (!codec_configuration_list.hasCodecConfiguration()) {
260 continue;
261 }
262 for (const auto& codec_configuration :
263 codec_configuration_list.getCodecConfiguration()) {
264 if (IsValidCodecConfiguration(codec_configuration)) {
265 codec_configuration_map_.insert(
266 make_pair(codec_configuration.getName(), codec_configuration));
267 }
268 }
269 }
270 }
271}
272
273void BluetoothLeAudioCodecsProvider::UpdateStrategyConfigurationsToMap(
274 const std::optional<setting::LeAudioOffloadSetting>&
275 le_audio_offload_setting) {
276 if (le_audio_offload_setting->hasStrategyConfigurationList()) {
277 for (const auto& strategy_configuration_list :
278 le_audio_offload_setting->getStrategyConfigurationList()) {
279 if (!strategy_configuration_list.hasStrategyConfiguration()) {
280 continue;
281 }
282 for (const auto& strategy_configuration :
283 strategy_configuration_list.getStrategyConfiguration()) {
284 if (IsValidStrategyConfiguration(strategy_configuration)) {
285 strategy_configuration_map_.insert(make_pair(
286 strategy_configuration.getName(), strategy_configuration));
287 }
288 }
289 }
290 }
291}
292
Bao Do6aeb5d72023-12-11 10:53:18 +0000293void BluetoothLeAudioCodecsProvider::LoadConfigurationToMap(
294 const std::optional<setting::LeAudioOffloadSetting>&
295 le_audio_offload_setting) {
296 ClearLeAudioCodecCapabilities();
297
298 supported_scenarios_ = GetScenarios(le_audio_offload_setting);
299 if (supported_scenarios_.empty()) {
300 LOG(ERROR) << __func__ << ": No scenarios in "
301 << kLeAudioCodecCapabilitiesFile;
302 return;
303 }
304
305 UpdateConfigurationsToMap(le_audio_offload_setting);
306 if (configuration_map_.empty()) {
307 LOG(ERROR) << __func__ << ": No configurations in "
308 << kLeAudioCodecCapabilitiesFile;
309 return;
310 }
311
312 UpdateCodecConfigurationsToMap(le_audio_offload_setting);
313 if (codec_configuration_map_.empty()) {
314 LOG(ERROR) << __func__ << ": No codec configurations in "
315 << kLeAudioCodecCapabilitiesFile;
316 return;
317 }
318
319 UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
320 if (strategy_configuration_map_.empty()) {
321 LOG(ERROR) << __func__ << ": No strategy configurations in "
322 << kLeAudioCodecCapabilitiesFile;
323 return;
324 }
325}
326
shihchienc8ed901a2022-09-06 08:44:44 +0000327std::vector<LeAudioCodecCapabilitiesSetting>
328BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
329 const std::vector<setting::Scenario>& supported_scenarios) {
330 std::vector<LeAudioCodecCapabilitiesSetting> le_audio_codec_capabilities;
331 for (const auto& scenario : supported_scenarios) {
332 UnicastCapability unicast_encode_capability =
333 GetUnicastCapability(scenario.getEncode());
334 UnicastCapability unicast_decode_capability =
335 GetUnicastCapability(scenario.getDecode());
shihchienc8ed901a2022-09-06 08:44:44 +0000336 BroadcastCapability broadcast_capability = {.codecType =
337 CodecType::UNKNOWN};
Patty Huangac077ef2022-11-23 14:45:15 +0800338
339 if (scenario.hasBroadcast()) {
340 broadcast_capability = GetBroadcastCapability(scenario.getBroadcast());
341 }
342
343 // At least one capability should be valid
344 if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
345 unicast_decode_capability.codecType == CodecType::UNKNOWN &&
346 broadcast_capability.codecType == CodecType::UNKNOWN) {
347 LOG(ERROR) << __func__ << ": None of the capability is valid.";
348 continue;
349 }
350
shihchienc8ed901a2022-09-06 08:44:44 +0000351 le_audio_codec_capabilities.push_back(
352 {.unicastEncodeCapability = unicast_encode_capability,
353 .unicastDecodeCapability = unicast_decode_capability,
354 .broadcastCapability = broadcast_capability});
355 }
356 return le_audio_codec_capabilities;
357}
358
359UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability(
360 const std::string& coding_direction) {
361 if (coding_direction == "invalid") {
362 return {.codecType = CodecType::UNKNOWN};
363 }
364
365 auto configuration_iter = configuration_map_.find(coding_direction);
366 if (configuration_iter == configuration_map_.end()) {
367 return {.codecType = CodecType::UNKNOWN};
368 }
369
370 auto codec_configuration_iter = codec_configuration_map_.find(
371 configuration_iter->second.getCodecConfiguration());
372 if (codec_configuration_iter == codec_configuration_map_.end()) {
373 return {.codecType = CodecType::UNKNOWN};
374 }
375
376 auto strategy_configuration_iter = strategy_configuration_map_.find(
377 configuration_iter->second.getStrategyConfiguration());
378 if (strategy_configuration_iter == strategy_configuration_map_.end()) {
379 return {.codecType = CodecType::UNKNOWN};
380 }
381
382 CodecType codec_type =
383 GetCodecType(codec_configuration_iter->second.getCodec());
384 if (codec_type == CodecType::LC3) {
385 return ComposeUnicastCapability(
386 codec_type,
387 GetAudioLocation(
388 strategy_configuration_iter->second.getAudioLocation()),
389 strategy_configuration_iter->second.getConnectedDevice(),
390 strategy_configuration_iter->second.getChannelCount(),
391 ComposeLc3Capability(codec_configuration_iter->second));
Alice Kuof850de62023-10-04 04:02:24 +0800392 } else if (codec_type == CodecType::APTX_ADAPTIVE_LE ||
393 codec_type == CodecType::APTX_ADAPTIVE_LEX) {
394 return ComposeUnicastCapability(
395 codec_type,
396 GetAudioLocation(
397 strategy_configuration_iter->second.getAudioLocation()),
398 strategy_configuration_iter->second.getConnectedDevice(),
399 strategy_configuration_iter->second.getChannelCount(),
400 ComposeAptxAdaptiveLeCapability(codec_configuration_iter->second));
shihchienc8ed901a2022-09-06 08:44:44 +0000401 }
402 return {.codecType = CodecType::UNKNOWN};
403}
404
Patty Huangac077ef2022-11-23 14:45:15 +0800405BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
406 const std::string& coding_direction) {
407 if (coding_direction == "invalid") {
408 return {.codecType = CodecType::UNKNOWN};
409 }
410
411 auto configuration_iter = configuration_map_.find(coding_direction);
412 if (configuration_iter == configuration_map_.end()) {
413 return {.codecType = CodecType::UNKNOWN};
414 }
415
416 auto codec_configuration_iter = codec_configuration_map_.find(
417 configuration_iter->second.getCodecConfiguration());
418 if (codec_configuration_iter == codec_configuration_map_.end()) {
419 return {.codecType = CodecType::UNKNOWN};
420 }
421
422 auto strategy_configuration_iter = strategy_configuration_map_.find(
423 configuration_iter->second.getStrategyConfiguration());
424 if (strategy_configuration_iter == strategy_configuration_map_.end()) {
425 return {.codecType = CodecType::UNKNOWN};
426 }
427
428 CodecType codec_type =
429 GetCodecType(codec_configuration_iter->second.getCodec());
430 std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
431 1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
432
433 if (codec_type == CodecType::LC3) {
434 return ComposeBroadcastCapability(
435 codec_type,
436 GetAudioLocation(
437 strategy_configuration_iter->second.getAudioLocation()),
438 strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
439 }
440 return {.codecType = CodecType::UNKNOWN};
441}
442
443template <class T>
444BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
445 const CodecType& codec_type, const AudioLocation& audio_location,
446 const uint8_t& channel_count, const std::vector<T>& capability) {
447 return {.codecType = codec_type,
448 .supportedChannel = audio_location,
449 .channelCountPerStream = channel_count,
450 .leAudioCodecCapabilities = std::optional(capability)};
451}
452
shihchienc8ed901a2022-09-06 08:44:44 +0000453template <class T>
454UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
455 const CodecType& codec_type, const AudioLocation& audio_location,
456 const uint8_t& device_cnt, const uint8_t& channel_count,
457 const T& capability) {
458 return {
459 .codecType = codec_type,
460 .supportedChannel = audio_location,
461 .deviceCount = device_cnt,
462 .channelCountPerDevice = channel_count,
463 .leAudioCodecCapabilities =
464 UnicastCapability::LeAudioCodecCapabilities(capability),
465 };
466}
467
468Lc3Capabilities BluetoothLeAudioCodecsProvider::ComposeLc3Capability(
469 const setting::CodecConfiguration& codec_configuration) {
470 return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
471 .frameDurationUs = {codec_configuration.getFrameDurationUs()},
472 .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
473}
474
Alice Kuof850de62023-10-04 04:02:24 +0800475AptxAdaptiveLeCapabilities
476BluetoothLeAudioCodecsProvider::ComposeAptxAdaptiveLeCapability(
477 const setting::CodecConfiguration& codec_configuration) {
478 return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
479 .frameDurationUs = {codec_configuration.getFrameDurationUs()},
480 .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
481}
482
shihchienc8ed901a2022-09-06 08:44:44 +0000483AudioLocation BluetoothLeAudioCodecsProvider::GetAudioLocation(
484 const setting::AudioLocation& audio_location) {
485 switch (audio_location) {
486 case setting::AudioLocation::MONO:
487 return kMonoAudio;
488 case setting::AudioLocation::STEREO:
489 return kStereoAudio;
490 default:
491 return AudioLocation::UNKNOWN;
492 }
493}
494
495CodecType BluetoothLeAudioCodecsProvider::GetCodecType(
496 const setting::CodecType& codec_type) {
497 switch (codec_type) {
498 case setting::CodecType::LC3:
499 return CodecType::LC3;
Alice Kuof850de62023-10-04 04:02:24 +0800500 case setting::CodecType::APTX_ADAPTIVE_LE:
501 return CodecType::APTX_ADAPTIVE_LE;
502 case setting::CodecType::APTX_ADAPTIVE_LEX:
503 return CodecType::APTX_ADAPTIVE_LEX;
shihchienc8ed901a2022-09-06 08:44:44 +0000504 default:
505 return CodecType::UNKNOWN;
506 }
507}
508
509bool BluetoothLeAudioCodecsProvider::IsValidCodecConfiguration(
510 const setting::CodecConfiguration& codec_configuration) {
511 return codec_configuration.hasName() && codec_configuration.hasCodec() &&
512 codec_configuration.hasSamplingFrequency() &&
513 codec_configuration.hasFrameDurationUs() &&
514 codec_configuration.hasOctetsPerCodecFrame();
515}
516
517bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
518 const setting::StrategyConfiguration& strategy_configuration) {
519 if (!strategy_configuration.hasName() ||
520 !strategy_configuration.hasAudioLocation() ||
521 !strategy_configuration.hasConnectedDevice() ||
522 !strategy_configuration.hasChannelCount()) {
523 return false;
524 }
525 if (strategy_configuration.getAudioLocation() ==
526 setting::AudioLocation::STEREO) {
527 if ((strategy_configuration.getConnectedDevice() == 2 &&
528 strategy_configuration.getChannelCount() == 1) ||
529 (strategy_configuration.getConnectedDevice() == 1 &&
530 strategy_configuration.getChannelCount() == 2)) {
531 // Stereo
532 // 1. two connected device, one for L one for R
533 // 2. one connected device for both L and R
534 return true;
Patty Huangac077ef2022-11-23 14:45:15 +0800535 } else if (strategy_configuration.getConnectedDevice() == 0 &&
536 strategy_configuration.getChannelCount() == 2) {
537 // Broadcast
538 return true;
shihchienc8ed901a2022-09-06 08:44:44 +0000539 }
540 } else if (strategy_configuration.getAudioLocation() ==
541 setting::AudioLocation::MONO) {
542 if (strategy_configuration.getConnectedDevice() == 1 &&
543 strategy_configuration.getChannelCount() == 1) {
544 // Mono
545 return true;
546 }
547 }
548 return false;
549}
550
551} // namespace audio
552} // namespace bluetooth
553} // namespace hardware
554} // namespace android
555} // namespace aidl