• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #define LOG_TAG "BTAudioProviderLeAudioHW"
18 
19 #include "LeAudioOffloadAudioProvider.h"
20 
21 #include <BluetoothAudioCodecs.h>
22 #include <BluetoothAudioSessionReport.h>
23 #include <android-base/logging.h>
24 
25 namespace aidl {
26 namespace android {
27 namespace hardware {
28 namespace bluetooth {
29 namespace audio {
30 
31 constexpr uint8_t kLeAudioDirectionSink = 0x01;
32 constexpr uint8_t kLeAudioDirectionSource = 0x02;
33 constexpr uint8_t kIsoDataPathHci = 0x00;
34 constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
35 
36 const std::map<CodecSpecificConfigurationLtv::SamplingFrequency, uint32_t>
37     freq_to_support_bitmask_map = {
38         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000,
39          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000},
40         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025,
41          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ11025},
42         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
43          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000},
44         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ22050,
45          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ22050},
46         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
47          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ24000},
48         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000,
49          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ32000},
50         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000,
51          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000},
52         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ88200,
53          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ88200},
54         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000,
55          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ96000},
56         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ176400,
57          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ176400},
58         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ192000,
59          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ192000},
60         {CodecSpecificConfigurationLtv::SamplingFrequency::HZ384000,
61          CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ384000},
62 };
63 
64 // Helper map from capability's tag to configuration's tag
65 std::map<CodecSpecificCapabilitiesLtv::Tag, CodecSpecificConfigurationLtv::Tag>
66     cap_to_cfg_tag_map = {
67         {CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies,
68          CodecSpecificConfigurationLtv::Tag::samplingFrequency},
69         {CodecSpecificCapabilitiesLtv::Tag::supportedMaxCodecFramesPerSDU,
70          CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU},
71         {CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations,
72          CodecSpecificConfigurationLtv::Tag::frameDuration},
73         {CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts,
74          CodecSpecificConfigurationLtv::Tag::audioChannelAllocation},
75         {CodecSpecificCapabilitiesLtv::Tag::supportedOctetsPerCodecFrame,
76          CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame},
77 };
78 
79 const std::map<CodecSpecificConfigurationLtv::FrameDuration, uint32_t>
80     fduration_to_support_fduration_map = {
81         {CodecSpecificConfigurationLtv::FrameDuration::US7500,
82          CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500},
83         {CodecSpecificConfigurationLtv::FrameDuration::US10000,
84          CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000},
85         {CodecSpecificConfigurationLtv::FrameDuration::US20000,
86          CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US20000},
87 };
88 
89 std::map<int32_t, CodecSpecificConfigurationLtv::SamplingFrequency>
90     sampling_freq_map = {
91         {16000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
92         {24000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000},
93         {48000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000},
94         {96000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000},
95 };
96 
97 std::map<int32_t, CodecSpecificConfigurationLtv::FrameDuration>
98     frame_duration_map = {
99         {7500, CodecSpecificConfigurationLtv::FrameDuration::US7500},
100         {10000, CodecSpecificConfigurationLtv::FrameDuration::US10000},
101 };
102 
LeAudioOffloadOutputAudioProvider()103 LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
104     : LeAudioOffloadAudioProvider() {
105   session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
106 }
107 
LeAudioOffloadInputAudioProvider()108 LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
109     : LeAudioOffloadAudioProvider() {
110   session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
111 }
112 
LeAudioOffloadBroadcastAudioProvider()113 LeAudioOffloadBroadcastAudioProvider::LeAudioOffloadBroadcastAudioProvider()
114     : LeAudioOffloadAudioProvider() {
115   session_type_ =
116       SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
117 }
118 
LeAudioOffloadAudioProvider()119 LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
120     : BluetoothAudioProvider() {}
121 
isValid(const SessionType & sessionType)122 bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
123   return (sessionType == session_type_);
124 }
125 
startSession(const std::shared_ptr<IBluetoothAudioPort> & host_if,const AudioConfiguration & audio_config,const std::vector<LatencyMode> & latency_modes,DataMQDesc * _aidl_return)126 ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
127     const std::shared_ptr<IBluetoothAudioPort>& host_if,
128     const AudioConfiguration& audio_config,
129     const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
130   if (session_type_ ==
131       SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
132     if (audio_config.getTag() != AudioConfiguration::leAudioBroadcastConfig) {
133       LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
134                    << audio_config.toString();
135       *_aidl_return = DataMQDesc();
136       return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
137     }
138   } else if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
139     LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
140                  << audio_config.toString();
141     *_aidl_return = DataMQDesc();
142     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
143   }
144 
145   return BluetoothAudioProvider::startSession(host_if, audio_config,
146                                               latency_modes, _aidl_return);
147 }
148 
onSessionReady(DataMQDesc * _aidl_return)149 ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
150     DataMQDesc* _aidl_return) {
151   BluetoothAudioSessionReport::OnSessionStarted(
152       session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
153   *_aidl_return = DataMQDesc();
154   return ndk::ScopedAStatus::ok();
155 }
setCodecPriority(const CodecId & in_codecId,int32_t in_priority)156 ndk::ScopedAStatus LeAudioOffloadAudioProvider::setCodecPriority(
157     const CodecId& in_codecId, int32_t in_priority) {
158   codec_priority_map_[in_codecId] = in_priority;
159   return ndk::ScopedAStatus::ok();
160 };
161 
isMatchedValidCodec(CodecId cfg_codec,CodecId req_codec)162 bool LeAudioOffloadAudioProvider::isMatchedValidCodec(CodecId cfg_codec,
163                                                       CodecId req_codec) {
164   auto priority = codec_priority_map_.find(cfg_codec);
165   if (priority != codec_priority_map_.end() &&
166       priority->second ==
167           LeAudioOffloadAudioProvider::CODEC_PRIORITY_DISABLED) {
168     return false;
169   }
170   return cfg_codec == req_codec;
171 }
172 
filterCapabilitiesMatchedContext(AudioContext & setting_context,const IBluetoothAudioProvider::LeAudioDeviceCapabilities & capabilities)173 bool LeAudioOffloadAudioProvider::filterCapabilitiesMatchedContext(
174     AudioContext& setting_context,
175     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
176   // If has no metadata, assume match
177   if (!capabilities.metadata.has_value()) return true;
178 
179   for (auto metadata : capabilities.metadata.value()) {
180     if (!metadata.has_value()) continue;
181     if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
182       // Check all pref audio context to see if anything matched
183       auto& prefer_context =
184           metadata.value()
185               .get<MetadataLtv::Tag::preferredAudioContexts>()
186               .values;
187       if (setting_context.bitmask & prefer_context.bitmask) {
188         // New mask with matched capability
189         setting_context.bitmask &= prefer_context.bitmask;
190         return true;
191       }
192     }
193   }
194 
195   return false;
196 }
197 
isMatchedSamplingFreq(CodecSpecificConfigurationLtv::SamplingFrequency & cfg_freq,CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies & capability_freq)198 bool LeAudioOffloadAudioProvider::isMatchedSamplingFreq(
199     CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
200     CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
201         capability_freq) {
202   auto p = freq_to_support_bitmask_map.find(cfg_freq);
203   if (p != freq_to_support_bitmask_map.end()) {
204     if (capability_freq.bitmask & p->second) {
205       return true;
206     }
207   }
208   return false;
209 }
210 
isMatchedFrameDuration(CodecSpecificConfigurationLtv::FrameDuration & cfg_fduration,CodecSpecificCapabilitiesLtv::SupportedFrameDurations & capability_fduration)211 bool LeAudioOffloadAudioProvider::isMatchedFrameDuration(
212     CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
213     CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
214         capability_fduration) {
215   auto p = fduration_to_support_fduration_map.find(cfg_fduration);
216   if (p != fduration_to_support_fduration_map.end())
217     if (capability_fduration.bitmask & p->second) {
218       return true;
219     }
220   return false;
221 }
222 
getCountFromBitmask(int bitmask)223 int getCountFromBitmask(int bitmask) {
224   return std::bitset<32>(bitmask).count();
225 }
226 
isMatchedAudioChannel(CodecSpecificConfigurationLtv::AudioChannelAllocation & cfg_channel,CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts & capability_channel)227 bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
228     CodecSpecificConfigurationLtv::AudioChannelAllocation& cfg_channel,
229     CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
230         capability_channel) {
231   int count = getCountFromBitmask(cfg_channel.bitmask);
232   if (count == 1 &&
233       !(capability_channel.bitmask &
234         CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts::ONE))
235     return false;
236   if (count == 2 &&
237       !(capability_channel.bitmask &
238         CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts::TWO))
239     return false;
240   return true;
241 }
242 
isMatchedCodecFramesPerSDU(CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU & cfg_frame_sdu,CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU & capability_frame_sdu)243 bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
244     CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU& cfg_frame_sdu,
245     CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU&
246         capability_frame_sdu) {
247   return cfg_frame_sdu.value <= capability_frame_sdu.value;
248 }
249 
isMatchedOctetsPerCodecFrame(CodecSpecificConfigurationLtv::OctetsPerCodecFrame & cfg_octets,CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame & capability_octets)250 bool LeAudioOffloadAudioProvider::isMatchedOctetsPerCodecFrame(
251     CodecSpecificConfigurationLtv::OctetsPerCodecFrame& cfg_octets,
252     CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame&
253         capability_octets) {
254   return cfg_octets.value >= capability_octets.min &&
255          cfg_octets.value <= capability_octets.max;
256 }
257 
isCapabilitiesMatchedCodecConfiguration(std::vector<CodecSpecificConfigurationLtv> & codec_cfg,std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities)258 bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedCodecConfiguration(
259     std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
260     std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities) {
261   // Convert all codec_cfg into a map of tags -> correct data
262   std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
263       cfg_tag_map;
264   for (auto codec_cfg_data : codec_cfg)
265     cfg_tag_map[codec_cfg_data.getTag()] = codec_cfg_data;
266 
267   for (auto& codec_capability : codec_capabilities) {
268     auto cfg = cfg_tag_map.find(cap_to_cfg_tag_map[codec_capability.getTag()]);
269     // If capability has this tag, but our configuration doesn't
270     // Then we will assume it is matched
271     if (cfg == cfg_tag_map.end()) {
272       continue;
273     }
274 
275     switch (codec_capability.getTag()) {
276       case CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies: {
277         if (!isMatchedSamplingFreq(
278                 cfg->second.get<
279                     CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
280                 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
281                                          supportedSamplingFrequencies>())) {
282           return false;
283         }
284         break;
285       }
286 
287       case CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations: {
288         if (!isMatchedFrameDuration(
289                 cfg->second
290                     .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
291                 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
292                                          supportedFrameDurations>())) {
293           return false;
294         }
295         break;
296       }
297 
298       case CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts: {
299         if (!isMatchedAudioChannel(
300                 cfg->second.get<CodecSpecificConfigurationLtv::Tag::
301                                     audioChannelAllocation>(),
302                 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
303                                          supportedAudioChannelCounts>())) {
304           return false;
305         }
306         break;
307       }
308 
309       case CodecSpecificCapabilitiesLtv::Tag::supportedMaxCodecFramesPerSDU: {
310         if (!isMatchedCodecFramesPerSDU(
311                 cfg->second.get<CodecSpecificConfigurationLtv::Tag::
312                                     codecFrameBlocksPerSDU>(),
313                 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
314                                          supportedMaxCodecFramesPerSDU>())) {
315           return false;
316         }
317         break;
318       }
319 
320       case CodecSpecificCapabilitiesLtv::Tag::supportedOctetsPerCodecFrame: {
321         if (!isMatchedOctetsPerCodecFrame(
322                 cfg->second.get<
323                     CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
324                 codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
325                                          supportedOctetsPerCodecFrame>())) {
326           return false;
327         }
328         break;
329       }
330     }
331   }
332 
333   return true;
334 }
335 
filterMatchedAseConfiguration(LeAudioAseConfiguration & setting_cfg,const LeAudioAseConfiguration & requirement_cfg)336 bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
337     LeAudioAseConfiguration& setting_cfg,
338     const LeAudioAseConfiguration& requirement_cfg) {
339   // Check matching for codec configuration <=> requirement ASE codec
340   // Also match if no CodecId requirement
341   if (requirement_cfg.codecId.has_value()) {
342     if (!setting_cfg.codecId.has_value()) return false;
343     if (!isMatchedValidCodec(setting_cfg.codecId.value(),
344                              requirement_cfg.codecId.value())) {
345       return false;
346     }
347   }
348 
349   if (requirement_cfg.targetLatency !=
350           LeAudioAseConfiguration::TargetLatency::UNDEFINED &&
351       setting_cfg.targetLatency != requirement_cfg.targetLatency) {
352     return false;
353   }
354   // Ignore PHY requirement
355 
356   // Check all codec configuration
357   std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
358       cfg_tag_map;
359   for (auto cfg : setting_cfg.codecConfiguration)
360     cfg_tag_map[cfg.getTag()] = cfg;
361 
362   for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
363     // Directly compare CodecSpecificConfigurationLtv
364     auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
365     // Config not found for this requirement, cannot match
366     if (cfg == cfg_tag_map.end()) {
367       return false;
368     }
369 
370     // Ignore matching for audio channel allocation
371     // since the rule is complicated. Match outside instead
372     if (requirement_cfg.getTag() ==
373         CodecSpecificConfigurationLtv::Tag::audioChannelAllocation)
374       continue;
375 
376     if (cfg->second != requirement_cfg) {
377       return false;
378     }
379   }
380   // Ignore vendor configuration and metadata requirement
381 
382   return true;
383 }
384 
isMatchedBISConfiguration(LeAudioBisConfiguration bis_cfg,const IBluetoothAudioProvider::LeAudioDeviceCapabilities & capabilities)385 bool LeAudioOffloadAudioProvider::isMatchedBISConfiguration(
386     LeAudioBisConfiguration bis_cfg,
387     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
388   if (!isMatchedValidCodec(bis_cfg.codecId, capabilities.codecId)) {
389     return false;
390   }
391   if (!isCapabilitiesMatchedCodecConfiguration(
392           bis_cfg.codecConfiguration, capabilities.codecSpecificCapabilities)) {
393     return false;
394   }
395   return true;
396 }
397 
filterCapabilitiesAseDirectionConfiguration(std::vector<std::optional<AseDirectionConfiguration>> & direction_configurations,const IBluetoothAudioProvider::LeAudioDeviceCapabilities & capabilities,std::vector<std::optional<AseDirectionConfiguration>> & valid_direction_configurations)398 void LeAudioOffloadAudioProvider::filterCapabilitiesAseDirectionConfiguration(
399     std::vector<std::optional<AseDirectionConfiguration>>&
400         direction_configurations,
401     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
402     std::vector<std::optional<AseDirectionConfiguration>>&
403         valid_direction_configurations) {
404   for (auto direction_configuration : direction_configurations) {
405     if (!direction_configuration.has_value()) continue;
406     if (!direction_configuration.value().aseConfiguration.codecId.has_value())
407       continue;
408     if (!isMatchedValidCodec(
409             direction_configuration.value().aseConfiguration.codecId.value(),
410             capabilities.codecId))
411       continue;
412     // Check matching for codec configuration <=> codec capabilities
413     if (!isCapabilitiesMatchedCodecConfiguration(
414             direction_configuration.value().aseConfiguration.codecConfiguration,
415             capabilities.codecSpecificCapabilities))
416       continue;
417     valid_direction_configurations.push_back(direction_configuration);
418   }
419 }
420 
getLeAudioAseConfigurationAllocationBitmask(LeAudioAseConfiguration cfg)421 int getLeAudioAseConfigurationAllocationBitmask(LeAudioAseConfiguration cfg) {
422   for (auto cfg_ltv : cfg.codecConfiguration) {
423     if (cfg_ltv.getTag() ==
424         CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
425       return cfg_ltv
426           .get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
427           .bitmask;
428     }
429   }
430   return 0;
431 }
432 
findValidMonoConfig(std::vector<AseDirectionConfiguration> & valid_direction_configurations,int bitmask)433 std::optional<AseDirectionConfiguration> findValidMonoConfig(
434     std::vector<AseDirectionConfiguration>& valid_direction_configurations,
435     int bitmask) {
436   for (auto& cfg : valid_direction_configurations) {
437     int cfg_bitmask =
438         getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
439     if (getCountFromBitmask(cfg_bitmask) <= 1) {
440       // Modify the bitmask to be the same as the requirement
441       for (auto& codec_cfg : cfg.aseConfiguration.codecConfiguration) {
442         if (codec_cfg.getTag() ==
443             CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
444           codec_cfg
445               .get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
446               .bitmask = bitmask;
447           return cfg;
448         }
449       }
450     }
451   }
452   return std::nullopt;
453 }
454 
getValidConfigurationsFromAllocation(int req_allocation_bitmask,std::vector<AseDirectionConfiguration> & valid_direction_configurations,bool isExact)455 std::vector<AseDirectionConfiguration> getValidConfigurationsFromAllocation(
456     int req_allocation_bitmask,
457     std::vector<AseDirectionConfiguration>& valid_direction_configurations,
458     bool isExact) {
459   // Prefer the same allocation_bitmask
460   int channel_count = getCountFromBitmask(req_allocation_bitmask);
461 
462   if (isExact) {
463     for (auto& cfg : valid_direction_configurations) {
464       int cfg_bitmask =
465           getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
466       if (cfg_bitmask == req_allocation_bitmask) {
467         LOG(DEBUG)
468             << __func__
469             << ": Found an exact match for the requirement allocation of "
470             << cfg_bitmask;
471         return {cfg};
472       }
473     }
474     return {};
475   }
476   // Not using exact match strategy
477   if (channel_count <= 1) {
478     // Mono requirement matched if cfg is a mono config
479     auto cfg = findValidMonoConfig(valid_direction_configurations,
480                                    req_allocation_bitmask);
481     if (cfg.has_value()) return {cfg.value()};
482   } else {
483     // Stereo requirement returns 2 mono configs
484     // that has a combined bitmask equal to the stereo config
485     std::vector<AseDirectionConfiguration> temp;
486     for (int bit = 0; bit < 32; ++bit)
487       if (req_allocation_bitmask & (1 << bit)) {
488         auto cfg =
489             findValidMonoConfig(valid_direction_configurations, (1 << bit));
490         if (cfg.has_value()) temp.push_back(cfg.value());
491       }
492     if (temp.size() == channel_count) return temp;
493   }
494   return {};
495 }
496 
497 // Check and filter each index to see if it's a match.
filterRequirementAseDirectionConfiguration(std::optional<std::vector<std::optional<AseDirectionConfiguration>>> & direction_configurations,const std::vector<std::optional<AseDirectionRequirement>> & requirements,std::optional<std::vector<std::optional<AseDirectionConfiguration>>> & valid_direction_configurations,bool isExact)498 void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
499     std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
500         direction_configurations,
501     const std::vector<std::optional<AseDirectionRequirement>>& requirements,
502     std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
503         valid_direction_configurations,
504     bool isExact) {
505   if (!direction_configurations.has_value()) return;
506 
507   if (!valid_direction_configurations.has_value()) {
508     valid_direction_configurations =
509         std::vector<std::optional<AseDirectionConfiguration>>();
510   }
511 
512   if (isExact) {
513     // Exact matching process
514     // Need to respect the number of device
515     for (int i = 0; i < requirements.size(); ++i) {
516       auto requirement = requirements[i];
517       auto direction_configuration = direction_configurations.value()[i];
518       if (!direction_configuration.has_value()) {
519         valid_direction_configurations = std::nullopt;
520         return;
521       }
522       auto cfg = direction_configuration.value();
523       if (!filterMatchedAseConfiguration(
524               cfg.aseConfiguration, requirement.value().aseConfiguration)) {
525         valid_direction_configurations = std::nullopt;
526         return;  // No way to match
527       }
528       // For exact match, we require this direction to have the same allocation.
529       // If stereo, need stereo.
530       // If mono, need mono (modified to the correct required allocation)
531       auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
532           requirement.value().aseConfiguration);
533       int req_channel_count = getCountFromBitmask(req_allocation_bitmask);
534       int cfg_bitmask =
535           getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
536       int cfg_channel_count = getCountFromBitmask(cfg_bitmask);
537       if (req_channel_count <= 1) {
538         // MONO case, is a match if also mono, modify to the same allocation
539         if (cfg_channel_count > 1) {
540           valid_direction_configurations = std::nullopt;
541           return;  // Not a match
542         }
543         // Modify the bitmask to be the same as the requirement
544         for (auto& codec_cfg : cfg.aseConfiguration.codecConfiguration) {
545           if (codec_cfg.getTag() ==
546               CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
547             codec_cfg
548                 .get<CodecSpecificConfigurationLtv::Tag::
549                          audioChannelAllocation>()
550                 .bitmask = req_allocation_bitmask;
551             break;
552           }
553         }
554       } else {
555         // STEREO case, is a match if same allocation
556         if (req_allocation_bitmask != cfg_bitmask) {
557           valid_direction_configurations = std::nullopt;
558           return;  // Not a match
559         }
560       }
561       // Push to list if valid
562       valid_direction_configurations.value().push_back(cfg);
563     }
564   } else {
565     // Loose matching process
566     for (auto& requirement : requirements) {
567       if (!requirement.has_value()) continue;
568       auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
569           requirement.value().aseConfiguration);
570       auto req_channel_count = getCountFromBitmask(req_allocation_bitmask);
571 
572       auto temp = std::vector<AseDirectionConfiguration>();
573 
574       for (auto direction_configuration : direction_configurations.value()) {
575         if (!direction_configuration.has_value()) continue;
576         if (!filterMatchedAseConfiguration(
577                 direction_configuration.value().aseConfiguration,
578                 requirement.value().aseConfiguration))
579           continue;
580         // Valid if match any requirement.
581         temp.push_back(direction_configuration.value());
582       }
583 
584       // Get the best matching config based on channel allocation
585       auto total_cfg_channel_count = 0;
586       auto req_valid_configs = getValidConfigurationsFromAllocation(
587           req_allocation_bitmask, temp, isExact);
588       // Count and check required channel counts
589       for (auto& cfg : req_valid_configs) {
590         total_cfg_channel_count += getCountFromBitmask(
591             getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration));
592         valid_direction_configurations.value().push_back(cfg);
593       }
594       if (total_cfg_channel_count != req_channel_count) {
595         valid_direction_configurations = std::nullopt;
596         return;
597       }
598     }
599   }
600 }
601 
602 /* Get a new LeAudioAseConfigurationSetting by matching a setting with a
603  * capabilities. The new setting will have a filtered list of
604  * AseDirectionConfiguration that matched the capabilities */
605 std::optional<LeAudioAseConfigurationSetting>
getCapabilitiesMatchedAseConfigurationSettings(IBluetoothAudioProvider::LeAudioAseConfigurationSetting & setting,const IBluetoothAudioProvider::LeAudioDeviceCapabilities & capabilities,uint8_t direction)606 LeAudioOffloadAudioProvider::getCapabilitiesMatchedAseConfigurationSettings(
607     IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
608     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
609     uint8_t direction) {
610   // Create a new LeAudioAseConfigurationSetting and return
611   LeAudioAseConfigurationSetting filtered_setting{
612       .audioContext = setting.audioContext,
613       .sinkAseConfiguration = setting.sinkAseConfiguration,
614       .sourceAseConfiguration = setting.sourceAseConfiguration,
615       .flags = setting.flags,
616       .packing = setting.packing,
617   };
618 
619   // Get a list of all matched AseDirectionConfiguration
620   // for the input direction
621   std::vector<std::optional<AseDirectionConfiguration>>*
622       direction_configuration = nullptr;
623   if (direction == kLeAudioDirectionSink) {
624     if (!filtered_setting.sinkAseConfiguration.has_value()) return std::nullopt;
625     direction_configuration = &filtered_setting.sinkAseConfiguration.value();
626   } else {
627     if (!filtered_setting.sourceAseConfiguration.has_value())
628       return std::nullopt;
629     direction_configuration = &filtered_setting.sourceAseConfiguration.value();
630   }
631   std::vector<std::optional<AseDirectionConfiguration>>
632       valid_direction_configuration;
633   filterCapabilitiesAseDirectionConfiguration(
634       *direction_configuration, capabilities, valid_direction_configuration);
635 
636   // No valid configuration for this direction
637   if (valid_direction_configuration.empty()) {
638     return std::nullopt;
639   }
640 
641   // Create a new LeAudioAseConfigurationSetting and return
642   // For other direction will contain all settings
643   if (direction == kLeAudioDirectionSink) {
644     filtered_setting.sinkAseConfiguration = valid_direction_configuration;
645   } else {
646     filtered_setting.sourceAseConfiguration = valid_direction_configuration;
647   }
648 
649   return filtered_setting;
650 }
651 
652 /* Get a new LeAudioAseConfigurationSetting by matching a setting with a
653  * requirement. The new setting will have a filtered list of
654  * AseDirectionConfiguration that matched the requirement */
655 std::optional<LeAudioAseConfigurationSetting>
getRequirementMatchedAseConfigurationSettings(IBluetoothAudioProvider::LeAudioAseConfigurationSetting & setting,const IBluetoothAudioProvider::LeAudioConfigurationRequirement & requirement,bool isExact)656 LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
657     IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
658     const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
659     bool isExact) {
660   // Create a new LeAudioAseConfigurationSetting to return
661   // Make context the same as the requirement
662   LeAudioAseConfigurationSetting filtered_setting{
663       .audioContext = requirement.audioContext,
664       .packing = setting.packing,
665       .flags = setting.flags,
666   };
667 
668   // The number of AseDirectionRequirement in the requirement
669   // is the number of device.
670 
671   // The exact matching process is as follow:
672   // 1. Setting direction has the same number of cfg (ignore when null
673   // require)
674   // 2. For each index, it's a 1-1 filter / mapping.
675   if (isExact) {
676     if (requirement.sinkAseRequirement.has_value() &&
677         requirement.sinkAseRequirement.value().size() !=
678             setting.sinkAseConfiguration.value().size()) {
679       return std::nullopt;
680     }
681 
682     if (requirement.sourceAseRequirement.has_value() &&
683         requirement.sourceAseRequirement.value().size() !=
684             setting.sourceAseConfiguration.value().size()) {
685       return std::nullopt;
686     }
687   }
688 
689   if (requirement.sinkAseRequirement.has_value()) {
690     filterRequirementAseDirectionConfiguration(
691         setting.sinkAseConfiguration, requirement.sinkAseRequirement.value(),
692         filtered_setting.sinkAseConfiguration, isExact);
693     if (!filtered_setting.sinkAseConfiguration.has_value()) {
694       return std::nullopt;
695     }
696   }
697 
698   if (requirement.sourceAseRequirement.has_value()) {
699     filterRequirementAseDirectionConfiguration(
700         setting.sourceAseConfiguration,
701         requirement.sourceAseRequirement.value(),
702         filtered_setting.sourceAseConfiguration, isExact);
703     if (!filtered_setting.sourceAseConfiguration.has_value()) {
704       return std::nullopt;
705     }
706   }
707 
708   return filtered_setting;
709 }
710 
711 std::optional<std::pair<
712     std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
matchWithRequirement(std::vector<std::pair<std::string,IBluetoothAudioProvider::LeAudioAseConfigurationSetting>> & matched_ase_configuration_settings,const IBluetoothAudioProvider::LeAudioConfigurationRequirement & requirement,bool isMatchContext,bool isExact,bool isMatchFlags)713 LeAudioOffloadAudioProvider::matchWithRequirement(
714     std::vector<std::pair<
715         std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>&
716         matched_ase_configuration_settings,
717     const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
718     bool isMatchContext, bool isExact, bool isMatchFlags) {
719   LOG(INFO) << __func__ << ": Trying to match for the requirement "
720             << requirement.toString() << ", match context = " << isMatchContext
721             << ", match exact = " << isExact
722             << ", match flags = " << isMatchFlags;
723   // Don't have to match with flag if requirements don't have flags.
724   auto requirement_flags_bitmask = 0;
725   if (isMatchFlags) {
726     if (!requirement.flags.has_value()) return std::nullopt;
727     requirement_flags_bitmask = requirement.flags.value().bitmask;
728   }
729   for (auto& [setting_name, setting] : matched_ase_configuration_settings) {
730     // Try to match context.
731     if (isMatchContext) {
732       if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
733           requirement.audioContext.bitmask)
734         continue;
735       LOG(DEBUG) << __func__
736                  << ": Setting with matched context: name: " << setting_name
737                  << ", setting: " << setting.toString();
738     }
739 
740     // Try to match configuration flags
741     if (isMatchFlags) {
742       if (!setting.flags.has_value()) continue;
743       if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
744           requirement_flags_bitmask)
745         continue;
746       LOG(DEBUG) << __func__
747                  << ": Setting with matched flags: name: " << setting_name
748                  << ", setting: " << setting.toString();
749     }
750 
751     auto filtered_ase_configuration_setting =
752         getRequirementMatchedAseConfigurationSettings(setting, requirement,
753                                                       isExact);
754     if (filtered_ase_configuration_setting.has_value()) {
755       LOG(INFO) << __func__ << ": Result found: name: " << setting_name
756                 << ", setting: "
757                 << filtered_ase_configuration_setting.value().toString();
758       // Found a matched setting, ignore other settings
759       return {{setting_name, filtered_ase_configuration_setting.value()}};
760     }
761   }
762   // If cannot satisfy this requirement, return nullopt
763   LOG(WARNING) << __func__ << ": Cannot match the requirement "
764                << requirement.toString()
765                << ", match context = " << isMatchContext;
766   return std::nullopt;
767 }
768 
769 // For each requirement, a valid ASE configuration will satify:
770 // - matched with the sink capability (if presented)
771 // - AND matched with the source capability (if presented)
772 // - and the setting need to pass the requirement
getLeAudioAseConfiguration(const std::optional<std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>> & in_remoteSinkAudioCapabilities,const std::optional<std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>> & in_remoteSourceAudioCapabilities,const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement> & in_requirements,std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> * _aidl_return)773 ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
774     const std::optional<std::vector<
775         std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
776         in_remoteSinkAudioCapabilities,
777     const std::optional<std::vector<
778         std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
779         in_remoteSourceAudioCapabilities,
780     const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
781         in_requirements,
782     std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>*
783         _aidl_return) {
784   // Get all configuration settings
785   std::vector<std::pair<
786       std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
787       ase_configuration_settings =
788           BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
789 
790   if (!in_remoteSinkAudioCapabilities.has_value() &&
791       !in_remoteSourceAudioCapabilities.has_value()) {
792     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
793   }
794 
795   // Matched ASE configuration with ignored audio context
796   std::vector<std::pair<
797       std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
798       sink_matched_ase_configuration_settings;
799   std::vector<std::pair<
800       std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
801       matched_ase_configuration_settings;
802 
803   // A setting must match both source and sink.
804   // First filter all setting matched with sink capability
805   if (in_remoteSinkAudioCapabilities.has_value()) {
806     for (auto& [setting_name, setting] : ase_configuration_settings) {
807       for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
808         if (!capability.has_value()) continue;
809         auto filtered_ase_configuration_setting =
810             getCapabilitiesMatchedAseConfigurationSettings(
811                 setting, capability.value(), kLeAudioDirectionSink);
812         if (filtered_ase_configuration_setting.has_value()) {
813           sink_matched_ase_configuration_settings.push_back(
814               {setting_name, filtered_ase_configuration_setting.value()});
815         }
816       }
817     }
818   } else {
819     sink_matched_ase_configuration_settings = ase_configuration_settings;
820   }
821 
822   // Combine filter every source capability
823   if (in_remoteSourceAudioCapabilities.has_value()) {
824     for (auto& [setting_name, setting] :
825          sink_matched_ase_configuration_settings)
826       for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
827         if (!capability.has_value()) continue;
828         auto filtered_ase_configuration_setting =
829             getCapabilitiesMatchedAseConfigurationSettings(
830                 setting, capability.value(), kLeAudioDirectionSource);
831         if (filtered_ase_configuration_setting.has_value()) {
832           matched_ase_configuration_settings.push_back(
833               {setting_name, filtered_ase_configuration_setting.value()});
834         }
835       }
836   } else {
837     matched_ase_configuration_settings =
838         sink_matched_ase_configuration_settings;
839   }
840 
841   std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
842       result_no_name;
843   std::vector<std::pair<
844       std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
845       result;
846   for (auto& requirement : in_requirements) {
847     // For each requirement, try to match with a setting.
848     // If we cannot match, return an empty result.
849 
850     // Matching priority list:
851     // Matched configuration flags, i.e. for asymmetric requirement.
852     // Preferred context - exact match with allocation
853     // Preferred context - loose match with allocation
854     // Any context - exact match with allocation
855     // Any context - loose match with allocation
856     bool found = false;
857     for (bool match_flag : {true, false}) {
858       for (bool match_context : {true, false}) {
859         for (bool match_exact : {true, false}) {
860           auto matched_setting = matchWithRequirement(
861               matched_ase_configuration_settings, requirement, match_context,
862               match_exact, match_flag);
863           if (matched_setting.has_value()) {
864             result.push_back(matched_setting.value());
865             found = true;
866             break;
867           }
868         }
869         if (found) break;
870       }
871       if (found) break;
872     }
873 
874     if (!found) {
875       LOG(ERROR) << __func__
876                  << ": Cannot find any match for this requirement, exitting...";
877       *_aidl_return = result_no_name;
878       return ndk::ScopedAStatus::ok();
879     }
880   }
881 
882   LOG(INFO) << __func__
883             << ": Found matches for all requirements, chosen settings:";
884   for (auto& [setting_name, setting] : result) {
885     LOG(INFO) << __func__ << ": name: " << setting_name
886               << ", setting: " << setting.toString();
887     result_no_name.push_back(setting);
888   }
889   *_aidl_return = result_no_name;
890   return ndk::ScopedAStatus::ok();
891 };
892 
isMatchedQosRequirement(LeAudioAseQosConfiguration setting_qos,AseQosDirectionRequirement requirement_qos)893 bool LeAudioOffloadAudioProvider::isMatchedQosRequirement(
894     LeAudioAseQosConfiguration setting_qos,
895     AseQosDirectionRequirement requirement_qos) {
896   if (setting_qos.retransmissionNum !=
897       requirement_qos.preferredRetransmissionNum) {
898     return false;
899   }
900   if (setting_qos.maxTransportLatencyMs >
901       requirement_qos.maxTransportLatencyMs) {
902     return false;
903   }
904   return true;
905 }
906 
isValidQosRequirement(AseQosDirectionRequirement qosRequirement)907 bool isValidQosRequirement(AseQosDirectionRequirement qosRequirement) {
908   return ((qosRequirement.maxTransportLatencyMs > 0) &&
909           (qosRequirement.presentationDelayMaxUs > 0) &&
910           (qosRequirement.presentationDelayMaxUs >=
911            qosRequirement.presentationDelayMinUs));
912 }
913 
914 std::optional<LeAudioAseQosConfiguration>
getDirectionQosConfiguration(uint8_t direction,const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement & qosRequirement,std::vector<std::pair<std::string,LeAudioAseConfigurationSetting>> & ase_configuration_settings,bool isExact,bool isMatchFlags)915 LeAudioOffloadAudioProvider::getDirectionQosConfiguration(
916     uint8_t direction,
917     const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
918         qosRequirement,
919     std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>&
920         ase_configuration_settings,
921     bool isExact, bool isMatchFlags) {
922   auto requirement_flags_bitmask = 0;
923   if (isMatchFlags) {
924     if (!qosRequirement.flags.has_value()) return std::nullopt;
925     requirement_flags_bitmask = qosRequirement.flags.value().bitmask;
926   }
927 
928   std::optional<AseQosDirectionRequirement> direction_qos_requirement =
929       std::nullopt;
930 
931   // Get the correct direction
932   if (direction == kLeAudioDirectionSink) {
933     direction_qos_requirement = qosRequirement.sinkAseQosRequirement.value();
934   } else {
935     direction_qos_requirement = qosRequirement.sourceAseQosRequirement.value();
936   }
937 
938   for (auto& [setting_name, setting] : ase_configuration_settings) {
939     // Context matching
940     if ((setting.audioContext.bitmask & qosRequirement.audioContext.bitmask) !=
941         qosRequirement.audioContext.bitmask)
942       continue;
943     LOG(DEBUG) << __func__
944                << ": Setting with matched context: name: " << setting_name
945                << ", setting: " << setting.toString();
946 
947     // Match configuration flags
948     if (isMatchFlags) {
949       if (!setting.flags.has_value()) continue;
950       if ((setting.flags.value().bitmask & requirement_flags_bitmask) !=
951           requirement_flags_bitmask)
952         continue;
953       LOG(DEBUG) << __func__
954                  << ": Setting with matched flags: name: " << setting_name
955                  << ", setting: " << setting.toString();
956     }
957 
958     // Get a list of all matched AseDirectionConfiguration
959     // for the input direction
960     std::optional<std::vector<std::optional<AseDirectionConfiguration>>>
961         direction_configuration = std::nullopt;
962     if (direction == kLeAudioDirectionSink) {
963       if (!setting.sinkAseConfiguration.has_value()) continue;
964       direction_configuration.emplace(setting.sinkAseConfiguration.value());
965     } else {
966       if (!setting.sourceAseConfiguration.has_value()) continue;
967       direction_configuration.emplace(setting.sourceAseConfiguration.value());
968     }
969 
970     if (!direction_configuration.has_value()) {
971       return std::nullopt;
972     }
973 
974     // Collect all valid cfg into a vector
975     // Then try to get the best match for audio allocation
976 
977     auto temp = std::vector<AseDirectionConfiguration>();
978 
979     for (auto& cfg : direction_configuration.value()) {
980       if (!cfg.has_value()) continue;
981       // If no requirement, return the first QoS
982       if (!direction_qos_requirement.has_value()) {
983         return cfg.value().qosConfiguration;
984       }
985 
986       // If has requirement, return the first matched QoS
987       // Try to match the ASE configuration
988       // and QoS with requirement
989       if (!cfg.value().qosConfiguration.has_value()) continue;
990       if (filterMatchedAseConfiguration(
991               cfg.value().aseConfiguration,
992               direction_qos_requirement.value().aseConfiguration) &&
993           isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
994                                   direction_qos_requirement.value())) {
995         temp.push_back(cfg.value());
996       }
997     }
998     LOG(WARNING) << __func__ << ": Got " << temp.size()
999                  << " configs, start matching allocation";
1000 
1001     int qos_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
1002         direction_qos_requirement.value().aseConfiguration);
1003     // Get the best matching config based on channel allocation
1004     auto req_valid_configs = getValidConfigurationsFromAllocation(
1005         qos_allocation_bitmask, temp, isExact);
1006     if (req_valid_configs.empty()) {
1007       LOG(WARNING) << __func__
1008                    << ": Cannot find matching allocation for bitmask "
1009                    << qos_allocation_bitmask;
1010 
1011     } else {
1012       return req_valid_configs[0].qosConfiguration;
1013     }
1014   }
1015 
1016   return std::nullopt;
1017 }
1018 
getLeAudioAseQosConfiguration(const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement & in_qosRequirement,IBluetoothAudioProvider::LeAudioAseQosConfigurationPair * _aidl_return)1019 ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseQosConfiguration(
1020     const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
1021         in_qosRequirement,
1022     IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return) {
1023   IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
1024 
1025   // Get all configuration settings
1026   std::vector<std::pair<
1027       std::string, IBluetoothAudioProvider::LeAudioAseConfigurationSetting>>
1028       ase_configuration_settings =
1029           BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
1030 
1031   // Direction QoS matching
1032   // Only handle one direction input case
1033   if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
1034     if (!isValidQosRequirement(in_qosRequirement.sinkAseQosRequirement.value()))
1035       return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1036     bool found = false;
1037     for (bool match_flag : {true, false}) {
1038       for (bool match_exact : {true, false}) {
1039         auto setting = getDirectionQosConfiguration(
1040             kLeAudioDirectionSink, in_qosRequirement,
1041             ase_configuration_settings, match_exact, match_flag);
1042         if (setting.has_value()) {
1043           found = true;
1044           result.sinkQosConfiguration = setting;
1045           break;
1046         }
1047       }
1048       if (found) break;
1049     }
1050   }
1051   if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
1052     if (!isValidQosRequirement(
1053             in_qosRequirement.sourceAseQosRequirement.value()))
1054       return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1055     bool found = false;
1056     for (bool match_flag : {true, false}) {
1057       for (bool match_exact : {true, false}) {
1058         auto setting = getDirectionQosConfiguration(
1059             kLeAudioDirectionSource, in_qosRequirement,
1060             ase_configuration_settings, match_exact, match_flag);
1061         if (setting.has_value()) {
1062           found = true;
1063           result.sourceQosConfiguration = setting;
1064           break;
1065         }
1066       }
1067       if (found) break;
1068     }
1069   }
1070 
1071   *_aidl_return = result;
1072   return ndk::ScopedAStatus::ok();
1073 };
1074 
onSinkAseMetadataChanged(IBluetoothAudioProvider::AseState in_state,int32_t,int32_t,const std::optional<std::vector<std::optional<MetadataLtv>>> & in_metadata)1075 ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSinkAseMetadataChanged(
1076     IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
1077     int32_t /*in_cisId*/,
1078     const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
1079   (void)in_state;
1080   (void)in_metadata;
1081   return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1082 };
1083 
onSourceAseMetadataChanged(IBluetoothAudioProvider::AseState in_state,int32_t,int32_t,const std::optional<std::vector<std::optional<MetadataLtv>>> & in_metadata)1084 ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSourceAseMetadataChanged(
1085     IBluetoothAudioProvider::AseState in_state, int32_t /*in_cigId*/,
1086     int32_t /*in_cisId*/,
1087     const std::optional<std::vector<std::optional<MetadataLtv>>>& in_metadata) {
1088   (void)in_state;
1089   (void)in_metadata;
1090   return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1091 };
1092 
getDefaultBroadcastSetting(int context_bitmask,IBluetoothAudioProvider::BroadcastQuality quality)1093 LeAudioBroadcastConfigurationSetting getDefaultBroadcastSetting(
1094     int context_bitmask, IBluetoothAudioProvider::BroadcastQuality quality) {
1095   LeAudioBroadcastConfigurationSetting setting;
1096   setting.retransmitionNum = 4;
1097   setting.maxTransportLatencyMs = 60;
1098   setting.sduIntervalUs = 10000;
1099   setting.maxSduOctets = 40;
1100 
1101   if (quality == IBluetoothAudioProvider::BroadcastQuality::HIGH) {
1102     LOG(INFO) << __func__ << ": High quality, returning high quality settings";
1103     setting.retransmitionNum = 4;
1104     setting.maxTransportLatencyMs = 65;
1105     setting.maxSduOctets = 200;
1106     return setting;
1107   }
1108 
1109   // Populate other settings base on context
1110   // TODO: Populate with better design
1111   if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME)) {
1112     setting.retransmitionNum = 2;
1113     setting.maxTransportLatencyMs = 10;
1114     setting.maxSduOctets = 120;
1115   } else if (context_bitmask & (AudioContext::INSTRUCTIONAL)) {
1116     setting.retransmitionNum = 2;
1117     setting.maxTransportLatencyMs = 10;
1118     setting.maxSduOctets = 40;
1119   } else if (context_bitmask &
1120              (AudioContext::SOUND_EFFECTS | AudioContext::UNSPECIFIED)) {
1121     setting.retransmitionNum = 4;
1122     setting.maxTransportLatencyMs = 60;
1123     setting.maxSduOctets = 80;
1124   } else if (context_bitmask &
1125              (AudioContext::ALERTS | AudioContext::NOTIFICATIONS |
1126               AudioContext::EMERGENCY_ALARM)) {
1127     setting.retransmitionNum = 4;
1128     setting.maxTransportLatencyMs = 60;
1129     setting.maxSduOctets = 40;
1130   } else if (context_bitmask & AudioContext::MEDIA) {
1131     setting.retransmitionNum = 4;
1132     setting.maxTransportLatencyMs = 60;
1133     setting.maxSduOctets = 120;
1134   }
1135 
1136   return setting;
1137 }
modifySubBISConfigAllocation(IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration & sub_bis_cfg,int allocation_bitmask)1138 void modifySubBISConfigAllocation(
1139     IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration& sub_bis_cfg,
1140     int allocation_bitmask) {
1141   for (auto& codec_cfg : sub_bis_cfg.bisConfiguration.codecConfiguration) {
1142     if (codec_cfg.getTag() ==
1143         CodecSpecificConfigurationLtv::audioChannelAllocation) {
1144       codec_cfg.get<CodecSpecificConfigurationLtv::audioChannelAllocation>()
1145           .bitmask = allocation_bitmask;
1146       break;
1147     }
1148   }
1149 }
modifySubgroupConfiguration(IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration & subgroup_cfg,int context_bitmask)1150 void modifySubgroupConfiguration(
1151     IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration&
1152         subgroup_cfg,
1153     int context_bitmask) {
1154   // STEREO configs
1155   // Split into 2 sub BIS config, each has numBis = 1
1156   if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME |
1157                          AudioContext::SOUND_EFFECTS |
1158                          AudioContext::UNSPECIFIED | AudioContext::MEDIA)) {
1159     if (subgroup_cfg.bisConfigurations.size() == 1)
1160       subgroup_cfg.bisConfigurations.push_back(
1161           subgroup_cfg.bisConfigurations[0]);
1162 
1163     subgroup_cfg.bisConfigurations[0].numBis = 1;
1164     modifySubBISConfigAllocation(
1165         subgroup_cfg.bisConfigurations[0],
1166         CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT);
1167 
1168     subgroup_cfg.bisConfigurations[1].numBis = 1;
1169     modifySubBISConfigAllocation(
1170         subgroup_cfg.bisConfigurations[1],
1171         CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT);
1172     return;
1173   }
1174 
1175   // MONO configs
1176   for (auto& sub_bis_cfg : subgroup_cfg.bisConfigurations) {
1177     sub_bis_cfg.numBis = 1;
1178     modifySubBISConfigAllocation(
1179         sub_bis_cfg,
1180         CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER);
1181   }
1182 }
1183 
getBroadcastSettings()1184 void LeAudioOffloadAudioProvider::getBroadcastSettings() {
1185   if (!broadcast_settings.empty()) return;
1186 
1187   LOG(INFO) << __func__
1188             << ": Loading basic broadcast settings from provider info";
1189 
1190   std::vector<CodecInfo> db_codec_info =
1191       BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
1192           SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
1193   for (auto x : db_codec_info) {
1194     LOG(INFO) << __func__ << ": codec info = " << x.toString();
1195   }
1196   broadcast_settings.clear();
1197 
1198   // Default value population
1199   CodecSpecificConfigurationLtv::AudioChannelAllocation default_allocation;
1200   default_allocation.bitmask =
1201       CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
1202   CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU default_frame;
1203   default_frame.value = 1;
1204 
1205   for (auto& codec_info : db_codec_info) {
1206     if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
1207       continue;
1208     auto& transport = codec_info.transport.get<CodecInfo::Transport::leAudio>();
1209     LeAudioBroadcastConfigurationSetting setting;
1210     setting.retransmitionNum = 4;
1211     setting.maxTransportLatencyMs = 60;
1212     setting.sduIntervalUs = 10000;
1213     setting.maxSduOctets = 40;
1214     // Default setting
1215     setting.numBis = 1;
1216     setting.phy = {Phy::TWO_M};
1217     // Populate BIS configuration info using codec_info
1218     LeAudioBisConfiguration bis_cfg;
1219     bis_cfg.codecId = codec_info.id;
1220 
1221     CodecSpecificConfigurationLtv::OctetsPerCodecFrame octets;
1222     octets.value = transport.bitdepth[0];
1223 
1224     bis_cfg.codecConfiguration = {
1225         sampling_freq_map[transport.samplingFrequencyHz[0]],
1226         octets,
1227         frame_duration_map[transport.frameDurationUs[0]],
1228         default_allocation,
1229         default_frame,
1230     };
1231 
1232     // Ignore bis_cfg.metadata
1233 
1234     // Add information to structure
1235     IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration sub_bis_cfg;
1236     sub_bis_cfg.numBis = 1;
1237     sub_bis_cfg.bisConfiguration = bis_cfg;
1238     IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration sub_cfg;
1239     // Populate the same sub config
1240     sub_cfg.bisConfigurations = {sub_bis_cfg};
1241     setting.subgroupsConfigurations = {sub_cfg};
1242 
1243     broadcast_settings.push_back(setting);
1244   }
1245 
1246   LOG(INFO) << __func__
1247             << ": Done loading broadcast settings from provider info";
1248 }
1249 
1250 /* Get a new LeAudioAseConfigurationSetting by matching a setting with a
1251  * capabilities. The new setting will have a filtered list of
1252  * AseDirectionConfiguration that matched the capabilities */
1253 std::optional<LeAudioBroadcastConfigurationSetting>
1254 LeAudioOffloadAudioProvider::
getCapabilitiesMatchedBroadcastConfigurationSettings(LeAudioBroadcastConfigurationSetting & setting,const IBluetoothAudioProvider::LeAudioDeviceCapabilities & capabilities)1255     getCapabilitiesMatchedBroadcastConfigurationSettings(
1256         LeAudioBroadcastConfigurationSetting& setting,
1257         const IBluetoothAudioProvider::LeAudioDeviceCapabilities&
1258             capabilities) {
1259   std::vector<IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration>
1260       filter_subgroup;
1261   for (auto& sub_cfg : setting.subgroupsConfigurations) {
1262     std::vector<IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration>
1263         filtered_bis_cfg;
1264     for (auto& bis_cfg : sub_cfg.bisConfigurations)
1265       if (isMatchedBISConfiguration(bis_cfg.bisConfiguration, capabilities)) {
1266         filtered_bis_cfg.push_back(bis_cfg);
1267       }
1268     if (!filtered_bis_cfg.empty()) {
1269       IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration
1270           subgroup_cfg;
1271       subgroup_cfg.bisConfigurations = filtered_bis_cfg;
1272       filter_subgroup.push_back(subgroup_cfg);
1273     }
1274   }
1275   if (filter_subgroup.empty()) return std::nullopt;
1276 
1277   // Create a new LeAudioAseConfigurationSetting and return
1278   LeAudioBroadcastConfigurationSetting filtered_setting(setting);
1279   filtered_setting.subgroupsConfigurations = filter_subgroup;
1280 
1281   return filtered_setting;
1282 }
1283 
getCodecRequirementBasedOnContext(int context_bitmask,IBluetoothAudioProvider::BroadcastQuality quality)1284 std::vector<CodecSpecificConfigurationLtv> getCodecRequirementBasedOnContext(
1285     int context_bitmask, IBluetoothAudioProvider::BroadcastQuality quality) {
1286   // Default requirement: lc3_stereo_16_2
1287   std::vector<CodecSpecificConfigurationLtv> requirement = {
1288       CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
1289       CodecSpecificConfigurationLtv::FrameDuration::US10000,
1290   };
1291 
1292   if (quality == IBluetoothAudioProvider::BroadcastQuality::HIGH) {
1293     LOG(INFO) << __func__
1294               << ": High quality, returning high quality requirement";
1295     requirement = {
1296         CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000,
1297         CodecSpecificConfigurationLtv::FrameDuration::US10000,
1298     };
1299     return requirement;
1300   }
1301 
1302   if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME)) {
1303     // lc3_stereo_24_2_1
1304     requirement = {
1305         CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
1306         CodecSpecificConfigurationLtv::FrameDuration::US10000,
1307     };
1308   } else if (context_bitmask & (AudioContext::INSTRUCTIONAL)) {
1309     // lc3_mono_16_2
1310     requirement = {
1311         CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
1312         CodecSpecificConfigurationLtv::FrameDuration::US10000,
1313     };
1314   } else if (context_bitmask &
1315              (AudioContext::SOUND_EFFECTS | AudioContext::UNSPECIFIED)) {
1316     // lc3_stereo_16_2
1317     requirement = {
1318         CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
1319         CodecSpecificConfigurationLtv::FrameDuration::US10000,
1320     };
1321   } else if (context_bitmask &
1322              (AudioContext::ALERTS | AudioContext::NOTIFICATIONS |
1323               AudioContext::EMERGENCY_ALARM)) {
1324     // Default requirement: lc3_stereo_16_2
1325     requirement = {
1326         CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
1327         CodecSpecificConfigurationLtv::FrameDuration::US10000,
1328     };
1329   } else if (context_bitmask & AudioContext::MEDIA) {
1330     // Default requirement: lc3_stereo_16_2
1331     // Return the 48k requirement
1332     requirement = {
1333         CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
1334         CodecSpecificConfigurationLtv::FrameDuration::US10000,
1335     };
1336   }
1337   return requirement;
1338 }
1339 
isSubgroupConfigurationMatchedContext(AudioContext requirement_context,IBluetoothAudioProvider::BroadcastQuality quality,LeAudioBroadcastSubgroupConfiguration configuration)1340 bool LeAudioOffloadAudioProvider::isSubgroupConfigurationMatchedContext(
1341     AudioContext requirement_context,
1342     IBluetoothAudioProvider::BroadcastQuality quality,
1343     LeAudioBroadcastSubgroupConfiguration configuration) {
1344   // Find any valid context metadata in the bisConfigurations
1345   // assuming the bis configuration in the same bis subgroup
1346   // will have the same context metadata
1347   std::optional<AudioContext> config_context = std::nullopt;
1348 
1349   auto codec_requirement =
1350       getCodecRequirementBasedOnContext(requirement_context.bitmask, quality);
1351   std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
1352       req_tag_map;
1353   for (auto x : codec_requirement) req_tag_map[x.getTag()] = x;
1354 
1355   for (auto& bis_cfg : configuration.bisConfigurations) {
1356     // Check every sub_bis_cfg to see which match
1357     for (auto& x : bis_cfg.bisConfiguration.codecConfiguration) {
1358       auto p = req_tag_map.find(x.getTag());
1359       if (p == req_tag_map.end()) continue;
1360       if (p->second != x) {
1361         LOG(WARNING) << __func__ << ": does not match for context "
1362                      << requirement_context.toString()
1363                      << ", cfg = " << x.toString();
1364         return false;
1365       }
1366     }
1367   }
1368   return true;
1369 }
1370 
1371 ndk::ScopedAStatus
getLeAudioBroadcastConfiguration(const std::optional<std::vector<std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>> & in_remoteSinkAudioCapabilities,const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement & in_requirement,LeAudioBroadcastConfigurationSetting * _aidl_return)1372 LeAudioOffloadAudioProvider::getLeAudioBroadcastConfiguration(
1373     const std::optional<std::vector<
1374         std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
1375         in_remoteSinkAudioCapabilities,
1376     const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
1377         in_requirement,
1378     LeAudioBroadcastConfigurationSetting* _aidl_return) {
1379   if (in_requirement.subgroupConfigurationRequirements.empty()) {
1380     LOG(WARNING) << __func__ << ": Empty requirement";
1381     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1382   }
1383 
1384   // Broadcast setting are from provider info
1385   // We will allow empty capability input, match all settings with requirements.
1386   getBroadcastSettings();
1387   std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
1388   if (!in_remoteSinkAudioCapabilities.has_value() ||
1389       in_remoteSinkAudioCapabilities.value().empty()) {
1390     LOG(INFO) << __func__ << ": Empty capability, get all broadcast settings";
1391     filtered_settings = broadcast_settings;
1392   } else {
1393     for (auto& setting : broadcast_settings) {
1394       for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
1395         if (!capability.has_value()) continue;
1396         auto filtered_setting =
1397             getCapabilitiesMatchedBroadcastConfigurationSettings(
1398                 setting, capability.value());
1399         if (filtered_setting.has_value())
1400           filtered_settings.push_back(filtered_setting.value());
1401       }
1402     }
1403   }
1404 
1405   if (filtered_settings.empty()) {
1406     LOG(WARNING) << __func__ << ": Cannot match any remote capability";
1407     return ndk::ScopedAStatus::ok();
1408   }
1409 
1410   if (in_requirement.subgroupConfigurationRequirements.empty()) {
1411     LOG(INFO) << __func__ << ": Empty requirement";
1412     *_aidl_return = filtered_settings[0];
1413     return ndk::ScopedAStatus::ok();
1414   }
1415 
1416   // For each subgroup config requirement, find a suitable subgroup config.
1417   // Gather these suitable subgroup config in an array.
1418   // If the setting can satisfy all requirement, we can return the setting
1419   // with the filtered array.
1420 
1421   auto context_bitmask =
1422       in_requirement.subgroupConfigurationRequirements[0].audioContext.bitmask;
1423   auto quality = in_requirement.subgroupConfigurationRequirements[0].quality;
1424   LeAudioBroadcastConfigurationSetting return_setting =
1425       getDefaultBroadcastSetting(context_bitmask, quality);
1426   // Default setting
1427   return_setting.numBis = 0;
1428   return_setting.subgroupsConfigurations = {};
1429 
1430   LeAudioDataPathConfiguration path;
1431   path.isoDataPathConfiguration.isTransparent = true;
1432   path.dataPathId = kIsoDataPathPlatformDefault;
1433 
1434   // Each subreq, find a setting that match
1435   for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
1436     bool is_setting_matched = false;
1437     for (auto setting : filtered_settings) {
1438       bool is_matched = true;
1439       // Check if every sub BIS config satisfy
1440       for (auto& sub_group_config : setting.subgroupsConfigurations) {
1441         if (!isSubgroupConfigurationMatchedContext(
1442                 sub_req.audioContext, sub_req.quality, sub_group_config)) {
1443           is_matched = false;
1444           break;
1445         }
1446         path.isoDataPathConfiguration.codecId =
1447             sub_group_config.bisConfigurations[0].bisConfiguration.codecId;
1448         // Also modify the subgroup config to match the context
1449         modifySubgroupConfiguration(sub_group_config, context_bitmask);
1450       }
1451 
1452       if (is_matched) {
1453         is_setting_matched = true;
1454         for (auto& sub_group_config : setting.subgroupsConfigurations)
1455           return_setting.subgroupsConfigurations.push_back(sub_group_config);
1456         break;
1457       }
1458     }
1459 
1460     if (!is_setting_matched) {
1461       LOG(WARNING) << __func__
1462                    << ": Cannot find a setting that match requirement "
1463                    << sub_req.toString();
1464       return ndk::ScopedAStatus::ok();
1465     }
1466   }
1467 
1468   // Populate all numBis
1469   for (auto& sub_group_config : return_setting.subgroupsConfigurations) {
1470     for (auto& sub_bis_config : sub_group_config.bisConfigurations) {
1471       return_setting.numBis += sub_bis_config.numBis;
1472     }
1473   }
1474   return_setting.phy = std::vector<Phy>(return_setting.numBis, Phy::TWO_M);
1475   // Populate data path config
1476   return_setting.dataPathConfiguration = path;
1477   // TODO: Workaround for STEREO configs maxSduOctets being doubled
1478   if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME |
1479                          AudioContext::SOUND_EFFECTS |
1480                          AudioContext::UNSPECIFIED | AudioContext::MEDIA)) {
1481     return_setting.maxSduOctets /= 2;
1482   }
1483   LOG(INFO) << __func__
1484             << ": Combined setting that match: " << return_setting.toString();
1485   *_aidl_return = return_setting;
1486   return ndk::ScopedAStatus::ok();
1487 };
1488 
1489 }  // namespace audio
1490 }  // namespace bluetooth
1491 }  // namespace hardware
1492 }  // namespace android
1493 }  // namespace aidl
1494