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 <vector>
23
24 #include "bta/le_audio/audio_hal_client/audio_hal_client.h"
25 #include "bta_le_audio_broadcaster_api.h"
26 #include "btm_ble_api_types.h"
27 #include "internal_include/stack_config.h"
28 #include "osi/include/properties.h"
29 #include "stack/include/bt_types.h"
30
31 using bluetooth::le_audio::BasicAudioAnnouncementBisConfig;
32 using bluetooth::le_audio::BasicAudioAnnouncementCodecConfig;
33 using bluetooth::le_audio::BasicAudioAnnouncementData;
34 using bluetooth::le_audio::BasicAudioAnnouncementSubgroup;
35 using bluetooth::le_audio::types::LeAudioContextType;
36
37 namespace bluetooth::le_audio {
38 namespace broadcaster {
39
EmitHeader(const BasicAudioAnnouncementData & announcement_data,std::vector<uint8_t> & data)40 static void EmitHeader(const BasicAudioAnnouncementData& announcement_data,
41 std::vector<uint8_t>& data) {
42 size_t old_size = data.size();
43 data.resize(old_size + 3);
44
45 // Set the cursor behind the old data
46 uint8_t* p_value = data.data() + old_size;
47
48 UINT24_TO_STREAM(p_value, announcement_data.presentation_delay_us);
49 }
50
EmitCodecConfiguration(const BasicAudioAnnouncementCodecConfig & config,std::vector<uint8_t> & data,const BasicAudioAnnouncementCodecConfig * lower_lvl_config)51 static void EmitCodecConfiguration(
52 const BasicAudioAnnouncementCodecConfig& config, std::vector<uint8_t>& data,
53 const BasicAudioAnnouncementCodecConfig* lower_lvl_config) {
54 size_t old_size = data.size();
55
56 // Add 5 for full, or 1 for short Codec ID
57 uint8_t codec_config_length = 5;
58
59 auto ltv = types::LeAudioLtvMap(config.codec_specific_params);
60 auto codec_spec_raw_sz = ltv.RawPacketSize();
61 if (config.vendor_codec_specific_params) {
62 codec_spec_raw_sz = config.vendor_codec_specific_params->size();
63 }
64
65 // Add 1 for the codec spec. config length + config spec. data itself
66 codec_config_length += 1 + codec_spec_raw_sz;
67
68 // Resize and set the cursor behind the old data
69 data.resize(old_size + codec_config_length);
70 uint8_t* p_value = data.data() + old_size;
71
72 // Codec ID
73 UINT8_TO_STREAM(p_value, config.codec_id);
74 UINT16_TO_STREAM(p_value, config.vendor_company_id);
75 UINT16_TO_STREAM(p_value, config.vendor_codec_id);
76
77 // Codec specific config length and data (either vendor specific or the LTVs)
78 UINT8_TO_STREAM(p_value, codec_spec_raw_sz);
79 if (config.vendor_codec_specific_params) {
80 ARRAY_TO_STREAM(
81 p_value, config.vendor_codec_specific_params->data(),
82 static_cast<int>(config.vendor_codec_specific_params->size()));
83 } else {
84 p_value = ltv.RawPacket(p_value);
85 }
86 }
87
EmitMetadata(const std::map<uint8_t,std::vector<uint8_t>> & metadata,std::vector<uint8_t> & data)88 static void EmitMetadata(
89 const std::map<uint8_t, std::vector<uint8_t>>& metadata,
90 std::vector<uint8_t>& data) {
91 auto ltv = types::LeAudioLtvMap(metadata);
92 auto ltv_raw_sz = ltv.RawPacketSize();
93
94 size_t old_size = data.size();
95 data.resize(old_size + ltv_raw_sz + 1);
96
97 // Set the cursor behind the old data
98 uint8_t* p_value = data.data() + old_size;
99
100 UINT8_TO_STREAM(p_value, ltv_raw_sz);
101 if (ltv_raw_sz > 0) {
102 p_value = ltv.RawPacket(p_value);
103 }
104 }
105
EmitBroadcastName(const std::string & name,std::vector<uint8_t> & data)106 static void EmitBroadcastName(const std::string& name,
107 std::vector<uint8_t>& data) {
108 int name_len = name.length();
109 size_t old_size = data.size();
110 data.resize(old_size + name_len + 2);
111
112 // Set the cursor behind the old data
113 uint8_t* p_value = data.data() + old_size;
114 UINT8_TO_STREAM(p_value, name_len + 1);
115 UINT8_TO_STREAM(p_value, BTM_BLE_AD_TYPE_BROADCAST_NAME);
116
117 std::vector<uint8_t> vec(name.begin(), name.end());
118 ARRAY_TO_STREAM(p_value, vec.data(), name_len);
119 }
120
EmitBisConfigs(const std::vector<BasicAudioAnnouncementBisConfig> & bis_configs,std::vector<uint8_t> & data)121 static void EmitBisConfigs(
122 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,
166 std::vector<uint8_t>& data) {
167 EmitHeader(in, data);
168
169 // Set the cursor behind the old data and resize
170 size_t old_size = data.size();
171 data.resize(old_size + 1);
172 uint8_t* p_value = data.data() + old_size;
173
174 // Emit the subgroup size and each subgroup
175 // That's the level 1 Num_Subgroups
176 UINT8_TO_STREAM(p_value, in.subgroup_configs.size());
177 for (const auto& subgroup_config : in.subgroup_configs) {
178 // That's the level 2 and higher level data
179 EmitSubgroup(subgroup_config, data);
180 }
181
182 return true;
183 }
184
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)185 void PrepareAdvertisingData(
186 bool is_public, const std::string& broadcast_name,
187 bluetooth::le_audio::BroadcastId& broadcast_id,
188 const bluetooth::le_audio::PublicBroadcastAnnouncementData&
189 public_announcement,
190 std::vector<uint8_t>& adv_data) {
191 adv_data.resize(7);
192 uint8_t* data_ptr = adv_data.data();
193 UINT8_TO_STREAM(data_ptr, 6);
194 UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
195 UINT16_TO_STREAM(data_ptr, kBroadcastAudioAnnouncementServiceUuid);
196 UINT24_TO_STREAM(data_ptr, broadcast_id);
197
198 // Prepare public broadcast announcement data
199 if (is_public) {
200 size_t old_size = adv_data.size();
201 // 5: datalen(1) + adtype(1) + serviceuuid(2) + features(1)
202 adv_data.resize(old_size + 5);
203 // Skip the data length field until the full content is generated
204 data_ptr = adv_data.data() + old_size + 1;
205 UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
206 UINT16_TO_STREAM(data_ptr, kPublicBroadcastAnnouncementServiceUuid);
207 UINT8_TO_STREAM(data_ptr, public_announcement.features);
208 // Set metadata length to 0 if no meta data present
209 EmitMetadata(public_announcement.metadata, adv_data);
210
211 // Update the length field accordingly
212 data_ptr = adv_data.data() + old_size;
213 UINT8_TO_STREAM(data_ptr, adv_data.size() - old_size - 1);
214
215 // Prepare broadcast name
216 if (!broadcast_name.empty()) {
217 EmitBroadcastName(broadcast_name, adv_data);
218 }
219 }
220 }
221
PreparePeriodicData(const BasicAudioAnnouncementData & announcement,std::vector<uint8_t> & periodic_data)222 void PreparePeriodicData(const BasicAudioAnnouncementData& announcement,
223 std::vector<uint8_t>& periodic_data) {
224 /* Account for AD Type + Service UUID */
225 periodic_data.resize(4);
226 /* Skip the data length field until the full content is generated */
227 uint8_t* data_ptr = periodic_data.data() + 1;
228 UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
229 UINT16_TO_STREAM(data_ptr, kBasicAudioAnnouncementServiceUuid);
230
231 /* Append the announcement */
232 ToRawPacket(announcement, periodic_data);
233
234 /* Update the length field accordingly */
235 data_ptr = periodic_data.data();
236 UINT8_TO_STREAM(data_ptr, periodic_data.size() - 1);
237 }
238
239 le_audio::LeAudioCodecConfiguration
GetAudioHalClientConfig() const240 BroadcastConfiguration::GetAudioHalClientConfig() const {
241 return {
242 // Get the maximum number of channels
243 .num_channels = GetNumChannelsMax(),
244 // Get the max sampling frequency
245 .sample_rate = GetSamplingFrequencyHzMax(),
246 // Use the default 16 bits per sample resolution in the audio framework
247 .bits_per_sample = 16,
248 // Get the data interval
249 .data_interval_us = GetSduIntervalUs(),
250 };
251 }
252
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig & config)253 std::ostream& operator<<(
254 std::ostream& os,
255 const bluetooth::le_audio::broadcaster::BroadcastSubgroupCodecConfig&
256 config) {
257 os << " BroadcastSubgroupCodecConfig={";
258 os << "CodecID="
259 << "{" << +config.GetLeAudioCodecId().coding_format << ":"
260 << +config.GetLeAudioCodecId().vendor_company_id << ":"
261 << +config.GetLeAudioCodecId().vendor_codec_id << "}, ";
262 os << "BISes=[";
263 if (!config.bis_codec_configs_.empty()) {
264 for (auto const& bis_config : config.bis_codec_configs_) {
265 os << bis_config << ", ";
266 }
267 os << "\b\b";
268 }
269 os << "]";
270 os << ", BitsPerSample=" << +config.GetBitsPerSample() << "}";
271 os << "}";
272 return os;
273 }
274
operator <<(std::ostream & os,const le_audio::broadcaster::BroadcastSubgroupBisCodecConfig & config)275 std::ostream& operator<<(
276 std::ostream& os,
277 const le_audio::broadcaster::BroadcastSubgroupBisCodecConfig& config) {
278 os << "BisCfg={numBis=" << +config.GetNumBis()
279 << ", NumChannelsPerBis=" << +config.GetNumChannelsPerBis()
280 << ", CodecSpecific=" << config.GetCodecSpecData().GetAsCoreCodecConfig();
281 if (config.GetVendorCodecSpecific().has_value()) {
282 os << ", VendorSpecific=[";
283 if (!config.GetVendorCodecSpecific()->empty()) {
284 os << base::HexEncode(config.GetVendorCodecSpecific()->data(),
285 config.GetVendorCodecSpecific()->size());
286 }
287 os << "]";
288 }
289 os << "}";
290 return os;
291 }
292
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastQosConfig & config)293 std::ostream& operator<<(
294 std::ostream& os,
295 const bluetooth::le_audio::broadcaster::BroadcastQosConfig& config) {
296 os << " BroadcastQosConfig=[";
297 os << "RTN=" << +config.getRetransmissionNumber();
298 os << ", MaxTransportLatency=" << config.getMaxTransportLatency();
299 os << "]";
300 return os;
301 }
302
operator <<(std::ostream & os,const le_audio::broadcaster::BroadcastConfiguration & config)303 std::ostream& operator<<(
304 std::ostream& os,
305 const le_audio::broadcaster::BroadcastConfiguration& config) {
306 os << "BroadcastCfg={";
307 for (const auto& subgroup_cfg : config.subgroups) {
308 os << subgroup_cfg << std::endl;
309 }
310 os << config.qos << std::endl;
311 os << config.data_path << std::endl;
312 os << ", sduIntervalUs=" << config.sduIntervalUs;
313 os << ", maxSduOctets=" << config.maxSduOctets;
314 os << ", phy=" << config.phy;
315 os << ", packing=" << config.packing;
316 os << ", framing=" << config.framing;
317 os << "}" << std::endl;
318
319 return os;
320 }
321
322 } /* namespace broadcaster */
323 } // namespace bluetooth::le_audio
324
325 /* Helper functions for comparing BroadcastAnnouncements */
326 namespace bluetooth::le_audio {
327
isMetadataSame(std::map<uint8_t,std::vector<uint8_t>> m1,std::map<uint8_t,std::vector<uint8_t>> m2)328 static bool isMetadataSame(std::map<uint8_t, std::vector<uint8_t>> m1,
329 std::map<uint8_t, std::vector<uint8_t>> m2) {
330 if (m1.size() != m2.size()) return false;
331
332 for (auto& m1pair : m1) {
333 if (m2.count(m1pair.first) == 0) return false;
334
335 auto& m2val = m2.at(m1pair.first);
336 if (m1pair.second.size() != m2val.size()) return false;
337
338 if (m1pair.second.size() != 0) {
339 if (memcmp(m1pair.second.data(), m2val.data(), m2val.size()) != 0)
340 return false;
341 }
342 }
343 return true;
344 }
345
operator ==(const BasicAudioAnnouncementData & lhs,const BasicAudioAnnouncementData & rhs)346 bool operator==(const BasicAudioAnnouncementData& lhs,
347 const BasicAudioAnnouncementData& rhs) {
348 if (lhs.presentation_delay_us != rhs.presentation_delay_us) return false;
349
350 if (lhs.subgroup_configs.size() != rhs.subgroup_configs.size()) return false;
351
352 for (auto i = 0lu; i < lhs.subgroup_configs.size(); ++i) {
353 auto& lhs_subgroup = lhs.subgroup_configs[i];
354 auto& rhs_subgroup = rhs.subgroup_configs[i];
355
356 if (lhs_subgroup.codec_config.codec_id !=
357 rhs_subgroup.codec_config.codec_id)
358 return false;
359
360 if (lhs_subgroup.codec_config.vendor_company_id !=
361 rhs_subgroup.codec_config.vendor_company_id)
362 return false;
363
364 if (lhs_subgroup.codec_config.vendor_codec_id !=
365 rhs_subgroup.codec_config.vendor_codec_id)
366 return false;
367
368 if (!isMetadataSame(lhs_subgroup.codec_config.codec_specific_params,
369 rhs_subgroup.codec_config.codec_specific_params))
370 return false;
371
372 if (!isMetadataSame(lhs_subgroup.metadata, rhs_subgroup.metadata))
373 return false;
374
375 for (auto j = 0lu; j < lhs_subgroup.bis_configs.size(); ++j) {
376 auto& lhs_bis_config = lhs_subgroup.bis_configs[i];
377 auto& rhs_bis_config = rhs_subgroup.bis_configs[i];
378 if (lhs_bis_config.bis_index != rhs_bis_config.bis_index) return false;
379
380 if (!isMetadataSame(lhs_bis_config.codec_specific_params,
381 rhs_bis_config.codec_specific_params))
382 return false;
383 }
384 }
385
386 return true;
387 }
388
operator ==(const PublicBroadcastAnnouncementData & lhs,const PublicBroadcastAnnouncementData & rhs)389 bool operator==(const PublicBroadcastAnnouncementData& lhs,
390 const PublicBroadcastAnnouncementData& rhs) {
391 if (lhs.features != rhs.features) return false;
392 if (!isMetadataSame(lhs.metadata, rhs.metadata)) return false;
393
394 return true;
395 }
396 } // namespace bluetooth::le_audio
397