1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "BTAudioCodecStatusAIDL"
18
19 #include "codec_status_aidl.h"
20
21 #include <bluetooth/log.h>
22
23 #include <unordered_set>
24 #include <vector>
25
26 #include "a2dp_aac_constants.h"
27 #include "a2dp_sbc_constants.h"
28 #include "a2dp_vendor_aptx_constants.h"
29 #include "a2dp_vendor_aptx_hd_constants.h"
30 #include "a2dp_vendor_ldac_constants.h"
31 #include "bta/av/bta_av_int.h"
32 #include "client_interface_aidl.h"
33
34 namespace bluetooth {
35 namespace audio {
36 namespace aidl {
37 namespace a2dp {
38 namespace codec {
39
40 using ::aidl::android::hardware::bluetooth::audio::AacCapabilities;
41 using ::aidl::android::hardware::bluetooth::audio::AacConfiguration;
42 using ::aidl::android::hardware::bluetooth::audio::AacObjectType;
43 using ::aidl::android::hardware::bluetooth::audio::AptxCapabilities;
44 using ::aidl::android::hardware::bluetooth::audio::AptxConfiguration;
45 using ::aidl::android::hardware::bluetooth::audio::AudioCapabilities;
46 using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
47 using ::aidl::android::hardware::bluetooth::audio::CodecCapabilities;
48 using ::aidl::android::hardware::bluetooth::audio::CodecType;
49 using ::aidl::android::hardware::bluetooth::audio::LdacCapabilities;
50 using ::aidl::android::hardware::bluetooth::audio::LdacChannelMode;
51 using ::aidl::android::hardware::bluetooth::audio::LdacConfiguration;
52 using ::aidl::android::hardware::bluetooth::audio::LdacQualityIndex;
53 using ::aidl::android::hardware::bluetooth::audio::OpusCapabilities;
54 using ::aidl::android::hardware::bluetooth::audio::OpusConfiguration;
55 using ::aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
56 using ::aidl::android::hardware::bluetooth::audio::SbcCapabilities;
57 using ::aidl::android::hardware::bluetooth::audio::SbcChannelMode;
58 using ::aidl::android::hardware::bluetooth::audio::SbcConfiguration;
59
60 namespace {
61
62 // capabilities from BluetoothAudioClientInterface::GetAudioCapabilities()
63 std::vector<AudioCapabilities> audio_hal_capabilities(0);
64 // capabilities that audio HAL supports and frameworks / Bluetooth SoC / runtime
65 // preference would like to use.
66 std::vector<AudioCapabilities> offloading_preference(0);
67
68 template <typename T>
69 struct identity {
70 typedef T type;
71 };
72
73 template <class T>
ContainedInVector(const std::vector<T> & vector,const typename identity<T>::type & target)74 bool ContainedInVector(const std::vector<T>& vector, const typename identity<T>::type& target) {
75 return std::find(vector.begin(), vector.end(), target) != vector.end();
76 }
77
sbc_offloading_capability_match(const SbcCapabilities & sbc_capability,const SbcConfiguration & sbc_config)78 bool sbc_offloading_capability_match(const SbcCapabilities& sbc_capability,
79 const SbcConfiguration& sbc_config) {
80 if (!ContainedInVector(sbc_capability.channelMode, sbc_config.channelMode) ||
81 !ContainedInVector(sbc_capability.allocMethod, sbc_config.allocMethod) ||
82 !ContainedInVector(sbc_capability.blockLength, sbc_config.blockLength) ||
83 !ContainedInVector(sbc_capability.numSubbands, sbc_config.numSubbands) ||
84 !ContainedInVector(sbc_capability.bitsPerSample, sbc_config.bitsPerSample) ||
85 !ContainedInVector(sbc_capability.sampleRateHz, sbc_config.sampleRateHz) ||
86 (sbc_config.minBitpool < sbc_capability.minBitpool ||
87 sbc_config.maxBitpool < sbc_config.minBitpool ||
88 sbc_capability.maxBitpool < sbc_config.maxBitpool)) {
89 log::warn("software codec={} capability={}", sbc_config.toString(), sbc_capability.toString());
90 return false;
91 }
92 log::info("offload codec={} capability={}", sbc_config.toString(), sbc_capability.toString());
93 return true;
94 }
95
aac_offloading_capability_match(const AacCapabilities & aac_capability,const AacConfiguration & aac_config)96 bool aac_offloading_capability_match(const AacCapabilities& aac_capability,
97 const AacConfiguration& aac_config) {
98 if (!ContainedInVector(aac_capability.channelMode, aac_config.channelMode) ||
99 !ContainedInVector(aac_capability.objectType, aac_config.objectType) ||
100 !ContainedInVector(aac_capability.bitsPerSample, aac_config.bitsPerSample) ||
101 !ContainedInVector(aac_capability.sampleRateHz, aac_config.sampleRateHz) ||
102 (!aac_capability.variableBitRateSupported && aac_config.variableBitRateEnabled)) {
103 log::warn("software codec={} capability={}", aac_config.toString(), aac_capability.toString());
104 return false;
105 }
106 log::info("offloading codec={} capability={}", aac_config.toString(), aac_capability.toString());
107 return true;
108 }
109
aptx_offloading_capability_match(const AptxCapabilities & aptx_capability,const AptxConfiguration & aptx_config)110 bool aptx_offloading_capability_match(const AptxCapabilities& aptx_capability,
111 const AptxConfiguration& aptx_config) {
112 if (!ContainedInVector(aptx_capability.channelMode, aptx_config.channelMode) ||
113 !ContainedInVector(aptx_capability.bitsPerSample, aptx_config.bitsPerSample) ||
114 !ContainedInVector(aptx_capability.sampleRateHz, aptx_config.sampleRateHz)) {
115 log::warn("software codec={} capability={}", aptx_config.toString(),
116 aptx_capability.toString());
117 return false;
118 }
119 log::info("offloading codec={} capability={}", aptx_config.toString(),
120 aptx_capability.toString());
121 return true;
122 }
123
ldac_offloading_capability_match(const LdacCapabilities & ldac_capability,const LdacConfiguration & ldac_config)124 bool ldac_offloading_capability_match(const LdacCapabilities& ldac_capability,
125 const LdacConfiguration& ldac_config) {
126 if (!ContainedInVector(ldac_capability.channelMode, ldac_config.channelMode) ||
127 !ContainedInVector(ldac_capability.bitsPerSample, ldac_config.bitsPerSample) ||
128 !ContainedInVector(ldac_capability.sampleRateHz, ldac_config.sampleRateHz)) {
129 log::warn("software codec={} capability={}", ldac_config.toString(),
130 ldac_capability.toString());
131 return false;
132 }
133 log::info("offloading codec={} capability={}", ldac_config.toString(),
134 ldac_capability.toString());
135 return true;
136 }
137
opus_offloading_capability_match(const std::optional<OpusCapabilities> & opus_capability,const std::optional<OpusConfiguration> & opus_config)138 bool opus_offloading_capability_match(const std::optional<OpusCapabilities>& opus_capability,
139 const std::optional<OpusConfiguration>& opus_config) {
140 if (!ContainedInVector(opus_capability->channelMode, opus_config->channelMode) ||
141 !ContainedInVector(opus_capability->frameDurationUs, opus_config->frameDurationUs) ||
142 !ContainedInVector(opus_capability->samplingFrequencyHz, opus_config->samplingFrequencyHz)) {
143 log::warn("software codec={} capability={}", opus_config->toString(),
144 opus_capability->toString());
145 return false;
146 }
147 log::info("offloading codec={} capability={}", opus_config->toString(),
148 opus_capability->toString());
149 return true;
150 }
151
152 } // namespace
153
154 const CodecConfiguration kInvalidCodecConfiguration = {};
155
A2dpCodecToHalSampleRate(const btav_a2dp_codec_config_t & a2dp_codec_config)156 int32_t A2dpCodecToHalSampleRate(const btav_a2dp_codec_config_t& a2dp_codec_config) {
157 switch (a2dp_codec_config.sample_rate) {
158 case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
159 return 44100;
160 case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
161 return 48000;
162 case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
163 return 88200;
164 case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
165 return 96000;
166 case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
167 return 176400;
168 case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
169 return 192000;
170 case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
171 return 16000;
172 case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
173 return 24000;
174 default:
175 return 0;
176 }
177 }
178
A2dpCodecToHalBitsPerSample(const btav_a2dp_codec_config_t & a2dp_codec_config)179 int8_t A2dpCodecToHalBitsPerSample(const btav_a2dp_codec_config_t& a2dp_codec_config) {
180 switch (a2dp_codec_config.bits_per_sample) {
181 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
182 return 16;
183 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
184 return 24;
185 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
186 return 32;
187 default:
188 return 0;
189 }
190 }
191
A2dpCodecToHalChannelMode(const btav_a2dp_codec_config_t & a2dp_codec_config)192 ChannelMode A2dpCodecToHalChannelMode(const btav_a2dp_codec_config_t& a2dp_codec_config) {
193 switch (a2dp_codec_config.channel_mode) {
194 case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
195 return ChannelMode::MONO;
196 case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
197 return ChannelMode::STEREO;
198 default:
199 return ChannelMode::UNKNOWN;
200 }
201 }
202
A2dpSbcToHalConfig(CodecConfiguration * codec_config,A2dpCodecConfig * a2dp_config)203 bool A2dpSbcToHalConfig(CodecConfiguration* codec_config, A2dpCodecConfig* a2dp_config) {
204 btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
205 if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_SBC &&
206 current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SINK_SBC) {
207 return false;
208 }
209 tBT_A2DP_OFFLOAD a2dp_offload;
210 a2dp_config->getCodecSpecificConfig(&a2dp_offload);
211 codec_config->codecType = CodecType::SBC;
212 SbcConfiguration sbc_config = {};
213 sbc_config.sampleRateHz = A2dpCodecToHalSampleRate(current_codec);
214 if (sbc_config.sampleRateHz <= 0) {
215 log::error("Unknown SBC sample_rate={}", current_codec.sample_rate);
216 return false;
217 }
218 uint8_t channel_mode = a2dp_offload.codec_info[3] & A2DP_SBC_IE_CH_MD_MSK;
219 switch (channel_mode) {
220 case A2DP_SBC_IE_CH_MD_JOINT:
221 sbc_config.channelMode = SbcChannelMode::JOINT_STEREO;
222 break;
223 case A2DP_SBC_IE_CH_MD_STEREO:
224 sbc_config.channelMode = SbcChannelMode::STEREO;
225 break;
226 case A2DP_SBC_IE_CH_MD_DUAL:
227 sbc_config.channelMode = SbcChannelMode::DUAL;
228 break;
229 case A2DP_SBC_IE_CH_MD_MONO:
230 sbc_config.channelMode = SbcChannelMode::MONO;
231 break;
232 default:
233 log::error("Unknown SBC channel_mode={}", channel_mode);
234 sbc_config.channelMode = SbcChannelMode::UNKNOWN;
235 return false;
236 }
237 uint8_t block_length = a2dp_offload.codec_info[0] & A2DP_SBC_IE_BLOCKS_MSK;
238 switch (block_length) {
239 case A2DP_SBC_IE_BLOCKS_4:
240 sbc_config.blockLength = 4;
241 break;
242 case A2DP_SBC_IE_BLOCKS_8:
243 sbc_config.blockLength = 8;
244 break;
245 case A2DP_SBC_IE_BLOCKS_12:
246 sbc_config.blockLength = 12;
247 break;
248 case A2DP_SBC_IE_BLOCKS_16:
249 sbc_config.blockLength = 16;
250 break;
251 default:
252 log::error("Unknown SBC block_length={}", block_length);
253 return false;
254 }
255 uint8_t sub_bands = a2dp_offload.codec_info[0] & A2DP_SBC_IE_SUBBAND_MSK;
256 switch (sub_bands) {
257 case A2DP_SBC_IE_SUBBAND_4:
258 sbc_config.numSubbands = 4;
259 break;
260 case A2DP_SBC_IE_SUBBAND_8:
261 sbc_config.numSubbands = 8;
262 break;
263 default:
264 log::error("Unknown SBC Subbands={}", sub_bands);
265 return false;
266 }
267 uint8_t alloc_method = a2dp_offload.codec_info[0] & A2DP_SBC_IE_ALLOC_MD_MSK;
268 switch (alloc_method) {
269 case A2DP_SBC_IE_ALLOC_MD_S:
270 sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_S;
271 break;
272 case A2DP_SBC_IE_ALLOC_MD_L:
273 sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_L;
274 break;
275 default:
276 log::error("Unknown SBC alloc_method={}", alloc_method);
277 return false;
278 }
279 sbc_config.minBitpool = a2dp_offload.codec_info[1];
280 sbc_config.maxBitpool = a2dp_offload.codec_info[2];
281 sbc_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
282 if (sbc_config.bitsPerSample <= 0) {
283 log::error("Unknown SBC bits_per_sample={}", current_codec.bits_per_sample);
284 return false;
285 }
286 codec_config->config.set<CodecConfiguration::CodecSpecific::sbcConfig>(sbc_config);
287 return true;
288 }
289
A2dpAacToHalConfig(CodecConfiguration * codec_config,A2dpCodecConfig * a2dp_config)290 bool A2dpAacToHalConfig(CodecConfiguration* codec_config, A2dpCodecConfig* a2dp_config) {
291 btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
292 if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_AAC &&
293 current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SINK_AAC) {
294 return false;
295 }
296 tBT_A2DP_OFFLOAD a2dp_offload;
297 a2dp_config->getCodecSpecificConfig(&a2dp_offload);
298 codec_config->codecType = CodecType::AAC;
299 AacConfiguration aac_config = {};
300 uint8_t object_type = a2dp_offload.codec_info[0];
301 switch (object_type) {
302 case A2DP_AAC_OBJECT_TYPE_MPEG2_LC:
303 aac_config.objectType = AacObjectType::MPEG2_LC;
304 break;
305 case A2DP_AAC_OBJECT_TYPE_MPEG4_LC:
306 aac_config.objectType = AacObjectType::MPEG4_LC;
307 break;
308 case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP:
309 aac_config.objectType = AacObjectType::MPEG4_LTP;
310 break;
311 case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE:
312 aac_config.objectType = AacObjectType::MPEG4_SCALABLE;
313 break;
314 default:
315 log::error("Unknown AAC object_type={}", object_type);
316 return false;
317 }
318 aac_config.sampleRateHz = A2dpCodecToHalSampleRate(current_codec);
319 if (aac_config.sampleRateHz <= 0) {
320 log::error("Unknown AAC sample_rate={}", current_codec.sample_rate);
321 return false;
322 }
323 aac_config.channelMode = A2dpCodecToHalChannelMode(current_codec);
324 if (aac_config.channelMode == ChannelMode::UNKNOWN) {
325 log::error("Unknown AAC channel_mode={}", current_codec.channel_mode);
326 return false;
327 }
328 uint8_t vbr_enabled = a2dp_offload.codec_info[1] & A2DP_AAC_VARIABLE_BIT_RATE_MASK;
329 switch (vbr_enabled) {
330 case A2DP_AAC_VARIABLE_BIT_RATE_ENABLED:
331 aac_config.variableBitRateEnabled = true;
332 break;
333 case A2DP_AAC_VARIABLE_BIT_RATE_DISABLED:
334 aac_config.variableBitRateEnabled = false;
335 break;
336 default:
337 log::error("Unknown AAC VBR={}", vbr_enabled);
338 return false;
339 }
340 aac_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
341 if (aac_config.bitsPerSample <= 0) {
342 log::error("Unknown AAC bits_per_sample={}", current_codec.bits_per_sample);
343 return false;
344 }
345 codec_config->config.set<CodecConfiguration::CodecSpecific::aacConfig>(aac_config);
346 return true;
347 }
348
A2dpAptxToHalConfig(CodecConfiguration * codec_config,A2dpCodecConfig * a2dp_config)349 bool A2dpAptxToHalConfig(CodecConfiguration* codec_config, A2dpCodecConfig* a2dp_config) {
350 btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
351 if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_APTX &&
352 current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD) {
353 return false;
354 }
355 tBT_A2DP_OFFLOAD a2dp_offload;
356 a2dp_config->getCodecSpecificConfig(&a2dp_offload);
357 if (current_codec.codec_type == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX) {
358 codec_config->codecType = CodecType::APTX;
359 } else {
360 codec_config->codecType = CodecType::APTX_HD;
361 }
362 AptxConfiguration aptx_config = {};
363 aptx_config.sampleRateHz = A2dpCodecToHalSampleRate(current_codec);
364 if (aptx_config.sampleRateHz <= 0) {
365 log::error("Unknown aptX sample_rate={}", current_codec.sample_rate);
366 return false;
367 }
368 aptx_config.channelMode = A2dpCodecToHalChannelMode(current_codec);
369 if (aptx_config.channelMode == ChannelMode::UNKNOWN) {
370 log::error("Unknown aptX channel_mode={}", current_codec.channel_mode);
371 return false;
372 }
373 aptx_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
374 if (aptx_config.bitsPerSample <= 0) {
375 log::error("Unknown aptX bits_per_sample={}", current_codec.bits_per_sample);
376 return false;
377 }
378 codec_config->config.set<CodecConfiguration::CodecSpecific::aptxConfig>(aptx_config);
379 return true;
380 }
381
A2dpLdacToHalConfig(CodecConfiguration * codec_config,A2dpCodecConfig * a2dp_config)382 bool A2dpLdacToHalConfig(CodecConfiguration* codec_config, A2dpCodecConfig* a2dp_config) {
383 btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
384 if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC) {
385 return false;
386 }
387 tBT_A2DP_OFFLOAD a2dp_offload;
388 a2dp_config->getCodecSpecificConfig(&a2dp_offload);
389 codec_config->codecType = CodecType::LDAC;
390 LdacConfiguration ldac_config = {};
391 ldac_config.sampleRateHz = A2dpCodecToHalSampleRate(current_codec);
392 if (ldac_config.sampleRateHz <= 0) {
393 log::error("Unknown LDAC sample_rate={}", current_codec.sample_rate);
394 return false;
395 }
396 switch (a2dp_offload.codec_info[7]) {
397 case A2DP_LDAC_CHANNEL_MODE_STEREO:
398 ldac_config.channelMode = LdacChannelMode::STEREO;
399 break;
400 case A2DP_LDAC_CHANNEL_MODE_DUAL:
401 ldac_config.channelMode = LdacChannelMode::DUAL;
402 break;
403 case A2DP_LDAC_CHANNEL_MODE_MONO:
404 ldac_config.channelMode = LdacChannelMode::MONO;
405 break;
406 default:
407 log::error("Unknown LDAC channel_mode={}", a2dp_offload.codec_info[7]);
408 ldac_config.channelMode = LdacChannelMode::UNKNOWN;
409 return false;
410 }
411 switch (a2dp_offload.codec_info[6]) {
412 case A2DP_LDAC_QUALITY_HIGH:
413 ldac_config.qualityIndex = LdacQualityIndex::HIGH;
414 break;
415 case A2DP_LDAC_QUALITY_MID:
416 ldac_config.qualityIndex = LdacQualityIndex::MID;
417 break;
418 case A2DP_LDAC_QUALITY_LOW:
419 ldac_config.qualityIndex = LdacQualityIndex::LOW;
420 break;
421 case A2DP_LDAC_QUALITY_ABR_OFFLOAD:
422 ldac_config.qualityIndex = LdacQualityIndex::ABR;
423 break;
424 default:
425 log::error("Unknown LDAC QualityIndex={}", a2dp_offload.codec_info[6]);
426 return false;
427 }
428 ldac_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
429 if (ldac_config.bitsPerSample <= 0) {
430 log::error("Unknown LDAC bits_per_sample={}", current_codec.bits_per_sample);
431 return false;
432 }
433 codec_config->config.set<CodecConfiguration::CodecSpecific::ldacConfig>(ldac_config);
434 return true;
435 }
436
A2dpOpusToHalConfig(CodecConfiguration * codec_config,A2dpCodecConfig * a2dp_config)437 bool A2dpOpusToHalConfig(CodecConfiguration* codec_config, A2dpCodecConfig* a2dp_config) {
438 btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
439 if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS) {
440 codec_config = {};
441 return false;
442 }
443 tBT_A2DP_OFFLOAD a2dp_offload;
444 a2dp_config->getCodecSpecificConfig(&a2dp_offload);
445 codec_config->codecType = CodecType::OPUS;
446 OpusConfiguration opus_config = {};
447
448 opus_config.pcmBitDepth = A2dpCodecToHalBitsPerSample(current_codec);
449 if (opus_config.pcmBitDepth <= 0) {
450 log::error("Unknown Opus bits_per_sample={}", current_codec.bits_per_sample);
451 return false;
452 }
453 opus_config.samplingFrequencyHz = A2dpCodecToHalSampleRate(current_codec);
454 if (opus_config.samplingFrequencyHz <= 0) {
455 log::error("Unknown Opus sample_rate={}", current_codec.sample_rate);
456 return false;
457 }
458 opus_config.channelMode = A2dpCodecToHalChannelMode(current_codec);
459 if (opus_config.channelMode == ChannelMode::UNKNOWN) {
460 log::error("Unknown Opus channel_mode={}", current_codec.channel_mode);
461 return false;
462 }
463
464 opus_config.frameDurationUs = 20000;
465
466 if (opus_config.channelMode == ChannelMode::STEREO) {
467 opus_config.octetsPerFrame = 640;
468 } else {
469 opus_config.octetsPerFrame = 320;
470 }
471
472 codec_config->config.set<CodecConfiguration::CodecSpecific::opusConfig>(opus_config);
473 return true;
474 }
475
UpdateOffloadingCapabilities(const std::vector<btav_a2dp_codec_config_t> & framework_preference)476 bool UpdateOffloadingCapabilities(
477 const std::vector<btav_a2dp_codec_config_t>& framework_preference) {
478 audio_hal_capabilities = BluetoothAudioClientInterface::GetAudioCapabilities(
479 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
480 std::unordered_set<CodecType> codec_type_set;
481 for (auto preference : framework_preference) {
482 switch (preference.codec_type) {
483 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
484 codec_type_set.insert(CodecType::SBC);
485 break;
486 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
487 codec_type_set.insert(CodecType::AAC);
488 break;
489 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
490 codec_type_set.insert(CodecType::APTX);
491 break;
492 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
493 codec_type_set.insert(CodecType::APTX_HD);
494 break;
495 case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
496 codec_type_set.insert(CodecType::LDAC);
497 break;
498 case BTAV_A2DP_CODEC_INDEX_SOURCE_LC3:
499 log::warn("Ignore source codec_type={}, not implemented", preference.codec_type);
500 break;
501 case BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS:
502 codec_type_set.insert(CodecType::OPUS);
503 break;
504 case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
505 [[fallthrough]];
506 case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
507 [[fallthrough]];
508 case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
509 [[fallthrough]];
510 case BTAV_A2DP_CODEC_INDEX_SINK_OPUS:
511 log::warn("Ignore sink codec_type={}", preference.codec_type);
512 break;
513 case BTAV_A2DP_CODEC_INDEX_MAX:
514 [[fallthrough]];
515 default:
516 log::error("Unknown codec_type={}", preference.codec_type);
517 return false;
518 }
519 }
520 offloading_preference.clear();
521 for (auto capability : audio_hal_capabilities) {
522 auto codec_type = capability.get<AudioCapabilities::a2dpCapabilities>().codecType;
523 if (codec_type_set.find(codec_type) != codec_type_set.end()) {
524 log::info("enabled offloading capability={}", capability.toString());
525 offloading_preference.push_back(capability);
526 } else {
527 log::info("disabled offloading capability={}", capability.toString());
528 }
529 }
530
531 // TODO: Bluetooth SoC and runtime property
532 return true;
533 }
534
535 /***
536 * Check whether this codec is supported by the audio HAL and is allowed to
537 * use by preference of framework / Bluetooth SoC / runtime property.
538 ***/
IsCodecOffloadingEnabled(const CodecConfiguration & codec_config)539 bool IsCodecOffloadingEnabled(const CodecConfiguration& codec_config) {
540 for (auto preference : offloading_preference) {
541 if (codec_config.codecType != preference.get<AudioCapabilities::a2dpCapabilities>().codecType) {
542 continue;
543 }
544 auto codec_capability = preference.get<AudioCapabilities::a2dpCapabilities>();
545 switch (codec_capability.codecType) {
546 case CodecType::SBC: {
547 auto sbc_capability = codec_capability.capabilities
548 .get<CodecCapabilities::Capabilities::sbcCapabilities>();
549 auto sbc_config = codec_config.config.get<CodecConfiguration::CodecSpecific::sbcConfig>();
550 return sbc_offloading_capability_match(sbc_capability, sbc_config);
551 }
552 case CodecType::AAC: {
553 auto aac_capability = codec_capability.capabilities
554 .get<CodecCapabilities::Capabilities::aacCapabilities>();
555 auto aac_config = codec_config.config.get<CodecConfiguration::CodecSpecific::aacConfig>();
556 return aac_offloading_capability_match(aac_capability, aac_config);
557 }
558 case CodecType::APTX:
559 [[fallthrough]];
560 case CodecType::APTX_HD: {
561 auto aptx_capability = codec_capability.capabilities
562 .get<CodecCapabilities::Capabilities::aptxCapabilities>();
563 auto aptx_config = codec_config.config.get<CodecConfiguration::CodecSpecific::aptxConfig>();
564 return aptx_offloading_capability_match(aptx_capability, aptx_config);
565 }
566 case CodecType::LDAC: {
567 auto ldac_capability = codec_capability.capabilities
568 .get<CodecCapabilities::Capabilities::ldacCapabilities>();
569 auto ldac_config = codec_config.config.get<CodecConfiguration::CodecSpecific::ldacConfig>();
570 return ldac_offloading_capability_match(ldac_capability, ldac_config);
571 }
572 case CodecType::OPUS: {
573 std::optional<OpusCapabilities> opus_capability =
574 codec_capability.capabilities
575 .get<CodecCapabilities::Capabilities::opusCapabilities>();
576 std::optional<OpusConfiguration> opus_config =
577 codec_config.config.get<CodecConfiguration::CodecSpecific::opusConfig>();
578 return opus_offloading_capability_match(opus_capability, opus_config);
579 }
580 case CodecType::UNKNOWN:
581 [[fallthrough]];
582 default:
583 log::error("Unknown codecType={}", toString(codec_capability.codecType));
584 return false;
585 }
586 }
587 log::info("software codec={}", codec_config.toString());
588 return false;
589 }
590
591 } // namespace codec
592 } // namespace a2dp
593 } // namespace aidl
594 } // namespace audio
595 } // namespace bluetooth
596