blob: 26da5fbe8173eb2c642573e6ede27e0d53d67ac6 [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
17#define LOG_TAG "BTAudioCodecsProviderAidl"
18
19#include "BluetoothLeAudioCodecsProvider.h"
20
21namespace aidl {
22namespace android {
23namespace hardware {
24namespace bluetooth {
25namespace audio {
26
27static const char* kLeAudioCodecCapabilitiesFile =
28 "/vendor/etc/le_audio_codec_capabilities.xml";
29
30static const AudioLocation kStereoAudio = static_cast<AudioLocation>(
31 static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
32 static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
33static const AudioLocation kMonoAudio = AudioLocation::UNKNOWN;
34
35static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
36
shihchiencd7f565a2022-10-14 13:45:37 +000037static bool isInvalidFileContent = false;
shihchienc8ed901a2022-09-06 08:44:44 +000038
shihchiencd7f565a2022-10-14 13:45:37 +000039std::optional<setting::LeAudioOffloadSetting>
40BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() {
41 if (!leAudioCodecCapabilities.empty() || isInvalidFileContent) {
42 return std::nullopt;
43 }
44 auto le_audio_offload_setting =
shihchienc8ed901a2022-09-06 08:44:44 +000045 setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
46 if (!le_audio_offload_setting.has_value()) {
47 LOG(ERROR) << __func__ << ": Failed to read "
48 << kLeAudioCodecCapabilitiesFile;
shihchiencd7f565a2022-10-14 13:45:37 +000049 }
50 return le_audio_offload_setting;
51}
52
53std::vector<LeAudioCodecCapabilitiesSetting>
54BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
55 const std::optional<setting::LeAudioOffloadSetting>&
56 le_audio_offload_setting) {
57 if (!leAudioCodecCapabilities.empty()) {
58 return leAudioCodecCapabilities;
59 }
60
61 if (!le_audio_offload_setting.has_value()) {
62 LOG(ERROR)
63 << __func__
64 << ": input le_audio_offload_setting content need to be non empty";
shihchienc8ed901a2022-09-06 08:44:44 +000065 return {};
66 }
67
shihchiencd7f565a2022-10-14 13:45:37 +000068 ClearLeAudioCodecCapabilities();
69 isInvalidFileContent = true;
70
shihchienc8ed901a2022-09-06 08:44:44 +000071 std::vector<setting::Scenario> supported_scenarios =
72 GetScenarios(le_audio_offload_setting);
73 if (supported_scenarios.empty()) {
74 LOG(ERROR) << __func__ << ": No scenarios in "
75 << kLeAudioCodecCapabilitiesFile;
76 return {};
77 }
78
79 UpdateConfigurationsToMap(le_audio_offload_setting);
80 if (configuration_map_.empty()) {
81 LOG(ERROR) << __func__ << ": No configurations in "
82 << kLeAudioCodecCapabilitiesFile;
83 return {};
84 }
85
86 UpdateCodecConfigurationsToMap(le_audio_offload_setting);
87 if (codec_configuration_map_.empty()) {
88 LOG(ERROR) << __func__ << ": No codec configurations in "
89 << kLeAudioCodecCapabilitiesFile;
90 return {};
91 }
92
93 UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
94 if (strategy_configuration_map_.empty()) {
95 LOG(ERROR) << __func__ << ": No strategy configurations in "
96 << kLeAudioCodecCapabilitiesFile;
97 return {};
98 }
99
100 leAudioCodecCapabilities =
101 ComposeLeAudioCodecCapabilities(supported_scenarios);
shihchiencd7f565a2022-10-14 13:45:37 +0000102 isInvalidFileContent = leAudioCodecCapabilities.empty();
103
shihchienc8ed901a2022-09-06 08:44:44 +0000104 return leAudioCodecCapabilities;
105}
106
shihchiencd7f565a2022-10-14 13:45:37 +0000107void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() {
108 leAudioCodecCapabilities.clear();
109 configuration_map_.clear();
110 codec_configuration_map_.clear();
111 strategy_configuration_map_.clear();
112}
113
shihchienc8ed901a2022-09-06 08:44:44 +0000114std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
115 const std::optional<setting::LeAudioOffloadSetting>&
116 le_audio_offload_setting) {
117 std::vector<setting::Scenario> supported_scenarios;
118 if (le_audio_offload_setting->hasScenarioList()) {
119 for (const auto& scenario_list :
120 le_audio_offload_setting->getScenarioList()) {
121 if (!scenario_list.hasScenario()) {
122 continue;
123 }
124 for (const auto& scenario : scenario_list.getScenario()) {
125 if (scenario.hasEncode() && scenario.hasDecode()) {
126 supported_scenarios.push_back(scenario);
127 }
128 }
129 }
130 }
131 return supported_scenarios;
132}
133
134void BluetoothLeAudioCodecsProvider::UpdateConfigurationsToMap(
135 const std::optional<setting::LeAudioOffloadSetting>&
136 le_audio_offload_setting) {
137 if (le_audio_offload_setting->hasConfigurationList()) {
138 for (const auto& configuration_list :
139 le_audio_offload_setting->getConfigurationList()) {
140 if (!configuration_list.hasConfiguration()) {
141 continue;
142 }
143 for (const auto& configuration : configuration_list.getConfiguration()) {
144 if (configuration.hasName() && configuration.hasCodecConfiguration() &&
145 configuration.hasStrategyConfiguration()) {
146 configuration_map_.insert(
147 make_pair(configuration.getName(), configuration));
148 }
149 }
150 }
151 }
152}
153
154void BluetoothLeAudioCodecsProvider::UpdateCodecConfigurationsToMap(
155 const std::optional<setting::LeAudioOffloadSetting>&
156 le_audio_offload_setting) {
157 if (le_audio_offload_setting->hasCodecConfigurationList()) {
158 for (const auto& codec_configuration_list :
159 le_audio_offload_setting->getCodecConfigurationList()) {
160 if (!codec_configuration_list.hasCodecConfiguration()) {
161 continue;
162 }
163 for (const auto& codec_configuration :
164 codec_configuration_list.getCodecConfiguration()) {
165 if (IsValidCodecConfiguration(codec_configuration)) {
166 codec_configuration_map_.insert(
167 make_pair(codec_configuration.getName(), codec_configuration));
168 }
169 }
170 }
171 }
172}
173
174void BluetoothLeAudioCodecsProvider::UpdateStrategyConfigurationsToMap(
175 const std::optional<setting::LeAudioOffloadSetting>&
176 le_audio_offload_setting) {
177 if (le_audio_offload_setting->hasStrategyConfigurationList()) {
178 for (const auto& strategy_configuration_list :
179 le_audio_offload_setting->getStrategyConfigurationList()) {
180 if (!strategy_configuration_list.hasStrategyConfiguration()) {
181 continue;
182 }
183 for (const auto& strategy_configuration :
184 strategy_configuration_list.getStrategyConfiguration()) {
185 if (IsValidStrategyConfiguration(strategy_configuration)) {
186 strategy_configuration_map_.insert(make_pair(
187 strategy_configuration.getName(), strategy_configuration));
188 }
189 }
190 }
191 }
192}
193
194std::vector<LeAudioCodecCapabilitiesSetting>
195BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
196 const std::vector<setting::Scenario>& supported_scenarios) {
197 std::vector<LeAudioCodecCapabilitiesSetting> le_audio_codec_capabilities;
198 for (const auto& scenario : supported_scenarios) {
199 UnicastCapability unicast_encode_capability =
200 GetUnicastCapability(scenario.getEncode());
201 UnicastCapability unicast_decode_capability =
202 GetUnicastCapability(scenario.getDecode());
shihchienc8ed901a2022-09-06 08:44:44 +0000203 BroadcastCapability broadcast_capability = {.codecType =
204 CodecType::UNKNOWN};
Patty Huangac077ef2022-11-23 14:45:15 +0800205
206 if (scenario.hasBroadcast()) {
207 broadcast_capability = GetBroadcastCapability(scenario.getBroadcast());
208 }
209
210 // At least one capability should be valid
211 if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
212 unicast_decode_capability.codecType == CodecType::UNKNOWN &&
213 broadcast_capability.codecType == CodecType::UNKNOWN) {
214 LOG(ERROR) << __func__ << ": None of the capability is valid.";
215 continue;
216 }
217
shihchienc8ed901a2022-09-06 08:44:44 +0000218 le_audio_codec_capabilities.push_back(
219 {.unicastEncodeCapability = unicast_encode_capability,
220 .unicastDecodeCapability = unicast_decode_capability,
221 .broadcastCapability = broadcast_capability});
222 }
223 return le_audio_codec_capabilities;
224}
225
226UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability(
227 const std::string& coding_direction) {
228 if (coding_direction == "invalid") {
229 return {.codecType = CodecType::UNKNOWN};
230 }
231
232 auto configuration_iter = configuration_map_.find(coding_direction);
233 if (configuration_iter == configuration_map_.end()) {
234 return {.codecType = CodecType::UNKNOWN};
235 }
236
237 auto codec_configuration_iter = codec_configuration_map_.find(
238 configuration_iter->second.getCodecConfiguration());
239 if (codec_configuration_iter == codec_configuration_map_.end()) {
240 return {.codecType = CodecType::UNKNOWN};
241 }
242
243 auto strategy_configuration_iter = strategy_configuration_map_.find(
244 configuration_iter->second.getStrategyConfiguration());
245 if (strategy_configuration_iter == strategy_configuration_map_.end()) {
246 return {.codecType = CodecType::UNKNOWN};
247 }
248
249 CodecType codec_type =
250 GetCodecType(codec_configuration_iter->second.getCodec());
251 if (codec_type == CodecType::LC3) {
252 return ComposeUnicastCapability(
253 codec_type,
254 GetAudioLocation(
255 strategy_configuration_iter->second.getAudioLocation()),
256 strategy_configuration_iter->second.getConnectedDevice(),
257 strategy_configuration_iter->second.getChannelCount(),
258 ComposeLc3Capability(codec_configuration_iter->second));
Alice Kuof850de62023-10-04 04:02:24 +0800259 } else if (codec_type == CodecType::APTX_ADAPTIVE_LE ||
260 codec_type == CodecType::APTX_ADAPTIVE_LEX) {
261 return ComposeUnicastCapability(
262 codec_type,
263 GetAudioLocation(
264 strategy_configuration_iter->second.getAudioLocation()),
265 strategy_configuration_iter->second.getConnectedDevice(),
266 strategy_configuration_iter->second.getChannelCount(),
267 ComposeAptxAdaptiveLeCapability(codec_configuration_iter->second));
shihchienc8ed901a2022-09-06 08:44:44 +0000268 }
269 return {.codecType = CodecType::UNKNOWN};
270}
271
Patty Huangac077ef2022-11-23 14:45:15 +0800272BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
273 const std::string& coding_direction) {
274 if (coding_direction == "invalid") {
275 return {.codecType = CodecType::UNKNOWN};
276 }
277
278 auto configuration_iter = configuration_map_.find(coding_direction);
279 if (configuration_iter == configuration_map_.end()) {
280 return {.codecType = CodecType::UNKNOWN};
281 }
282
283 auto codec_configuration_iter = codec_configuration_map_.find(
284 configuration_iter->second.getCodecConfiguration());
285 if (codec_configuration_iter == codec_configuration_map_.end()) {
286 return {.codecType = CodecType::UNKNOWN};
287 }
288
289 auto strategy_configuration_iter = strategy_configuration_map_.find(
290 configuration_iter->second.getStrategyConfiguration());
291 if (strategy_configuration_iter == strategy_configuration_map_.end()) {
292 return {.codecType = CodecType::UNKNOWN};
293 }
294
295 CodecType codec_type =
296 GetCodecType(codec_configuration_iter->second.getCodec());
297 std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
298 1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
299
300 if (codec_type == CodecType::LC3) {
301 return ComposeBroadcastCapability(
302 codec_type,
303 GetAudioLocation(
304 strategy_configuration_iter->second.getAudioLocation()),
305 strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
306 }
307 return {.codecType = CodecType::UNKNOWN};
308}
309
310template <class T>
311BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
312 const CodecType& codec_type, const AudioLocation& audio_location,
313 const uint8_t& channel_count, const std::vector<T>& capability) {
314 return {.codecType = codec_type,
315 .supportedChannel = audio_location,
316 .channelCountPerStream = channel_count,
317 .leAudioCodecCapabilities = std::optional(capability)};
318}
319
shihchienc8ed901a2022-09-06 08:44:44 +0000320template <class T>
321UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
322 const CodecType& codec_type, const AudioLocation& audio_location,
323 const uint8_t& device_cnt, const uint8_t& channel_count,
324 const T& capability) {
325 return {
326 .codecType = codec_type,
327 .supportedChannel = audio_location,
328 .deviceCount = device_cnt,
329 .channelCountPerDevice = channel_count,
330 .leAudioCodecCapabilities =
331 UnicastCapability::LeAudioCodecCapabilities(capability),
332 };
333}
334
335Lc3Capabilities BluetoothLeAudioCodecsProvider::ComposeLc3Capability(
336 const setting::CodecConfiguration& codec_configuration) {
337 return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
338 .frameDurationUs = {codec_configuration.getFrameDurationUs()},
339 .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
340}
341
Alice Kuof850de62023-10-04 04:02:24 +0800342AptxAdaptiveLeCapabilities
343BluetoothLeAudioCodecsProvider::ComposeAptxAdaptiveLeCapability(
344 const setting::CodecConfiguration& codec_configuration) {
345 return {.samplingFrequencyHz = {codec_configuration.getSamplingFrequency()},
346 .frameDurationUs = {codec_configuration.getFrameDurationUs()},
347 .octetsPerFrame = {codec_configuration.getOctetsPerCodecFrame()}};
348}
349
shihchienc8ed901a2022-09-06 08:44:44 +0000350AudioLocation BluetoothLeAudioCodecsProvider::GetAudioLocation(
351 const setting::AudioLocation& audio_location) {
352 switch (audio_location) {
353 case setting::AudioLocation::MONO:
354 return kMonoAudio;
355 case setting::AudioLocation::STEREO:
356 return kStereoAudio;
357 default:
358 return AudioLocation::UNKNOWN;
359 }
360}
361
362CodecType BluetoothLeAudioCodecsProvider::GetCodecType(
363 const setting::CodecType& codec_type) {
364 switch (codec_type) {
365 case setting::CodecType::LC3:
366 return CodecType::LC3;
Alice Kuof850de62023-10-04 04:02:24 +0800367 case setting::CodecType::APTX_ADAPTIVE_LE:
368 return CodecType::APTX_ADAPTIVE_LE;
369 case setting::CodecType::APTX_ADAPTIVE_LEX:
370 return CodecType::APTX_ADAPTIVE_LEX;
shihchienc8ed901a2022-09-06 08:44:44 +0000371 default:
372 return CodecType::UNKNOWN;
373 }
374}
375
376bool BluetoothLeAudioCodecsProvider::IsValidCodecConfiguration(
377 const setting::CodecConfiguration& codec_configuration) {
378 return codec_configuration.hasName() && codec_configuration.hasCodec() &&
379 codec_configuration.hasSamplingFrequency() &&
380 codec_configuration.hasFrameDurationUs() &&
381 codec_configuration.hasOctetsPerCodecFrame();
382}
383
384bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
385 const setting::StrategyConfiguration& strategy_configuration) {
386 if (!strategy_configuration.hasName() ||
387 !strategy_configuration.hasAudioLocation() ||
388 !strategy_configuration.hasConnectedDevice() ||
389 !strategy_configuration.hasChannelCount()) {
390 return false;
391 }
392 if (strategy_configuration.getAudioLocation() ==
393 setting::AudioLocation::STEREO) {
394 if ((strategy_configuration.getConnectedDevice() == 2 &&
395 strategy_configuration.getChannelCount() == 1) ||
396 (strategy_configuration.getConnectedDevice() == 1 &&
397 strategy_configuration.getChannelCount() == 2)) {
398 // Stereo
399 // 1. two connected device, one for L one for R
400 // 2. one connected device for both L and R
401 return true;
Patty Huangac077ef2022-11-23 14:45:15 +0800402 } else if (strategy_configuration.getConnectedDevice() == 0 &&
403 strategy_configuration.getChannelCount() == 2) {
404 // Broadcast
405 return true;
shihchienc8ed901a2022-09-06 08:44:44 +0000406 }
407 } else if (strategy_configuration.getAudioLocation() ==
408 setting::AudioLocation::MONO) {
409 if (strategy_configuration.getConnectedDevice() == 1 &&
410 strategy_configuration.getChannelCount() == 1) {
411 // Mono
412 return true;
413 }
414 }
415 return false;
416}
417
418} // namespace audio
419} // namespace bluetooth
420} // namespace hardware
421} // namespace android
422} // namespace aidl