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