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