blob: 406856896cdccd418d275298bcede83c89c7bb1d [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
Josh Wu6ab53e72021-12-29 23:53:33 -080085LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
86 : LeAudioOffloadAudioProvider() {
87 session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
88}
89
90LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
91 : LeAudioOffloadAudioProvider() {
92 session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
93}
94
Alice Kuoe80a5762022-02-09 14:44:29 +080095LeAudioOffloadBroadcastAudioProvider::LeAudioOffloadBroadcastAudioProvider()
96 : LeAudioOffloadAudioProvider() {
97 session_type_ =
98 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
99}
100
Josh Wu6ab53e72021-12-29 23:53:33 -0800101LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
102 : BluetoothAudioProvider() {}
103
104bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
105 return (sessionType == session_type_);
106}
107
108ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
109 const std::shared_ptr<IBluetoothAudioPort>& host_if,
Chen Chenc92270e2022-02-14 18:29:52 -0800110 const AudioConfiguration& audio_config,
Cheney Ni6ecbc762022-03-03 00:12:48 +0800111 const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
Alice Kuoee398a92022-07-10 23:59:18 +0800112 if (session_type_ ==
113 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
114 if (audio_config.getTag() != AudioConfiguration::leAudioBroadcastConfig) {
115 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
116 << audio_config.toString();
117 *_aidl_return = DataMQDesc();
118 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
119 }
120 } else if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
Josh Wu6ab53e72021-12-29 23:53:33 -0800121 LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
122 << audio_config.toString();
123 *_aidl_return = DataMQDesc();
124 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
125 }
Josh Wu6ab53e72021-12-29 23:53:33 -0800126
Bao Do6112bda2023-11-15 03:57:59 +0000127 return BluetoothAudioProvider::startSession(host_if, audio_config,
128 latency_modes, _aidl_return);
Josh Wu6ab53e72021-12-29 23:53:33 -0800129}
130
131ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
132 DataMQDesc* _aidl_return) {
Cheney Ni6ecbc762022-03-03 00:12:48 +0800133 BluetoothAudioSessionReport::OnSessionStarted(
134 session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
Josh Wu6ab53e72021-12-29 23:53:33 -0800135 *_aidl_return = DataMQDesc();
136 return ndk::ScopedAStatus::ok();
137}
Bao Do6112bda2023-11-15 03:57:59 +0000138ndk::ScopedAStatus LeAudioOffloadAudioProvider::setCodecPriority(
139 const CodecId& in_codecId, int32_t in_priority) {
140 codec_priority_map_[in_codecId] = in_priority;
141 return ndk::ScopedAStatus::ok();
142};
143
Bao Do867af602023-11-15 05:41:12 +0000144bool LeAudioOffloadAudioProvider::isMatchedValidCodec(CodecId cfg_codec,
145 CodecId req_codec) {
146 auto priority = codec_priority_map_.find(cfg_codec);
147 if (priority != codec_priority_map_.end() && priority->second == -1)
148 return false;
149 return cfg_codec == req_codec;
150}
151
152bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedContext(
153 AudioContext setting_context,
154 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
155 // If has no metadata, assume match
156 if (!capabilities.metadata.has_value()) return true;
157
158 for (auto metadata : capabilities.metadata.value()) {
159 if (!metadata.has_value()) continue;
160 if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
161 // Check all pref audio context to see if anything matched
162 auto& context = metadata.value()
163 .get<MetadataLtv::Tag::preferredAudioContexts>()
164 .values;
165 if (setting_context.bitmask & context.bitmask) return true;
166 }
167 }
168
169 return false;
170}
171
172bool LeAudioOffloadAudioProvider::isMatchedSamplingFreq(
173 CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
174 CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
175 capability_freq) {
176 for (auto [freq, bitmask] : freq_to_support_bitmask_map)
177 if (cfg_freq == freq) return (capability_freq.bitmask & bitmask);
178 return false;
179}
180
181bool LeAudioOffloadAudioProvider::isMatchedFrameDuration(
182 CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
183 CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
184 capability_fduration) {
185 for (auto [fduration, bitmask] : fduration_to_support_fduration_map)
186 if (cfg_fduration == fduration)
187 return (capability_fduration.bitmask & bitmask);
188 return false;
189}
190
191bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
192 CodecSpecificConfigurationLtv::AudioChannelAllocation&
193 /*cfg_channel*/,
194 CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
195 /*capability_channel*/) {
196 bool isMatched = true;
197 // TODO: how to match?
198 return isMatched;
199}
200
201bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
202 CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU& cfg_frame_sdu,
203 CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU&
204 capability_frame_sdu) {
205 return cfg_frame_sdu.value <= capability_frame_sdu.value;
206}
207
208bool LeAudioOffloadAudioProvider::isMatchedOctetsPerCodecFrame(
209 CodecSpecificConfigurationLtv::OctetsPerCodecFrame& cfg_octets,
210 CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame&
211 capability_octets) {
212 return cfg_octets.value >= capability_octets.minimum &&
213 cfg_octets.value <= capability_octets.maximum;
214}
215
216bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedCodecConfiguration(
217 std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
218 std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities) {
219 // Convert all codec_cfg into a map of tags -> correct data
220 std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
221 cfg_tag_map;
222 for (auto codec_cfg_data : codec_cfg)
223 cfg_tag_map[codec_cfg_data.getTag()] = codec_cfg_data;
224
225 for (auto& codec_capability : codec_capabilities) {
226 auto cfg = cfg_tag_map.find(cap_to_cfg_tag_map[codec_capability.getTag()]);
227 // Cannot find tag for the capability:
228 if (cfg == cfg_tag_map.end()) return false;
229
230 // Matching logic for sampling frequency
231 if (codec_capability.getTag() ==
232 CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies) {
233 if (!isMatchedSamplingFreq(
234 cfg->second
235 .get<CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
236 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
237 supportedSamplingFrequencies>()))
238 return false;
239 } else if (codec_capability.getTag() ==
240 CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations) {
241 if (!isMatchedFrameDuration(
242 cfg->second
243 .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
244 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
245 supportedFrameDurations>()))
246 return false;
247 } else if (codec_capability.getTag() ==
248 CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts) {
249 if (!isMatchedAudioChannel(
250 cfg->second.get<
251 CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>(),
252 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
253 supportedAudioChannelCounts>()))
254 return false;
255 } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
256 supportedMaxCodecFramesPerSDU) {
257 if (!isMatchedCodecFramesPerSDU(
258 cfg->second.get<
259 CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU>(),
260 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
261 supportedMaxCodecFramesPerSDU>()))
262 return false;
263 } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
264 supportedOctetsPerCodecFrame) {
265 if (!isMatchedOctetsPerCodecFrame(
266 cfg->second.get<
267 CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
268 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
269 supportedOctetsPerCodecFrame>()))
270 return false;
271 }
272 }
273
274 return true;
275}
276
277bool LeAudioOffloadAudioProvider::isMatchedAseConfiguration(
278 LeAudioAseConfiguration setting_cfg,
279 LeAudioAseConfiguration requirement_cfg) {
280 // Check matching for codec configuration <=> requirement ASE codec
281 // Also match if no CodecId requirement
282 if (requirement_cfg.codecId.has_value()) {
283 if (!setting_cfg.codecId.has_value()) return false;
284 if (!isMatchedValidCodec(setting_cfg.codecId.value(),
285 requirement_cfg.codecId.value()))
286 return false;
287 }
288
289 if (setting_cfg.targetLatency != requirement_cfg.targetLatency) return false;
290 // Ignore PHY requirement
291
292 // Check all codec configuration
293 std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
294 cfg_tag_map;
295 for (auto cfg : setting_cfg.codecConfiguration)
296 cfg_tag_map[cfg.getTag()] = cfg;
297
298 for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
299 // Directly compare CodecSpecificConfigurationLtv
300 auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
301 if (cfg == cfg_tag_map.end()) return false;
302
303 if (cfg->second != requirement_cfg) return false;
304 }
305 // Ignore vendor configuration and metadata requirement
306
307 return true;
308}
309
310void LeAudioOffloadAudioProvider::filterCapabilitiesAseDirectionConfiguration(
311 std::vector<std::optional<AseDirectionConfiguration>>&
312 direction_configurations,
313 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
314 std::vector<std::optional<AseDirectionConfiguration>>&
315 valid_direction_configurations) {
316 for (auto direction_configuration : direction_configurations) {
317 if (!direction_configuration.has_value()) continue;
318 if (!direction_configuration.value().aseConfiguration.codecId.has_value())
319 continue;
320 if (!isMatchedValidCodec(
321 direction_configuration.value().aseConfiguration.codecId.value(),
322 capabilities.codecId))
323 continue;
324 // Check matching for codec configuration <=> codec capabilities
325 if (!isCapabilitiesMatchedCodecConfiguration(
326 direction_configuration.value().aseConfiguration.codecConfiguration,
327 capabilities.codecSpecificCapabilities))
328 continue;
329 valid_direction_configurations.push_back(direction_configuration);
330 }
331}
332
333void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
334 std::vector<std::optional<AseDirectionConfiguration>>&
335 direction_configurations,
336 const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
337 requirements,
338 std::vector<std::optional<AseDirectionConfiguration>>&
339 valid_direction_configurations) {
340 for (auto direction_configuration : direction_configurations) {
341 if (!requirements.has_value()) {
342 // If there's no requirement, all are valid
343 valid_direction_configurations.push_back(direction_configuration);
344 continue;
345 }
346 if (!direction_configuration.has_value()) continue;
347
348 for (auto& requirement : requirements.value()) {
349 if (!requirement.has_value()) continue;
350 if (!isMatchedAseConfiguration(
351 direction_configuration.value().aseConfiguration,
352 requirement.value().aseConfiguration))
353 continue;
354 // Valid if match any requirement.
355 valid_direction_configurations.push_back(direction_configuration);
356 break;
357 }
358 }
359}
360
361/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
362 * capabilities. The new setting will have a filtered list of
363 * AseDirectionConfiguration that matched the capabilities */
364std::optional<LeAudioAseConfigurationSetting>
365LeAudioOffloadAudioProvider::getCapabilitiesMatchedAseConfigurationSettings(
366 IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
367 const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
368 uint8_t direction) {
369 // Try to match context in metadata.
370 if (!isCapabilitiesMatchedContext(setting.audioContext, capabilities))
371 return std::nullopt;
372
373 // Get a list of all matched AseDirectionConfiguration
374 // for the input direction
375 std::vector<std::optional<AseDirectionConfiguration>>*
376 direction_configuration = nullptr;
377 if (direction == kLeAudioDirectionSink) {
378 if (!setting.sinkAseConfiguration.has_value()) return std::nullopt;
379 direction_configuration = &setting.sinkAseConfiguration.value();
380 } else {
381 if (!setting.sourceAseConfiguration.has_value()) return std::nullopt;
382 direction_configuration = &setting.sourceAseConfiguration.value();
383 }
384 std::vector<std::optional<AseDirectionConfiguration>>
385 valid_direction_configuration;
386 filterCapabilitiesAseDirectionConfiguration(
387 *direction_configuration, capabilities, valid_direction_configuration);
388 if (valid_direction_configuration.empty()) return std::nullopt;
389
390 // Create a new LeAudioAseConfigurationSetting and return
391 LeAudioAseConfigurationSetting filtered_setting;
392 filtered_setting.audioContext = setting.audioContext;
393 filtered_setting.packing = setting.packing;
394 if (direction == kLeAudioDirectionSink) {
395 filtered_setting.sinkAseConfiguration = valid_direction_configuration;
396 } else {
397 filtered_setting.sourceAseConfiguration = valid_direction_configuration;
398 }
399 filtered_setting.flags = setting.flags;
400
401 return filtered_setting;
402}
403
404/* Get a new LeAudioAseConfigurationSetting by matching a setting with a
405 * requirement. The new setting will have a filtered list of
406 * AseDirectionConfiguration that matched the requirement */
407std::optional<LeAudioAseConfigurationSetting>
408LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
409 IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
410 const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
411 requirement) {
412 // Try to match context in metadata.
413 if (setting.audioContext != requirement.audioContext) return std::nullopt;
414
415 // Check requirement for the correct direction
416 const std::optional<std::vector<std::optional<AseDirectionRequirement>>>*
417 direction_requirement;
418 std::vector<std::optional<AseDirectionConfiguration>>*
419 direction_configuration;
420 if (setting.sinkAseConfiguration.has_value()) {
421 direction_configuration = &setting.sinkAseConfiguration.value();
422 direction_requirement = &requirement.sinkAseRequirement;
423 } else {
424 direction_configuration = &setting.sourceAseConfiguration.value();
425 direction_requirement = &requirement.sourceAseRequirement;
426 }
427
428 std::vector<std::optional<AseDirectionConfiguration>>
429 valid_direction_configuration;
430 filterRequirementAseDirectionConfiguration(*direction_configuration,
431 *direction_requirement,
432 valid_direction_configuration);
433 if (valid_direction_configuration.empty()) return std::nullopt;
434
435 // Create a new LeAudioAseConfigurationSetting and return
436 LeAudioAseConfigurationSetting filtered_setting;
437 filtered_setting.audioContext = setting.audioContext;
438 filtered_setting.packing = setting.packing;
439 if (setting.sinkAseConfiguration.has_value())
440 filtered_setting.sinkAseConfiguration = valid_direction_configuration;
441 else
442 filtered_setting.sourceAseConfiguration = valid_direction_configuration;
443 filtered_setting.flags = setting.flags;
444
445 return filtered_setting;
446}
447
Bao Do6112bda2023-11-15 03:57:59 +0000448ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
449 const std::optional<std::vector<
450 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
451 in_remoteSinkAudioCapabilities,
452 const std::optional<std::vector<
453 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
454 in_remoteSourceAudioCapabilities,
455 const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
456 in_requirements,
457 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
458 _aidl_return) {
Bao Do867af602023-11-15 05:41:12 +0000459 // Get all configuration settings
460 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
461 ase_configuration_settings =
462 BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
463
464 // Currently won't handle case where both sink and source capabilities
465 // are passed in. Only handle one of them.
466 const std::optional<std::vector<
467 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>*
468 in_remoteAudioCapabilities;
469 uint8_t direction = 0;
470 if (in_remoteSinkAudioCapabilities.has_value()) {
471 direction = kLeAudioDirectionSink;
472 in_remoteAudioCapabilities = &in_remoteSinkAudioCapabilities;
473 } else {
474 direction = kLeAudioDirectionSource;
475 in_remoteAudioCapabilities = &in_remoteSourceAudioCapabilities;
476 }
477
478 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
479 capability_matched_ase_configuration_settings;
480 // Matching with remote capabilities
481 for (auto& setting : ase_configuration_settings) {
482 for (auto& capability : in_remoteAudioCapabilities->value()) {
483 if (!capability.has_value()) continue;
484 auto filtered_ase_configuration_setting =
485 getCapabilitiesMatchedAseConfigurationSettings(
486 setting, capability.value(), direction);
487 if (filtered_ase_configuration_setting.has_value()) {
488 capability_matched_ase_configuration_settings.push_back(
489 filtered_ase_configuration_setting.value());
490 }
491 }
492 }
493
494 // Matching with requirements
495 std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
496 for (auto& setting : capability_matched_ase_configuration_settings) {
497 for (auto& requirement : in_requirements) {
498 auto filtered_ase_configuration_setting =
499 getRequirementMatchedAseConfigurationSettings(setting, requirement);
500 if (filtered_ase_configuration_setting.has_value()) {
501 result.push_back(filtered_ase_configuration_setting.value());
502 }
503 }
504 }
505
506 *_aidl_return = result;
507 return ndk::ScopedAStatus::ok();
Bao Do6112bda2023-11-15 03:57:59 +0000508};
509
510ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseQosConfiguration(
511 const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
512 in_qosRequirement,
513 IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return) {
514 /* TODO: Implement */
515 (void)in_qosRequirement;
516 (void)_aidl_return;
517 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
518};
519
520ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSinkAseMetadataChanged(
521 IBluetoothAudioProvider::AseState in_state,
522 const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
523 (void)in_state;
524 (void)in_metadata;
525 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
526};
527
528ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSourceAseMetadataChanged(
529 IBluetoothAudioProvider::AseState in_state,
530 const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
531 (void)in_state;
532 (void)in_metadata;
533 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
534};
535
536ndk::ScopedAStatus
537LeAudioOffloadAudioProvider::getLeAudioBroadcastConfiguration(
538 const std::optional<std::vector<
539 std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
540 in_remoteSinkAudioCapabilities,
541 const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
542 in_requirement,
543 IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting*
544 _aidl_return) {
545 /* TODO: Implement */
546 (void)in_remoteSinkAudioCapabilities;
547 (void)in_requirement;
548 (void)_aidl_return;
549 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
550};
Josh Wu6ab53e72021-12-29 23:53:33 -0800551
552} // namespace audio
553} // namespace bluetooth
554} // namespace hardware
555} // namespace android
Cheney Ni6ecbc762022-03-03 00:12:48 +0800556} // namespace aidl