blob: b4cba495021a7527fcf8212f0150277079383dd1 [file] [log] [blame]
Josh Wu20bac522021-12-29 23:52:39 -08001/*
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 "BTAudioCodecsAidl"
18
19#include "BluetoothAudioCodecs.h"
20
21#include <aidl/android/hardware/bluetooth/audio/AacCapabilities.h>
22#include <aidl/android/hardware/bluetooth/audio/AacObjectType.h>
23#include <aidl/android/hardware/bluetooth/audio/AptxCapabilities.h>
24#include <aidl/android/hardware/bluetooth/audio/ChannelMode.h>
25#include <aidl/android/hardware/bluetooth/audio/LdacCapabilities.h>
26#include <aidl/android/hardware/bluetooth/audio/LdacChannelMode.h>
27#include <aidl/android/hardware/bluetooth/audio/LdacQualityIndex.h>
28#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
Omer Osmana2587da2022-05-01 03:54:11 +000029#include <aidl/android/hardware/bluetooth/audio/OpusCapabilities.h>
30#include <aidl/android/hardware/bluetooth/audio/OpusConfiguration.h>
Josh Wu20bac522021-12-29 23:52:39 -080031#include <aidl/android/hardware/bluetooth/audio/SbcCapabilities.h>
32#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
33#include <android-base/logging.h>
34
shihchienc8ed901a2022-09-06 08:44:44 +000035#include "BluetoothLeAudioCodecsProvider.h"
36
Josh Wu20bac522021-12-29 23:52:39 -080037namespace aidl {
38namespace android {
39namespace hardware {
40namespace bluetooth {
41namespace audio {
42
43static const PcmCapabilities kDefaultSoftwarePcmCapabilities = {
Ɓukasz Rymanowski4d14c1e2022-05-06 17:12:50 +000044 .sampleRateHz = {16000, 24000, 32000, 44100, 48000, 88200, 96000},
Josh Wu20bac522021-12-29 23:52:39 -080045 .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
46 .bitsPerSample = {16, 24, 32},
47 .dataIntervalUs = {},
48};
49
50static const SbcCapabilities kDefaultOffloadSbcCapability = {
51 .sampleRateHz = {44100},
52 .channelMode = {SbcChannelMode::MONO, SbcChannelMode::JOINT_STEREO},
53 .blockLength = {4, 8, 12, 16},
54 .numSubbands = {8},
55 .allocMethod = {SbcAllocMethod::ALLOC_MD_L},
56 .bitsPerSample = {16},
57 .minBitpool = 2,
58 .maxBitpool = 53};
59
60static const AacCapabilities kDefaultOffloadAacCapability = {
61 .objectType = {AacObjectType::MPEG2_LC},
62 .sampleRateHz = {44100},
63 .channelMode = {ChannelMode::STEREO},
64 .variableBitRateSupported = true,
65 .bitsPerSample = {16}};
66
67static const LdacCapabilities kDefaultOffloadLdacCapability = {
68 .sampleRateHz = {44100, 48000, 88200, 96000},
69 .channelMode = {LdacChannelMode::DUAL, LdacChannelMode::STEREO},
70 .qualityIndex = {LdacQualityIndex::HIGH},
71 .bitsPerSample = {16, 24, 32}};
72
73static const AptxCapabilities kDefaultOffloadAptxCapability = {
74 .sampleRateHz = {44100, 48000},
75 .channelMode = {ChannelMode::STEREO},
76 .bitsPerSample = {16},
77};
78
79static const AptxCapabilities kDefaultOffloadAptxHdCapability = {
80 .sampleRateHz = {44100, 48000},
81 .channelMode = {ChannelMode::STEREO},
82 .bitsPerSample = {24},
83};
84
Omer Osmana2587da2022-05-01 03:54:11 +000085static const OpusCapabilities kDefaultOffloadOpusCapability = {
86 .samplingFrequencyHz = {48000},
87 .frameDurationUs = {10000, 20000},
Josh Wu20bac522021-12-29 23:52:39 -080088 .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
89};
90
91const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
92 {.codecType = CodecType::SBC, .capabilities = {}},
93 {.codecType = CodecType::AAC, .capabilities = {}},
94 {.codecType = CodecType::LDAC, .capabilities = {}},
95 {.codecType = CodecType::APTX, .capabilities = {}},
96 {.codecType = CodecType::APTX_HD, .capabilities = {}},
Omer Osmana2587da2022-05-01 03:54:11 +000097 {.codecType = CodecType::OPUS, .capabilities = {}}};
Josh Wu20bac522021-12-29 23:52:39 -080098
99std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
100
Josh Wu20bac522021-12-29 23:52:39 -0800101template <class T>
102bool BluetoothAudioCodecs::ContainedInVector(
103 const std::vector<T>& vector, const typename identity<T>::type& target) {
104 return std::find(vector.begin(), vector.end(), target) != vector.end();
105}
106
107bool BluetoothAudioCodecs::IsOffloadSbcConfigurationValid(
108 const CodecConfiguration::CodecSpecific& codec_specific) {
109 if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::sbcConfig) {
110 LOG(WARNING) << __func__
111 << ": Invalid CodecSpecific=" << codec_specific.toString();
112 return false;
113 }
114 const SbcConfiguration sbc_data =
115 codec_specific.get<CodecConfiguration::CodecSpecific::sbcConfig>();
116
117 if (ContainedInVector(kDefaultOffloadSbcCapability.sampleRateHz,
118 sbc_data.sampleRateHz) &&
119 ContainedInVector(kDefaultOffloadSbcCapability.blockLength,
120 sbc_data.blockLength) &&
121 ContainedInVector(kDefaultOffloadSbcCapability.numSubbands,
122 sbc_data.numSubbands) &&
123 ContainedInVector(kDefaultOffloadSbcCapability.bitsPerSample,
124 sbc_data.bitsPerSample) &&
125 ContainedInVector(kDefaultOffloadSbcCapability.channelMode,
126 sbc_data.channelMode) &&
127 ContainedInVector(kDefaultOffloadSbcCapability.allocMethod,
128 sbc_data.allocMethod) &&
129 sbc_data.minBitpool <= sbc_data.maxBitpool &&
130 kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
131 kDefaultOffloadSbcCapability.maxBitpool >= sbc_data.maxBitpool) {
132 return true;
133 }
134 LOG(WARNING) << __func__
135 << ": Unsupported CodecSpecific=" << codec_specific.toString();
136 return false;
137}
138
139bool BluetoothAudioCodecs::IsOffloadAacConfigurationValid(
140 const CodecConfiguration::CodecSpecific& codec_specific) {
141 if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::aacConfig) {
142 LOG(WARNING) << __func__
143 << ": Invalid CodecSpecific=" << codec_specific.toString();
144 return false;
145 }
146 const AacConfiguration aac_data =
147 codec_specific.get<CodecConfiguration::CodecSpecific::aacConfig>();
148
149 if (ContainedInVector(kDefaultOffloadAacCapability.sampleRateHz,
150 aac_data.sampleRateHz) &&
151 ContainedInVector(kDefaultOffloadAacCapability.bitsPerSample,
152 aac_data.bitsPerSample) &&
153 ContainedInVector(kDefaultOffloadAacCapability.channelMode,
154 aac_data.channelMode) &&
155 ContainedInVector(kDefaultOffloadAacCapability.objectType,
156 aac_data.objectType) &&
157 (!aac_data.variableBitRateEnabled ||
158 kDefaultOffloadAacCapability.variableBitRateSupported)) {
159 return true;
160 }
161 LOG(WARNING) << __func__
162 << ": Unsupported CodecSpecific=" << codec_specific.toString();
163 return false;
164}
165
166bool BluetoothAudioCodecs::IsOffloadLdacConfigurationValid(
167 const CodecConfiguration::CodecSpecific& codec_specific) {
168 if (codec_specific.getTag() !=
169 CodecConfiguration::CodecSpecific::ldacConfig) {
170 LOG(WARNING) << __func__
171 << ": Invalid CodecSpecific=" << codec_specific.toString();
172 return false;
173 }
174 const LdacConfiguration ldac_data =
175 codec_specific.get<CodecConfiguration::CodecSpecific::ldacConfig>();
176
177 if (ContainedInVector(kDefaultOffloadLdacCapability.sampleRateHz,
178 ldac_data.sampleRateHz) &&
179 ContainedInVector(kDefaultOffloadLdacCapability.bitsPerSample,
180 ldac_data.bitsPerSample) &&
181 ContainedInVector(kDefaultOffloadLdacCapability.channelMode,
182 ldac_data.channelMode) &&
183 ContainedInVector(kDefaultOffloadLdacCapability.qualityIndex,
184 ldac_data.qualityIndex)) {
185 return true;
186 }
187 LOG(WARNING) << __func__
188 << ": Unsupported CodecSpecific=" << codec_specific.toString();
189 return false;
190}
191
192bool BluetoothAudioCodecs::IsOffloadAptxConfigurationValid(
193 const CodecConfiguration::CodecSpecific& codec_specific) {
194 if (codec_specific.getTag() !=
195 CodecConfiguration::CodecSpecific::aptxConfig) {
196 LOG(WARNING) << __func__
197 << ": Invalid CodecSpecific=" << codec_specific.toString();
198 return false;
199 }
200 const AptxConfiguration aptx_data =
201 codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
202
203 if (ContainedInVector(kDefaultOffloadAptxCapability.sampleRateHz,
204 aptx_data.sampleRateHz) &&
205 ContainedInVector(kDefaultOffloadAptxCapability.bitsPerSample,
206 aptx_data.bitsPerSample) &&
207 ContainedInVector(kDefaultOffloadAptxCapability.channelMode,
208 aptx_data.channelMode)) {
209 return true;
210 }
211 LOG(WARNING) << __func__
212 << ": Unsupported CodecSpecific=" << codec_specific.toString();
213 return false;
214}
215
216bool BluetoothAudioCodecs::IsOffloadAptxHdConfigurationValid(
217 const CodecConfiguration::CodecSpecific& codec_specific) {
218 if (codec_specific.getTag() !=
219 CodecConfiguration::CodecSpecific::aptxConfig) {
220 LOG(WARNING) << __func__
221 << ": Invalid CodecSpecific=" << codec_specific.toString();
222 return false;
223 }
224 const AptxConfiguration aptx_data =
225 codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
226
227 if (ContainedInVector(kDefaultOffloadAptxHdCapability.sampleRateHz,
228 aptx_data.sampleRateHz) &&
229 ContainedInVector(kDefaultOffloadAptxHdCapability.bitsPerSample,
230 aptx_data.bitsPerSample) &&
231 ContainedInVector(kDefaultOffloadAptxHdCapability.channelMode,
232 aptx_data.channelMode)) {
233 return true;
234 }
235 LOG(WARNING) << __func__
236 << ": Unsupported CodecSpecific=" << codec_specific.toString();
237 return false;
238}
239
Omer Osmana2587da2022-05-01 03:54:11 +0000240bool BluetoothAudioCodecs::IsOffloadOpusConfigurationValid(
Josh Wu20bac522021-12-29 23:52:39 -0800241 const CodecConfiguration::CodecSpecific& codec_specific) {
Omer Osmana2587da2022-05-01 03:54:11 +0000242 if (codec_specific.getTag() !=
243 CodecConfiguration::CodecSpecific::opusConfig) {
Josh Wu20bac522021-12-29 23:52:39 -0800244 LOG(WARNING) << __func__
245 << ": Invalid CodecSpecific=" << codec_specific.toString();
246 return false;
247 }
Omer Osmana2587da2022-05-01 03:54:11 +0000248 std::optional<OpusConfiguration> opus_data =
249 codec_specific.get<CodecConfiguration::CodecSpecific::opusConfig>();
Josh Wu20bac522021-12-29 23:52:39 -0800250
Omer Osmana2587da2022-05-01 03:54:11 +0000251 if (opus_data.has_value() &&
252 ContainedInVector(kDefaultOffloadOpusCapability.samplingFrequencyHz,
253 opus_data->samplingFrequencyHz) &&
254 ContainedInVector(kDefaultOffloadOpusCapability.frameDurationUs,
255 opus_data->frameDurationUs) &&
256 ContainedInVector(kDefaultOffloadOpusCapability.channelMode,
257 opus_data->channelMode)) {
Josh Wu20bac522021-12-29 23:52:39 -0800258 return true;
259 }
260 LOG(WARNING) << __func__
261 << ": Unsupported CodecSpecific=" << codec_specific.toString();
262 return false;
263}
264
Josh Wu20bac522021-12-29 23:52:39 -0800265std::vector<PcmCapabilities>
266BluetoothAudioCodecs::GetSoftwarePcmCapabilities() {
267 return {kDefaultSoftwarePcmCapabilities};
268}
269
270std::vector<CodecCapabilities>
271BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(
272 const SessionType& session_type) {
Alice Kuoadcceec2022-03-28 13:28:43 +0800273 if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
274 session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800275 return {};
276 }
277 std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
278 kDefaultOffloadA2dpCodecCapabilities;
279 for (auto& codec_capability : offload_a2dp_codec_capabilities) {
280 switch (codec_capability.codecType) {
281 case CodecType::SBC:
282 codec_capability.capabilities
283 .set<CodecCapabilities::Capabilities::sbcCapabilities>(
284 kDefaultOffloadSbcCapability);
285 break;
286 case CodecType::AAC:
287 codec_capability.capabilities
288 .set<CodecCapabilities::Capabilities::aacCapabilities>(
289 kDefaultOffloadAacCapability);
290 break;
291 case CodecType::LDAC:
292 codec_capability.capabilities
293 .set<CodecCapabilities::Capabilities::ldacCapabilities>(
294 kDefaultOffloadLdacCapability);
295 break;
296 case CodecType::APTX:
297 codec_capability.capabilities
298 .set<CodecCapabilities::Capabilities::aptxCapabilities>(
299 kDefaultOffloadAptxCapability);
300 break;
301 case CodecType::APTX_HD:
302 codec_capability.capabilities
303 .set<CodecCapabilities::Capabilities::aptxCapabilities>(
304 kDefaultOffloadAptxHdCapability);
305 break;
Omer Osmana2587da2022-05-01 03:54:11 +0000306 case CodecType::OPUS:
Josh Wu20bac522021-12-29 23:52:39 -0800307 codec_capability.capabilities
Omer Osmana2587da2022-05-01 03:54:11 +0000308 .set<CodecCapabilities::Capabilities::opusCapabilities>(
309 kDefaultOffloadOpusCapability);
Josh Wu20bac522021-12-29 23:52:39 -0800310 break;
311 case CodecType::UNKNOWN:
Alice Kuo79c936d2022-01-20 23:10:10 +0800312 case CodecType::VENDOR:
Omer Osmana2587da2022-05-01 03:54:11 +0000313 case CodecType::LC3:
Sagar Vermad13bbb32022-01-08 20:09:04 +0530314 case CodecType::APTX_ADAPTIVE:
Sagar Verma62df9102022-12-07 17:56:04 +0530315 case CodecType::APTX_ADAPTIVE_LE:
316 case CodecType::APTX_ADAPTIVE_LEX:
Josh Wu20bac522021-12-29 23:52:39 -0800317 break;
318 }
319 }
320 return offload_a2dp_codec_capabilities;
321}
322
323bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(
324 const PcmConfiguration& pcm_config) {
325 if (ContainedInVector(kDefaultSoftwarePcmCapabilities.sampleRateHz,
326 pcm_config.sampleRateHz) &&
327 ContainedInVector(kDefaultSoftwarePcmCapabilities.bitsPerSample,
328 pcm_config.bitsPerSample) &&
329 ContainedInVector(kDefaultSoftwarePcmCapabilities.channelMode,
330 pcm_config.channelMode)
331 // data interval is not checked for now
332 // && pcm_config.dataIntervalUs != 0
333 ) {
334 return true;
335 }
336 LOG(WARNING) << __func__
337 << ": Unsupported CodecSpecific=" << pcm_config.toString();
338 return false;
339}
340
341bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
342 const SessionType& session_type, const CodecConfiguration& codec_config) {
Alice Kuoadcceec2022-03-28 13:28:43 +0800343 if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
344 session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800345 LOG(ERROR) << __func__
346 << ": Invalid SessionType=" << toString(session_type);
347 return false;
348 }
349 const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
350 switch (codec_config.codecType) {
351 case CodecType::SBC:
352 if (IsOffloadSbcConfigurationValid(codec_specific)) {
353 return true;
354 }
355 break;
356 case CodecType::AAC:
357 if (IsOffloadAacConfigurationValid(codec_specific)) {
358 return true;
359 }
360 break;
361 case CodecType::LDAC:
362 if (IsOffloadLdacConfigurationValid(codec_specific)) {
363 return true;
364 }
365 break;
366 case CodecType::APTX:
367 if (IsOffloadAptxConfigurationValid(codec_specific)) {
368 return true;
369 }
370 break;
371 case CodecType::APTX_HD:
372 if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
373 return true;
374 }
375 break;
Omer Osmana2587da2022-05-01 03:54:11 +0000376 case CodecType::OPUS:
377 if (IsOffloadOpusConfigurationValid(codec_specific)) {
Josh Wu20bac522021-12-29 23:52:39 -0800378 return true;
379 }
380 break;
Sagar Vermad13bbb32022-01-08 20:09:04 +0530381 case CodecType::APTX_ADAPTIVE:
Sagar Verma62df9102022-12-07 17:56:04 +0530382 case CodecType::APTX_ADAPTIVE_LE:
383 case CodecType::APTX_ADAPTIVE_LEX:
Omer Osmana2587da2022-05-01 03:54:11 +0000384 case CodecType::LC3:
Josh Wu20bac522021-12-29 23:52:39 -0800385 case CodecType::UNKNOWN:
Alice Kuo79c936d2022-01-20 23:10:10 +0800386 case CodecType::VENDOR:
Josh Wu20bac522021-12-29 23:52:39 -0800387 break;
388 }
389 return false;
390}
391
Josh Wu20bac522021-12-29 23:52:39 -0800392std::vector<LeAudioCodecCapabilitiesSetting>
393BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
394 const SessionType& session_type) {
395 if (session_type !=
396 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
397 session_type !=
Josh Wu5d50dc02022-02-15 08:41:53 -0800398 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
399 session_type !=
400 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
Josh Wu20bac522021-12-29 23:52:39 -0800401 return std::vector<LeAudioCodecCapabilitiesSetting>(0);
402 }
403
404 if (kDefaultOffloadLeAudioCapabilities.empty()) {
shihchiencd7f565a2022-10-14 13:45:37 +0000405 auto le_audio_offload_setting =
406 BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile();
shihchienc8ed901a2022-09-06 08:44:44 +0000407 kDefaultOffloadLeAudioCapabilities =
shihchiencd7f565a2022-10-14 13:45:37 +0000408 BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
409 le_audio_offload_setting);
Sagar Verma62df9102022-12-07 17:56:04 +0530410 }
Josh Wu20bac522021-12-29 23:52:39 -0800411 return kDefaultOffloadLeAudioCapabilities;
412}
413
414} // namespace audio
415} // namespace bluetooth
416} // namespace hardware
417} // namespace android
Sagar Vermad13bbb32022-01-08 20:09:04 +0530418} // namespace aidl