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