blob: cff3b2582c6fc51fb20a7f7ac32f8eeb3d34749e [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);
160 if (priority != codec_priority_map_.end() && priority->second == -1)
161 return false;
162 return cfg_codec == req_codec;
163}
164
165bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedContext(
166 AudioContext setting_context,
167 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
168 // If has no metadata, assume match
169 if (!capabilities.metadata.has_value()) return true;
170
171 for (auto metadata : capabilities.metadata.value()) {
172 if (!metadata.has_value()) continue;
173 if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
174 // Check all pref audio context to see if anything matched
175 auto& context = metadata.value()
176 .get<MetadataLtv::Tag::preferredAudioContexts>()
177 .values;
178 if (setting_context.bitmask & context.bitmask) return true;
179 }
180 }
181
182 return false;
183}
184
185bool LeAudioOffloadAudioProvider::isMatchedSamplingFreq(
186 CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
187 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
188 capability_freq) {
189 for (auto [freq, bitmask] : freq_to_support_bitmask_map)
190 if (cfg_freq == freq) return (capability_freq.bitmask & bitmask);
191 return false;
192}
193
194bool LeAudioOffloadAudioProvider::isMatchedFrameDuration(
195 CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
196 CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
197 capability_fduration) {
198 for (auto [fduration, bitmask] : fduration_to_support_fduration_map)
199 if (cfg_fduration == fduration)
200 return (capability_fduration.bitmask & bitmask);
201 return false;
202}
203
204bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
205 CodecSpecificConfigurationLtv::AudioChannelAllocation&
206 /*cfg_channel*/,
207 CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
208 /*capability_channel*/) {
209 bool isMatched = true;
210 // TODO: how to match?
211 return isMatched;
212}
213
214bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
215 CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU& cfg_frame_sdu,
216 CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU&
217 capability_frame_sdu) {
218 return cfg_frame_sdu.value <= capability_frame_sdu.value;
219}
220
221bool LeAudioOffloadAudioProvider::isMatchedOctetsPerCodecFrame(
222 CodecSpecificConfigurationLtv::OctetsPerCodecFrame& cfg_octets,
223 CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame&
224 capability_octets) {
225 return cfg_octets.value >= capability_octets.minimum &&
226 cfg_octets.value <= capability_octets.maximum;
227}
228
229bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedCodecConfiguration(
230 std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
231 std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities) {
232 // Convert all codec_cfg into a map of tags -> correct data
233 std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
234 cfg_tag_map;
235 for (auto codec_cfg_data : codec_cfg)
236 cfg_tag_map[codec_cfg_data.getTag()] = codec_cfg_data;
237
238 for (auto& codec_capability : codec_capabilities) {
239 auto cfg = cfg_tag_map.find(cap_to_cfg_tag_map[codec_capability.getTag()]);
240 // Cannot find tag for the capability:
241 if (cfg == cfg_tag_map.end()) return false;
242
243 // Matching logic for sampling frequency
244 if (codec_capability.getTag() ==
245 CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies) {
246 if (!isMatchedSamplingFreq(
247 cfg->second
248 .get<CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
249 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
250 supportedSamplingFrequencies>()))
251 return false;
252 } else if (codec_capability.getTag() ==
253 CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations) {
254 if (!isMatchedFrameDuration(
255 cfg->second
256 .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
257 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
258 supportedFrameDurations>()))
259 return false;
260 } else if (codec_capability.getTag() ==
261 CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts) {
262 if (!isMatchedAudioChannel(
263 cfg->second.get<
264 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>(),
265 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
266 supportedAudioChannelCounts>()))
267 return false;
268 } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
269 supportedMaxCodecFramesPerSDU) {
270 if (!isMatchedCodecFramesPerSDU(
271 cfg->second.get<
272 CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU>(),
273 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
274 supportedMaxCodecFramesPerSDU>()))
275 return false;
276 } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
277 supportedOctetsPerCodecFrame) {
278 if (!isMatchedOctetsPerCodecFrame(
279 cfg->second.get<
280 CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
281 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
282 supportedOctetsPerCodecFrame>()))
283 return false;
284 }
285 }
286
287 return true;
288}
289
290bool LeAudioOffloadAudioProvider::isMatchedAseConfiguration(
291 LeAudioAseConfiguration setting_cfg,
292 LeAudioAseConfiguration requirement_cfg) {
293 // Check matching for codec configuration <=> requirement ASE codec
294 // Also match if no CodecId requirement
295 if (requirement_cfg.codecId.has_value()) {
296 if (!setting_cfg.codecId.has_value()) return false;
297 if (!isMatchedValidCodec(setting_cfg.codecId.value(),
298 requirement_cfg.codecId.value()))
299 return false;
300 }
301
302 if (setting_cfg.targetLatency != requirement_cfg.targetLatency) return false;
303 // Ignore PHY requirement
304
305 // Check all codec configuration
306 std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
307 cfg_tag_map;
308 for (auto cfg : setting_cfg.codecConfiguration)
309 cfg_tag_map[cfg.getTag()] = cfg;
310
311 for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
312 // Directly compare CodecSpecificConfigurationLtv
313 auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
314 if (cfg == cfg_tag_map.end()) return false;
315
316 if (cfg->second != requirement_cfg) return false;
317 }
318 // Ignore vendor configuration and metadata requirement
319
320 return true;
321}
322
Bao Do5b2fdab2023-11-20 08:02:55 +0000323bool LeAudioOffloadAudioProvider::isMatchedBISConfiguration(
324 LeAudioBisConfiguration bis_cfg,
325 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
326 if (!isMatchedValidCodec(bis_cfg.codecId, capabilities.codecId)) return false;
327 if (!isCapabilitiesMatchedCodecConfiguration(
328 bis_cfg.codecConfiguration, capabilities.codecSpecificCapabilities))
329 return false;
330 return true;
331}
332
Bao Do867af602023-11-15 05:41:12 +0000333void LeAudioOffloadAudioProvider::filterCapabilitiesAseDirectionConfiguration(
334 std::vector<std::optional<AseDirectionConfiguration>>&
335 direction_configurations,
336 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
337 std::vector<std::optional<AseDirectionConfiguration>>&
338 valid_direction_configurations) {
339 for (auto direction_configuration : direction_configurations) {
340 if (!direction_configuration.has_value()) continue;
341 if (!direction_configuration.value().aseConfiguration.codecId.has_value())
342 continue;
343 if (!isMatchedValidCodec(
344 direction_configuration.value().aseConfiguration.codecId.value(),
345 capabilities.codecId))
346 continue;
347 // Check matching for codec configuration <=> codec capabilities
348 if (!isCapabilitiesMatchedCodecConfiguration(
349 direction_configuration.value().aseConfiguration.codecConfiguration,
350 capabilities.codecSpecificCapabilities))
351 continue;
352 valid_direction_configurations.push_back(direction_configuration);
353 }
354}
355
356void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
357 std::vector<std::optional<AseDirectionConfiguration>>&
358 direction_configurations,
359 const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
360 requirements,
361 std::vector<std::optional<AseDirectionConfiguration>>&
362 valid_direction_configurations) {
363 for (auto direction_configuration : direction_configurations) {
364 if (!requirements.has_value()) {
365 // If there's no requirement, all are valid
366 valid_direction_configurations.push_back(direction_configuration);
367 continue;
368 }
369 if (!direction_configuration.has_value()) continue;
370
371 for (auto& requirement : requirements.value()) {
372 if (!requirement.has_value()) continue;
373 if (!isMatchedAseConfiguration(
374 direction_configuration.value().aseConfiguration,
375 requirement.value().aseConfiguration))
376 continue;
377 // Valid if match any requirement.
378 valid_direction_configurations.push_back(direction_configuration);
379 break;
380 }
381 }
382}
383
384/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
385 * capabilities. The new setting will have a filtered list of
386 * AseDirectionConfiguration that matched the capabilities */
387std::optional<LeAudioAseConfigurationSetting>
388LeAudioOffloadAudioProvider::getCapabilitiesMatchedAseConfigurationSettings(
389 IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
390 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
391 uint8_t direction) {
392 // Try to match context in metadata.
393 if (!isCapabilitiesMatchedContext(setting.audioContext, capabilities))
394 return std::nullopt;
395
396 // Get a list of all matched AseDirectionConfiguration
397 // for the input direction
398 std::vector<std::optional<AseDirectionConfiguration>>*
399 direction_configuration = nullptr;
400 if (direction == kLeAudioDirectionSink) {
401 if (!setting.sinkAseConfiguration.has_value()) return std::nullopt;
402 direction_configuration = &setting.sinkAseConfiguration.value();
403 } else {
404 if (!setting.sourceAseConfiguration.has_value()) return std::nullopt;
405 direction_configuration = &setting.sourceAseConfiguration.value();
406 }
407 std::vector<std::optional<AseDirectionConfiguration>>
408 valid_direction_configuration;
409 filterCapabilitiesAseDirectionConfiguration(
410 *direction_configuration, capabilities, valid_direction_configuration);
411 if (valid_direction_configuration.empty()) return std::nullopt;
412
413 // Create a new LeAudioAseConfigurationSetting and return
414 LeAudioAseConfigurationSetting filtered_setting;
415 filtered_setting.audioContext = setting.audioContext;
416 filtered_setting.packing = setting.packing;
417 if (direction == kLeAudioDirectionSink) {
418 filtered_setting.sinkAseConfiguration = valid_direction_configuration;
419 } else {
420 filtered_setting.sourceAseConfiguration = valid_direction_configuration;
421 }
422 filtered_setting.flags = setting.flags;
423
424 return filtered_setting;
425}
426
427/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
428 * requirement. The new setting will have a filtered list of
429 * AseDirectionConfiguration that matched the requirement */
430std::optional<LeAudioAseConfigurationSetting>
431LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
432 IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
433 const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
434 requirement) {
435 // Try to match context in metadata.
436 if (setting.audioContext != requirement.audioContext) return std::nullopt;
437
438 // Check requirement for the correct direction
439 const std::optional<std::vector<std::optional<AseDirectionRequirement>>>*
440 direction_requirement;
441 std::vector<std::optional<AseDirectionConfiguration>>*
442 direction_configuration;
443 if (setting.sinkAseConfiguration.has_value()) {
444 direction_configuration = &setting.sinkAseConfiguration.value();
445 direction_requirement = &requirement.sinkAseRequirement;
446 } else {
447 direction_configuration = &setting.sourceAseConfiguration.value();
448 direction_requirement = &requirement.sourceAseRequirement;
449 }
450
451 std::vector<std::optional<AseDirectionConfiguration>>
452 valid_direction_configuration;
453 filterRequirementAseDirectionConfiguration(*direction_configuration,
454 *direction_requirement,
455 valid_direction_configuration);
456 if (valid_direction_configuration.empty()) return std::nullopt;
457
458 // Create a new LeAudioAseConfigurationSetting and return
459 LeAudioAseConfigurationSetting filtered_setting;
460 filtered_setting.audioContext = setting.audioContext;
461 filtered_setting.packing = setting.packing;
462 if (setting.sinkAseConfiguration.has_value())
463 filtered_setting.sinkAseConfiguration = valid_direction_configuration;
464 else
465 filtered_setting.sourceAseConfiguration = valid_direction_configuration;
466 filtered_setting.flags = setting.flags;
467
468 return filtered_setting;
469}
470
Bao Do6112bda2023-11-15 03:57:59 +0000471ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
472 const std::optional<std::vector<
473 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
474 in_remoteSinkAudioCapabilities,
475 const std::optional<std::vector<
476 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
477 in_remoteSourceAudioCapabilities,
478 const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
479 in_requirements,
480 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
481 _aidl_return) {
Bao Do867af602023-11-15 05:41:12 +0000482 // Get all configuration settings
483 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
484 ase_configuration_settings =
485 BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
486
487 // Currently won't handle case where both sink and source capabilities
488 // are passed in. Only handle one of them.
489 const std::optional<std::vector<
490 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>*
491 in_remoteAudioCapabilities;
492 uint8_t direction = 0;
493 if (in_remoteSinkAudioCapabilities.has_value()) {
494 direction = kLeAudioDirectionSink;
495 in_remoteAudioCapabilities = &in_remoteSinkAudioCapabilities;
496 } else {
497 direction = kLeAudioDirectionSource;
498 in_remoteAudioCapabilities = &in_remoteSourceAudioCapabilities;
499 }
500
501 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
502 capability_matched_ase_configuration_settings;
503 // Matching with remote capabilities
504 for (auto& setting : ase_configuration_settings) {
505 for (auto& capability : in_remoteAudioCapabilities->value()) {
506 if (!capability.has_value()) continue;
507 auto filtered_ase_configuration_setting =
508 getCapabilitiesMatchedAseConfigurationSettings(
509 setting, capability.value(), direction);
510 if (filtered_ase_configuration_setting.has_value()) {
511 capability_matched_ase_configuration_settings.push_back(
512 filtered_ase_configuration_setting.value());
513 }
514 }
515 }
516
517 // Matching with requirements
518 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
519 for (auto& setting : capability_matched_ase_configuration_settings) {
520 for (auto& requirement : in_requirements) {
521 auto filtered_ase_configuration_setting =
522 getRequirementMatchedAseConfigurationSettings(setting, requirement);
523 if (filtered_ase_configuration_setting.has_value()) {
524 result.push_back(filtered_ase_configuration_setting.value());
525 }
526 }
527 }
528
529 *_aidl_return = result;
530 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000531};
532
Bao Doc4adf242023-11-15 08:03:20 +0000533bool LeAudioOffloadAudioProvider::isMatchedQosRequirement(
534 LeAudioAseQosConfiguration setting_qos,
535 AseQosDirectionRequirement requirement_qos) {
536 if (setting_qos.retransmissionNum !=
537 requirement_qos.preferredRetransmissionNum)
538 return false;
539 if (setting_qos.maxTransportLatencyMs > requirement_qos.maxTransportLatencyMs)
540 return false;
541 // Ignore other parameters, as they are not populated in the setting_qos
542 return true;
543}
544
Bao Do6112bda2023-11-15 03:57:59 +0000545ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseQosConfiguration(
546 const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
547 in_qosRequirement,
548 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return) {
Bao Doc4adf242023-11-15 08:03:20 +0000549 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
550 // Get all configuration settings
551 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
552 ase_configuration_settings =
553 BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
554
555 // Direction QoS matching
556 // Only handle one direction input case
557 uint8_t direction = 0;
558 std::optional<AseQosDirectionRequirement> direction_qos_requirement =
559 std::nullopt;
560 if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
561 direction_qos_requirement = in_qosRequirement.sinkAseQosRequirement.value();
562 direction = kLeAudioDirectionSink;
563 } else if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
564 direction_qos_requirement =
565 in_qosRequirement.sourceAseQosRequirement.value();
566 direction = kLeAudioDirectionSource;
567 }
568
569 for (auto& setting : ase_configuration_settings) {
570 // Context matching
571 if (setting.audioContext != in_qosRequirement.contextType) continue;
572
573 // Match configuration flags
574 // Currently configuration flags are not populated, ignore.
575
576 // Get a list of all matched AseDirectionConfiguration
577 // for the input direction
578 std::vector<std::optional<AseDirectionConfiguration>>*
579 direction_configuration = nullptr;
580 if (direction == kLeAudioDirectionSink) {
581 if (!setting.sinkAseConfiguration.has_value()) continue;
582 direction_configuration = &setting.sinkAseConfiguration.value();
583 } else {
584 if (!setting.sourceAseConfiguration.has_value()) continue;
585 direction_configuration = &setting.sourceAseConfiguration.value();
586 }
587
588 for (auto cfg : *direction_configuration) {
589 if (!cfg.has_value()) continue;
590 // If no requirement, return the first QoS
591 if (!direction_qos_requirement.has_value()) {
592 result.sinkQosConfiguration = cfg.value().qosConfiguration;
593 result.sourceQosConfiguration = cfg.value().qosConfiguration;
594 *_aidl_return = result;
595 return ndk::ScopedAStatus::ok();
596 }
597
598 // If has requirement, return the first matched QoS
599 // Try to match the ASE configuration
600 // and QoS with requirement
601 if (!cfg.value().qosConfiguration.has_value()) continue;
602 if (isMatchedAseConfiguration(
603 cfg.value().aseConfiguration,
604 direction_qos_requirement.value().aseConfiguration) &&
605 isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
606 direction_qos_requirement.value())) {
607 if (direction == kLeAudioDirectionSink)
608 result.sinkQosConfiguration = cfg.value().qosConfiguration;
609 else
610 result.sourceQosConfiguration = cfg.value().qosConfiguration;
611 *_aidl_return = result;
612 return ndk::ScopedAStatus::ok();
613 }
614 }
615 }
616
617 // No match, return empty QoS
618 *_aidl_return = result;
619 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000620};
621
622ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSinkAseMetadataChanged(
Bao Do5b2fdab2023-11-20 08:02:55 +0000623 IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
624 int32_t /*in_cisId*/,
Bao Do6112bda2023-11-15 03:57:59 +0000625 const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
626 (void)in_state;
627 (void)in_metadata;
628 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
629};
630
631ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSourceAseMetadataChanged(
Bao Do5b2fdab2023-11-20 08:02:55 +0000632 IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
633 int32_t /*in_cisId*/,
Bao Do6112bda2023-11-15 03:57:59 +0000634 const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
635 (void)in_state;
636 (void)in_metadata;
637 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
638};
639
Bao Do5b2fdab2023-11-20 08:02:55 +0000640void LeAudioOffloadAudioProvider::getBroadcastSettings() {
641 if (!broadcast_settings.empty()) return;
642
643 LOG(INFO) << __func__ << ": Loading broadcast settings from provider info";
644
645 std::vector<CodecInfo> db_codec_info =
646 BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
647 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
648 broadcast_settings.clear();
649 CodecSpecificConfigurationLtv::AudioChannelAllocation default_allocation;
650 default_allocation.bitmask =
651 CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
652
653 for (auto& codec_info : db_codec_info) {
654 if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
655 continue;
656 auto& transport = codec_info.transport.get<CodecInfo::Transport::leAudio>();
657 LeAudioBroadcastConfigurationSetting setting;
658 // Default setting
659 setting.numBis = 1;
660 setting.phy = {Phy::TWO_M};
661 // Populate BIS configuration info using codec_info
662 LeAudioBisConfiguration bis_cfg;
663 bis_cfg.codecId = codec_info.id;
664
665 CodecSpecificConfigurationLtv::OctetsPerCodecFrame octets;
666 octets.value = transport.bitdepth[0];
667
668 bis_cfg.codecConfiguration = {
669 sampling_freq_map[transport.samplingFrequencyHz[0]], octets,
670 frame_duration_map[transport.frameDurationUs[0]], default_allocation};
671
672 // Add information to structure
673 IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration sub_bis_cfg;
674 sub_bis_cfg.numBis = 1;
675 sub_bis_cfg.bisConfiguration = bis_cfg;
676 IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration sub_cfg;
677 sub_cfg.bisConfigurations = {sub_bis_cfg};
678 setting.subgroupsConfigurations = {sub_cfg};
679
680 broadcast_settings.push_back(setting);
681 }
682
683 LOG(INFO) << __func__
684 << ": Done loading broadcast settings from provider info";
685}
686
687/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
688 * capabilities. The new setting will have a filtered list of
689 * AseDirectionConfiguration that matched the capabilities */
690std::optional<LeAudioBroadcastConfigurationSetting>
691LeAudioOffloadAudioProvider::
692 getCapabilitiesMatchedBroadcastConfigurationSettings(
693 LeAudioBroadcastConfigurationSetting& setting,
694 const IBluetoothAudioProvider::LeAudioDeviceCapabilities&
695 capabilities) {
696 std::vector<IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration>
697 filter_subgroup;
698 for (auto& sub_cfg : setting.subgroupsConfigurations) {
699 std::vector<IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration>
700 filtered_bis_cfg;
701 for (auto& bis_cfg : sub_cfg.bisConfigurations)
702 if (isMatchedBISConfiguration(bis_cfg.bisConfiguration, capabilities)) {
703 filtered_bis_cfg.push_back(bis_cfg);
704 }
705 if (!filtered_bis_cfg.empty()) {
706 IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration
707 subgroup_cfg;
708 subgroup_cfg.bisConfigurations = filtered_bis_cfg;
709 filter_subgroup.push_back(subgroup_cfg);
710 }
711 }
712 if (filter_subgroup.empty()) return std::nullopt;
713
714 // Create a new LeAudioAseConfigurationSetting and return
715 LeAudioBroadcastConfigurationSetting filtered_setting(setting);
716 filtered_setting.subgroupsConfigurations = filter_subgroup;
717
718 return filtered_setting;
719}
720
Bao Do6112bda2023-11-15 03:57:59 +0000721ndk::ScopedAStatus
722LeAudioOffloadAudioProvider::getLeAudioBroadcastConfiguration(
723 const std::optional<std::vector<
724 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
725 in_remoteSinkAudioCapabilities,
726 const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
727 in_requirement,
Bao Do5b2fdab2023-11-20 08:02:55 +0000728 LeAudioBroadcastConfigurationSetting* _aidl_return) {
729 getBroadcastSettings();
730 _aidl_return = nullptr;
731
732 // Match and filter capability
733 std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
734 if (!in_remoteSinkAudioCapabilities.has_value()) {
735 LOG(WARNING) << __func__ << ": Empty capability";
736 return ndk::ScopedAStatus::ok();
737 }
738 for (auto& setting : broadcast_settings) {
739 for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
740 if (!capability.has_value()) continue;
741 auto filtered_setting =
742 getCapabilitiesMatchedBroadcastConfigurationSettings(
743 setting, capability.value());
744 if (filtered_setting.has_value())
745 filtered_settings.push_back(filtered_setting.value());
746 }
747 }
748
749 if (filtered_settings.empty()) {
750 LOG(WARNING) << __func__ << ": Cannot match any remote capability";
751 return ndk::ScopedAStatus::ok();
752 }
753
754 // Match and return the first matched requirement
755 if (in_requirement.subgroupConfigurationRequirements.empty()) {
756 LOG(INFO) << __func__ << ": Empty requirement";
757 *_aidl_return = filtered_settings[0];
758 return ndk::ScopedAStatus::ok();
759 }
760
761 for (auto& setting : filtered_settings) {
762 // Further filter out bis configuration
763 LeAudioBroadcastConfigurationSetting filtered_setting(setting);
764 filtered_setting.subgroupsConfigurations.clear();
765 for (auto& sub_cfg : setting.subgroupsConfigurations) {
766 bool isMatched = false;
767 for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
768 // Matching number of BIS
769 if (sub_req.bisNumPerSubgroup != sub_cfg.bisConfigurations.size())
770 continue;
771 // Currently will ignore quality and context hint.
772 isMatched = true;
773 break;
774 }
775 if (isMatched)
776 filtered_setting.subgroupsConfigurations.push_back(sub_cfg);
777 }
778 // Return the first match
779 if (!filtered_setting.subgroupsConfigurations.empty()) {
780 LOG(INFO) << __func__ << ": Matched requirement";
781 *_aidl_return = filtered_setting;
782 return ndk::ScopedAStatus::ok();
783 }
784 }
785
786 LOG(WARNING) << __func__ << ": Cannot match any requirement";
787 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000788};
Josh Wu6ab53e72021-12-29 23:53:33 -0800789
790} // namespace audio
791} // namespace bluetooth
792} // namespace hardware
793} // namespace android
Cheney Ni6ecbc762022-03-03 00:12:48 +0800794} // namespace aidl