1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "broadcaster_types.h"
19
20 #include <base/strings/string_number_conversions.h>
21
22 #include <cstddef>
23 #include <cstdint>
24 #include <cstring>
25 #include <map>
26 #include <ostream>
27 #include <string>
28 #include <vector>
29
30 #include "bta/le_audio/audio_hal_client/audio_hal_client.h"
31 #include "btm_ble_api_types.h"
32 #include "hardware/bt_le_audio.h"
33 #include "le_audio/le_audio_types.h"
34 #include "stack/include/bt_types.h"
35
36 using bluetooth::le_audio::BasicAudioAnnouncementBisConfig;
37 using bluetooth::le_audio::BasicAudioAnnouncementCodecConfig;
38 using bluetooth::le_audio::BasicAudioAnnouncementData;
39 using bluetooth::le_audio::BasicAudioAnnouncementSubgroup;
40
41 namespace bluetooth::le_audio {
42 namespace broadcaster {
43
EmitHeader(const BasicAudioAnnouncementData & announcement_data,std::vector<uint8_t> & data)44 static void EmitHeader(const BasicAudioAnnouncementData& announcement_data,
45 std::vector<uint8_t>& data) {
46 size_t old_size = data.size();
47 data.resize(old_size + 3);
48
49 // Set the cursor behind the old data
50 uint8_t* p_value = data.data() + old_size;
51
52 UINT24_TO_STREAM(p_value, announcement_data.presentation_delay_us);
53 }
54
EmitCodecConfiguration(const BasicAudioAnnouncementCodecConfig & config,std::vector<uint8_t> & data,const BasicAudioAnnouncementCodecConfig *)55 static void EmitCodecConfiguration(const BasicAudioAnnouncementCodecConfig& config,
56 std::vector<uint8_t>& data,
57 const BasicAudioAnnouncementCodecConfig* /*lower_lvl_config*/) {
58 size_t old_size = data.size();
59
60 // Add 5 for full, or 1 for short Codec ID
61 uint8_t codec_config_length = 5;
62
63 auto ltv = types::LeAudioLtvMap(config.codec_specific_params);
64 auto codec_spec_raw_sz = ltv.RawPacketSize();
65 if (config.vendor_codec_specific_params) {
66 codec_spec_raw_sz = config.vendor_codec_specific_params->size();
67 }
68
69 // Add 1 for the codec spec. config length + config spec. data itself
70 codec_config_length += 1 + codec_spec_raw_sz;
71
72 // Resize and set the cursor behind the old data
73 data.resize(old_size + codec_config_length);
74 uint8_t* p_value = data.data() + old_size;
75
76 // Codec ID
77 UINT8_TO_STREAM(p_value, config.codec_id);
78 UINT16_TO_STREAM(p_value, config.vendor_company_id);
79 UINT16_TO_STREAM(p_value, config.vendor_codec_id);
80
81 // Codec specific config length and data (either vendor specific or the LTVs)
82 UINT8_TO_STREAM(p_value, codec_spec_raw_sz);
83 if (config.vendor_codec_specific_params) {
84 ARRAY_TO_STREAM(p_value, config.vendor_codec_specific_params->data(),
85 static_cast<int>(config.vendor_codec_specific_params->size()));
86 } else {
87 p_value = ltv.RawPacket(p_value);
88 }
89 }
90
EmitMetadata(const std::map<uint8_t,std::vector<uint8_t>> & metadata,std::vector<uint8_t> & data)91 static void EmitMetadata(const std::map<uint8_t, std::vector<uint8_t>>& metadata,
92 std::vector<uint8_t>& data) {
93 auto ltv = types::LeAudioLtvMap(metadata);
94 auto ltv_raw_sz = ltv.RawPacketSize();
95
96 size_t old_size = data.size();
97 data.resize(old_size + ltv_raw_sz + 1);
98
99 // Set the cursor behind the old data
100 uint8_t* p_value = data.data() + old_size;
101
102 UINT8_TO_STREAM(p_value, ltv_raw_sz);
103 if (ltv_raw_sz > 0) {
104 p_value = ltv.RawPacket(p_value);
105 }
106 }
107
EmitBroadcastName(const std::string & name,std::vector<uint8_t> & data)108 static void EmitBroadcastName(const std::string& name, std::vector<uint8_t>& data) {
109 int name_len = name.length();
110 size_t old_size = data.size();
111 data.resize(old_size + name_len + 2);
112
113 // Set the cursor behind the old data
114 uint8_t* p_value = data.data() + old_size;
115 UINT8_TO_STREAM(p_value, name_len + 1);
116 UINT8_TO_STREAM(p_value, BTM_BLE_AD_TYPE_BROADCAST_NAME);
117
118 std::vector<uint8_t> vec(name.begin(), name.end());
119 ARRAY_TO_STREAM(p_value, vec.data(), name_len);
120 }
121
EmitBisConfigs(const std::vector<BasicAudioAnnouncementBisConfig> & bis_configs,std::vector<uint8_t> & data)122 static void EmitBisConfigs(const std::vector<BasicAudioAnnouncementBisConfig>& bis_configs,
123 std::vector<uint8_t>& data) {
124 // Emit each BIS config - that's the level 3 data
125 for (auto const& bis_config : bis_configs) {
126 auto ltv = types::LeAudioLtvMap(bis_config.codec_specific_params);
127 auto ltv_raw_sz = ltv.RawPacketSize();
128
129 size_t old_size = data.size();
130 data.resize(old_size + ltv_raw_sz + 2);
131
132 // Set the cursor behind the old data
133 auto* p_value = data.data() + old_size;
134
135 // BIS_index[i[k]]
136 UINT8_TO_STREAM(p_value, bis_config.bis_index);
137
138 // Per BIS Codec Specific Params[i[k]]
139 UINT8_TO_STREAM(p_value, ltv_raw_sz);
140 if (ltv_raw_sz > 0) {
141 p_value = ltv.RawPacket(p_value);
142 }
143 }
144 }
145
EmitSubgroup(const BasicAudioAnnouncementSubgroup & subgroup_config,std::vector<uint8_t> & data)146 static void EmitSubgroup(const BasicAudioAnnouncementSubgroup& subgroup_config,
147 std::vector<uint8_t>& data) {
148 // That's the level 2 data
149
150 // Resize for the num_bis
151 size_t initial_offset = data.size();
152 data.resize(initial_offset + 1);
153
154 // Set the cursor behind the old data and adds the level 2 Num_BIS[i]
155 uint8_t* p_value = data.data() + initial_offset;
156 UINT8_TO_STREAM(p_value, subgroup_config.bis_configs.size());
157
158 EmitCodecConfiguration(subgroup_config.codec_config, data, nullptr);
159 EmitMetadata(subgroup_config.metadata, data);
160
161 // This adds the level 3 data
162 EmitBisConfigs(subgroup_config.bis_configs, data);
163 }
164
ToRawPacket(BasicAudioAnnouncementData const & in,std::vector<uint8_t> & data)165 bool ToRawPacket(BasicAudioAnnouncementData const& in, std::vector<uint8_t>& data) {
166 EmitHeader(in, data);
167
168 // Set the cursor behind the old data and resize
169 size_t old_size = data.size();
170 data.resize(old_size + 1);
171 uint8_t* p_value = data.data() + old_size;
172
173 // Emit the subgroup size and each subgroup
174 // That's the level 1 Num_Subgroups
175 UINT8_TO_STREAM(p_value, in.subgroup_configs.size());
176 for (const auto& subgroup_config : in.subgroup_configs) {
177 // That's the level 2 and higher level data
178 EmitSubgroup(subgroup_config, data);
179 }
180
181 return true;
182 }
183
PrepareAdvertisingData(bool is_public,const std::string & broadcast_name,bluetooth::le_audio::BroadcastId & broadcast_id,const bluetooth::le_audio::PublicBroadcastAnnouncementData & public_announcement,std::vector<uint8_t> & adv_data)184 void PrepareAdvertisingData(
185 bool is_public, const std::string& broadcast_name,
186 bluetooth::le_audio::BroadcastId& broadcast_id,
187 const bluetooth::le_audio::PublicBroadcastAnnouncementData& public_announcement,
188 std::vector<uint8_t>& adv_data) {
189 adv_data.resize(7);
190 uint8_t* data_ptr = adv_data.data();
191 UINT8_TO_STREAM(data_ptr, 6);
192 UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
193 UINT16_TO_STREAM(data_ptr, kBroadcastAudioAnnouncementServiceUuid);
194 UINT24_TO_STREAM(data_ptr, broadcast_id);
195
196 // Prepare public broadcast announcement data
197 if (is_public) {
198 size_t old_size = adv_data.size();
199 // 5: datalen(1) + adtype(1) + serviceuuid(2) + features(1)
200 adv_data.resize(old_size + 5);
201 // Skip the data length field until the full content is generated
202 data_ptr = adv_data.data() + old_size + 1;
203 UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
204 UINT16_TO_STREAM(data_ptr, kPublicBroadcastAnnouncementServiceUuid);
205 UINT8_TO_STREAM(data_ptr, public_announcement.features);
206 // Set metadata length to 0 if no meta data present
207 EmitMetadata(public_announcement.metadata, adv_data);
208
209 // Update the length field accordingly
210 data_ptr = adv_data.data() + old_size;
211 UINT8_TO_STREAM(data_ptr, adv_data.size() - old_size - 1);
212
213 // Prepare broadcast name
214 if (!broadcast_name.empty()) {
215 EmitBroadcastName(broadcast_name, adv_data);
216 }
217 }
218 }
219
PreparePeriodicData(const BasicAudioAnnouncementData & announcement,std::vector<uint8_t> & periodic_data)220 void PreparePeriodicData(const BasicAudioAnnouncementData& announcement,
221 std::vector<uint8_t>& periodic_data) {
222 /* Account for AD Type + Service UUID */
223 periodic_data.resize(4);
224 /* Skip the data length field until the full content is generated */
225 uint8_t* data_ptr = periodic_data.data() + 1;
226 UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
227 UINT16_TO_STREAM(data_ptr, kBasicAudioAnnouncementServiceUuid);
228
229 /* Append the announcement */
230 ToRawPacket(announcement, periodic_data);
231
232 /* Update the length field accordingly */
233 data_ptr = periodic_data.data();
234 UINT8_TO_STREAM(data_ptr, periodic_data.size() - 1);
235 }
236
GetAudioHalClientConfig() const237 le_audio::LeAudioCodecConfiguration BroadcastConfiguration::GetAudioHalClientConfig() const {
238 return {
239 // Get the maximum number of channels
240 .num_channels = GetNumChannelsMax(),
241 // Get the max sampling frequency
242 .sample_rate = GetSamplingFrequencyHzMax(),
243 // Use the default 16 bits per sample resolution in the audio framework
244 .bits_per_sample = 16,
245 // Get the data interval
246 .data_interval_us = GetSduIntervalUs(),
247 };
248 }
249
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig & config)250 std::ostream& operator<<(
251 std::ostream& os,
252 const bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig& config) {
253 os << " BroadcastSubgroupCodecConfig={";
254 os << "CodecID=" << "{" << +config.GetLeAudioCodecId().coding_format << ":"
255 << +config.GetLeAudioCodecId().vendor_company_id << ":"
256 << +config.GetLeAudioCodecId().vendor_codec_id << "}, ";
257 os << "BISes=[";
258 if (!config.bis_codec_configs_.empty()) {
259 for (auto const& bis_config : config.bis_codec_configs_) {
260 os << bis_config << ", ";
261 }
262 os << "\b\b";
263 }
264 os << "]";
265 os << ", BitsPerSample=" << +config.GetBitsPerSample() << "}";
266 os << "}";
267 return os;
268 }
269
operator <<(std::ostream & os,const le_audio::broadcaster::BroadcastSubgroupBisCodecConfig & config)270 std::ostream& operator<<(std::ostream& os,
271 const le_audio::broadcaster::BroadcastSubgroupBisCodecConfig& config) {
272 os << "BisCfg={numBis=" << +config.GetNumBis()
273 << ", NumChannelsPerBis=" << +config.GetNumChannelsPerBis()
274 << ", CodecSpecific=" << config.GetCodecSpecData().GetAsCoreCodecConfig();
275 if (config.GetVendorCodecSpecific().has_value()) {
276 os << ", VendorSpecific=[";
277 if (!config.GetVendorCodecSpecific()->empty()) {
278 os << base::HexEncode(config.GetVendorCodecSpecific()->data(),
279 config.GetVendorCodecSpecific()->size());
280 }
281 os << "]";
282 }
283 os << "}";
284 return os;
285 }
286
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastQosConfig & config)287 std::ostream& operator<<(std::ostream& os,
288 const bluetooth::le_audio::broadcaster::BroadcastQosConfig& config) {
289 os << " BroadcastQosConfig=[";
290 os << "RTN=" << +config.getRetransmissionNumber();
291 os << ", MaxTransportLatency=" << config.getMaxTransportLatency();
292 os << "]";
293 return os;
294 }
295
operator <<(std::ostream & os,const le_audio::broadcaster::BroadcastConfiguration & config)296 std::ostream& operator<<(std::ostream& os,
297 const le_audio::broadcaster::BroadcastConfiguration& config) {
298 os << "BroadcastCfg={";
299 for (const auto& subgroup_cfg : config.subgroups) {
300 os << subgroup_cfg << std::endl;
301 }
302 os << config.qos << std::endl;
303 os << config.data_path << std::endl;
304 os << ", sduIntervalUs=" << config.sduIntervalUs;
305 os << ", maxSduOctets=" << config.maxSduOctets;
306 os << ", phy=" << config.phy;
307 os << ", packing=" << config.packing;
308 os << ", framing=" << config.framing;
309 os << "}" << std::endl;
310
311 return os;
312 }
313
314 } /* namespace broadcaster */
315 } // namespace bluetooth::le_audio
316
317 /* Helper functions for comparing BroadcastAnnouncements */
318 namespace bluetooth::le_audio {
319
isMetadataSame(std::map<uint8_t,std::vector<uint8_t>> m1,std::map<uint8_t,std::vector<uint8_t>> m2)320 static bool isMetadataSame(std::map<uint8_t, std::vector<uint8_t>> m1,
321 std::map<uint8_t, std::vector<uint8_t>> m2) {
322 if (m1.size() != m2.size()) {
323 return false;
324 }
325
326 for (auto& m1pair : m1) {
327 if (m2.count(m1pair.first) == 0) {
328 return false;
329 }
330
331 auto& m2val = m2.at(m1pair.first);
332 if (m1pair.second.size() != m2val.size()) {
333 return false;
334 }
335
336 if (m1pair.second.size() != 0) {
337 if (memcmp(m1pair.second.data(), m2val.data(), m2val.size()) != 0) {
338 return false;
339 }
340 }
341 }
342 return true;
343 }
344
operator ==(const BasicAudioAnnouncementData & lhs,const BasicAudioAnnouncementData & rhs)345 bool operator==(const BasicAudioAnnouncementData& lhs, const BasicAudioAnnouncementData& rhs) {
346 if (lhs.presentation_delay_us != rhs.presentation_delay_us) {
347 return false;
348 }
349
350 if (lhs.subgroup_configs.size() != rhs.subgroup_configs.size()) {
351 return false;
352 }
353
354 for (auto i = 0lu; i < lhs.subgroup_configs.size(); ++i) {
355 auto& lhs_subgroup = lhs.subgroup_configs[i];
356 auto& rhs_subgroup = rhs.subgroup_configs[i];
357
358 if (lhs_subgroup.codec_config.codec_id != rhs_subgroup.codec_config.codec_id) {
359 return false;
360 }
361
362 if (lhs_subgroup.codec_config.vendor_company_id !=
363 rhs_subgroup.codec_config.vendor_company_id) {
364 return false;
365 }
366
367 if (lhs_subgroup.codec_config.vendor_codec_id != rhs_subgroup.codec_config.vendor_codec_id) {
368 return false;
369 }
370
371 if (!isMetadataSame(lhs_subgroup.codec_config.codec_specific_params,
372 rhs_subgroup.codec_config.codec_specific_params)) {
373 return false;
374 }
375
376 if (!isMetadataSame(lhs_subgroup.metadata, rhs_subgroup.metadata)) {
377 return false;
378 }
379
380 for (auto j = 0lu; j < lhs_subgroup.bis_configs.size(); ++j) {
381 auto& lhs_bis_config = lhs_subgroup.bis_configs[i];
382 auto& rhs_bis_config = rhs_subgroup.bis_configs[i];
383 if (lhs_bis_config.bis_index != rhs_bis_config.bis_index) {
384 return false;
385 }
386
387 if (!isMetadataSame(lhs_bis_config.codec_specific_params,
388 rhs_bis_config.codec_specific_params)) {
389 return false;
390 }
391 }
392 }
393
394 return true;
395 }
396
operator ==(const PublicBroadcastAnnouncementData & lhs,const PublicBroadcastAnnouncementData & rhs)397 bool operator==(const PublicBroadcastAnnouncementData& lhs,
398 const PublicBroadcastAnnouncementData& rhs) {
399 if (lhs.features != rhs.features) {
400 return false;
401 }
402 if (!isMetadataSame(lhs.metadata, rhs.metadata)) {
403 return false;
404 }
405
406 return true;
407 }
408 } // namespace bluetooth::le_audio
409