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 <vector>
21 
22 #include "bt_types.h"
23 #include "bta_le_audio_broadcaster_api.h"
24 #include "btm_ble_api_types.h"
25 #include "embdrv/lc3/include/lc3.h"
26 #include "internal_include/stack_config.h"
27 #include "osi/include/properties.h"
28 
29 using bluetooth::le_audio::BasicAudioAnnouncementBisConfig;
30 using bluetooth::le_audio::BasicAudioAnnouncementCodecConfig;
31 using bluetooth::le_audio::BasicAudioAnnouncementData;
32 using bluetooth::le_audio::BasicAudioAnnouncementSubgroup;
33 using le_audio::types::LeAudioContextType;
34 
35 namespace le_audio {
36 namespace broadcaster {
37 
EmitHeader(const BasicAudioAnnouncementData & announcement_data,std::vector<uint8_t> & data)38 static void EmitHeader(const BasicAudioAnnouncementData& announcement_data,
39                        std::vector<uint8_t>& data) {
40   size_t old_size = data.size();
41   data.resize(old_size + 3);
42 
43   // Set the cursor behind the old data
44   uint8_t* p_value = data.data() + old_size;
45 
46   UINT24_TO_STREAM(p_value, announcement_data.presentation_delay);
47 }
48 
EmitCodecConfiguration(const BasicAudioAnnouncementCodecConfig & config,std::vector<uint8_t> & data,const BasicAudioAnnouncementCodecConfig * lower_lvl_config)49 static void EmitCodecConfiguration(
50     const BasicAudioAnnouncementCodecConfig& config, std::vector<uint8_t>& data,
51     const BasicAudioAnnouncementCodecConfig* lower_lvl_config) {
52   size_t old_size = data.size();
53 
54   // Add 5 for full, or 1 for short Codec ID
55   uint8_t codec_config_length = 5;
56 
57   auto ltv = types::LeAudioLtvMap(config.codec_specific_params);
58   auto ltv_raw_sz = ltv.RawPacketSize();
59 
60   // Add 1 for the codec spec. config length + config spec. data itself
61   codec_config_length += 1 + ltv_raw_sz;
62 
63   // Resize and set the cursor behind the old data
64   data.resize(old_size + codec_config_length);
65   uint8_t* p_value = data.data() + old_size;
66 
67   // Codec ID
68   UINT8_TO_STREAM(p_value, config.codec_id);
69   UINT16_TO_STREAM(p_value, config.vendor_company_id);
70   UINT16_TO_STREAM(p_value, config.vendor_codec_id);
71 
72   // Codec specific config length and data
73   UINT8_TO_STREAM(p_value, ltv_raw_sz);
74   p_value = ltv.RawPacket(p_value);
75 }
76 
EmitMetadata(const std::map<uint8_t,std::vector<uint8_t>> & metadata,std::vector<uint8_t> & data)77 static void EmitMetadata(
78     const std::map<uint8_t, std::vector<uint8_t>>& metadata,
79     std::vector<uint8_t>& data) {
80   auto ltv = types::LeAudioLtvMap(metadata);
81   auto ltv_raw_sz = ltv.RawPacketSize();
82 
83   size_t old_size = data.size();
84   data.resize(old_size + ltv_raw_sz + 1);
85 
86   // Set the cursor behind the old data
87   uint8_t* p_value = data.data() + old_size;
88 
89   UINT8_TO_STREAM(p_value, ltv_raw_sz);
90   if (ltv_raw_sz > 0) {
91     p_value = ltv.RawPacket(p_value);
92   }
93 }
94 
EmitBroadcastName(const std::string & name,std::vector<uint8_t> & data)95 static void EmitBroadcastName(const std::string& name,
96                               std::vector<uint8_t>& data) {
97   int name_len = name.length();
98   size_t old_size = data.size();
99   data.resize(old_size + name_len + 2);
100 
101   // Set the cursor behind the old data
102   uint8_t* p_value = data.data() + old_size;
103   UINT8_TO_STREAM(p_value, name_len + 1);
104   UINT8_TO_STREAM(p_value, BTM_BLE_AD_TYPE_BROADCAST_NAME);
105 
106   std::vector<uint8_t> vec(name.begin(), name.end());
107   ARRAY_TO_STREAM(p_value, vec.data(), name_len);
108 }
109 
EmitBisConfigs(const std::vector<BasicAudioAnnouncementBisConfig> & bis_configs,std::vector<uint8_t> & data)110 static void EmitBisConfigs(
111     const std::vector<BasicAudioAnnouncementBisConfig>& bis_configs,
112     std::vector<uint8_t>& data) {
113   // Emit each BIS config - that's the level 3 data
114   for (auto const& bis_config : bis_configs) {
115     auto ltv = types::LeAudioLtvMap(bis_config.codec_specific_params);
116     auto ltv_raw_sz = ltv.RawPacketSize();
117 
118     size_t old_size = data.size();
119     data.resize(old_size + ltv_raw_sz + 2);
120 
121     // Set the cursor behind the old data
122     auto* p_value = data.data() + old_size;
123 
124     // BIS_index[i[k]]
125     UINT8_TO_STREAM(p_value, bis_config.bis_index);
126 
127     // Per BIS Codec Specific Params[i[k]]
128     UINT8_TO_STREAM(p_value, ltv_raw_sz);
129     if (ltv_raw_sz > 0) {
130       p_value = ltv.RawPacket(p_value);
131     }
132   }
133 }
134 
EmitSubgroup(const BasicAudioAnnouncementSubgroup & subgroup_config,std::vector<uint8_t> & data)135 static void EmitSubgroup(const BasicAudioAnnouncementSubgroup& subgroup_config,
136                          std::vector<uint8_t>& data) {
137   // That's the level 2 data
138 
139   // Resize for the num_bis
140   size_t initial_offset = data.size();
141   data.resize(initial_offset + 1);
142 
143   // Set the cursor behind the old data and adds the level 2 Num_BIS[i]
144   uint8_t* p_value = data.data() + initial_offset;
145   UINT8_TO_STREAM(p_value, subgroup_config.bis_configs.size());
146 
147   EmitCodecConfiguration(subgroup_config.codec_config, data, nullptr);
148   EmitMetadata(subgroup_config.metadata, data);
149 
150   // This adds the level 3 data
151   EmitBisConfigs(subgroup_config.bis_configs, data);
152 }
153 
ToRawPacket(BasicAudioAnnouncementData const & in,std::vector<uint8_t> & data)154 bool ToRawPacket(BasicAudioAnnouncementData const& in,
155                  std::vector<uint8_t>& data) {
156   EmitHeader(in, data);
157 
158   // Set the cursor behind the old data and resize
159   size_t old_size = data.size();
160   data.resize(old_size + 1);
161   uint8_t* p_value = data.data() + old_size;
162 
163   // Emit the subgroup size and each subgroup
164   // That's the level 1 Num_Subgroups
165   UINT8_TO_STREAM(p_value, in.subgroup_configs.size());
166   for (const auto& subgroup_config : in.subgroup_configs) {
167     // That's the level 2 and higher level data
168     EmitSubgroup(subgroup_config, data);
169   }
170 
171   return true;
172 }
173 
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)174 void PrepareAdvertisingData(
175     bool is_public, const std::string& broadcast_name,
176     bluetooth::le_audio::BroadcastId& broadcast_id,
177     const bluetooth::le_audio::PublicBroadcastAnnouncementData&
178         public_announcement,
179     std::vector<uint8_t>& adv_data) {
180   adv_data.resize(7);
181   uint8_t* data_ptr = adv_data.data();
182   UINT8_TO_STREAM(data_ptr, 6);
183   UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
184   UINT16_TO_STREAM(data_ptr, kBroadcastAudioAnnouncementServiceUuid);
185   UINT24_TO_STREAM(data_ptr, broadcast_id);
186 
187   // Prepare public broadcast announcement data
188   if (is_public) {
189     size_t old_size = adv_data.size();
190     // 5: datalen(1) + adtype(1) + serviceuuid(2) + features(1)
191     adv_data.resize(old_size + 5);
192     // Skip the data length field until the full content is generated
193     data_ptr = adv_data.data() + old_size + 1;
194     UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
195     UINT16_TO_STREAM(data_ptr, kPublicBroadcastAnnouncementServiceUuid);
196     UINT8_TO_STREAM(data_ptr, public_announcement.features);
197     // Set metadata length to 0 if no meta data present
198     EmitMetadata(public_announcement.metadata, adv_data);
199 
200     // Update the length field accordingly
201     data_ptr = adv_data.data() + old_size;
202     UINT8_TO_STREAM(data_ptr, adv_data.size() - old_size - 1);
203 
204     // Prepare broadcast name
205     if (!broadcast_name.empty()) {
206       EmitBroadcastName(broadcast_name, adv_data);
207     }
208   }
209 }
210 
PreparePeriodicData(const BasicAudioAnnouncementData & announcement,std::vector<uint8_t> & periodic_data)211 void PreparePeriodicData(const BasicAudioAnnouncementData& announcement,
212                          std::vector<uint8_t>& periodic_data) {
213   /* Account for AD Type + Service UUID */
214   periodic_data.resize(4);
215   /* Skip the data length field until the full content is generated */
216   uint8_t* data_ptr = periodic_data.data() + 1;
217   UINT8_TO_STREAM(data_ptr, BTM_BLE_AD_TYPE_SERVICE_DATA_TYPE);
218   UINT16_TO_STREAM(data_ptr, kBasicAudioAnnouncementServiceUuid);
219 
220   /* Append the announcement */
221   ToRawPacket(announcement, periodic_data);
222 
223   /* Update the length field accordingly */
224   data_ptr = periodic_data.data();
225   UINT8_TO_STREAM(data_ptr, periodic_data.size() - 1);
226 }
227 
228 constexpr types::LeAudioCodecId kLeAudioCodecIdLc3 = {
229     .coding_format = types::kLeAudioCodingFormatLC3,
230     .vendor_company_id = types::kLeAudioVendorCompanyIdUndefined,
231     .vendor_codec_id = types::kLeAudioVendorCodecIdUndefined};
232 
233 static const BroadcastCodecWrapper lc3_mono_16_2 = BroadcastCodecWrapper(
234     kLeAudioCodecIdLc3,
235     // LeAudioCodecConfiguration
236     {.num_channels = LeAudioCodecConfiguration::kChannelNumberMono,
237      .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
238      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
239      .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
240     // Bitrate
241     32000,
242     // Frame len.
243     40);
244 
245 static const BroadcastCodecWrapper lc3_stereo_16_2 = BroadcastCodecWrapper(
246     kLeAudioCodecIdLc3,
247     // LeAudioCodecConfiguration
248     {.num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
249      .sample_rate = LeAudioCodecConfiguration::kSampleRate16000,
250      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
251      .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
252     // Bitrate
253     32000,
254     // Frame len.
255     40);
256 
257 static const BroadcastCodecWrapper lc3_stereo_24_2 = BroadcastCodecWrapper(
258     kLeAudioCodecIdLc3,
259     // LeAudioCodecConfiguration
260     {.num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
261      .sample_rate = LeAudioCodecConfiguration::kSampleRate24000,
262      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
263      .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
264     // Bitrate
265     48000,
266     // Frame len.
267     60);
268 
269 static const BroadcastCodecWrapper lc3_stereo_48_1 = BroadcastCodecWrapper(
270     kLeAudioCodecIdLc3,
271     // LeAudioCodecConfiguration
272     {.num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
273      .sample_rate = LeAudioCodecConfiguration::kSampleRate48000,
274      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
275      .data_interval_us = LeAudioCodecConfiguration::kInterval7500Us},
276     // Bitrate
277     80000,
278     // Frame len.
279     75);
280 
281 static const BroadcastCodecWrapper lc3_stereo_48_2 = BroadcastCodecWrapper(
282     kLeAudioCodecIdLc3,
283     // LeAudioCodecConfiguration
284     {.num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
285      .sample_rate = LeAudioCodecConfiguration::kSampleRate48000,
286      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
287      .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
288     // Bitrate
289     80000,
290     // Frame len.
291     100);
292 
293 static const BroadcastCodecWrapper lc3_stereo_48_3 = BroadcastCodecWrapper(
294     kLeAudioCodecIdLc3,
295     // LeAudioCodecConfiguration
296     {.num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
297      .sample_rate = LeAudioCodecConfiguration::kSampleRate48000,
298      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
299      .data_interval_us = LeAudioCodecConfiguration::kInterval7500Us},
300     // Bitrate
301     96000,
302     // Frame len.
303     90);
304 
305 static const BroadcastCodecWrapper lc3_stereo_48_4 = BroadcastCodecWrapper(
306     kLeAudioCodecIdLc3,
307     // LeAudioCodecConfiguration
308     {.num_channels = LeAudioCodecConfiguration::kChannelNumberStereo,
309      .sample_rate = LeAudioCodecConfiguration::kSampleRate48000,
310      .bits_per_sample = LeAudioCodecConfiguration::kBitsPerSample16,
311      .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us},
312     // Bitrate
313     96000,
314     // Frame len.
315     120);
316 
317 const std::map<uint32_t, uint8_t> sample_rate_to_sampling_freq_map = {
318     {LeAudioCodecConfiguration::kSampleRate8000,
319      codec_spec_conf::kLeAudioSamplingFreq8000Hz},
320     {LeAudioCodecConfiguration::kSampleRate16000,
321      codec_spec_conf::kLeAudioSamplingFreq16000Hz},
322     {LeAudioCodecConfiguration::kSampleRate24000,
323      codec_spec_conf::kLeAudioSamplingFreq24000Hz},
324     {LeAudioCodecConfiguration::kSampleRate32000,
325      codec_spec_conf::kLeAudioSamplingFreq32000Hz},
326     {LeAudioCodecConfiguration::kSampleRate44100,
327      codec_spec_conf::kLeAudioSamplingFreq44100Hz},
328     {LeAudioCodecConfiguration::kSampleRate48000,
329      codec_spec_conf::kLeAudioSamplingFreq48000Hz},
330 };
331 
332 const std::map<uint32_t, uint8_t> data_interval_ms_to_frame_duration = {
333     {LeAudioCodecConfiguration::kInterval7500Us,
334      codec_spec_conf::kLeAudioCodecLC3FrameDur7500us},
335     {LeAudioCodecConfiguration::kInterval10000Us,
336      codec_spec_conf::kLeAudioCodecLC3FrameDur10000us},
337 };
338 
GetBisCodecSpecData(uint8_t bis_idx) const339 types::LeAudioLtvMap BroadcastCodecWrapper::GetBisCodecSpecData(
340     uint8_t bis_idx) const {
341   /* For a single channel this will be set at the subgroup lvl. */
342   if (source_codec_config.num_channels == 1) return {};
343 
344   switch (bis_idx) {
345     case 1:
346       return types::LeAudioLtvMap(
347           {{codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation,
348             UINT32_TO_VEC_UINT8(codec_spec_conf::kLeAudioLocationFrontLeft)}});
349     case 2:
350       return types::LeAudioLtvMap(
351           {{codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation,
352             UINT32_TO_VEC_UINT8(codec_spec_conf::kLeAudioLocationFrontRight)}});
353       break;
354     default:
355       return {};
356   }
357 }
358 
GetSubgroupCodecSpecData() const359 types::LeAudioLtvMap BroadcastCodecWrapper::GetSubgroupCodecSpecData() const {
360   LOG_ASSERT(
361       sample_rate_to_sampling_freq_map.count(source_codec_config.sample_rate))
362       << "Invalid sample_rate";
363   LOG_ASSERT(data_interval_ms_to_frame_duration.count(
364       source_codec_config.data_interval_us))
365       << "Invalid data_interval";
366 
367   std::map<uint8_t, std::vector<uint8_t>> codec_spec_ltvs = {
368       {codec_spec_conf::kLeAudioCodecLC3TypeSamplingFreq,
369        UINT8_TO_VEC_UINT8(sample_rate_to_sampling_freq_map.at(
370            source_codec_config.sample_rate))},
371       {codec_spec_conf::kLeAudioCodecLC3TypeFrameDuration,
372        UINT8_TO_VEC_UINT8(data_interval_ms_to_frame_duration.at(
373            source_codec_config.data_interval_us))},
374   };
375 
376   if (codec_id.coding_format == kLeAudioCodecIdLc3.coding_format) {
377     uint16_t bc =
378         lc3_frame_bytes(source_codec_config.data_interval_us, codec_bitrate);
379     codec_spec_ltvs[codec_spec_conf::kLeAudioCodecLC3TypeOctetPerFrame] =
380         UINT16_TO_VEC_UINT8(bc);
381   }
382 
383   if (source_codec_config.num_channels == 1) {
384     codec_spec_ltvs
385         [codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation] =
386             UINT32_TO_VEC_UINT8(codec_spec_conf::kLeAudioLocationFrontCenter);
387   }
388 
389   return types::LeAudioLtvMap(codec_spec_ltvs);
390 }
391 
operator <<(std::ostream & os,const le_audio::broadcaster::BroadcastCodecWrapper & config)392 std::ostream& operator<<(
393     std::ostream& os,
394     const le_audio::broadcaster::BroadcastCodecWrapper& config) {
395   os << " BroadcastCodecWrapper=[";
396   os << "CodecID="
397      << "{" << +config.GetLeAudioCodecId().coding_format << ":"
398      << +config.GetLeAudioCodecId().vendor_company_id << ":"
399      << +config.GetLeAudioCodecId().vendor_codec_id << "}";
400   os << ", LeAudioCodecConfiguration="
401      << "{NumChannels=" << +config.GetNumChannels()
402      << ", SampleRate=" << +config.GetSampleRate()
403      << ", BitsPerSample=" << +config.GetBitsPerSample()
404      << ", DataIntervalUs=" << +config.GetDataIntervalUs() << "}";
405   os << ", Bitrate=" << +config.GetBitrate();
406   os << "]";
407   return os;
408 }
409 
operator <<(std::ostream & os,const le_audio::broadcaster::BroadcastQosConfig & config)410 std::ostream& operator<<(
411     std::ostream& os, const le_audio::broadcaster::BroadcastQosConfig& config) {
412   os << " BroadcastQosConfig=[";
413   os << "RTN=" << +config.getRetransmissionNumber();
414   os << ", MaxTransportLatency=" << config.getMaxTransportLatency();
415   os << "]";
416   return os;
417 }
418 
419 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
420     lc3_mono_16_2_1 = {lc3_mono_16_2, qos_config_2_10};
421 
422 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
423     lc3_mono_16_2_2 = {lc3_mono_16_2, qos_config_4_60};
424 
425 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
426     lc3_stereo_16_2_2 = {lc3_stereo_16_2, qos_config_4_60};
427 
428 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
429     lc3_stereo_24_2_1 = {lc3_stereo_24_2, qos_config_2_10};
430 
431 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
432     lc3_stereo_24_2_2 = {lc3_stereo_24_2, qos_config_4_60};
433 
434 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
435     lc3_stereo_48_1_2 = {lc3_stereo_48_1, qos_config_4_50};
436 
437 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
438     lc3_stereo_48_2_2 = {lc3_stereo_48_2, qos_config_4_65};
439 
440 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
441     lc3_stereo_48_3_2 = {lc3_stereo_48_3, qos_config_4_50};
442 
443 static const std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
444     lc3_stereo_48_4_2 = {lc3_stereo_48_4, qos_config_4_65};
445 
446 std::pair<const BroadcastCodecWrapper&, const BroadcastQosConfig&>
getStreamConfigForContext(types::AudioContexts context)447 getStreamConfigForContext(types::AudioContexts context) {
448   const std::string* options =
449       stack_config_get_interface()->get_pts_broadcast_audio_config_options();
450   if (options) {
451     if (!options->compare("lc3_stereo_48_1_2")) return lc3_stereo_48_1_2;
452     if (!options->compare("lc3_stereo_48_2_2")) return lc3_stereo_48_2_2;
453     if (!options->compare("lc3_stereo_48_3_2")) return lc3_stereo_48_3_2;
454     if (!options->compare("lc3_stereo_48_4_2")) return lc3_stereo_48_4_2;
455   }
456   // High quality, Low Latency
457   if (context.test_any(LeAudioContextType::GAME | LeAudioContextType::LIVE))
458     return lc3_stereo_24_2_1;
459 
460   // Low quality, Low Latency
461   if (context.test(LeAudioContextType::INSTRUCTIONAL)) return lc3_mono_16_2_1;
462 
463   // Low quality, High Reliability
464   if (context.test_any(LeAudioContextType::SOUNDEFFECTS |
465                        LeAudioContextType::UNSPECIFIED))
466     return lc3_stereo_16_2_2;
467 
468   if (context.test_any(LeAudioContextType::ALERTS |
469                        LeAudioContextType::NOTIFICATIONS |
470                        LeAudioContextType::EMERGENCYALARM))
471     return lc3_mono_16_2_2;
472 
473   // High quality, High Reliability
474   if (context.test(LeAudioContextType::MEDIA)) return lc3_stereo_24_2_2;
475 
476   // Defaults: Low quality, High Reliability
477   return lc3_mono_16_2_2;
478 }
479 
480 } /* namespace broadcaster */
481 } /* namespace le_audio */
482 
483 /* Helper functions for comparing BroadcastAnnouncements */
484 namespace bluetooth {
485 namespace le_audio {
486 
isMetadataSame(std::map<uint8_t,std::vector<uint8_t>> m1,std::map<uint8_t,std::vector<uint8_t>> m2)487 static bool isMetadataSame(std::map<uint8_t, std::vector<uint8_t>> m1,
488                            std::map<uint8_t, std::vector<uint8_t>> m2) {
489   if (m1.size() != m2.size()) return false;
490 
491   for (auto& m1pair : m1) {
492     if (m2.count(m1pair.first) == 0) return false;
493 
494     auto& m2val = m2.at(m1pair.first);
495     if (m1pair.second.size() != m2val.size()) return false;
496 
497     if (m1pair.second.size() != 0) {
498       if (memcmp(m1pair.second.data(), m2val.data(), m2val.size()) != 0)
499         return false;
500     }
501   }
502   return true;
503 }
504 
operator ==(const BasicAudioAnnouncementData & lhs,const BasicAudioAnnouncementData & rhs)505 bool operator==(const BasicAudioAnnouncementData& lhs,
506                 const BasicAudioAnnouncementData& rhs) {
507   if (lhs.presentation_delay != rhs.presentation_delay) return false;
508 
509   if (lhs.subgroup_configs.size() != rhs.subgroup_configs.size()) return false;
510 
511   for (auto i = 0lu; i < lhs.subgroup_configs.size(); ++i) {
512     auto& lhs_subgroup = lhs.subgroup_configs[i];
513     auto& rhs_subgroup = rhs.subgroup_configs[i];
514 
515     if (lhs_subgroup.codec_config.codec_id !=
516         rhs_subgroup.codec_config.codec_id)
517       return false;
518 
519     if (lhs_subgroup.codec_config.vendor_company_id !=
520         rhs_subgroup.codec_config.vendor_company_id)
521       return false;
522 
523     if (lhs_subgroup.codec_config.vendor_codec_id !=
524         rhs_subgroup.codec_config.vendor_codec_id)
525       return false;
526 
527     if (!isMetadataSame(lhs_subgroup.codec_config.codec_specific_params,
528                         rhs_subgroup.codec_config.codec_specific_params))
529       return false;
530 
531     if (!isMetadataSame(lhs_subgroup.metadata, rhs_subgroup.metadata))
532       return false;
533 
534     for (auto j = 0lu; j < lhs_subgroup.bis_configs.size(); ++j) {
535       auto& lhs_bis_config = lhs_subgroup.bis_configs[i];
536       auto& rhs_bis_config = rhs_subgroup.bis_configs[i];
537       if (lhs_bis_config.bis_index != rhs_bis_config.bis_index) return false;
538 
539       if (!isMetadataSame(lhs_bis_config.codec_specific_params,
540                           rhs_bis_config.codec_specific_params))
541         return false;
542     }
543   }
544 
545   return true;
546 }
547 
operator ==(const PublicBroadcastAnnouncementData & lhs,const PublicBroadcastAnnouncementData & rhs)548 bool operator==(const PublicBroadcastAnnouncementData& lhs,
549                 const PublicBroadcastAnnouncementData& rhs) {
550   if (lhs.features != rhs.features) return false;
551   if (!isMetadataSame(lhs.metadata, rhs.metadata)) return false;
552 
553   return true;
554 }
555 }  // namespace le_audio
556 }  // namespace bluetooth
557