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