• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 STREAM_TO_UINT8(u8, p) \
18   {                            \
19     (u8) = (uint8_t)(*(p));    \
20     (p) += 1;                  \
21   }
22 #define STREAM_TO_UINT16(u16, p)                                  \
23   {                                                               \
24     (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
25     (p) += 2;                                                     \
26   }
27 #define STREAM_TO_UINT32(u32, p)                                      \
28   {                                                                   \
29     (u32) = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + \
30              ((((uint32_t)(*((p) + 2)))) << 16) +                     \
31              ((((uint32_t)(*((p) + 3)))) << 24));                     \
32     (p) += 4;                                                         \
33   }
34 
35 #define LOG_TAG "BTAudioAseConfigAidl"
36 
37 #include "BluetoothLeAudioAseConfigurationSettingProvider.h"
38 
39 #include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h>
40 #include <aidl/android/hardware/bluetooth/audio/AudioContext.h>
41 #include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
42 #include <aidl/android/hardware/bluetooth/audio/CodecId.h>
43 #include <aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.h>
44 #include <aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.h>
45 #include <aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h>
46 #include <aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.h>
47 #include <aidl/android/hardware/bluetooth/audio/Phy.h>
48 #include <android-base/logging.h>
49 
50 #include <optional>
51 
52 #include "flatbuffers/idl.h"
53 #include "flatbuffers/util.h"
54 
55 namespace aidl {
56 namespace android {
57 namespace hardware {
58 namespace bluetooth {
59 namespace audio {
60 
61 /* Internal structure definition */
62 std::map<std::string,
63          std::tuple<std::vector<std::optional<AseDirectionConfiguration>>,
64                     std::vector<std::optional<AseDirectionConfiguration>>,
65                     ConfigurationFlags>>
66     configurations_;
67 
68 std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
69     ase_configuration_settings_;
70 
71 constexpr uint8_t kIsoDataPathHci = 0x00;
72 constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
73 constexpr uint8_t kIsoDataPathDisabled = 0xFF;
74 
75 constexpr uint8_t kLeAudioDirectionSink = 0x01;
76 constexpr uint8_t kLeAudioDirectionSource = 0x02;
77 constexpr uint8_t kLeAudioDirectionBoth =
78     kLeAudioDirectionSink | kLeAudioDirectionSource;
79 
80 /* Sampling Frequencies */
81 constexpr uint8_t kLeAudioSamplingFreq8000Hz = 0x01;
82 constexpr uint8_t kLeAudioSamplingFreq11025Hz = 0x02;
83 constexpr uint8_t kLeAudioSamplingFreq16000Hz = 0x03;
84 constexpr uint8_t kLeAudioSamplingFreq22050Hz = 0x04;
85 constexpr uint8_t kLeAudioSamplingFreq24000Hz = 0x05;
86 constexpr uint8_t kLeAudioSamplingFreq32000Hz = 0x06;
87 constexpr uint8_t kLeAudioSamplingFreq44100Hz = 0x07;
88 constexpr uint8_t kLeAudioSamplingFreq48000Hz = 0x08;
89 constexpr uint8_t kLeAudioSamplingFreq88200Hz = 0x09;
90 constexpr uint8_t kLeAudioSamplingFreq96000Hz = 0x0A;
91 constexpr uint8_t kLeAudioSamplingFreq176400Hz = 0x0B;
92 constexpr uint8_t kLeAudioSamplingFreq192000Hz = 0x0C;
93 constexpr uint8_t kLeAudioSamplingFreq384000Hz = 0x0D;
94 
95 /* Frame Durations */
96 constexpr uint8_t kLeAudioCodecFrameDur7500us = 0x00;
97 constexpr uint8_t kLeAudioCodecFrameDur10000us = 0x01;
98 constexpr uint8_t kLeAudioCodecFrameDur20000us = 0x02;
99 
100 /* Audio Allocations */
101 constexpr uint32_t kLeAudioLocationMonoAudio = 0x00000000;
102 constexpr uint32_t kLeAudioLocationFrontLeft = 0x00000001;
103 constexpr uint32_t kLeAudioLocationFrontRight = 0x00000002;
104 constexpr uint32_t kLeAudioLocationFrontCenter = 0x00000004;
105 constexpr uint32_t kLeAudioLocationLowFreqEffects1 = 0x00000008;
106 constexpr uint32_t kLeAudioLocationBackLeft = 0x00000010;
107 constexpr uint32_t kLeAudioLocationBackRight = 0x00000020;
108 constexpr uint32_t kLeAudioLocationFrontLeftOfCenter = 0x00000040;
109 constexpr uint32_t kLeAudioLocationFrontRightOfCenter = 0x00000080;
110 constexpr uint32_t kLeAudioLocationBackCenter = 0x00000100;
111 constexpr uint32_t kLeAudioLocationLowFreqEffects2 = 0x00000200;
112 constexpr uint32_t kLeAudioLocationSideLeft = 0x00000400;
113 constexpr uint32_t kLeAudioLocationSideRight = 0x00000800;
114 constexpr uint32_t kLeAudioLocationTopFrontLeft = 0x00001000;
115 constexpr uint32_t kLeAudioLocationTopFrontRight = 0x00002000;
116 constexpr uint32_t kLeAudioLocationTopFrontCenter = 0x00004000;
117 constexpr uint32_t kLeAudioLocationTopCenter = 0x00008000;
118 constexpr uint32_t kLeAudioLocationTopBackLeft = 0x00010000;
119 constexpr uint32_t kLeAudioLocationTopBackRight = 0x00020000;
120 constexpr uint32_t kLeAudioLocationTopSideLeft = 0x00040000;
121 constexpr uint32_t kLeAudioLocationTopSideRight = 0x00080000;
122 constexpr uint32_t kLeAudioLocationTopBackCenter = 0x00100000;
123 constexpr uint32_t kLeAudioLocationBottomFrontCenter = 0x00200000;
124 constexpr uint32_t kLeAudioLocationBottomFrontLeft = 0x00400000;
125 constexpr uint32_t kLeAudioLocationBottomFrontRight = 0x00800000;
126 constexpr uint32_t kLeAudioLocationFrontLeftWide = 0x01000000;
127 constexpr uint32_t kLeAudioLocationFrontRightWide = 0x02000000;
128 constexpr uint32_t kLeAudioLocationLeftSurround = 0x04000000;
129 constexpr uint32_t kLeAudioLocationRightSurround = 0x08000000;
130 
131 constexpr uint32_t kLeAudioLocationAnyLeft =
132     kLeAudioLocationFrontLeft | kLeAudioLocationBackLeft |
133     kLeAudioLocationFrontLeftOfCenter | kLeAudioLocationSideLeft |
134     kLeAudioLocationTopFrontLeft | kLeAudioLocationTopBackLeft |
135     kLeAudioLocationTopSideLeft | kLeAudioLocationBottomFrontLeft |
136     kLeAudioLocationFrontLeftWide | kLeAudioLocationLeftSurround;
137 
138 constexpr uint32_t kLeAudioLocationAnyRight =
139     kLeAudioLocationFrontRight | kLeAudioLocationBackRight |
140     kLeAudioLocationFrontRightOfCenter | kLeAudioLocationSideRight |
141     kLeAudioLocationTopFrontRight | kLeAudioLocationTopBackRight |
142     kLeAudioLocationTopSideRight | kLeAudioLocationBottomFrontRight |
143     kLeAudioLocationFrontRightWide | kLeAudioLocationRightSurround;
144 
145 constexpr uint32_t kLeAudioLocationStereo =
146     kLeAudioLocationFrontLeft | kLeAudioLocationFrontRight;
147 
148 /* Octets Per Frame */
149 constexpr uint16_t kLeAudioCodecFrameLen30 = 30;
150 constexpr uint16_t kLeAudioCodecFrameLen40 = 40;
151 constexpr uint16_t kLeAudioCodecFrameLen60 = 60;
152 constexpr uint16_t kLeAudioCodecFrameLen80 = 80;
153 constexpr uint16_t kLeAudioCodecFrameLen100 = 100;
154 constexpr uint16_t kLeAudioCodecFrameLen120 = 120;
155 
156 /* Helper map for matching various sampling frequency notations */
157 const std::map<uint8_t, CodecSpecificConfigurationLtv::SamplingFrequency>
158     sampling_freq_map = {
159         {kLeAudioSamplingFreq8000Hz,
160          CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000},
161         {kLeAudioSamplingFreq16000Hz,
162          CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
163         {kLeAudioSamplingFreq24000Hz,
164          CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000},
165         {kLeAudioSamplingFreq32000Hz,
166          CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000},
167         {kLeAudioSamplingFreq44100Hz,
168          CodecSpecificConfigurationLtv::SamplingFrequency::HZ44100},
169         {kLeAudioSamplingFreq48000Hz,
170          CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000}};
171 
172 /* Helper map for matching various frame durations notations */
173 const std::map<uint8_t, CodecSpecificConfigurationLtv::FrameDuration>
174     frame_duration_map = {
175         {kLeAudioCodecFrameDur7500us,
176          CodecSpecificConfigurationLtv::FrameDuration::US7500},
177         {kLeAudioCodecFrameDur10000us,
178          CodecSpecificConfigurationLtv::FrameDuration::US10000},
179         {kLeAudioCodecFrameDur20000us,
180          CodecSpecificConfigurationLtv::FrameDuration::US20000}};
181 
182 /* Helper map for matching various audio channel allocation notations */
183 std::map<uint32_t, uint32_t> audio_channel_allocation_map = {
184     {kLeAudioLocationMonoAudio,
185      CodecSpecificConfigurationLtv::AudioChannelAllocation::MONO},
186     {kLeAudioLocationFrontLeft,
187      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT},
188     {kLeAudioLocationFrontRight,
189      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT},
190     {kLeAudioLocationFrontCenter,
191      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER},
192     {kLeAudioLocationLowFreqEffects1,
193      CodecSpecificConfigurationLtv::AudioChannelAllocation::
194          LOW_FREQUENCY_EFFECTS_1},
195     {kLeAudioLocationBackLeft,
196      CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_LEFT},
197     {kLeAudioLocationBackRight,
198      CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_RIGHT},
199     {kLeAudioLocationFrontLeftOfCenter,
200      CodecSpecificConfigurationLtv::AudioChannelAllocation::
201          FRONT_LEFT_OF_CENTER},
202     {kLeAudioLocationFrontRightOfCenter,
203      CodecSpecificConfigurationLtv::AudioChannelAllocation::
204          FRONT_RIGHT_OF_CENTER},
205     {kLeAudioLocationBackCenter,
206      CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_CENTER},
207     {kLeAudioLocationLowFreqEffects2,
208      CodecSpecificConfigurationLtv::AudioChannelAllocation::
209          LOW_FREQUENCY_EFFECTS_2},
210     {kLeAudioLocationSideLeft,
211      CodecSpecificConfigurationLtv::AudioChannelAllocation::SIDE_LEFT},
212     {kLeAudioLocationSideRight,
213      CodecSpecificConfigurationLtv::AudioChannelAllocation::SIDE_RIGHT},
214     {kLeAudioLocationTopFrontLeft,
215      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_LEFT},
216     {kLeAudioLocationTopFrontRight,
217      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_RIGHT},
218     {kLeAudioLocationTopFrontCenter,
219      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_CENTER},
220     {kLeAudioLocationTopCenter,
221      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_CENTER},
222     {kLeAudioLocationTopBackLeft,
223      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_LEFT},
224     {kLeAudioLocationTopBackRight,
225      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_RIGHT},
226     {kLeAudioLocationTopSideLeft,
227      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_SIDE_LEFT},
228     {kLeAudioLocationTopSideRight,
229      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_SIDE_RIGHT},
230     {kLeAudioLocationTopBackCenter,
231      CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_CENTER},
232     {kLeAudioLocationBottomFrontCenter,
233      CodecSpecificConfigurationLtv::AudioChannelAllocation::
234          BOTTOM_FRONT_CENTER},
235     {kLeAudioLocationBottomFrontLeft,
236      CodecSpecificConfigurationLtv::AudioChannelAllocation::BOTTOM_FRONT_LEFT},
237     {kLeAudioLocationBottomFrontRight,
238      CodecSpecificConfigurationLtv::AudioChannelAllocation::BOTTOM_FRONT_RIGHT},
239     {kLeAudioLocationFrontLeftWide,
240      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT_WIDE},
241     {kLeAudioLocationFrontRightWide,
242      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT_WIDE},
243     {kLeAudioLocationLeftSurround,
244      CodecSpecificConfigurationLtv::AudioChannelAllocation::LEFT_SURROUND},
245     {kLeAudioLocationRightSurround,
246      CodecSpecificConfigurationLtv::AudioChannelAllocation::RIGHT_SURROUND},
247 };
248 
249 // Set configuration and scenario files with fallback default
250 static const std::vector<
251     std::pair<const char* /*schema*/, const char* /*content*/>>
252     kLeAudioSetConfigs = {
253         {"/vendor/etc/aidl/le_audio/"
254          "aidl_audio_set_configurations.bfbs",
255          "/vendor/etc/aidl/le_audio/"
256          "aidl_audio_set_configurations.json"},
257 
258         {"/vendor/etc/aidl/le_audio/"
259          "aidl_audio_set_configurations.bfbs",
260          "/vendor/etc/aidl/le_audio/"
261          "aidl_default_audio_set_configurations.json"},
262 };
263 static const std::vector<
264     std::pair<const char* /*schema*/, const char* /*content*/>>
265     kLeAudioSetScenarios = {{"/vendor/etc/aidl/le_audio/"
266                              "aidl_audio_set_scenarios.bfbs",
267                              "/vendor/etc/aidl/le_audio/"
268                              "aidl_audio_set_scenarios.json"},
269 
270                             {"/vendor/etc/aidl/le_audio/"
271                              "aidl_audio_set_scenarios.bfbs",
272                              "/vendor/etc/aidl/le_audio/"
273                              "aidl_default_audio_set_scenarios.json"}};
274 
275 /* Implementation */
276 
277 std::vector<std::pair<std::string, LeAudioAseConfigurationSetting>>
GetLeAudioAseConfigurationSettings()278 AudioSetConfigurationProviderJson::GetLeAudioAseConfigurationSettings() {
279   AudioSetConfigurationProviderJson::LoadAudioSetConfigurationProviderJson();
280   return ase_configuration_settings_;
281 }
282 
283 void AudioSetConfigurationProviderJson::
LoadAudioSetConfigurationProviderJson()284     LoadAudioSetConfigurationProviderJson() {
285   if (configurations_.empty() || ase_configuration_settings_.empty()) {
286     ase_configuration_settings_.clear();
287     configurations_.clear();
288     auto loaded = LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios,
289                               CodecLocation::ADSP);
290     if (!loaded)
291       LOG(ERROR) << ": Unable to load le audio set configuration files.";
292   } else
293     LOG(INFO) << ": Reusing loaded le audio set configuration";
294 }
295 
296 const le_audio::CodecSpecificConfiguration*
LookupCodecSpecificParam(const flatbuffers::Vector<flatbuffers::Offset<le_audio::CodecSpecificConfiguration>> * flat_codec_specific_params,le_audio::CodecSpecificLtvGenericTypes type)297 AudioSetConfigurationProviderJson::LookupCodecSpecificParam(
298     const flatbuffers::Vector<flatbuffers::Offset<
299         le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params,
300     le_audio::CodecSpecificLtvGenericTypes type) {
301   auto it = std::find_if(
302       flat_codec_specific_params->cbegin(), flat_codec_specific_params->cend(),
303       [&type](const auto& csc) { return (csc->type() == type); });
304   return (it != flat_codec_specific_params->cend()) ? *it : nullptr;
305 }
306 
populateAudioChannelAllocation(CodecSpecificConfigurationLtv::AudioChannelAllocation & audio_channel_allocation,uint32_t audio_location)307 void AudioSetConfigurationProviderJson::populateAudioChannelAllocation(
308     CodecSpecificConfigurationLtv::AudioChannelAllocation&
309         audio_channel_allocation,
310     uint32_t audio_location) {
311   audio_channel_allocation.bitmask = 0;
312   for (auto [allocation, bitmask] : audio_channel_allocation_map) {
313     if (audio_location & allocation)
314       audio_channel_allocation.bitmask |= bitmask;
315   }
316 }
317 
populateConfigurationData(LeAudioAseConfiguration & ase,const flatbuffers::Vector<flatbuffers::Offset<le_audio::CodecSpecificConfiguration>> * flat_codec_specific_params)318 void AudioSetConfigurationProviderJson::populateConfigurationData(
319     LeAudioAseConfiguration& ase,
320     const flatbuffers::Vector<
321         flatbuffers::Offset<le_audio::CodecSpecificConfiguration>>*
322         flat_codec_specific_params) {
323   uint8_t sampling_frequency = 0;
324   uint8_t frame_duration = 0;
325   uint32_t audio_channel_allocation = 0;
326   uint16_t octets_per_codec_frame = 0;
327   uint8_t codec_frames_blocks_per_sdu = 0;
328 
329   auto param = LookupCodecSpecificParam(
330       flat_codec_specific_params,
331       le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_SAMPLING_FREQUENCY);
332   if (param) {
333     auto ptr = param->compound_value()->value()->data();
334     STREAM_TO_UINT8(sampling_frequency, ptr);
335   }
336 
337   param = LookupCodecSpecificParam(
338       flat_codec_specific_params,
339       le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_FRAME_DURATION);
340   if (param) {
341     auto ptr = param->compound_value()->value()->data();
342     STREAM_TO_UINT8(frame_duration, ptr);
343   }
344 
345   param = LookupCodecSpecificParam(
346       flat_codec_specific_params,
347       le_audio::
348           CodecSpecificLtvGenericTypes_SUPPORTED_AUDIO_CHANNEL_ALLOCATION);
349   if (param) {
350     auto ptr = param->compound_value()->value()->data();
351     STREAM_TO_UINT32(audio_channel_allocation, ptr);
352   }
353 
354   param = LookupCodecSpecificParam(
355       flat_codec_specific_params,
356       le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_OCTETS_PER_CODEC_FRAME);
357   if (param) {
358     auto ptr = param->compound_value()->value()->data();
359     STREAM_TO_UINT16(octets_per_codec_frame, ptr);
360   }
361 
362   param = LookupCodecSpecificParam(
363       flat_codec_specific_params,
364       le_audio::
365           CodecSpecificLtvGenericTypes_SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU);
366   if (param) {
367     auto ptr = param->compound_value()->value()->data();
368     STREAM_TO_UINT8(codec_frames_blocks_per_sdu, ptr);
369   }
370 
371   // Make the correct value
372   ase.codecConfiguration = std::vector<CodecSpecificConfigurationLtv>();
373 
374   auto sampling_freq_it = sampling_freq_map.find(sampling_frequency);
375   if (sampling_freq_it != sampling_freq_map.end())
376     ase.codecConfiguration.push_back(sampling_freq_it->second);
377   auto frame_duration_it = frame_duration_map.find(frame_duration);
378   if (frame_duration_it != frame_duration_map.end())
379     ase.codecConfiguration.push_back(frame_duration_it->second);
380 
381   CodecSpecificConfigurationLtv::AudioChannelAllocation channel_allocation;
382   populateAudioChannelAllocation(channel_allocation, audio_channel_allocation);
383   ase.codecConfiguration.push_back(channel_allocation);
384 
385   auto octet_structure = CodecSpecificConfigurationLtv::OctetsPerCodecFrame();
386   octet_structure.value = octets_per_codec_frame;
387   ase.codecConfiguration.push_back(octet_structure);
388 
389   auto frame_sdu_structure =
390       CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU();
391   frame_sdu_structure.value = codec_frames_blocks_per_sdu;
392   ase.codecConfiguration.push_back(frame_sdu_structure);
393 }
394 
populateAseConfiguration(LeAudioAseConfiguration & ase,const le_audio::AudioSetSubConfiguration * flat_subconfig,const le_audio::QosConfiguration * qos_cfg,ConfigurationFlags & configurationFlags)395 void AudioSetConfigurationProviderJson::populateAseConfiguration(
396     LeAudioAseConfiguration& ase,
397     const le_audio::AudioSetSubConfiguration* flat_subconfig,
398     const le_audio::QosConfiguration* qos_cfg,
399     ConfigurationFlags& configurationFlags) {
400   // Target latency
401   switch (qos_cfg->target_latency()) {
402     case le_audio::AudioSetConfigurationTargetLatency::
403         AudioSetConfigurationTargetLatency_BALANCED_RELIABILITY:
404       ase.targetLatency =
405           LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
406       break;
407     case le_audio::AudioSetConfigurationTargetLatency::
408         AudioSetConfigurationTargetLatency_HIGH_RELIABILITY:
409       ase.targetLatency =
410           LeAudioAseConfiguration::TargetLatency::HIGHER_RELIABILITY;
411       break;
412     case le_audio::AudioSetConfigurationTargetLatency::
413         AudioSetConfigurationTargetLatency_LOW:
414       ase.targetLatency = LeAudioAseConfiguration::TargetLatency::LOWER;
415       configurationFlags.bitmask |= ConfigurationFlags::LOW_LATENCY;
416       break;
417     default:
418       ase.targetLatency = LeAudioAseConfiguration::TargetLatency::UNDEFINED;
419       break;
420   };
421 
422   ase.targetPhy = Phy::TWO_M;
423   // Making CodecId
424   if (flat_subconfig->codec_id()->coding_format() ==
425       (uint8_t)CodecId::Core::LC3) {
426     ase.codecId = CodecId::Core::LC3;
427   } else {
428     auto vendorC = CodecId::Vendor();
429     vendorC.codecId = flat_subconfig->codec_id()->vendor_codec_id();
430     vendorC.id = flat_subconfig->codec_id()->vendor_company_id();
431     ase.codecId = vendorC;
432   }
433   // Codec configuration data
434   populateConfigurationData(ase, flat_subconfig->codec_configuration());
435 }
436 
populateAseQosConfiguration(LeAudioAseQosConfiguration & qos,const le_audio::QosConfiguration * qos_cfg,LeAudioAseConfiguration & ase,uint8_t ase_channel_cnt)437 void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
438     LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg,
439     LeAudioAseConfiguration& ase, uint8_t ase_channel_cnt) {
440   std::optional<CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU>
441       frameBlock = std::nullopt;
442   std::optional<CodecSpecificConfigurationLtv::FrameDuration> frameDuration =
443       std::nullopt;
444   std::optional<CodecSpecificConfigurationLtv::OctetsPerCodecFrame> octet =
445       std::nullopt;
446 
447   // Hack to put back allocation
448   CodecSpecificConfigurationLtv::AudioChannelAllocation allocation =
449       CodecSpecificConfigurationLtv::AudioChannelAllocation();
450   if (ase_channel_cnt == 1) {
451     allocation.bitmask |=
452         CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
453 
454   } else {
455     allocation.bitmask |=
456         CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
457         CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
458   }
459   for (auto& cfg_ltv : ase.codecConfiguration) {
460     auto tag = cfg_ltv.getTag();
461     if (tag == CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU) {
462       frameBlock =
463           cfg_ltv.get<CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU>();
464     } else if (tag == CodecSpecificConfigurationLtv::frameDuration) {
465       frameDuration =
466           cfg_ltv.get<CodecSpecificConfigurationLtv::frameDuration>();
467     } else if (tag == CodecSpecificConfigurationLtv::octetsPerCodecFrame) {
468       octet = cfg_ltv.get<CodecSpecificConfigurationLtv::octetsPerCodecFrame>();
469     } else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
470       // Change to the old hack allocation
471       cfg_ltv.set<CodecSpecificConfigurationLtv::audioChannelAllocation>(
472           allocation);
473     }
474   }
475 
476   int frameBlockValue = 1;
477   if (frameBlock.has_value()) frameBlockValue = frameBlock.value().value;
478 
479   // Populate maxSdu
480   if (octet.has_value()) {
481     qos.maxSdu = ase_channel_cnt * octet.value().value * frameBlockValue;
482   }
483   // Populate sduIntervalUs
484   if (frameDuration.has_value()) {
485     switch (frameDuration.value()) {
486       case CodecSpecificConfigurationLtv::FrameDuration::US7500:
487         qos.sduIntervalUs = 7500;
488         break;
489       case CodecSpecificConfigurationLtv::FrameDuration::US10000:
490         qos.sduIntervalUs = 10000;
491         break;
492       case CodecSpecificConfigurationLtv::FrameDuration::US20000:
493         qos.sduIntervalUs = 20000;
494         break;
495     }
496     qos.sduIntervalUs *= frameBlockValue;
497   }
498   qos.maxTransportLatencyMs = qos_cfg->max_transport_latency();
499   qos.retransmissionNum = qos_cfg->retransmission_number();
500 }
501 
502 // Parse into AseDirectionConfiguration
503 AseDirectionConfiguration
SetConfigurationFromFlatSubconfig(const le_audio::AudioSetSubConfiguration * flat_subconfig,const le_audio::QosConfiguration * qos_cfg,CodecLocation location,ConfigurationFlags & configurationFlags)504 AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
505     const le_audio::AudioSetSubConfiguration* flat_subconfig,
506     const le_audio::QosConfiguration* qos_cfg, CodecLocation location,
507     ConfigurationFlags& configurationFlags) {
508   AseDirectionConfiguration direction_conf;
509 
510   LeAudioAseConfiguration ase;
511   LeAudioAseQosConfiguration qos;
512   LeAudioDataPathConfiguration path;
513 
514   // Translate into LeAudioAseConfiguration
515   populateAseConfiguration(ase, flat_subconfig, qos_cfg, configurationFlags);
516 
517   // Translate into LeAudioAseQosConfiguration
518   populateAseQosConfiguration(qos, qos_cfg, ase,
519                               flat_subconfig->ase_channel_cnt());
520 
521   // Translate location to data path id
522   switch (location) {
523     case CodecLocation::ADSP:
524       path.isoDataPathConfiguration.isTransparent = true;
525       path.dataPathId = kIsoDataPathPlatformDefault;
526       break;
527     case CodecLocation::HOST:
528       path.isoDataPathConfiguration.isTransparent = true;
529       path.dataPathId = kIsoDataPathHci;
530       break;
531     case CodecLocation::CONTROLLER:
532       path.isoDataPathConfiguration.isTransparent = false;
533       path.dataPathId = kIsoDataPathPlatformDefault;
534       break;
535   }
536   // Move codecId to iso data path
537   path.isoDataPathConfiguration.codecId = ase.codecId.value();
538 
539   direction_conf.aseConfiguration = ase;
540   direction_conf.qosConfiguration = qos;
541   direction_conf.dataPathConfiguration = path;
542 
543   return direction_conf;
544 }
545 
546 // Parse into AseDirectionConfiguration and the ConfigurationFlags
547 // and put them in the given list.
processSubconfig(const le_audio::AudioSetSubConfiguration * subconfig,const le_audio::QosConfiguration * qos_cfg,std::vector<std::optional<AseDirectionConfiguration>> & directionAseConfiguration,CodecLocation location,ConfigurationFlags & configurationFlags)548 void AudioSetConfigurationProviderJson::processSubconfig(
549     const le_audio::AudioSetSubConfiguration* subconfig,
550     const le_audio::QosConfiguration* qos_cfg,
551     std::vector<std::optional<AseDirectionConfiguration>>&
552         directionAseConfiguration,
553     CodecLocation location, ConfigurationFlags& configurationFlags) {
554   auto ase_cnt = subconfig->ase_cnt();
555   auto config = SetConfigurationFromFlatSubconfig(subconfig, qos_cfg, location,
556                                                   configurationFlags);
557   directionAseConfiguration.push_back(config);
558   // Put the same setting again.
559   if (ase_cnt == 2) directionAseConfiguration.push_back(config);
560 }
561 
562 // Comparing if 2 AseDirectionConfiguration is equal.
563 // Configuration are copied in, so we can remove some fields for comparison
564 // without affecting the result.
isAseConfigurationEqual(AseDirectionConfiguration cfg_a,AseDirectionConfiguration cfg_b)565 bool isAseConfigurationEqual(AseDirectionConfiguration cfg_a,
566                              AseDirectionConfiguration cfg_b) {
567   // Remove unneeded fields when comparing.
568   cfg_a.aseConfiguration.metadata = std::nullopt;
569   cfg_b.aseConfiguration.metadata = std::nullopt;
570   return cfg_a == cfg_b;
571 }
572 
PopulateAseConfigurationFromFlat(const le_audio::AudioSetConfiguration * flat_cfg,std::vector<const le_audio::CodecConfiguration * > * codec_cfgs,std::vector<const le_audio::QosConfiguration * > * qos_cfgs,CodecLocation location,std::vector<std::optional<AseDirectionConfiguration>> & sourceAseConfiguration,std::vector<std::optional<AseDirectionConfiguration>> & sinkAseConfiguration,ConfigurationFlags & configurationFlags)573 void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
574     const le_audio::AudioSetConfiguration* flat_cfg,
575     std::vector<const le_audio::CodecConfiguration*>* codec_cfgs,
576     std::vector<const le_audio::QosConfiguration*>* qos_cfgs,
577     CodecLocation location,
578     std::vector<std::optional<AseDirectionConfiguration>>&
579         sourceAseConfiguration,
580     std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration,
581     ConfigurationFlags& configurationFlags) {
582   if (flat_cfg == nullptr) {
583     LOG(ERROR) << "flat_cfg cannot be null";
584     return;
585   }
586   std::string codec_config_key = flat_cfg->codec_config_name()->str();
587   auto* qos_config_key_array = flat_cfg->qos_config_name();
588 
589   constexpr std::string_view default_qos = "QoS_Config_Balanced_Reliability";
590 
591   std::string qos_sink_key(default_qos);
592   std::string qos_source_key(default_qos);
593 
594   /* We expect maximum two QoS settings. First for Sink and second for Source
595    */
596   if (qos_config_key_array->size() > 0) {
597     qos_sink_key = qos_config_key_array->Get(0)->str();
598     if (qos_config_key_array->size() > 1) {
599       qos_source_key = qos_config_key_array->Get(1)->str();
600     } else {
601       qos_source_key = qos_sink_key;
602     }
603   }
604 
605   LOG(INFO) << "Audio set config " << flat_cfg->name()->c_str()
606             << ": codec config " << codec_config_key.c_str() << ", qos_sink "
607             << qos_sink_key.c_str() << ", qos_source "
608             << qos_source_key.c_str();
609 
610   // Find the first qos config that match the name
611   const le_audio::QosConfiguration* qos_sink_cfg = nullptr;
612   for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
613     if ((*i)->name()->str() == qos_sink_key) {
614       qos_sink_cfg = *i;
615       break;
616     }
617   }
618 
619   const le_audio::QosConfiguration* qos_source_cfg = nullptr;
620   for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
621     if ((*i)->name()->str() == qos_source_key) {
622       qos_source_cfg = *i;
623       break;
624     }
625   }
626 
627   // First codec_cfg with the same name
628   const le_audio::CodecConfiguration* codec_cfg = nullptr;
629   for (auto i = codec_cfgs->begin(); i != codec_cfgs->end(); ++i) {
630     if ((*i)->name()->str() == codec_config_key) {
631       codec_cfg = *i;
632       break;
633     }
634   }
635 
636   // Process each subconfig and put it into the correct list
637   if (codec_cfg != nullptr && codec_cfg->subconfigurations()) {
638     /* Load subconfigurations */
639     for (auto subconfig : *codec_cfg->subconfigurations()) {
640       if (subconfig->direction() == kLeAudioDirectionSink) {
641         processSubconfig(subconfig, qos_sink_cfg, sinkAseConfiguration,
642                          location, configurationFlags);
643       } else {
644         processSubconfig(subconfig, qos_source_cfg, sourceAseConfiguration,
645                          location, configurationFlags);
646       }
647     }
648 
649     // After putting all subconfig, check if it's an asymmetric configuration
650     // and populate information for ConfigurationFlags
651     if (!sinkAseConfiguration.empty() && !sourceAseConfiguration.empty()) {
652       if (sinkAseConfiguration.size() == sourceAseConfiguration.size()) {
653         for (int i = 0; i < sinkAseConfiguration.size(); ++i) {
654           if (sinkAseConfiguration[i].has_value() !=
655               sourceAseConfiguration[i].has_value()) {
656             // Different configuration: one is not empty and other is.
657             configurationFlags.bitmask |=
658                 ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
659           } else if (sinkAseConfiguration[i].has_value()) {
660             // Both is not empty, comparing inner fields:
661             if (!isAseConfigurationEqual(sinkAseConfiguration[i].value(),
662                                          sourceAseConfiguration[i].value())) {
663               configurationFlags.bitmask |=
664                   ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
665             }
666           }
667         }
668       } else {
669         // Different number of ASE, is a different configuration.
670         configurationFlags.bitmask |=
671             ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS;
672       }
673     }
674   } else {
675     if (codec_cfg == nullptr) {
676       LOG(ERROR) << "No codec config matching key " << codec_config_key.c_str()
677                  << " found";
678     } else {
679       LOG(ERROR) << "Configuration '" << flat_cfg->name()->c_str()
680                  << "' has no valid subconfigurations.";
681     }
682   }
683 }
684 
LoadConfigurationsFromFiles(const char * schema_file,const char * content_file,CodecLocation location)685 bool AudioSetConfigurationProviderJson::LoadConfigurationsFromFiles(
686     const char* schema_file, const char* content_file, CodecLocation location) {
687   flatbuffers::Parser configurations_parser_;
688   std::string configurations_schema_binary_content;
689   bool ok = flatbuffers::LoadFile(schema_file, true,
690                                   &configurations_schema_binary_content);
691   LOG(INFO) << __func__ << ": Loading file " << schema_file;
692   if (!ok) return ok;
693 
694   /* Load the binary schema */
695   ok = configurations_parser_.Deserialize(
696       (uint8_t*)configurations_schema_binary_content.c_str(),
697       configurations_schema_binary_content.length());
698   if (!ok) return ok;
699 
700   /* Load the content from JSON */
701   std::string configurations_json_content;
702   LOG(INFO) << __func__ << ": Loading file " << content_file;
703   ok = flatbuffers::LoadFile(content_file, false, &configurations_json_content);
704   if (!ok) return ok;
705 
706   /* Parse */
707   LOG(INFO) << __func__ << ": Parse JSON content";
708   ok = configurations_parser_.Parse(configurations_json_content.c_str());
709   if (!ok) return ok;
710 
711   /* Import from flatbuffers */
712   LOG(INFO) << __func__ << ": Build flat buffer structure";
713   auto configurations_root = le_audio::GetAudioSetConfigurations(
714       configurations_parser_.builder_.GetBufferPointer());
715   if (!configurations_root) return false;
716 
717   auto flat_qos_configs = configurations_root->qos_configurations();
718   if ((flat_qos_configs == nullptr) || (flat_qos_configs->size() == 0))
719     return false;
720 
721   LOG(DEBUG) << ": Updating " << flat_qos_configs->size()
722              << " qos config entries.";
723   std::vector<const le_audio::QosConfiguration*> qos_cfgs;
724   for (auto const& flat_qos_cfg : *flat_qos_configs) {
725     qos_cfgs.push_back(flat_qos_cfg);
726   }
727 
728   auto flat_codec_configs = configurations_root->codec_configurations();
729   if ((flat_codec_configs == nullptr) || (flat_codec_configs->size() == 0))
730     return false;
731 
732   LOG(DEBUG) << ": Updating " << flat_codec_configs->size()
733              << " codec config entries.";
734   std::vector<const le_audio::CodecConfiguration*> codec_cfgs;
735   for (auto const& flat_codec_cfg : *flat_codec_configs) {
736     codec_cfgs.push_back(flat_codec_cfg);
737   }
738 
739   auto flat_configs = configurations_root->configurations();
740   if ((flat_configs == nullptr) || (flat_configs->size() == 0)) return false;
741 
742   LOG(DEBUG) << ": Updating " << flat_configs->size() << " config entries.";
743   for (auto const& flat_cfg : *flat_configs) {
744     // Create 3 vector to use
745     std::vector<std::optional<AseDirectionConfiguration>>
746         sourceAseConfiguration;
747     std::vector<std::optional<AseDirectionConfiguration>> sinkAseConfiguration;
748     ConfigurationFlags configurationFlags;
749     PopulateAseConfigurationFromFlat(flat_cfg, &codec_cfgs, &qos_cfgs, location,
750                                      sourceAseConfiguration,
751                                      sinkAseConfiguration, configurationFlags);
752     if (sourceAseConfiguration.empty() && sinkAseConfiguration.empty())
753       continue;
754     configurations_[flat_cfg->name()->str()] = std::make_tuple(
755         sourceAseConfiguration, sinkAseConfiguration, configurationFlags);
756   }
757 
758   return true;
759 }
760 
LoadScenariosFromFiles(const char * schema_file,const char * content_file)761 bool AudioSetConfigurationProviderJson::LoadScenariosFromFiles(
762     const char* schema_file, const char* content_file) {
763   flatbuffers::Parser scenarios_parser_;
764   std::string scenarios_schema_binary_content;
765   bool ok = flatbuffers::LoadFile(schema_file, true,
766                                   &scenarios_schema_binary_content);
767   LOG(INFO) << __func__ << ": Loading file " << schema_file;
768   if (!ok) return ok;
769 
770   /* Load the binary schema */
771   ok = scenarios_parser_.Deserialize(
772       (uint8_t*)scenarios_schema_binary_content.c_str(),
773       scenarios_schema_binary_content.length());
774   if (!ok) return ok;
775 
776   /* Load the content from JSON */
777   LOG(INFO) << __func__ << ": Loading file " << content_file;
778   std::string scenarios_json_content;
779   ok = flatbuffers::LoadFile(content_file, false, &scenarios_json_content);
780   if (!ok) return ok;
781 
782   /* Parse */
783   LOG(INFO) << __func__ << ": Parse json content";
784   ok = scenarios_parser_.Parse(scenarios_json_content.c_str());
785   if (!ok) return ok;
786 
787   /* Import from flatbuffers */
788   LOG(INFO) << __func__ << ": Build flat buffer structure";
789   auto scenarios_root = le_audio::GetAudioSetScenarios(
790       scenarios_parser_.builder_.GetBufferPointer());
791   if (!scenarios_root) return false;
792 
793   auto flat_scenarios = scenarios_root->scenarios();
794   if ((flat_scenarios == nullptr) || (flat_scenarios->size() == 0))
795     return false;
796 
797   LOG(INFO) << __func__ << ": Turn flat buffer into structure";
798   AudioContext media_context = AudioContext();
799   media_context.bitmask =
800       (AudioContext::ALERTS | AudioContext::INSTRUCTIONAL |
801        AudioContext::NOTIFICATIONS | AudioContext::EMERGENCY_ALARM |
802        AudioContext::UNSPECIFIED | AudioContext::MEDIA |
803        AudioContext::SOUND_EFFECTS);
804 
805   AudioContext conversational_context = AudioContext();
806   conversational_context.bitmask =
807       (AudioContext::RINGTONE_ALERTS | AudioContext::CONVERSATIONAL);
808 
809   AudioContext live_context = AudioContext();
810   live_context.bitmask = AudioContext::LIVE_AUDIO;
811 
812   AudioContext game_context = AudioContext();
813   game_context.bitmask = AudioContext::GAME;
814 
815   AudioContext voice_assistants_context = AudioContext();
816   voice_assistants_context.bitmask = AudioContext::VOICE_ASSISTANTS;
817 
818   LOG(DEBUG) << "Updating " << flat_scenarios->size() << " scenarios.";
819   for (auto const& scenario : *flat_scenarios) {
820     if (!scenario->configurations()) continue;
821     std::string scenario_name = scenario->name()->c_str();
822     AudioContext context;
823     if (scenario_name == "Media")
824       context = AudioContext(media_context);
825     else if (scenario_name == "Conversational")
826       context = AudioContext(conversational_context);
827     else if (scenario_name == "Live")
828       context = AudioContext(live_context);
829     else if (scenario_name == "Game")
830       context = AudioContext(game_context);
831     else if (scenario_name == "VoiceAssistants")
832       context = AudioContext(voice_assistants_context);
833     LOG(DEBUG) << "Scenario " << scenario->name()->c_str()
834                << " configs: " << scenario->configurations()->size()
835                << " context: " << context.toString();
836 
837     for (auto it = scenario->configurations()->begin();
838          it != scenario->configurations()->end(); ++it) {
839       auto config_name = it->str();
840       auto configuration = configurations_.find(config_name);
841       if (configuration == configurations_.end()) continue;
842       LOG(DEBUG) << "Getting configuration with name: " << config_name;
843       auto [source, sink, flags] = configuration->second;
844       // Each configuration will create a LeAudioAseConfigurationSetting
845       // with the same {context, packing}
846       // and different data
847       LeAudioAseConfigurationSetting setting;
848       setting.audioContext = context;
849       // TODO: Packing
850       setting.sourceAseConfiguration = source;
851       setting.sinkAseConfiguration = sink;
852       setting.flags = flags;
853       // Add to list of setting
854       LOG(DEBUG) << "Pushing configuration to list: " << config_name;
855       ase_configuration_settings_.push_back({config_name, setting});
856     }
857   }
858 
859   return true;
860 }
861 
LoadContent(std::vector<std::pair<const char *,const char * >> config_files,std::vector<std::pair<const char *,const char * >> scenario_files,CodecLocation location)862 bool AudioSetConfigurationProviderJson::LoadContent(
863     std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
864         config_files,
865     std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
866         scenario_files,
867     CodecLocation location) {
868   bool is_loaded_config = false;
869   for (auto [schema, content] : config_files) {
870     if (LoadConfigurationsFromFiles(schema, content, location)) {
871       is_loaded_config = true;
872       break;
873     }
874   }
875 
876   bool is_loaded_scenario = false;
877   for (auto [schema, content] : scenario_files) {
878     if (LoadScenariosFromFiles(schema, content)) {
879       is_loaded_scenario = true;
880       break;
881     }
882   }
883   return is_loaded_config && is_loaded_scenario;
884 }
885 
886 }  // namespace audio
887 }  // namespace bluetooth
888 }  // namespace hardware
889 }  // namespace android
890 }  // namespace aidl
891