blob: a692d84f998b477fa36827a53809122d30d24c0e [file] [log] [blame]
Josh Wu6ab53e72021-12-29 23:53:33 -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
Josh Wu98d7e082022-01-21 03:04:21 -080017#define LOG_TAG "BTAudioProviderLeAudioHW"
Josh Wu6ab53e72021-12-29 23:53:33 -080018
19#include "LeAudioOffloadAudioProvider.h"
20
21#include <BluetoothAudioCodecs.h>
22#include <BluetoothAudioSessionReport.h>
23#include <android-base/logging.h>
24
25namespace aidl {
26namespace android {
27namespace hardware {
28namespace bluetooth {
29namespace audio {
30
Bao Do867af602023-11-15 05:41:12 +000031constexpr uint8_t kLeAudioDirectionSink = 0x01;
32constexpr uint8_t kLeAudioDirectionSource = 0x02;
33
34const std::map<CodecSpecificConfigurationLtv::SamplingFrequency, uint32_t>
35 freq_to_support_bitmask_map = {
36 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000,
37 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000},
38 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025,
39 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ11025},
40 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
41 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000},
42 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ22050,
43 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ22050},
44 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
45 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ24000},
46 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000,
47 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ32000},
48 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000,
49 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000},
50 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ88200,
51 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ88200},
52 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000,
53 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ96000},
54 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ176400,
55 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ176400},
56 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ192000,
57 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ192000},
58 {CodecSpecificConfigurationLtv::SamplingFrequency::HZ384000,
59 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ384000},
60};
61
62// Helper map from capability's tag to configuration's tag
63std::map<CodecSpecificCapabilitiesLtv::Tag, CodecSpecificConfigurationLtv::Tag>
64 cap_to_cfg_tag_map = {
65 {CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies,
66 CodecSpecificConfigurationLtv::Tag::samplingFrequency},
67 {CodecSpecificCapabilitiesLtv::Tag::supportedMaxCodecFramesPerSDU,
68 CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU},
69 {CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations,
70 CodecSpecificConfigurationLtv::Tag::frameDuration},
71 {CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts,
72 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation},
73 {CodecSpecificCapabilitiesLtv::Tag::supportedOctetsPerCodecFrame,
74 CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame},
75};
76
77const std::map<CodecSpecificConfigurationLtv::FrameDuration, uint32_t>
78 fduration_to_support_fduration_map = {
79 {CodecSpecificConfigurationLtv::FrameDuration::US7500,
80 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500},
81 {CodecSpecificConfigurationLtv::FrameDuration::US10000,
82 CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000},
83};
84
Bao Do5b2fdab2023-11-20 08:02:55 +000085std::map<int32_t, CodecSpecificConfigurationLtv::SamplingFrequency>
86 sampling_freq_map = {
87 {16000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
88 {48000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000},
89 {96000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000},
90};
91
92std::map<int32_t, CodecSpecificConfigurationLtv::FrameDuration>
93 frame_duration_map = {
94 {7500, CodecSpecificConfigurationLtv::FrameDuration::US7500},
95 {10000, CodecSpecificConfigurationLtv::FrameDuration::US10000},
96};
97
Josh Wu6ab53e72021-12-29 23:53:33 -080098LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
99 : LeAudioOffloadAudioProvider() {
100 session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
101}
102
103LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
104 : LeAudioOffloadAudioProvider() {
105 session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
106}
107
Alice Kuoe80a5762022-02-09 14:44:29 +0800108LeAudioOffloadBroadcastAudioProvider::LeAudioOffloadBroadcastAudioProvider()
109 : LeAudioOffloadAudioProvider() {
110 session_type_ =
111 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
112}
113
Josh Wu6ab53e72021-12-29 23:53:33 -0800114LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
115 : BluetoothAudioProvider() {}
116
117bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
118 return (sessionType == session_type_);
119}
120
121ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
122 const std::shared_ptr<IBluetoothAudioPort>& host_if,
Chen Chenc92270e2022-02-14 18:29:52 -0800123 const AudioConfiguration& audio_config,
Cheney Ni6ecbc762022-03-03 00:12:48 +0800124 const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
Alice Kuoee398a92022-07-10 23:59:18 +0800125 if (session_type_ ==
126 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
127 if (audio_config.getTag() != AudioConfiguration::leAudioBroadcastConfig) {
128 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
129 << audio_config.toString();
130 *_aidl_return = DataMQDesc();
131 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
132 }
133 } else if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
Josh Wu6ab53e72021-12-29 23:53:33 -0800134 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
135 << audio_config.toString();
136 *_aidl_return = DataMQDesc();
137 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
138 }
Josh Wu6ab53e72021-12-29 23:53:33 -0800139
Bao Do6112bda2023-11-15 03:57:59 +0000140 return BluetoothAudioProvider::startSession(host_if, audio_config,
141 latency_modes, _aidl_return);
Josh Wu6ab53e72021-12-29 23:53:33 -0800142}
143
144ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
145 DataMQDesc* _aidl_return) {
Cheney Ni6ecbc762022-03-03 00:12:48 +0800146 BluetoothAudioSessionReport::OnSessionStarted(
147 session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
Josh Wu6ab53e72021-12-29 23:53:33 -0800148 *_aidl_return = DataMQDesc();
149 return ndk::ScopedAStatus::ok();
150}
Bao Do6112bda2023-11-15 03:57:59 +0000151ndk::ScopedAStatus LeAudioOffloadAudioProvider::setCodecPriority(
152 const CodecId& in_codecId, int32_t in_priority) {
153 codec_priority_map_[in_codecId] = in_priority;
154 return ndk::ScopedAStatus::ok();
155};
156
Bao Do867af602023-11-15 05:41:12 +0000157bool LeAudioOffloadAudioProvider::isMatchedValidCodec(CodecId cfg_codec,
158 CodecId req_codec) {
159 auto priority = codec_priority_map_.find(cfg_codec);
Jakub Tyszkowski1d214222024-01-16 09:44:48 +0000160 if (priority != codec_priority_map_.end() &&
161 priority->second ==
162 LeAudioOffloadAudioProvider::CODEC_PRIORITY_DISABLED) {
Bao Do867af602023-11-15 05:41:12 +0000163 return false;
Jakub Tyszkowski1d214222024-01-16 09:44:48 +0000164 }
Bao Do867af602023-11-15 05:41:12 +0000165 return cfg_codec == req_codec;
166}
167
168bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedContext(
169 AudioContext setting_context,
170 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
171 // If has no metadata, assume match
172 if (!capabilities.metadata.has_value()) return true;
173
174 for (auto metadata : capabilities.metadata.value()) {
175 if (!metadata.has_value()) continue;
176 if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
177 // Check all pref audio context to see if anything matched
178 auto& context = metadata.value()
179 .get<MetadataLtv::Tag::preferredAudioContexts>()
180 .values;
181 if (setting_context.bitmask & context.bitmask) return true;
182 }
183 }
184
185 return false;
186}
187
188bool LeAudioOffloadAudioProvider::isMatchedSamplingFreq(
189 CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
190 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
191 capability_freq) {
192 for (auto [freq, bitmask] : freq_to_support_bitmask_map)
193 if (cfg_freq == freq) return (capability_freq.bitmask & bitmask);
194 return false;
195}
196
197bool LeAudioOffloadAudioProvider::isMatchedFrameDuration(
198 CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
199 CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
200 capability_fduration) {
201 for (auto [fduration, bitmask] : fduration_to_support_fduration_map)
202 if (cfg_fduration == fduration)
203 return (capability_fduration.bitmask & bitmask);
204 return false;
205}
206
207bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
208 CodecSpecificConfigurationLtv::AudioChannelAllocation&
209 /*cfg_channel*/,
210 CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
211 /*capability_channel*/) {
212 bool isMatched = true;
213 // TODO: how to match?
214 return isMatched;
215}
216
217bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
218 CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU& cfg_frame_sdu,
219 CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU&
220 capability_frame_sdu) {
221 return cfg_frame_sdu.value <= capability_frame_sdu.value;
222}
223
224bool LeAudioOffloadAudioProvider::isMatchedOctetsPerCodecFrame(
225 CodecSpecificConfigurationLtv::OctetsPerCodecFrame& cfg_octets,
226 CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame&
227 capability_octets) {
Jakub Tyszkowski1d214222024-01-16 09:44:48 +0000228 return cfg_octets.value >= capability_octets.min &&
229 cfg_octets.value <= capability_octets.max;
Bao Do867af602023-11-15 05:41:12 +0000230}
231
232bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedCodecConfiguration(
233 std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
234 std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities) {
235 // Convert all codec_cfg into a map of tags -> correct data
236 std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
237 cfg_tag_map;
238 for (auto codec_cfg_data : codec_cfg)
239 cfg_tag_map[codec_cfg_data.getTag()] = codec_cfg_data;
240
241 for (auto& codec_capability : codec_capabilities) {
242 auto cfg = cfg_tag_map.find(cap_to_cfg_tag_map[codec_capability.getTag()]);
243 // Cannot find tag for the capability:
244 if (cfg == cfg_tag_map.end()) return false;
245
246 // Matching logic for sampling frequency
247 if (codec_capability.getTag() ==
248 CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies) {
249 if (!isMatchedSamplingFreq(
250 cfg->second
251 .get<CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
252 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
253 supportedSamplingFrequencies>()))
254 return false;
255 } else if (codec_capability.getTag() ==
256 CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations) {
257 if (!isMatchedFrameDuration(
258 cfg->second
259 .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
260 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
261 supportedFrameDurations>()))
262 return false;
263 } else if (codec_capability.getTag() ==
264 CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts) {
265 if (!isMatchedAudioChannel(
266 cfg->second.get<
267 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>(),
268 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
269 supportedAudioChannelCounts>()))
270 return false;
271 } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
272 supportedMaxCodecFramesPerSDU) {
273 if (!isMatchedCodecFramesPerSDU(
274 cfg->second.get<
275 CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU>(),
276 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
277 supportedMaxCodecFramesPerSDU>()))
278 return false;
279 } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
280 supportedOctetsPerCodecFrame) {
281 if (!isMatchedOctetsPerCodecFrame(
282 cfg->second.get<
283 CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
284 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
285 supportedOctetsPerCodecFrame>()))
286 return false;
287 }
288 }
289
290 return true;
291}
292
293bool LeAudioOffloadAudioProvider::isMatchedAseConfiguration(
294 LeAudioAseConfiguration setting_cfg,
295 LeAudioAseConfiguration requirement_cfg) {
296 // Check matching for codec configuration <=> requirement ASE codec
297 // Also match if no CodecId requirement
298 if (requirement_cfg.codecId.has_value()) {
299 if (!setting_cfg.codecId.has_value()) return false;
300 if (!isMatchedValidCodec(setting_cfg.codecId.value(),
301 requirement_cfg.codecId.value()))
302 return false;
303 }
304
305 if (setting_cfg.targetLatency != requirement_cfg.targetLatency) return false;
306 // Ignore PHY requirement
307
308 // Check all codec configuration
309 std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
310 cfg_tag_map;
311 for (auto cfg : setting_cfg.codecConfiguration)
312 cfg_tag_map[cfg.getTag()] = cfg;
313
314 for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
315 // Directly compare CodecSpecificConfigurationLtv
316 auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
317 if (cfg == cfg_tag_map.end()) return false;
318
319 if (cfg->second != requirement_cfg) return false;
320 }
321 // Ignore vendor configuration and metadata requirement
322
323 return true;
324}
325
Bao Do5b2fdab2023-11-20 08:02:55 +0000326bool LeAudioOffloadAudioProvider::isMatchedBISConfiguration(
327 LeAudioBisConfiguration bis_cfg,
328 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
329 if (!isMatchedValidCodec(bis_cfg.codecId, capabilities.codecId)) return false;
330 if (!isCapabilitiesMatchedCodecConfiguration(
331 bis_cfg.codecConfiguration, capabilities.codecSpecificCapabilities))
332 return false;
333 return true;
334}
335
Bao Do867af602023-11-15 05:41:12 +0000336void LeAudioOffloadAudioProvider::filterCapabilitiesAseDirectionConfiguration(
337 std::vector<std::optional<AseDirectionConfiguration>>&
338 direction_configurations,
339 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
340 std::vector<std::optional<AseDirectionConfiguration>>&
341 valid_direction_configurations) {
342 for (auto direction_configuration : direction_configurations) {
343 if (!direction_configuration.has_value()) continue;
344 if (!direction_configuration.value().aseConfiguration.codecId.has_value())
345 continue;
346 if (!isMatchedValidCodec(
347 direction_configuration.value().aseConfiguration.codecId.value(),
348 capabilities.codecId))
349 continue;
350 // Check matching for codec configuration <=> codec capabilities
351 if (!isCapabilitiesMatchedCodecConfiguration(
352 direction_configuration.value().aseConfiguration.codecConfiguration,
353 capabilities.codecSpecificCapabilities))
354 continue;
355 valid_direction_configurations.push_back(direction_configuration);
356 }
357}
358
359void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
360 std::vector<std::optional<AseDirectionConfiguration>>&
361 direction_configurations,
362 const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
363 requirements,
364 std::vector<std::optional<AseDirectionConfiguration>>&
365 valid_direction_configurations) {
366 for (auto direction_configuration : direction_configurations) {
367 if (!requirements.has_value()) {
368 // If there's no requirement, all are valid
369 valid_direction_configurations.push_back(direction_configuration);
370 continue;
371 }
372 if (!direction_configuration.has_value()) continue;
373
374 for (auto& requirement : requirements.value()) {
375 if (!requirement.has_value()) continue;
376 if (!isMatchedAseConfiguration(
377 direction_configuration.value().aseConfiguration,
378 requirement.value().aseConfiguration))
379 continue;
380 // Valid if match any requirement.
381 valid_direction_configurations.push_back(direction_configuration);
382 break;
383 }
384 }
385}
386
387/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
388 * capabilities. The new setting will have a filtered list of
389 * AseDirectionConfiguration that matched the capabilities */
390std::optional<LeAudioAseConfigurationSetting>
391LeAudioOffloadAudioProvider::getCapabilitiesMatchedAseConfigurationSettings(
392 IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
393 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
394 uint8_t direction) {
395 // Try to match context in metadata.
396 if (!isCapabilitiesMatchedContext(setting.audioContext, capabilities))
397 return std::nullopt;
398
399 // Get a list of all matched AseDirectionConfiguration
400 // for the input direction
401 std::vector<std::optional<AseDirectionConfiguration>>*
402 direction_configuration = nullptr;
403 if (direction == kLeAudioDirectionSink) {
404 if (!setting.sinkAseConfiguration.has_value()) return std::nullopt;
405 direction_configuration = &setting.sinkAseConfiguration.value();
406 } else {
407 if (!setting.sourceAseConfiguration.has_value()) return std::nullopt;
408 direction_configuration = &setting.sourceAseConfiguration.value();
409 }
410 std::vector<std::optional<AseDirectionConfiguration>>
411 valid_direction_configuration;
412 filterCapabilitiesAseDirectionConfiguration(
413 *direction_configuration, capabilities, valid_direction_configuration);
414 if (valid_direction_configuration.empty()) return std::nullopt;
415
416 // Create a new LeAudioAseConfigurationSetting and return
417 LeAudioAseConfigurationSetting filtered_setting;
418 filtered_setting.audioContext = setting.audioContext;
419 filtered_setting.packing = setting.packing;
420 if (direction == kLeAudioDirectionSink) {
421 filtered_setting.sinkAseConfiguration = valid_direction_configuration;
422 } else {
423 filtered_setting.sourceAseConfiguration = valid_direction_configuration;
424 }
425 filtered_setting.flags = setting.flags;
426
427 return filtered_setting;
428}
429
430/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
431 * requirement. The new setting will have a filtered list of
432 * AseDirectionConfiguration that matched the requirement */
433std::optional<LeAudioAseConfigurationSetting>
434LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
435 IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
436 const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
437 requirement) {
438 // Try to match context in metadata.
439 if (setting.audioContext != requirement.audioContext) return std::nullopt;
440
441 // Check requirement for the correct direction
442 const std::optional<std::vector<std::optional<AseDirectionRequirement>>>*
443 direction_requirement;
444 std::vector<std::optional<AseDirectionConfiguration>>*
445 direction_configuration;
446 if (setting.sinkAseConfiguration.has_value()) {
447 direction_configuration = &setting.sinkAseConfiguration.value();
448 direction_requirement = &requirement.sinkAseRequirement;
449 } else {
450 direction_configuration = &setting.sourceAseConfiguration.value();
451 direction_requirement = &requirement.sourceAseRequirement;
452 }
453
454 std::vector<std::optional<AseDirectionConfiguration>>
455 valid_direction_configuration;
456 filterRequirementAseDirectionConfiguration(*direction_configuration,
457 *direction_requirement,
458 valid_direction_configuration);
459 if (valid_direction_configuration.empty()) return std::nullopt;
460
461 // Create a new LeAudioAseConfigurationSetting and return
462 LeAudioAseConfigurationSetting filtered_setting;
463 filtered_setting.audioContext = setting.audioContext;
464 filtered_setting.packing = setting.packing;
465 if (setting.sinkAseConfiguration.has_value())
466 filtered_setting.sinkAseConfiguration = valid_direction_configuration;
467 else
468 filtered_setting.sourceAseConfiguration = valid_direction_configuration;
469 filtered_setting.flags = setting.flags;
470
471 return filtered_setting;
472}
473
Bao Do6112bda2023-11-15 03:57:59 +0000474ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
475 const std::optional<std::vector<
476 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
477 in_remoteSinkAudioCapabilities,
478 const std::optional<std::vector<
479 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
480 in_remoteSourceAudioCapabilities,
481 const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
482 in_requirements,
483 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
484 _aidl_return) {
Bao Do867af602023-11-15 05:41:12 +0000485 // Get all configuration settings
486 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
487 ase_configuration_settings =
488 BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
489
490 // Currently won't handle case where both sink and source capabilities
491 // are passed in. Only handle one of them.
492 const std::optional<std::vector<
493 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>*
494 in_remoteAudioCapabilities;
495 uint8_t direction = 0;
496 if (in_remoteSinkAudioCapabilities.has_value()) {
497 direction = kLeAudioDirectionSink;
498 in_remoteAudioCapabilities = &in_remoteSinkAudioCapabilities;
499 } else {
500 direction = kLeAudioDirectionSource;
501 in_remoteAudioCapabilities = &in_remoteSourceAudioCapabilities;
502 }
503
504 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
505 capability_matched_ase_configuration_settings;
506 // Matching with remote capabilities
507 for (auto& setting : ase_configuration_settings) {
508 for (auto& capability : in_remoteAudioCapabilities->value()) {
509 if (!capability.has_value()) continue;
510 auto filtered_ase_configuration_setting =
511 getCapabilitiesMatchedAseConfigurationSettings(
512 setting, capability.value(), direction);
513 if (filtered_ase_configuration_setting.has_value()) {
514 capability_matched_ase_configuration_settings.push_back(
515 filtered_ase_configuration_setting.value());
516 }
517 }
518 }
519
520 // Matching with requirements
521 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
522 for (auto& setting : capability_matched_ase_configuration_settings) {
523 for (auto& requirement : in_requirements) {
524 auto filtered_ase_configuration_setting =
525 getRequirementMatchedAseConfigurationSettings(setting, requirement);
526 if (filtered_ase_configuration_setting.has_value()) {
527 result.push_back(filtered_ase_configuration_setting.value());
528 }
529 }
530 }
531
532 *_aidl_return = result;
533 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000534};
535
Bao Doc4adf242023-11-15 08:03:20 +0000536bool LeAudioOffloadAudioProvider::isMatchedQosRequirement(
537 LeAudioAseQosConfiguration setting_qos,
538 AseQosDirectionRequirement requirement_qos) {
539 if (setting_qos.retransmissionNum !=
540 requirement_qos.preferredRetransmissionNum)
541 return false;
542 if (setting_qos.maxTransportLatencyMs > requirement_qos.maxTransportLatencyMs)
543 return false;
544 // Ignore other parameters, as they are not populated in the setting_qos
545 return true;
546}
547
Bao Do6112bda2023-11-15 03:57:59 +0000548ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseQosConfiguration(
549 const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
550 in_qosRequirement,
551 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return) {
Bao Doc4adf242023-11-15 08:03:20 +0000552 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
553 // Get all configuration settings
554 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
555 ase_configuration_settings =
556 BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
557
558 // Direction QoS matching
559 // Only handle one direction input case
560 uint8_t direction = 0;
561 std::optional<AseQosDirectionRequirement> direction_qos_requirement =
562 std::nullopt;
563 if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
564 direction_qos_requirement = in_qosRequirement.sinkAseQosRequirement.value();
565 direction = kLeAudioDirectionSink;
566 } else if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
567 direction_qos_requirement =
568 in_qosRequirement.sourceAseQosRequirement.value();
569 direction = kLeAudioDirectionSource;
570 }
571
572 for (auto& setting : ase_configuration_settings) {
573 // Context matching
Jakub Tyszkowski1d214222024-01-16 09:44:48 +0000574 if (setting.audioContext != in_qosRequirement.audioContext) continue;
Bao Doc4adf242023-11-15 08:03:20 +0000575
576 // Match configuration flags
577 // Currently configuration flags are not populated, ignore.
578
579 // Get a list of all matched AseDirectionConfiguration
580 // for the input direction
581 std::vector<std::optional<AseDirectionConfiguration>>*
582 direction_configuration = nullptr;
583 if (direction == kLeAudioDirectionSink) {
584 if (!setting.sinkAseConfiguration.has_value()) continue;
585 direction_configuration = &setting.sinkAseConfiguration.value();
586 } else {
587 if (!setting.sourceAseConfiguration.has_value()) continue;
588 direction_configuration = &setting.sourceAseConfiguration.value();
589 }
590
591 for (auto cfg : *direction_configuration) {
592 if (!cfg.has_value()) continue;
593 // If no requirement, return the first QoS
594 if (!direction_qos_requirement.has_value()) {
595 result.sinkQosConfiguration = cfg.value().qosConfiguration;
596 result.sourceQosConfiguration = cfg.value().qosConfiguration;
597 *_aidl_return = result;
598 return ndk::ScopedAStatus::ok();
599 }
600
601 // If has requirement, return the first matched QoS
602 // Try to match the ASE configuration
603 // and QoS with requirement
604 if (!cfg.value().qosConfiguration.has_value()) continue;
605 if (isMatchedAseConfiguration(
606 cfg.value().aseConfiguration,
607 direction_qos_requirement.value().aseConfiguration) &&
608 isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
609 direction_qos_requirement.value())) {
610 if (direction == kLeAudioDirectionSink)
611 result.sinkQosConfiguration = cfg.value().qosConfiguration;
612 else
613 result.sourceQosConfiguration = cfg.value().qosConfiguration;
614 *_aidl_return = result;
615 return ndk::ScopedAStatus::ok();
616 }
617 }
618 }
619
620 // No match, return empty QoS
621 *_aidl_return = result;
622 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000623};
624
625ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSinkAseMetadataChanged(
Bao Do5b2fdab2023-11-20 08:02:55 +0000626 IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
627 int32_t /*in_cisId*/,
Bao Do6112bda2023-11-15 03:57:59 +0000628 const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
629 (void)in_state;
630 (void)in_metadata;
631 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
632};
633
634ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSourceAseMetadataChanged(
Bao Do5b2fdab2023-11-20 08:02:55 +0000635 IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
636 int32_t /*in_cisId*/,
Bao Do6112bda2023-11-15 03:57:59 +0000637 const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
638 (void)in_state;
639 (void)in_metadata;
640 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
641};
642
Bao Do5b2fdab2023-11-20 08:02:55 +0000643void LeAudioOffloadAudioProvider::getBroadcastSettings() {
644 if (!broadcast_settings.empty()) return;
645
646 LOG(INFO) << __func__ << ": Loading broadcast settings from provider info";
647
648 std::vector<CodecInfo> db_codec_info =
649 BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
650 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
651 broadcast_settings.clear();
652 CodecSpecificConfigurationLtv::AudioChannelAllocation default_allocation;
653 default_allocation.bitmask =
654 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
655
656 for (auto& codec_info : db_codec_info) {
657 if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
658 continue;
659 auto& transport = codec_info.transport.get<CodecInfo::Transport::leAudio>();
660 LeAudioBroadcastConfigurationSetting setting;
661 // Default setting
662 setting.numBis = 1;
663 setting.phy = {Phy::TWO_M};
664 // Populate BIS configuration info using codec_info
665 LeAudioBisConfiguration bis_cfg;
666 bis_cfg.codecId = codec_info.id;
667
668 CodecSpecificConfigurationLtv::OctetsPerCodecFrame octets;
669 octets.value = transport.bitdepth[0];
670
671 bis_cfg.codecConfiguration = {
672 sampling_freq_map[transport.samplingFrequencyHz[0]], octets,
673 frame_duration_map[transport.frameDurationUs[0]], default_allocation};
674
675 // Add information to structure
676 IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration sub_bis_cfg;
677 sub_bis_cfg.numBis = 1;
678 sub_bis_cfg.bisConfiguration = bis_cfg;
679 IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration sub_cfg;
680 sub_cfg.bisConfigurations = {sub_bis_cfg};
681 setting.subgroupsConfigurations = {sub_cfg};
682
683 broadcast_settings.push_back(setting);
684 }
685
686 LOG(INFO) << __func__
687 << ": Done loading broadcast settings from provider info";
688}
689
690/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
691 * capabilities. The new setting will have a filtered list of
692 * AseDirectionConfiguration that matched the capabilities */
693std::optional<LeAudioBroadcastConfigurationSetting>
694LeAudioOffloadAudioProvider::
695 getCapabilitiesMatchedBroadcastConfigurationSettings(
696 LeAudioBroadcastConfigurationSetting& setting,
697 const IBluetoothAudioProvider::LeAudioDeviceCapabilities&
698 capabilities) {
699 std::vector<IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration>
700 filter_subgroup;
701 for (auto& sub_cfg : setting.subgroupsConfigurations) {
702 std::vector<IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration>
703 filtered_bis_cfg;
704 for (auto& bis_cfg : sub_cfg.bisConfigurations)
705 if (isMatchedBISConfiguration(bis_cfg.bisConfiguration, capabilities)) {
706 filtered_bis_cfg.push_back(bis_cfg);
707 }
708 if (!filtered_bis_cfg.empty()) {
709 IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration
710 subgroup_cfg;
711 subgroup_cfg.bisConfigurations = filtered_bis_cfg;
712 filter_subgroup.push_back(subgroup_cfg);
713 }
714 }
715 if (filter_subgroup.empty()) return std::nullopt;
716
717 // Create a new LeAudioAseConfigurationSetting and return
718 LeAudioBroadcastConfigurationSetting filtered_setting(setting);
719 filtered_setting.subgroupsConfigurations = filter_subgroup;
720
721 return filtered_setting;
722}
723
Bao Do6112bda2023-11-15 03:57:59 +0000724ndk::ScopedAStatus
725LeAudioOffloadAudioProvider::getLeAudioBroadcastConfiguration(
726 const std::optional<std::vector<
727 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
728 in_remoteSinkAudioCapabilities,
729 const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
730 in_requirement,
Bao Do5b2fdab2023-11-20 08:02:55 +0000731 LeAudioBroadcastConfigurationSetting* _aidl_return) {
732 getBroadcastSettings();
733 _aidl_return = nullptr;
734
735 // Match and filter capability
736 std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
737 if (!in_remoteSinkAudioCapabilities.has_value()) {
738 LOG(WARNING) << __func__ << ": Empty capability";
739 return ndk::ScopedAStatus::ok();
740 }
741 for (auto& setting : broadcast_settings) {
742 for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
743 if (!capability.has_value()) continue;
744 auto filtered_setting =
745 getCapabilitiesMatchedBroadcastConfigurationSettings(
746 setting, capability.value());
747 if (filtered_setting.has_value())
748 filtered_settings.push_back(filtered_setting.value());
749 }
750 }
751
752 if (filtered_settings.empty()) {
753 LOG(WARNING) << __func__ << ": Cannot match any remote capability";
754 return ndk::ScopedAStatus::ok();
755 }
756
757 // Match and return the first matched requirement
758 if (in_requirement.subgroupConfigurationRequirements.empty()) {
759 LOG(INFO) << __func__ << ": Empty requirement";
760 *_aidl_return = filtered_settings[0];
761 return ndk::ScopedAStatus::ok();
762 }
763
764 for (auto& setting : filtered_settings) {
765 // Further filter out bis configuration
766 LeAudioBroadcastConfigurationSetting filtered_setting(setting);
767 filtered_setting.subgroupsConfigurations.clear();
768 for (auto& sub_cfg : setting.subgroupsConfigurations) {
769 bool isMatched = false;
770 for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
771 // Matching number of BIS
772 if (sub_req.bisNumPerSubgroup != sub_cfg.bisConfigurations.size())
773 continue;
774 // Currently will ignore quality and context hint.
775 isMatched = true;
776 break;
777 }
778 if (isMatched)
779 filtered_setting.subgroupsConfigurations.push_back(sub_cfg);
780 }
781 // Return the first match
782 if (!filtered_setting.subgroupsConfigurations.empty()) {
783 LOG(INFO) << __func__ << ": Matched requirement";
784 *_aidl_return = filtered_setting;
785 return ndk::ScopedAStatus::ok();
786 }
787 }
788
789 LOG(WARNING) << __func__ << ": Cannot match any requirement";
790 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000791};
Josh Wu6ab53e72021-12-29 23:53:33 -0800792
793} // namespace audio
794} // namespace bluetooth
795} // namespace hardware
796} // namespace android
Cheney Ni6ecbc762022-03-03 00:12:48 +0800797} // namespace aidl