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