1 /*
2 * Copyright 2023 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 "AIDLA2dpProviderInfo"
18
19 #include "a2dp_provider_info.h"
20
21 #include <android/binder_manager.h>
22 #include <bluetooth/log.h>
23 #include <com_android_bluetooth_flags.h>
24
25 #include <optional>
26 #include <vector>
27
28 #include "a2dp_codec_api.h"
29 #include "a2dp_constants.h"
30 #include "a2dp_vendor.h"
31 #include "a2dp_vendor_aptx_constants.h"
32 #include "a2dp_vendor_aptx_hd_constants.h"
33 #include "a2dp_vendor_ldac_constants.h"
34 #include "a2dp_vendor_opus_constants.h"
35 #include "client_interface_aidl.h"
36 #include "os/log.h"
37
38 namespace bluetooth::audio::aidl::a2dp {
39
40 using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
41 using ::aidl::android::hardware::bluetooth::audio::CodecId;
42 using ::aidl::android::hardware::bluetooth::audio::CodecInfo;
43 using ::aidl::android::hardware::bluetooth::audio::
44 IBluetoothAudioProviderFactory;
45 using ::aidl::android::hardware::bluetooth::audio::SessionType;
46
47 /***
48 * Reads the provider information from the HAL.
49 * May return nullptr if the HAL does not implement
50 * getProviderInfo, or if the feature flag for codec
51 * extensibility is disabled.
52 ***/
GetProviderInfo(bool supports_a2dp_hw_offload_v2)53 std::unique_ptr<ProviderInfo> ProviderInfo::GetProviderInfo(
54 bool supports_a2dp_hw_offload_v2) {
55 if (!com::android::bluetooth::flags::a2dp_offload_codec_extensibility()) {
56 log::info(
57 "a2dp offload codec extensibility is disabled,"
58 " not going to load the ProviderInfo");
59 return nullptr;
60 }
61
62 if (!supports_a2dp_hw_offload_v2) {
63 log::info(
64 "a2dp hw offload v2 is not supported by the controller,"
65 " not going to load the ProviderInfo");
66 return nullptr;
67 }
68
69 auto source_provider_info = BluetoothAudioClientInterface::GetProviderInfo(
70 SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH, nullptr);
71
72 auto sink_provider_info = BluetoothAudioClientInterface::GetProviderInfo(
73 SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH, nullptr);
74
75 if (!source_provider_info.has_value() && !sink_provider_info.has_value()) {
76 log::info(
77 "a2dp offload codec extensibility is enabled,"
78 " but the provider info is empty");
79 return nullptr;
80 }
81
82 std::vector<CodecInfo> source_codecs;
83 std::vector<CodecInfo> sink_codecs;
84
85 if (source_provider_info.has_value()) {
86 source_codecs = std::move(source_provider_info->codecInfos);
87 }
88
89 if (sink_provider_info.has_value()) {
90 sink_codecs = std::move(sink_provider_info->codecInfos);
91 }
92
93 log::info("successfully loaded provider info");
94 return std::make_unique<ProviderInfo>(std::move(source_codecs),
95 std::move(sink_codecs));
96 }
97
98 /***
99 * Returns the codec with the selected index if supported
100 * by the provider.
101 ***/
GetCodec(btav_a2dp_codec_index_t codec_index) const102 std::optional<CodecInfo const*> ProviderInfo::GetCodec(
103 btav_a2dp_codec_index_t codec_index) const {
104 auto it = assigned_codec_indexes.find(codec_index);
105 return it == assigned_codec_indexes.end() ? std::nullopt
106 : std::make_optional(it->second);
107 }
108
109 /***
110 * Return the assigned source codec index if the codec
111 * matches a known codec, or pick a new codec index starting from
112 * ext_index.
113 ***/
assignSourceCodecIndex(CodecInfo const & codec,btav_a2dp_codec_index_t * ext_index)114 static std::optional<btav_a2dp_codec_index_t> assignSourceCodecIndex(
115 CodecInfo const& codec, btav_a2dp_codec_index_t* ext_index) {
116 switch (codec.id.getTag()) {
117 case CodecId::core:
118 default:
119 return std::nullopt;
120 case CodecId::a2dp:
121 switch (codec.id.get<CodecId::a2dp>()) {
122 case CodecId::A2dp::SBC:
123 return BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
124 case CodecId::A2dp::AAC:
125 return BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
126 default:
127 return std::nullopt;
128 }
129 break;
130 case CodecId::vendor: {
131 int vendor_id = codec.id.get<CodecId::vendor>().id;
132 int codec_id = codec.id.get<CodecId::vendor>().codecId;
133
134 /* match know vendor codecs */
135 if (vendor_id == A2DP_APTX_VENDOR_ID &&
136 codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
137 return BTAV_A2DP_CODEC_INDEX_SOURCE_APTX;
138 }
139 if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
140 codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
141 return BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD;
142 }
143 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
144 return BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC;
145 }
146 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
147 return BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS;
148 }
149
150 /* out of extension codec indexes */
151 if (*ext_index >= BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) {
152 log::error(
153 "unable to assign a source codec index for vendorId={}, codecId={}",
154 vendor_id, codec_id);
155 }
156
157 /* assign a new codec index for the
158 unknown vendor codec */
159 return *(ext_index++);
160 }
161 }
162 }
163
164 /***
165 * Return the assigned source codec index if the codec
166 * matches a known codec, or pick a new codec index starting from
167 * ext_index.
168 ***/
assignSinkCodecIndex(CodecInfo const & codec,btav_a2dp_codec_index_t * ext_index)169 static std::optional<btav_a2dp_codec_index_t> assignSinkCodecIndex(
170 CodecInfo const& codec, btav_a2dp_codec_index_t* ext_index) {
171 switch (codec.id.getTag()) {
172 case CodecId::core:
173 default:
174 return std::nullopt;
175 case CodecId::a2dp:
176 switch (codec.id.get<CodecId::a2dp>()) {
177 case CodecId::A2dp::SBC:
178 return BTAV_A2DP_CODEC_INDEX_SINK_SBC;
179 case CodecId::A2dp::AAC:
180 return BTAV_A2DP_CODEC_INDEX_SINK_AAC;
181 default:
182 return std::nullopt;
183 }
184 break;
185 case CodecId::vendor: {
186 int vendor_id = codec.id.get<CodecId::vendor>().id;
187 int codec_id = codec.id.get<CodecId::vendor>().codecId;
188
189 /* match know vendor codecs */
190 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
191 return BTAV_A2DP_CODEC_INDEX_SINK_LDAC;
192 }
193 if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
194 return BTAV_A2DP_CODEC_INDEX_SINK_OPUS;
195 }
196
197 /* out of extension codec indexes */
198 if (*ext_index >= BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX) {
199 log::error(
200 "unable to assign a sink codec index for vendorId={}, codecId={}",
201 vendor_id, codec_id);
202 }
203
204 /* assign a new codec index for the
205 unknown vendor codec */
206 return *(ext_index++);
207 }
208 }
209 }
210
ProviderInfo(std::vector<CodecInfo> source_codecs,std::vector<CodecInfo> sink_codecs)211 ProviderInfo::ProviderInfo(std::vector<CodecInfo> source_codecs,
212 std::vector<CodecInfo> sink_codecs)
213 : source_codecs(std::move(source_codecs)),
214 sink_codecs(std::move(sink_codecs)) {
215 btav_a2dp_codec_index_t ext_source_index =
216 BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN;
217 for (size_t i = 0; i < this->source_codecs.size(); i++) {
218 auto& codec = this->source_codecs[i];
219 log::info("supported source codec {}", codec.name);
220 auto index = assignSourceCodecIndex(codec, &ext_source_index);
221 if (index.has_value()) {
222 assigned_codec_indexes[index.value()] = &codec;
223 }
224 }
225
226 btav_a2dp_codec_index_t ext_sink_index = BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN;
227 for (size_t i = 0; i < this->sink_codecs.size(); i++) {
228 auto& codec = this->sink_codecs[i];
229 log::info("supports sink codec {}", codec.name);
230 auto index = assignSinkCodecIndex(codec, &ext_sink_index);
231 if (index.has_value()) {
232 assigned_codec_indexes[index.value()] = &codec;
233 }
234 }
235 }
236
SourceCodecIndex(CodecId const & codec_id) const237 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SourceCodecIndex(
238 CodecId const& codec_id) const {
239 for (auto const& [index, codec] : assigned_codec_indexes) {
240 if (codec->id == codec_id && index >= BTAV_A2DP_CODEC_INDEX_SOURCE_MIN &&
241 index < BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) {
242 return index;
243 }
244 }
245 return std::nullopt;
246 }
247
SourceCodecIndex(uint32_t vendor_id,uint16_t codec_id) const248 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SourceCodecIndex(
249 uint32_t vendor_id, uint16_t codec_id) const {
250 for (auto const& [index, codec] : assigned_codec_indexes) {
251 if (codec->id.getTag() == CodecId::vendor &&
252 codec->id.get<CodecId::vendor>().id == (int)vendor_id &&
253 codec->id.get<CodecId::vendor>().codecId == codec_id &&
254 index >= BTAV_A2DP_CODEC_INDEX_SOURCE_MIN &&
255 index < BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) {
256 return index;
257 }
258 }
259 return std::nullopt;
260 }
261
SourceCodecIndex(uint8_t const * codec_info) const262 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SourceCodecIndex(
263 uint8_t const* codec_info) const {
264 log::assert_that(codec_info != nullptr, "codec_info is unexpectedly null");
265 auto codec_type = A2DP_GetCodecType(codec_info);
266 switch (codec_type) {
267 case A2DP_MEDIA_CT_SBC: {
268 return SourceCodecIndex(CodecId::A2dp(CodecId::A2dp::SBC));
269 }
270 case A2DP_MEDIA_CT_AAC: {
271 return SourceCodecIndex(CodecId::A2dp(CodecId::A2dp::AAC));
272 }
273 case A2DP_MEDIA_CT_NON_A2DP: {
274 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(codec_info);
275 uint16_t codec_id = A2DP_VendorCodecGetCodecId(codec_info);
276 return SourceCodecIndex(vendor_id, codec_id);
277 }
278 default: {
279 return std::nullopt;
280 }
281 }
282 }
283
SinkCodecIndex(CodecId const & codec_id) const284 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SinkCodecIndex(
285 CodecId const& codec_id) const {
286 for (auto const& [index, codec] : assigned_codec_indexes) {
287 if (codec->id == codec_id && index >= BTAV_A2DP_CODEC_INDEX_SINK_MIN &&
288 index < BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX) {
289 return index;
290 }
291 }
292 return std::nullopt;
293 }
294
SinkCodecIndex(uint32_t vendor_id,uint16_t codec_id) const295 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SinkCodecIndex(
296 uint32_t vendor_id, uint16_t codec_id) const {
297 for (auto const& [index, codec] : assigned_codec_indexes) {
298 if (codec->id.getTag() == CodecId::vendor &&
299 codec->id.get<CodecId::vendor>().id == (int)vendor_id &&
300 codec->id.get<CodecId::vendor>().codecId == codec_id &&
301 index >= BTAV_A2DP_CODEC_INDEX_SINK_MIN &&
302 index < BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX) {
303 return index;
304 }
305 }
306 return std::nullopt;
307 }
308
SinkCodecIndex(uint8_t const * codec_info) const309 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SinkCodecIndex(
310 uint8_t const* codec_info) const {
311 log::assert_that(codec_info != nullptr, "codec_info is unexpectedly null");
312 auto codec_type = A2DP_GetCodecType(codec_info);
313 switch (codec_type) {
314 case A2DP_MEDIA_CT_SBC: {
315 return SinkCodecIndex(CodecId::A2dp(CodecId::A2dp::SBC));
316 }
317 case A2DP_MEDIA_CT_AAC: {
318 return SinkCodecIndex(CodecId::A2dp(CodecId::A2dp::AAC));
319 }
320 case A2DP_MEDIA_CT_NON_A2DP: {
321 uint32_t vendor_id = A2DP_VendorCodecGetVendorId(codec_info);
322 uint16_t codec_id = A2DP_VendorCodecGetCodecId(codec_info);
323 return SinkCodecIndex(vendor_id, codec_id);
324 }
325 default: {
326 return std::nullopt;
327 }
328 }
329 }
330
CodecIndexStr(btav_a2dp_codec_index_t codec_index) const331 std::optional<const char*> ProviderInfo::CodecIndexStr(
332 btav_a2dp_codec_index_t codec_index) const {
333 auto it = assigned_codec_indexes.find(codec_index);
334 return it != assigned_codec_indexes.end()
335 ? std::make_optional(it->second->name.c_str())
336 : std::nullopt;
337 }
338
SupportsCodec(btav_a2dp_codec_index_t codec_index) const339 bool ProviderInfo::SupportsCodec(btav_a2dp_codec_index_t codec_index) const {
340 return assigned_codec_indexes.find(codec_index) !=
341 assigned_codec_indexes.end();
342 }
343
BuildCodecCapabilities(CodecId const & codec_id,std::vector<uint8_t> const & capabilities,uint8_t * codec_info)344 bool ProviderInfo::BuildCodecCapabilities(
345 CodecId const& codec_id, std::vector<uint8_t> const& capabilities,
346 uint8_t* codec_info) {
347 switch (codec_id.getTag()) {
348 case CodecId::a2dp: {
349 auto id = codec_id.get<CodecId::a2dp>();
350 codec_info[0] = 2 + capabilities.size();
351 codec_info[1] = AVDT_MEDIA_TYPE_AUDIO << 4;
352 codec_info[2] = static_cast<uint8_t>(id);
353 memcpy(codec_info + 3, capabilities.data(), capabilities.size());
354 return true;
355 }
356 case CodecId::vendor: {
357 auto id = codec_id.get<CodecId::vendor>();
358 uint32_t vendor_id = static_cast<uint32_t>(id.id);
359 uint16_t codec_id = static_cast<uint16_t>(id.codecId);
360 codec_info[0] = 8 + capabilities.size();
361 codec_info[1] = AVDT_MEDIA_TYPE_AUDIO << 4;
362 codec_info[2] = A2DP_MEDIA_CT_NON_A2DP;
363 codec_info[3] = static_cast<uint8_t>(vendor_id >> 0);
364 codec_info[4] = static_cast<uint8_t>(vendor_id >> 8);
365 codec_info[5] = static_cast<uint8_t>(vendor_id >> 16);
366 codec_info[6] = static_cast<uint8_t>(vendor_id >> 24);
367 codec_info[7] = static_cast<uint8_t>(codec_id >> 0);
368 codec_info[8] = static_cast<uint8_t>(codec_id >> 8);
369 memcpy(codec_info + 9, capabilities.data(), capabilities.size());
370 return true;
371 }
372 case CodecId::core:
373 default:
374 break;
375 }
376 return false;
377 }
378
CodecCapabilities(btav_a2dp_codec_index_t codec_index,uint64_t * codec_id,uint8_t * codec_info,btav_a2dp_codec_config_t * codec_config) const379 bool ProviderInfo::CodecCapabilities(
380 btav_a2dp_codec_index_t codec_index, uint64_t* codec_id,
381 uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) const {
382 auto it = assigned_codec_indexes.find(codec_index);
383 if (it == assigned_codec_indexes.end()) {
384 return false;
385 }
386
387 CodecInfo const* codec = it->second;
388 auto transport = codec->transport.get<CodecInfo::Transport::a2dp>();
389
390 if (codec_id != nullptr) {
391 switch (codec->id.getTag()) {
392 case CodecId::a2dp: {
393 auto id = codec->id.get<CodecId::a2dp>();
394 *codec_id = static_cast<uint8_t>(id);
395 break;
396 }
397 case CodecId::vendor: {
398 auto id = codec->id.get<CodecId::vendor>();
399 *codec_id = 0xff | (static_cast<uint64_t>(id.id) << 8) |
400 (static_cast<uint64_t>(id.codecId) << 24);
401 break;
402 }
403 default:
404 break;
405 }
406 }
407 if (codec_config != nullptr) {
408 memset(codec_config, 0, sizeof(*codec_config));
409 for (auto const& channel_mode : transport.channelMode) {
410 switch (channel_mode) {
411 case ChannelMode::MONO:
412 codec_config->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
413 break;
414 case ChannelMode::STEREO:
415 codec_config->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
416 break;
417 case ChannelMode::DUALMONO:
418 case ChannelMode::UNKNOWN:
419 default:
420 break;
421 }
422 }
423 for (auto const& sample_rate : transport.samplingFrequencyHz) {
424 switch (sample_rate) {
425 case 44100:
426 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
427 break;
428 case 48000:
429 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
430 break;
431 case 88200:
432 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
433 break;
434 case 96000:
435 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
436 break;
437 case 176400:
438 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
439 break;
440 case 192000:
441 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
442 break;
443 case 16000:
444 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
445 break;
446 case 24000:
447 codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
448 break;
449 default:
450 break;
451 }
452 }
453 for (auto const& bitdepth : transport.bitdepth) {
454 switch (bitdepth) {
455 case 16:
456 codec_config->bits_per_sample |= BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
457 break;
458 case 24:
459 codec_config->bits_per_sample |= BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24;
460 break;
461 case 32:
462 codec_config->bits_per_sample |= BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
463 break;
464 default:
465 break;
466 }
467 }
468 }
469
470 return codec_info == nullptr ||
471 BuildCodecCapabilities(codec->id, transport.capabilities, codec_info);
472 }
473
474 } // namespace bluetooth::audio::aidl::a2dp
475