1 /*
2  * Copyright 2023 The Android Open Source Project
3  * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA
4  * - www.ehima.com
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "device_groups.h"
20 
21 #include <bluetooth/log.h>
22 
23 #include <optional>
24 
25 #include "bta/include/bta_gatt_api.h"
26 #include "bta_csis_api.h"
27 #include "btif/include/btif_profile_storage.h"
28 #include "btm_iso_api.h"
29 #include "hci/controller_interface.h"
30 #include "internal_include/bt_trace.h"
31 #include "le_audio/codec_manager.h"
32 #include "le_audio/devices.h"
33 #include "le_audio/le_audio_types.h"
34 #include "le_audio_set_configuration_provider.h"
35 #include "le_audio_utils.h"
36 #include "main/shim/entry.h"
37 #include "metrics_collector.h"
38 #include "os/log.h"
39 
40 namespace bluetooth::le_audio {
41 
42 using bluetooth::le_audio::types::ase;
43 using types::AseState;
44 using types::AudioContexts;
45 using types::AudioLocations;
46 using types::BidirectionalPair;
47 using types::CisState;
48 using types::CisType;
49 using types::DataPathState;
50 using types::LeAudioContextType;
51 using types::LeAudioCoreCodecConfig;
52 
53 /* LeAudioDeviceGroup Class methods implementation */
AddNode(const std::shared_ptr<LeAudioDevice> & leAudioDevice)54 void LeAudioDeviceGroup::AddNode(
55     const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
56   leAudioDevice->group_id_ = group_id_;
57   leAudioDevices_.push_back(std::weak_ptr<LeAudioDevice>(leAudioDevice));
58   MetricsCollector::Get()->OnGroupSizeUpdate(group_id_, leAudioDevices_.size());
59 }
60 
RemoveNode(const std::shared_ptr<LeAudioDevice> & leAudioDevice)61 void LeAudioDeviceGroup::RemoveNode(
62     const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
63   /* Group information cleaning in the device. */
64   leAudioDevice->group_id_ = bluetooth::groups::kGroupUnknown;
65   for (auto ase : leAudioDevice->ases_) {
66     ase.active = false;
67     ase.cis_conn_hdl = 0;
68   }
69 
70   leAudioDevices_.erase(
71       std::remove_if(
72           leAudioDevices_.begin(), leAudioDevices_.end(),
73           [&leAudioDevice](auto& d) { return d.lock() == leAudioDevice; }),
74       leAudioDevices_.end());
75   MetricsCollector::Get()->OnGroupSizeUpdate(group_id_, leAudioDevices_.size());
76 }
77 
IsEmpty(void) const78 bool LeAudioDeviceGroup::IsEmpty(void) const {
79   return leAudioDevices_.size() == 0;
80 }
81 
IsAnyDeviceConnected(void) const82 bool LeAudioDeviceGroup::IsAnyDeviceConnected(void) const {
83   return (NumOfConnected() != 0);
84 }
85 
Size(void) const86 int LeAudioDeviceGroup::Size(void) const { return leAudioDevices_.size(); }
87 
DesiredSize(void) const88 int LeAudioDeviceGroup::DesiredSize(void) const {
89   int group_size = 0;
90   if (bluetooth::csis::CsisClient::IsCsisClientRunning()) {
91     group_size = bluetooth::csis::CsisClient::Get()->GetDesiredSize(group_id_);
92   }
93 
94   return group_size > 0 ? group_size : leAudioDevices_.size();
95 }
96 
NumOfConnected() const97 int LeAudioDeviceGroup::NumOfConnected() const {
98   /* return number of connected devices from the set*/
99   return std::count_if(
100       leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& iter) {
101         auto dev = iter.lock();
102         if (dev) {
103           return (dev->conn_id_ != GATT_INVALID_CONN_ID) &&
104                  (dev->GetConnectionState() == DeviceConnectState::CONNECTED);
105         }
106         return false;
107       });
108 }
109 
NumOfAvailableForDirection(int direction) const110 int LeAudioDeviceGroup::NumOfAvailableForDirection(int direction) const {
111   bool check_ase_count = direction < types::kLeAudioDirectionBoth;
112 
113   /* return number of connected devices from the set with supported context */
114   return std::count_if(
115       leAudioDevices_.begin(), leAudioDevices_.end(), [&](auto& iter) {
116         auto dev = iter.lock();
117         if (dev) {
118           if (check_ase_count && (dev->GetAseCount(direction) == 0)) {
119             return false;
120           }
121           return (dev->conn_id_ != GATT_INVALID_CONN_ID) &&
122                  (dev->GetConnectionState() == DeviceConnectState::CONNECTED);
123         }
124         return false;
125       });
126 }
127 
ClearSinksFromConfiguration(void)128 void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
129   log::info("Group {}, group_id {}", fmt::ptr(this), group_id_);
130 
131   auto direction = types::kLeAudioDirectionSink;
132   stream_conf.stream_params.get(direction).clear();
133   CodecManager::GetInstance()->ClearCisConfiguration(direction);
134 }
135 
ClearSourcesFromConfiguration(void)136 void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
137   log::info("Group {}, group_id {}", fmt::ptr(this), group_id_);
138 
139   auto direction = types::kLeAudioDirectionSource;
140   stream_conf.stream_params.get(direction).clear();
141   CodecManager::GetInstance()->ClearCisConfiguration(direction);
142 }
143 
ClearAllCises(void)144 void LeAudioDeviceGroup::ClearAllCises(void) {
145   log::info("group_id: {}", group_id_);
146   cig.cises.clear();
147   ClearSinksFromConfiguration();
148   ClearSourcesFromConfiguration();
149 }
150 
UpdateCisConfiguration(uint8_t direction)151 void LeAudioDeviceGroup::UpdateCisConfiguration(uint8_t direction) {
152   CodecManager::GetInstance()->UpdateCisConfiguration(
153       cig.cises, stream_conf.stream_params.get(direction), direction);
154 }
155 
Cleanup(void)156 void LeAudioDeviceGroup::Cleanup(void) {
157   /* Bluetooth is off while streaming - disconnect CISes and remove CIG */
158   if (GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
159     auto& sink_stream_locations =
160         stream_conf.stream_params.sink.stream_locations;
161     auto& source_stream_locations =
162         stream_conf.stream_params.source.stream_locations;
163 
164     if (!sink_stream_locations.empty()) {
165       for (const auto kv_pair : sink_stream_locations) {
166         auto cis_handle = kv_pair.first;
167         bluetooth::hci::IsoManager::GetInstance()->DisconnectCis(
168             cis_handle, HCI_ERR_PEER_USER);
169 
170         /* Check the other direction if disconnecting bidirectional CIS */
171         if (source_stream_locations.empty()) {
172           continue;
173         }
174         source_stream_locations.erase(
175             std::remove_if(
176                 source_stream_locations.begin(), source_stream_locations.end(),
177                 [&cis_handle](auto& pair) { return pair.first == cis_handle; }),
178             source_stream_locations.end());
179       }
180     }
181 
182     /* Take care of the non-bidirectional CISes */
183     if (!source_stream_locations.empty()) {
184       for (auto [cis_handle, _] : source_stream_locations) {
185         bluetooth::hci::IsoManager::GetInstance()->DisconnectCis(
186             cis_handle, HCI_ERR_PEER_USER);
187       }
188     }
189   }
190 
191   /* Note: CIG will stay in the controller. We cannot remove it here, because
192    * Cises are not yet disconnected.
193    * When user start Bluetooth, HCI Reset should remove it
194    */
195 
196   leAudioDevices_.clear();
197   ClearAllCises();
198 }
199 
Deactivate(void)200 void LeAudioDeviceGroup::Deactivate(void) {
201   for (auto* leAudioDevice = GetFirstActiveDevice(); leAudioDevice;
202        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
203     for (auto* ase = leAudioDevice->GetFirstActiveAse(); ase;
204          ase = leAudioDevice->GetNextActiveAse(ase)) {
205       ase->active = false;
206       ase->reconfigure = 0;
207     }
208   }
209 }
210 
Activate(LeAudioContextType context_type,const BidirectionalPair<AudioContexts> & metadata_context_types,BidirectionalPair<std::vector<uint8_t>> ccid_lists)211 bool LeAudioDeviceGroup::Activate(
212   LeAudioContextType context_type,
213   const BidirectionalPair<AudioContexts>& metadata_context_types,
214   BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
215   bool is_activate = false;
216   for (auto leAudioDevice : leAudioDevices_) {
217     if (leAudioDevice.expired()) continue;
218 
219     bool activated = leAudioDevice.lock()->ActivateConfiguredAses(
220         context_type, metadata_context_types, ccid_lists);
221     log::info("Device {} is {}", leAudioDevice.lock().get()->address_,
222               activated ? "activated" : " not activated");
223     if (activated) {
224       if (!cig.AssignCisIds(leAudioDevice.lock().get())) {
225         return false;
226       }
227       is_activate = true;
228     }
229   }
230   return is_activate;
231 }
232 
GetSupportedContexts(int direction) const233 AudioContexts LeAudioDeviceGroup::GetSupportedContexts(int direction) const {
234   AudioContexts context;
235   for (auto& device : leAudioDevices_) {
236     auto shared_dev = device.lock();
237     if (shared_dev) {
238       context |= shared_dev->GetSupportedContexts(direction);
239     }
240   }
241   return context;
242 }
243 
GetFirstDevice(void) const244 LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) const {
245   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
246                            [](auto& iter) { return !iter.expired(); });
247 
248   if (iter == leAudioDevices_.end()) return nullptr;
249 
250   return (iter->lock()).get();
251 }
252 
GetFirstDeviceWithAvailableContext(LeAudioContextType context_type) const253 LeAudioDevice* LeAudioDeviceGroup::GetFirstDeviceWithAvailableContext(
254     LeAudioContextType context_type) const {
255   auto iter = std::find_if(
256       leAudioDevices_.begin(), leAudioDevices_.end(),
257       [&context_type](auto& iter) {
258         if (iter.expired()) return false;
259         return iter.lock()->GetAvailableContexts().test(context_type);
260       });
261 
262   if ((iter == leAudioDevices_.end()) || (iter->expired())) return nullptr;
263 
264   return (iter->lock()).get();
265 }
266 
GetNextDevice(LeAudioDevice * leAudioDevice) const267 LeAudioDevice* LeAudioDeviceGroup::GetNextDevice(
268     LeAudioDevice* leAudioDevice) const {
269   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
270                            [&leAudioDevice](auto& d) {
271                              if (d.expired())
272                                return false;
273                              else
274                                return (d.lock()).get() == leAudioDevice;
275                            });
276 
277   /* If reference device not found */
278   if (iter == leAudioDevices_.end()) return nullptr;
279 
280   std::advance(iter, 1);
281   /* If reference device is last in group */
282   if (iter == leAudioDevices_.end()) return nullptr;
283 
284   if (iter->expired()) return nullptr;
285 
286   return (iter->lock()).get();
287 }
288 
GetNextDeviceWithAvailableContext(LeAudioDevice * leAudioDevice,LeAudioContextType context_type) const289 LeAudioDevice* LeAudioDeviceGroup::GetNextDeviceWithAvailableContext(
290     LeAudioDevice* leAudioDevice, LeAudioContextType context_type) const {
291   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
292                            [&leAudioDevice](auto& d) {
293                              if (d.expired())
294                                return false;
295                              else
296                                return (d.lock()).get() == leAudioDevice;
297                            });
298 
299   /* If reference device not found */
300   if (iter == leAudioDevices_.end()) return nullptr;
301 
302   std::advance(iter, 1);
303   /* If reference device is last in group */
304   if (iter == leAudioDevices_.end()) return nullptr;
305 
306   iter = std::find_if(iter, leAudioDevices_.end(), [&context_type](auto& d) {
307     if (d.expired())
308       return false;
309     else
310       return d.lock()->GetAvailableContexts().test(context_type);
311     ;
312   });
313 
314   return (iter == leAudioDevices_.end()) ? nullptr : (iter->lock()).get();
315 }
316 
IsDeviceInTheGroup(LeAudioDevice * leAudioDevice) const317 bool LeAudioDeviceGroup::IsDeviceInTheGroup(
318     LeAudioDevice* leAudioDevice) const {
319   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
320                            [&leAudioDevice](auto& d) {
321                              if (d.expired())
322                                return false;
323                              else
324                                return (d.lock()).get() == leAudioDevice;
325                            });
326 
327   if ((iter == leAudioDevices_.end()) || (iter->expired())) return false;
328 
329   return true;
330 }
331 
IsGroupReadyToCreateStream(void) const332 bool LeAudioDeviceGroup::IsGroupReadyToCreateStream(void) const {
333   auto iter =
334       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
335         if (d.expired())
336           return false;
337         else
338           return !(((d.lock()).get())->IsReadyToCreateStream());
339       });
340 
341   return iter == leAudioDevices_.end();
342 }
343 
IsGroupReadyToSuspendStream(void) const344 bool LeAudioDeviceGroup::IsGroupReadyToSuspendStream(void) const {
345   auto iter =
346       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
347         if (d.expired())
348           return false;
349         else
350           return !(((d.lock()).get())->IsReadyToSuspendStream());
351       });
352 
353   return iter == leAudioDevices_.end();
354 }
355 
HaveAnyActiveDeviceInUnconfiguredState() const356 bool LeAudioDeviceGroup::HaveAnyActiveDeviceInUnconfiguredState() const {
357   auto iter =
358       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
359         if (d.expired())
360           return false;
361         else
362           return (((d.lock()).get())->HaveAnyUnconfiguredAses());
363       });
364 
365   return iter != leAudioDevices_.end();
366 }
367 
HaveAllActiveDevicesAsesTheSameState(AseState state) const368 bool LeAudioDeviceGroup::HaveAllActiveDevicesAsesTheSameState(
369     AseState state) const {
370   auto iter = std::find_if(
371       leAudioDevices_.begin(), leAudioDevices_.end(), [&state](auto& d) {
372         if (d.expired())
373           return false;
374         else
375           return !(((d.lock()).get())->HaveAllActiveAsesSameState(state));
376       });
377 
378   return iter == leAudioDevices_.end();
379 }
380 
GetFirstActiveDevice(void) const381 LeAudioDevice* LeAudioDeviceGroup::GetFirstActiveDevice(void) const {
382   auto iter =
383       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
384         if (d.expired())
385           return false;
386         else
387           return ((d.lock()).get())->HaveActiveAse();
388       });
389 
390   if (iter == leAudioDevices_.end() || iter->expired()) return nullptr;
391 
392   return (iter->lock()).get();
393 }
394 
GetNextActiveDevice(LeAudioDevice * leAudioDevice) const395 LeAudioDevice* LeAudioDeviceGroup::GetNextActiveDevice(
396     LeAudioDevice* leAudioDevice) const {
397   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
398                            [&leAudioDevice](auto& d) {
399                              if (d.expired())
400                                return false;
401                              else
402                                return (d.lock()).get() == leAudioDevice;
403                            });
404 
405   if (iter == leAudioDevices_.end() ||
406       std::distance(iter, leAudioDevices_.end()) < 1)
407     return nullptr;
408 
409   iter = std::find_if(std::next(iter, 1), leAudioDevices_.end(), [](auto& d) {
410     if (d.expired())
411       return false;
412     else
413       return ((d.lock()).get())->HaveActiveAse();
414   });
415 
416   return (iter == leAudioDevices_.end()) ? nullptr : (iter->lock()).get();
417 }
418 
GetFirstActiveDeviceByCisAndDataPathState(CisState cis_state,DataPathState data_path_state) const419 LeAudioDevice* LeAudioDeviceGroup::GetFirstActiveDeviceByCisAndDataPathState(
420     CisState cis_state, DataPathState data_path_state) const {
421   auto iter =
422       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
423                    [&data_path_state, &cis_state](auto& d) {
424                      if (d.expired()) {
425                        return false;
426                      }
427 
428                      return (((d.lock()).get())
429                                  ->GetFirstActiveAseByCisAndDataPathState(
430                                      cis_state, data_path_state) != nullptr);
431                    });
432 
433   if (iter == leAudioDevices_.end()) {
434     return nullptr;
435   }
436 
437   return iter->lock().get();
438 }
439 
GetNextActiveDeviceByCisAndDataPathState(LeAudioDevice * leAudioDevice,CisState cis_state,DataPathState data_path_state) const440 LeAudioDevice* LeAudioDeviceGroup::GetNextActiveDeviceByCisAndDataPathState(
441     LeAudioDevice* leAudioDevice, CisState cis_state,
442     DataPathState data_path_state) const {
443   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
444                            [&leAudioDevice](auto& d) {
445                              if (d.expired()) {
446                                return false;
447                              }
448 
449                              return d.lock().get() == leAudioDevice;
450                            });
451 
452   if (std::distance(iter, leAudioDevices_.end()) < 1) {
453     return nullptr;
454   }
455 
456   iter = std::find_if(std::next(iter, 1), leAudioDevices_.end(),
457                       [&cis_state, &data_path_state](auto& d) {
458                         if (d.expired()) {
459                           return false;
460                         }
461 
462                         return (((d.lock()).get())
463                                     ->GetFirstActiveAseByCisAndDataPathState(
464                                         cis_state, data_path_state) != nullptr);
465                       });
466 
467   if (iter == leAudioDevices_.end()) {
468     return nullptr;
469   }
470 
471   return iter->lock().get();
472 }
473 
GetSduInterval(uint8_t direction) const474 uint32_t LeAudioDeviceGroup::GetSduInterval(uint8_t direction) const {
475   for (LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
476        leAudioDevice != nullptr;
477        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
478     struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
479     if (!ase) continue;
480     return ase->qos_config.sdu_interval;
481   }
482 
483   return 0;
484 }
485 
GetSCA(void) const486 uint8_t LeAudioDeviceGroup::GetSCA(void) const {
487   uint8_t sca = bluetooth::hci::iso_manager::kIsoSca0To20Ppm;
488 
489   for (const auto& leAudioDevice : leAudioDevices_) {
490     uint8_t dev_sca =
491         BTM_GetPeerSCA(leAudioDevice.lock()->address_, BT_TRANSPORT_LE);
492 
493     /* If we could not read SCA from the peer device or sca is 0,
494      * then there is no reason to continue.
495      */
496     if ((dev_sca == 0xFF) || (dev_sca == 0)) return 0;
497 
498     /* The Slaves_Clock_Accuracy parameter shall be the worst-case sleep clock
499      *accuracy of all the slaves that will participate in the CIG.
500      */
501     if (dev_sca < sca) {
502       sca = dev_sca;
503     }
504   }
505 
506   return sca;
507 }
508 
GetPacking(void) const509 uint8_t LeAudioDeviceGroup::GetPacking(void) const {
510   if (!stream_conf.conf) {
511     log::error("No stream configuration has been set.");
512     return bluetooth::hci::kIsoCigPackingSequential;
513   }
514   return stream_conf.conf->packing;
515 }
516 
GetFraming(void) const517 uint8_t LeAudioDeviceGroup::GetFraming(void) const {
518   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
519   log::assert_that(leAudioDevice,
520                    "Shouldn't be called without an active device.");
521 
522   do {
523     struct ase* ase = leAudioDevice->GetFirstActiveAse();
524     if (!ase) continue;
525 
526     do {
527       if (ase->qos_preferences.supported_framing ==
528           types::kFramingUnframedPduUnsupported)
529         return bluetooth::hci::kIsoCigFramingFramed;
530     } while ((ase = leAudioDevice->GetNextActiveAse(ase)));
531   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
532 
533   return bluetooth::hci::kIsoCigFramingUnframed;
534 }
535 
536 /* TODO: Preferred parameter may be other than minimum */
find_max_transport_latency(const LeAudioDeviceGroup * group,uint8_t direction)537 static uint16_t find_max_transport_latency(const LeAudioDeviceGroup* group,
538                                            uint8_t direction) {
539   uint16_t max_transport_latency = 0;
540 
541   for (LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice();
542        leAudioDevice != nullptr;
543        leAudioDevice = group->GetNextActiveDevice(leAudioDevice)) {
544     for (ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
545          ase != nullptr;
546          ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)) {
547       if (!ase) break;
548 
549       if (max_transport_latency == 0) {
550         // first assignment
551         max_transport_latency = ase->qos_config.max_transport_latency;
552       } else if (ase->qos_config.max_transport_latency <
553                  max_transport_latency) {
554         if (ase->qos_config.max_transport_latency != 0) {
555           max_transport_latency = ase->qos_config.max_transport_latency;
556         } else {
557           log::warn("Trying to set latency back to 0, ASE ID {}", ase->id);
558         }
559       }
560     }
561   }
562 
563   if (max_transport_latency < types::kMaxTransportLatencyMin) {
564     max_transport_latency = types::kMaxTransportLatencyMin;
565   } else if (max_transport_latency > types::kMaxTransportLatencyMax) {
566     max_transport_latency = types::kMaxTransportLatencyMax;
567   }
568 
569   return max_transport_latency;
570 }
571 
GetMaxTransportLatencyStom(void) const572 uint16_t LeAudioDeviceGroup::GetMaxTransportLatencyStom(void) const {
573   return find_max_transport_latency(this, types::kLeAudioDirectionSource);
574 }
575 
GetMaxTransportLatencyMtos(void) const576 uint16_t LeAudioDeviceGroup::GetMaxTransportLatencyMtos(void) const {
577   return find_max_transport_latency(this, types::kLeAudioDirectionSink);
578 }
579 
GetTransportLatencyUs(uint8_t direction) const580 uint32_t LeAudioDeviceGroup::GetTransportLatencyUs(uint8_t direction) const {
581   if (direction == types::kLeAudioDirectionSink) {
582     return transport_latency_mtos_us_;
583   } else if (direction == types::kLeAudioDirectionSource) {
584     return transport_latency_stom_us_;
585   } else {
586     log::error("invalid direction");
587     return 0;
588   }
589 }
590 
SetTransportLatency(uint8_t direction,uint32_t new_transport_latency_us)591 void LeAudioDeviceGroup::SetTransportLatency(
592     uint8_t direction, uint32_t new_transport_latency_us) {
593   uint32_t* transport_latency_us;
594 
595   if (direction == types::kLeAudioDirectionSink) {
596     transport_latency_us = &transport_latency_mtos_us_;
597   } else if (direction == types::kLeAudioDirectionSource) {
598     transport_latency_us = &transport_latency_stom_us_;
599   } else {
600     log::error("invalid direction");
601     return;
602   }
603 
604   if (*transport_latency_us == new_transport_latency_us) return;
605 
606   if ((*transport_latency_us != 0) &&
607       (*transport_latency_us != new_transport_latency_us)) {
608     log::warn(
609         "Different transport latency for group:  old: {} [us], new: {} [us]",
610         static_cast<int>(*transport_latency_us),
611         static_cast<int>(new_transport_latency_us));
612     return;
613   }
614 
615   log::info("updated group {} transport latency: {} [us]",
616             static_cast<int>(group_id_),
617             static_cast<int>(new_transport_latency_us));
618   *transport_latency_us = new_transport_latency_us;
619 }
620 
GetRtn(uint8_t direction,uint8_t cis_id) const621 uint8_t LeAudioDeviceGroup::GetRtn(uint8_t direction, uint8_t cis_id) const {
622   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
623   log::assert_that(leAudioDevice,
624                    "Shouldn't be called without an active device.");
625 
626   do {
627     auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);
628 
629     if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
630       return ases_pair.sink->qos_config.retrans_nb;
631     } else if (ases_pair.source &&
632                direction == types::kLeAudioDirectionSource) {
633       return ases_pair.source->qos_config.retrans_nb;
634     }
635   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
636 
637   return 0;
638 }
639 
GetMaxSduSize(uint8_t direction,uint8_t cis_id) const640 uint16_t LeAudioDeviceGroup::GetMaxSduSize(uint8_t direction,
641                                            uint8_t cis_id) const {
642   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
643   log::assert_that(leAudioDevice,
644                    "Shouldn't be called without an active device.");
645 
646   do {
647     auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);
648 
649     if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
650       return ases_pair.sink->qos_config.max_sdu_size;
651     } else if (ases_pair.source &&
652                direction == types::kLeAudioDirectionSource) {
653       return ases_pair.source->qos_config.max_sdu_size;
654     }
655   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
656 
657   return 0;
658 }
659 
GetPhyBitmask(uint8_t direction) const660 uint8_t LeAudioDeviceGroup::GetPhyBitmask(uint8_t direction) const {
661   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
662   log::assert_that(leAudioDevice,
663                    "Shouldn't be called without an active device.");
664 
665   // local supported PHY's
666   uint8_t phy_bitfield = bluetooth::hci::kIsoCigPhy1M;
667   auto controller = bluetooth::shim::GetController();
668   if (controller && controller->SupportsBle2mPhy())
669     phy_bitfield |= bluetooth::hci::kIsoCigPhy2M;
670 
671   if (!leAudioDevice) {
672     log::error("No active leaudio device for direction?: {}", direction);
673     return phy_bitfield;
674   }
675 
676   do {
677     struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
678     if (!ase) return phy_bitfield;
679 
680     do {
681       if (direction == ase->direction) {
682         phy_bitfield &= leAudioDevice->GetPhyBitmask();
683 
684         // A value of 0x00 denotes no preference
685         if (ase->qos_preferences.preferred_phy &&
686             (phy_bitfield & ase->qos_preferences.preferred_phy)) {
687           phy_bitfield &= ase->qos_preferences.preferred_phy;
688           log::debug("Using ASE preferred phy 0x{:02x}",
689                      static_cast<int>(phy_bitfield));
690         } else {
691           log::warn(
692               "ASE preferred 0x{:02x} has nothing common with phy_bitfield "
693               "0x{:02x}",
694               static_cast<int>(ase->qos_preferences.preferred_phy),
695               static_cast<int>(phy_bitfield));
696         }
697       }
698     } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
699   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
700 
701   return phy_bitfield;
702 }
703 
GetTargetPhy(uint8_t direction) const704 uint8_t LeAudioDeviceGroup::GetTargetPhy(uint8_t direction) const {
705   uint8_t phy_bitfield = GetPhyBitmask(direction);
706 
707   // prefer to use 2M if supported
708   if (phy_bitfield & bluetooth::hci::kIsoCigPhy2M)
709     return types::kTargetPhy2M;
710   else if (phy_bitfield & bluetooth::hci::kIsoCigPhy1M)
711     return types::kTargetPhy1M;
712   else
713     return 0;
714 }
715 
GetPresentationDelay(uint32_t * delay,uint8_t direction) const716 bool LeAudioDeviceGroup::GetPresentationDelay(uint32_t* delay,
717                                               uint8_t direction) const {
718   uint32_t delay_min = 0;
719   uint32_t delay_max = UINT32_MAX;
720   uint32_t preferred_delay_min = delay_min;
721   uint32_t preferred_delay_max = delay_max;
722 
723   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
724   log::assert_that(leAudioDevice,
725                    "Shouldn't be called without an active device.");
726 
727   do {
728     struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
729     if (!ase) continue;  // device has no active ASEs in this direction
730 
731     do {
732       /* No common range check */
733       if (ase->qos_preferences.pres_delay_min > delay_max ||
734           ase->qos_preferences.pres_delay_max < delay_min)
735         return false;
736 
737       if (ase->qos_preferences.pres_delay_min > delay_min)
738         delay_min = ase->qos_preferences.pres_delay_min;
739       if (ase->qos_preferences.pres_delay_max < delay_max)
740         delay_max = ase->qos_preferences.pres_delay_max;
741       if (ase->qos_preferences.preferred_pres_delay_min > preferred_delay_min)
742         preferred_delay_min = ase->qos_preferences.preferred_pres_delay_min;
743       if (ase->qos_preferences.preferred_pres_delay_max < preferred_delay_max &&
744           ase->qos_preferences.preferred_pres_delay_max !=
745               types::kPresDelayNoPreference)
746         preferred_delay_max = ase->qos_preferences.preferred_pres_delay_max;
747     } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
748   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
749 
750   if (preferred_delay_min <= preferred_delay_max &&
751       preferred_delay_min > delay_min && preferred_delay_min < delay_max) {
752     *delay = preferred_delay_min;
753   } else {
754     *delay = delay_min;
755   }
756 
757   return true;
758 }
759 
GetRemoteDelay(uint8_t direction) const760 uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) const {
761   uint16_t remote_delay_ms = 0;
762   uint32_t presentation_delay;
763 
764   if (!GetFirstActiveDevice() ||
765       !GetPresentationDelay(&presentation_delay, direction)) {
766     /* This should never happens at stream request time but to be safe return
767      * some sample value to not break streaming
768      */
769     log::error("No active device available. Default value used.");
770     return 100;
771   }
772 
773   /* us to ms */
774   remote_delay_ms = presentation_delay / 1000;
775   remote_delay_ms += GetTransportLatencyUs(direction) / 1000;
776 
777   return remote_delay_ms;
778 }
779 
UpdateAudioContextAvailability(void)780 bool LeAudioDeviceGroup::UpdateAudioContextAvailability(void) {
781   log::debug("{}", group_id_);
782   auto old_contexts = GetAvailableContexts();
783   SetAvailableContexts(GetLatestAvailableContexts());
784   return old_contexts != GetAvailableContexts();
785 }
786 
787 CodecManager::UnicastConfigurationRequirements
GetAudioSetConfigurationRequirements(types::LeAudioContextType ctx_type) const788 LeAudioDeviceGroup::GetAudioSetConfigurationRequirements(
789     types::LeAudioContextType ctx_type) const {
790   auto new_req = CodecManager::UnicastConfigurationRequirements{
791       .audio_context_type = ctx_type,
792   };
793 
794   // Define a requirement for each location. Knowing codec specific
795   // capabilities (i.e. multiplexing capability) the config provider can
796   // determine the number of ASEs to activate.
797   for (auto const& weak_dev_ptr : leAudioDevices_) {
798     auto device = weak_dev_ptr.lock();
799     BidirectionalPair<bool> has_location = {false, false};
800 
801     for (auto direction :
802          {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) {
803       // Do not put any requirements on the Source if Sink only scenario is used
804       // Note: With the RINGTONE we should already prepare for a call.
805       if ((direction == types::kLeAudioDirectionSource) &&
806           ((types::kLeAudioContextAllRemoteSinkOnly.test(ctx_type) &&
807             (ctx_type != types::LeAudioContextType::RINGTONE)) ||
808            ctx_type == types::LeAudioContextType::UNSPECIFIED)) {
809         log::debug("Skipping the remote source requirements.");
810         continue;
811       }
812 
813       if (device->GetAseCount(direction) == 0) {
814         log::warn("Device {} has no ASEs for direction: {}", device->address_,
815                   (int)direction);
816         continue;
817       }
818 
819       auto& dev_locations = (direction == types::kLeAudioDirectionSink)
820                                 ? device->snk_audio_locations_
821                                 : device->src_audio_locations_;
822       if (dev_locations.none()) {
823         log::warn("Device {} has no locations for direction: {}",
824                   device->address_, (int)direction);
825         continue;
826       }
827 
828       has_location.get(direction) = true;
829       auto& direction_req = (direction == types::kLeAudioDirectionSink)
830                                 ? new_req.sink_requirements
831                                 : new_req.source_requirements;
832       if (!direction_req) {
833         direction_req =
834             std::vector<CodecManager::UnicastConfigurationRequirements::
835                             DeviceDirectionRequirements>();
836       }
837 
838       // Pass the audio channel allocation requirement according to TMAP
839       auto locations = dev_locations.to_ulong() &
840                        (codec_spec_conf::kLeAudioLocationFrontLeft |
841                         codec_spec_conf::kLeAudioLocationFrontRight);
842       CodecManager::UnicastConfigurationRequirements::
843           DeviceDirectionRequirements config_req;
844       config_req.params.Add(
845           codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
846           (uint32_t)locations);
847       config_req.target_latency =
848           utils::GetTargetLatencyForAudioContext(ctx_type);
849       log::warn("Device {} pushes requirement, location: {}, direction: {}",
850                 device->address_, (int)locations, (int)direction);
851       direction_req->push_back(std::move(config_req));
852     }
853 
854     // Push sink PACs if there are some sink requirements
855     if (has_location.sink && !device->snk_pacs_.empty()) {
856       if (!new_req.sink_pacs) {
857         new_req.sink_pacs = std::vector<types::acs_ac_record>{};
858       }
859       for (auto const& [_, pac_char] : device->snk_pacs_) {
860         for (auto const& pac_record : pac_char) {
861           new_req.sink_pacs->push_back(pac_record);
862         }
863       }
864     }
865 
866     // Push source PACs if there are some source requirements
867     if (has_location.source && !device->src_pacs_.empty()) {
868       if (!new_req.source_pacs) {
869         new_req.source_pacs = std::vector<types::acs_ac_record>{};
870       }
871       for (auto& [_, pac_char] : device->src_pacs_) {
872         for (auto const& pac_record : pac_char) {
873           new_req.source_pacs->push_back(pac_record);
874         }
875       }
876     }
877   }
878 
879   return new_req;
880 }
881 
UpdateAudioSetConfigurationCache(LeAudioContextType ctx_type) const882 bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache(
883     LeAudioContextType ctx_type) const {
884   auto requirements = GetAudioSetConfigurationRequirements(ctx_type);
885   auto new_conf = CodecManager::GetInstance()->GetCodecConfig(
886       requirements,
887       std::bind(&LeAudioDeviceGroup::FindFirstSupportedConfiguration, this,
888                 std::placeholders::_1, std::placeholders::_2));
889   auto update_config = true;
890 
891   if (context_to_configuration_cache_map.count(ctx_type) != 0) {
892     auto& [is_valid, existing_conf] =
893         context_to_configuration_cache_map.at(ctx_type);
894     update_config = (new_conf.get() != existing_conf.get());
895     /* Just mark it as still valid */
896     if (!update_config && !is_valid) {
897       context_to_configuration_cache_map.at(ctx_type).first = true;
898       return false;
899     }
900   }
901 
902   if (update_config) {
903     log::info("config: {} -> {}", ToHexString(ctx_type),
904               (new_conf ? new_conf->name.c_str() : "(none)"));
905     context_to_configuration_cache_map.erase(ctx_type);
906     if (new_conf)
907       context_to_configuration_cache_map.insert(
908           std::make_pair(ctx_type, std::make_pair(true, std::move(new_conf))));
909   }
910   return update_config;
911 }
912 
InvalidateCachedConfigurations(void)913 void LeAudioDeviceGroup::InvalidateCachedConfigurations(void) {
914   log::info("Group id: {}", group_id_);
915   context_to_configuration_cache_map.clear();
916 }
917 
918 types::BidirectionalPair<AudioContexts>
GetLatestAvailableContexts() const919 LeAudioDeviceGroup::GetLatestAvailableContexts() const {
920   types::BidirectionalPair<AudioContexts> contexts;
921   for (const auto& device : leAudioDevices_) {
922     auto shared_ptr = device.lock();
923     if (shared_ptr &&
924         shared_ptr->GetConnectionState() == DeviceConnectState::CONNECTED) {
925       contexts.sink |=
926           shared_ptr->GetAvailableContexts(types::kLeAudioDirectionSink);
927       contexts.source |=
928           shared_ptr->GetAvailableContexts(types::kLeAudioDirectionSource);
929     }
930   }
931   return contexts;
932 }
933 
ReloadAudioLocations(void)934 bool LeAudioDeviceGroup::ReloadAudioLocations(void) {
935   AudioLocations updated_snk_audio_locations_ =
936       codec_spec_conf::kLeAudioLocationNotAllowed;
937   AudioLocations updated_src_audio_locations_ =
938       codec_spec_conf::kLeAudioLocationNotAllowed;
939 
940   for (const auto& device : leAudioDevices_) {
941     if (device.expired() || (device.lock().get()->GetConnectionState() !=
942                              DeviceConnectState::CONNECTED))
943       continue;
944     updated_snk_audio_locations_ |= device.lock().get()->snk_audio_locations_;
945     updated_src_audio_locations_ |= device.lock().get()->src_audio_locations_;
946   }
947 
948   /* Nothing has changed */
949   if ((updated_snk_audio_locations_ == snk_audio_locations_) &&
950       (updated_src_audio_locations_ == src_audio_locations_))
951     return false;
952 
953   snk_audio_locations_ = updated_snk_audio_locations_;
954   src_audio_locations_ = updated_src_audio_locations_;
955 
956   return true;
957 }
958 
ReloadAudioDirections(void)959 bool LeAudioDeviceGroup::ReloadAudioDirections(void) {
960   uint8_t updated_audio_directions = 0x00;
961 
962   for (const auto& device : leAudioDevices_) {
963     if (device.expired() || (device.lock().get()->GetConnectionState() !=
964                              DeviceConnectState::CONNECTED))
965       continue;
966     updated_audio_directions |= device.lock().get()->audio_directions_;
967   }
968 
969   /* Nothing has changed */
970   if (updated_audio_directions == audio_directions_) return false;
971 
972   audio_directions_ = updated_audio_directions;
973 
974   return true;
975 }
976 
IsInTransition(void) const977 bool LeAudioDeviceGroup::IsInTransition(void) const { return in_transition_; }
978 
IsStreaming(void) const979 bool LeAudioDeviceGroup::IsStreaming(void) const {
980   return current_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
981 }
982 
IsReleasingOrIdle(void) const983 bool LeAudioDeviceGroup::IsReleasingOrIdle(void) const {
984   return (target_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) ||
985          (current_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
986 }
987 
IsGroupStreamReady(void) const988 bool LeAudioDeviceGroup::IsGroupStreamReady(void) const {
989   bool is_device_ready = false;
990 
991   /* All connected devices must be ready */
992   for (auto& weak : leAudioDevices_) {
993     auto dev = weak.lock();
994     if (!dev) return false;
995 
996     /* We are interested here in devices which are connected on profile level
997      * and devices which are configured (meaning, have actived ASE(s))*/
998     if (dev->GetConnectionState() == DeviceConnectState::CONNECTED &&
999         dev->HaveActiveAse()) {
1000       if (!dev->IsReadyToStream()) {
1001         return false;
1002       }
1003       is_device_ready = true;
1004     }
1005   }
1006   return is_device_ready;
1007 }
1008 
HaveAllCisesDisconnected(void) const1009 bool LeAudioDeviceGroup::HaveAllCisesDisconnected(void) const {
1010   for (auto const dev : leAudioDevices_) {
1011     if (dev.expired()) continue;
1012     if (dev.lock().get()->HaveAnyCisConnected()) return false;
1013   }
1014   return true;
1015 }
1016 
GetFirstFreeCisId(CisType cis_type) const1017 uint8_t LeAudioDeviceGroup::CigConfiguration::GetFirstFreeCisId(
1018     CisType cis_type) const {
1019   log::info("Group: {}, group_id: {} cis_type: {}", fmt::ptr(group_),
1020             group_->group_id_, static_cast<int>(cis_type));
1021   for (size_t id = 0; id < cises.size(); id++) {
1022     if (cises[id].addr.IsEmpty() && cises[id].type == cis_type) {
1023       return id;
1024     }
1025   }
1026   return kInvalidCisId;
1027 }
1028 
GetGroupSinkStrategy() const1029 types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupSinkStrategy()
1030     const {
1031   /* Update the strategy if not set yet or was invalidated */
1032   if (!strategy_) {
1033     /* Choose the group configuration strategy based on PAC records */
1034     strategy_ = [this]() {
1035       int expected_group_size = Size();
1036 
1037       /* Simple strategy picker */
1038       log::debug("Group {} size {}", group_id_, expected_group_size);
1039       if (expected_group_size > 1) {
1040         return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
1041       }
1042 
1043       log::debug("audio location 0x{:04x}", snk_audio_locations_.to_ulong());
1044       if (!(snk_audio_locations_.to_ulong() &
1045             codec_spec_conf::kLeAudioLocationAnyLeft) ||
1046           !(snk_audio_locations_.to_ulong() &
1047             codec_spec_conf::kLeAudioLocationAnyRight)) {
1048         return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
1049       }
1050 
1051       auto device = GetFirstDevice();
1052       /* Note: Currently, the audio channel counts LTV is only mandatory for
1053        * LC3. */
1054       auto channel_count_bitmap =
1055           device->GetSupportedAudioChannelCounts(types::kLeAudioDirectionSink);
1056       log::debug("Supported channel counts for group {} (device {}) is {}",
1057                  group_id_, device->address_, channel_count_bitmap);
1058       if (channel_count_bitmap == 1) {
1059         return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE;
1060       }
1061 
1062       return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE;
1063     }();
1064 
1065     log::info(
1066         "Group strategy set to: {}",
1067         [](types::LeAudioConfigurationStrategy strategy) {
1068           switch (strategy) {
1069             case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
1070               return "MONO_ONE_CIS_PER_DEVICE";
1071             case types::LeAudioConfigurationStrategy::
1072                 STEREO_TWO_CISES_PER_DEVICE:
1073               return "STEREO_TWO_CISES_PER_DEVICE";
1074             case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
1075               return "STEREO_ONE_CIS_PER_DEVICE";
1076             default:
1077               return "RFU";
1078           }
1079         }(*strategy_));
1080   }
1081   return *strategy_;
1082 }
1083 
GetAseCount(uint8_t direction) const1084 int LeAudioDeviceGroup::GetAseCount(uint8_t direction) const {
1085   int result = 0;
1086   for (const auto& device_iter : leAudioDevices_) {
1087     result += device_iter.lock()->GetAseCount(direction);
1088   }
1089 
1090   return result;
1091 }
1092 
GenerateCisIds(LeAudioContextType context_type)1093 void LeAudioDeviceGroup::CigConfiguration::GenerateCisIds(
1094     LeAudioContextType context_type) {
1095   log::info("Group {}, group_id: {}, context_type: {}", fmt::ptr(group_),
1096             group_->group_id_, bluetooth::common::ToString(context_type));
1097 
1098   if (cises.size() > 0) {
1099     log::info("CIS IDs already generated");
1100     return;
1101   }
1102 
1103   uint8_t cis_count_bidir = 0;
1104   uint8_t cis_count_unidir_sink = 0;
1105   uint8_t cis_count_unidir_source = 0;
1106   int group_size = group_->DesiredSize();
1107 
1108   set_configurations::get_cis_count(
1109       context_type, group_size, group_->GetGroupSinkStrategy(),
1110       group_->GetAseCount(types::kLeAudioDirectionSink),
1111       group_->GetAseCount(types::kLeAudioDirectionSource), cis_count_bidir,
1112       cis_count_unidir_sink, cis_count_unidir_source);
1113 
1114   uint8_t idx = 0;
1115   while (cis_count_bidir > 0) {
1116     struct bluetooth::le_audio::types::cis cis_entry = {
1117         .id = idx,
1118         .type = CisType::CIS_TYPE_BIDIRECTIONAL,
1119         .conn_handle = 0,
1120         .addr = RawAddress::kEmpty,
1121     };
1122     cises.push_back(cis_entry);
1123     cis_count_bidir--;
1124     idx++;
1125   }
1126 
1127   while (cis_count_unidir_sink > 0) {
1128     struct bluetooth::le_audio::types::cis cis_entry = {
1129         .id = idx,
1130         .type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK,
1131         .conn_handle = 0,
1132         .addr = RawAddress::kEmpty,
1133     };
1134     cises.push_back(cis_entry);
1135     cis_count_unidir_sink--;
1136     idx++;
1137   }
1138 
1139   while (cis_count_unidir_source > 0) {
1140     struct bluetooth::le_audio::types::cis cis_entry = {
1141         .id = idx,
1142         .type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE,
1143         .conn_handle = 0,
1144         .addr = RawAddress::kEmpty,
1145     };
1146     cises.push_back(cis_entry);
1147     cis_count_unidir_source--;
1148     idx++;
1149   }
1150 }
1151 
AssignCisIds(LeAudioDevice * leAudioDevice)1152 bool LeAudioDeviceGroup::CigConfiguration::AssignCisIds(
1153     LeAudioDevice* leAudioDevice) {
1154   log::assert_that(leAudioDevice, "invalid device");
1155   log::info("device: {}", leAudioDevice->address_);
1156 
1157   struct ase* ase = leAudioDevice->GetFirstActiveAse();
1158   if (!ase) {
1159     log::error("Device {} shouldn't be called without an active ASE",
1160                leAudioDevice->address_);
1161     return false;
1162   }
1163 
1164   for (; ase != nullptr; ase = leAudioDevice->GetNextActiveAse(ase)) {
1165     uint8_t cis_id = kInvalidCisId;
1166     /* CIS ID already set */
1167     if (ase->cis_id != kInvalidCisId) {
1168       log::info("ASE ID: {}, is already assigned CIS ID: {}, type {}", ase->id,
1169                 ase->cis_id, cises[ase->cis_id].type);
1170       if (!cises[ase->cis_id].addr.IsEmpty()) {
1171         log::info("Bi-Directional CIS already assigned");
1172         continue;
1173       }
1174       /* Reuse existing CIS ID if available*/
1175       cis_id = ase->cis_id;
1176     }
1177 
1178     /* First check if we have bidirectional ASEs. If so, assign same CIS ID.*/
1179     struct ase* matching_bidir_ase =
1180         leAudioDevice->GetNextActiveAseWithDifferentDirection(ase);
1181 
1182     for (; matching_bidir_ase != nullptr;
1183          matching_bidir_ase = leAudioDevice->GetNextActiveAseWithSameDirection(
1184              matching_bidir_ase)) {
1185       if ((matching_bidir_ase->cis_id != kInvalidCisId) &&
1186           (matching_bidir_ase->cis_id != cis_id)) {
1187         log::info("Bi-Directional CIS is already used. ASE Id: {} cis_id={}",
1188                   matching_bidir_ase->id, matching_bidir_ase->cis_id);
1189         continue;
1190       }
1191       break;
1192     }
1193 
1194     if (matching_bidir_ase) {
1195       if (cis_id == kInvalidCisId) {
1196         cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1197       }
1198 
1199       if (cis_id != kInvalidCisId) {
1200         ase->cis_id = cis_id;
1201         matching_bidir_ase->cis_id = cis_id;
1202         cises[cis_id].addr = leAudioDevice->address_;
1203 
1204         log::info(
1205             "ASE ID: {} and ASE ID: {}, assigned Bi-Directional CIS ID: {}",
1206             ase->id, matching_bidir_ase->id, ase->cis_id);
1207         continue;
1208       }
1209 
1210       log::warn(
1211           "ASE ID: {}, unable to get free Bi-Directional CIS ID but maybe "
1212           "thats fine. Try using unidirectional.",
1213           ase->id);
1214     }
1215 
1216     if (ase->direction == types::kLeAudioDirectionSink) {
1217       if (cis_id == kInvalidCisId) {
1218         cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_UNIDIRECTIONAL_SINK);
1219       }
1220 
1221       if (cis_id == kInvalidCisId) {
1222         log::warn(
1223             "Unable to get free Uni-Directional Sink CIS ID - maybe there is "
1224             "bi-directional available");
1225         /* This could happen when scenarios for given context type allows for
1226          * Sink and Source configuration but also only Sink configuration.
1227          */
1228         cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1229         if (cis_id == kInvalidCisId) {
1230           log::error("Unable to get free Uni-Directional Sink CIS ID");
1231           return false;
1232         }
1233       }
1234 
1235       ase->cis_id = cis_id;
1236       cises[cis_id].addr = leAudioDevice->address_;
1237       log::info("ASE ID: {}, assigned Uni-Directional Sink CIS ID: {}", ase->id,
1238                 ase->cis_id);
1239       continue;
1240     }
1241 
1242     /* Source direction */
1243     log::assert_that(ase->direction == types::kLeAudioDirectionSource,
1244                      "Expected Source direction, actual={}", ase->direction);
1245 
1246     if (cis_id == kInvalidCisId) {
1247       cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE);
1248     }
1249 
1250     if (cis_id == kInvalidCisId) {
1251       /* This could happen when scenarios for given context type allows for
1252        * Sink and Source configuration but also only Sink configuration.
1253        */
1254       log::warn(
1255           "Unable to get free Uni-Directional Source CIS ID - maybe there is "
1256           "bi-directional available");
1257       cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1258       if (cis_id == kInvalidCisId) {
1259         log::error("Unable to get free Uni-Directional Source CIS ID");
1260         return false;
1261       }
1262     }
1263 
1264     ase->cis_id = cis_id;
1265     cises[cis_id].addr = leAudioDevice->address_;
1266     log::info("ASE ID: {}, assigned Uni-Directional Source CIS ID: {}", ase->id,
1267               ase->cis_id);
1268   }
1269 
1270   return true;
1271 }
1272 
AssignCisConnHandles(const std::vector<uint16_t> & conn_handles)1273 void LeAudioDeviceGroup::CigConfiguration::AssignCisConnHandles(
1274     const std::vector<uint16_t>& conn_handles) {
1275   log::info("num of cis handles {}", static_cast<int>(conn_handles.size()));
1276   for (size_t i = 0; i < cises.size(); i++) {
1277     cises[i].conn_handle = conn_handles[i];
1278     log::info("assigning cis[{}] conn_handle: {}", cises[i].id,
1279               cises[i].conn_handle);
1280   }
1281 }
1282 
AssignCisConnHandlesToAses(LeAudioDevice * leAudioDevice)1283 void LeAudioDeviceGroup::AssignCisConnHandlesToAses(
1284     LeAudioDevice* leAudioDevice) {
1285   log::assert_that(leAudioDevice, "Invalid device");
1286   log::info("group: {}, group_id: {}, device: {}", fmt::ptr(this), group_id_,
1287             leAudioDevice->address_);
1288 
1289   /* Assign all CIS connection handles to ases */
1290   struct bluetooth::le_audio::types::ase* ase =
1291       leAudioDevice->GetFirstActiveAseByCisAndDataPathState(
1292           CisState::IDLE, DataPathState::IDLE);
1293   if (!ase) {
1294     log::warn("No active ASE with Cis and Data path state set to IDLE");
1295     return;
1296   }
1297 
1298   for (; ase != nullptr;
1299        ase = leAudioDevice->GetFirstActiveAseByCisAndDataPathState(
1300            CisState::IDLE, DataPathState::IDLE)) {
1301     auto ases_pair = leAudioDevice->GetAsesByCisId(ase->cis_id);
1302 
1303     if (ases_pair.sink && ases_pair.sink->active) {
1304       ases_pair.sink->cis_conn_hdl = cig.cises[ase->cis_id].conn_handle;
1305       ases_pair.sink->cis_state = CisState::ASSIGNED;
1306     }
1307     if (ases_pair.source && ases_pair.source->active) {
1308       ases_pair.source->cis_conn_hdl = cig.cises[ase->cis_id].conn_handle;
1309       ases_pair.source->cis_state = CisState::ASSIGNED;
1310     }
1311   }
1312 }
1313 
AssignCisConnHandlesToAses(void)1314 void LeAudioDeviceGroup::AssignCisConnHandlesToAses(void) {
1315   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
1316   log::assert_that(leAudioDevice,
1317                    "Shouldn't be called without an active device.");
1318 
1319   log::info("Group {}, group_id {}", fmt::ptr(this), group_id_);
1320 
1321   /* Assign all CIS connection handles to ases */
1322   for (; leAudioDevice != nullptr;
1323        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
1324     AssignCisConnHandlesToAses(leAudioDevice);
1325   }
1326 }
1327 
UnassignCis(LeAudioDevice * leAudioDevice)1328 void LeAudioDeviceGroup::CigConfiguration::UnassignCis(
1329     LeAudioDevice* leAudioDevice) {
1330   log::assert_that(leAudioDevice, "Invalid device");
1331 
1332   log::info("Group {}, group_id {}, device: {}", fmt::ptr(group_),
1333             group_->group_id_, leAudioDevice->address_);
1334 
1335   for (struct bluetooth::le_audio::types::cis& cis_entry : cises) {
1336     if (cis_entry.addr == leAudioDevice->address_) {
1337       cis_entry.addr = RawAddress::kEmpty;
1338     }
1339   }
1340 }
1341 
CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,const set_configurations::AseConfiguration & conf,uint8_t direction,const LeAudioDevice & device)1342 bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,
1343                               const set_configurations::AseConfiguration& conf,
1344                               uint8_t direction, const LeAudioDevice& device) {
1345   /* Check direction and if audio location allows to create more cises to a
1346    * single device.
1347    */
1348   types::AudioLocations audio_locations =
1349       (direction == types::kLeAudioDirectionSink) ? device.snk_audio_locations_
1350                                                   : device.src_audio_locations_;
1351 
1352   log::debug("strategy: {}, locations: {}", (int)strategy,
1353              audio_locations.to_ulong());
1354 
1355   switch (strategy) {
1356     case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
1357       return audio_locations.any();
1358     case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
1359       if ((audio_locations.to_ulong() &
1360            codec_spec_conf::kLeAudioLocationAnyLeft) &&
1361           (audio_locations.to_ulong() &
1362            codec_spec_conf::kLeAudioLocationAnyRight))
1363         return true;
1364       else
1365         return false;
1366     case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE: {
1367       if (!(audio_locations.to_ulong() &
1368             codec_spec_conf::kLeAudioLocationAnyLeft) ||
1369           !(audio_locations.to_ulong() &
1370             codec_spec_conf::kLeAudioLocationAnyRight))
1371         return false;
1372 
1373       auto channel_count_mask =
1374           device.GetSupportedAudioChannelCounts(direction);
1375       auto requested_channel_count = conf.codec.GetChannelCountPerIsoStream();
1376       log::debug("Requested channel count: {}, supp. channel counts: 0x{:x}",
1377                  requested_channel_count, channel_count_mask);
1378 
1379       /* Return true if requested channel count is set in the supported channel
1380        * counts. In the channel_count_mask, bit 0 is set when 1 channel is
1381        * supported.
1382        */
1383       return ((1 << (requested_channel_count - 1)) & channel_count_mask);
1384     }
1385     default:
1386       return false;
1387   }
1388 
1389   return false;
1390 }
1391 
1392 /* This method check if group support given audio configuration
1393  * requirement for connected devices in the group and available ASEs
1394  * (no matter on the ASE state) and for given context type
1395  */
IsAudioSetConfigurationSupported(const CodecManager::UnicastConfigurationRequirements & requirements,const set_configurations::AudioSetConfiguration * audio_set_conf) const1396 bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
1397     const CodecManager::UnicastConfigurationRequirements& requirements,
1398     const set_configurations::AudioSetConfiguration* audio_set_conf) const {
1399   /* TODO For now: set ase if matching with first pac.
1400    * 1) We assume as well that devices will match requirements in order
1401    *    e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc.
1402    * 2) ASEs should be active only if best (according to priority list) full
1403    *    scenarion will be covered.
1404    * 3) ASEs should be filled according to performance profile.
1405    */
1406   auto required_snk_strategy = GetGroupSinkStrategy();
1407   bool status = false;
1408   for (auto direction :
1409        {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) {
1410     log::debug("Looking for configuration: {} - {}", audio_set_conf->name,
1411                direction == types::kLeAudioDirectionSink ? "Sink" : "Source");
1412     auto const& ase_confs = audio_set_conf->confs.get(direction);
1413     if (ase_confs.empty()) {
1414       log::debug("No configurations for direction {}, skip it.",
1415                  (int)direction);
1416       continue;
1417     }
1418 
1419     // In some tests we expect the configuration to be there even when the
1420     // contexts are not supported. Then we might want to configure the device
1421     // but use UNSPECIFIED which is always supported (but can be unavailable)
1422     auto device_cnt = NumOfAvailableForDirection(direction);
1423     if (device_cnt == 0) {
1424       device_cnt = DesiredSize();
1425       if (device_cnt == 0) {
1426         log::error("Device count is 0");
1427         continue;
1428       }
1429     }
1430 
1431     auto const ase_cnt = ase_confs.size();
1432     if (ase_cnt == 0) {
1433       log::error("ASE count is 0");
1434       continue;
1435     }
1436 
1437     uint8_t const max_required_ase_per_dev =
1438         ase_cnt / device_cnt + (ase_cnt % device_cnt);
1439 
1440     // Use strategy for the whole group (not only the connected devices)
1441     auto const strategy = utils::GetStrategyForAseConfig(ase_confs, device_cnt);
1442 
1443     log::debug(
1444         "Number of devices: {}, number of ASEs: {},  Max ASE per device: {} "
1445         "config strategy: {}, group strategy: {}",
1446         device_cnt, ase_cnt, max_required_ase_per_dev,
1447         static_cast<int>(strategy), (int)required_snk_strategy);
1448 
1449     if (direction == types::kLeAudioDirectionSink &&
1450         strategy != required_snk_strategy) {
1451       log::debug("Sink strategy mismatch group!=cfg.entry ({}!={})",
1452                  static_cast<int>(required_snk_strategy),
1453                  static_cast<int>(strategy));
1454       return false;
1455     }
1456 
1457     uint8_t required_device_cnt = device_cnt;
1458     uint8_t active_ase_cnt = 0;
1459     for (auto* device = GetFirstDevice();
1460          device != nullptr && required_device_cnt > 0;
1461          device = GetNextDevice(device)) {
1462       if (device->ases_.empty()) {
1463         log::error("Device has no ASEs.");
1464         continue;
1465       }
1466 
1467       int needed_ase_per_dev =
1468           std::min(static_cast<int>(max_required_ase_per_dev),
1469                    static_cast<int>(ase_cnt - active_ase_cnt));
1470 
1471       for (auto const& ent : ase_confs) {
1472         // Verify PACS only if this is transparent LTV format
1473         auto const& pacs = (direction == types::kLeAudioDirectionSink)
1474                                ? device->snk_pacs_
1475                                : device->src_pacs_;
1476         if (utils::IsCodecUsingLtvFormat(ent.codec.id) &&
1477             !utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
1478           log::debug(
1479               "Insufficient PAC for {}",
1480               direction == types::kLeAudioDirectionSink ? "sink" : "source");
1481           continue;
1482         }
1483 
1484         if (!CheckIfStrategySupported(strategy, ent, direction, *device)) {
1485           log::debug("Strategy not supported");
1486           continue;
1487         }
1488         for (auto& ase : device->ases_) {
1489           if (ase.direction != direction) continue;
1490 
1491           active_ase_cnt++;
1492           needed_ase_per_dev--;
1493 
1494           if (needed_ase_per_dev == 0) break;
1495         }
1496       }
1497 
1498       if (needed_ase_per_dev > 0) {
1499         log::debug("Not enough ASEs on the device (needs {} more).",
1500                    needed_ase_per_dev);
1501         return false;
1502       }
1503 
1504       required_device_cnt--;
1505     }
1506 
1507     if (required_device_cnt > 0) {
1508       /* Don't left any active devices if requirements are not met */
1509       log::debug("Could not configure all the devices for direction: {}",
1510                  direction == types::kLeAudioDirectionSink ? "Sink" : "Source");
1511       return false;
1512     }
1513 
1514     // At least one direction can be configured
1515     status = true;
1516   }
1517 
1518   /* when disabling 32k dual mic, for later join case, we need to
1519    * make sure the device is always choosing the config that its
1520    * sampling rate matches with the sampling rate which is used
1521    * when all devices in the group are connected.
1522    */
1523   bool dual_bidirection_swb_supported_ =
1524       CodecManager::GetInstance()->IsDualBiDirSwbSupported();
1525   if (DesiredSize() > 1 &&
1526       CodecManager::GetInstance()->CheckCodecConfigIsBiDirSwb(
1527           *audio_set_conf)) {
1528     if (!dual_bidirection_swb_supported_) {
1529       return false;
1530     }
1531   }
1532 
1533   if (status) {
1534     log::debug("Chosen ASE Configuration for group: {}, configuration: {}",
1535                group_id_, audio_set_conf->name);
1536   } else {
1537     log::error("Could not configure either direction for group {}", group_id_);
1538   }
1539   return status;
1540 }
1541 
1542 /* This method should choose aproperiate ASEs to be active and set a cached
1543  * configuration for codec and qos.
1544  */
ConfigureAses(const set_configurations::AudioSetConfiguration * audio_set_conf,LeAudioContextType context_type,const types::BidirectionalPair<AudioContexts> & metadata_context_types,const types::BidirectionalPair<std::vector<uint8_t>> & ccid_lists)1545 bool LeAudioDeviceGroup::ConfigureAses(
1546     const set_configurations::AudioSetConfiguration* audio_set_conf,
1547     LeAudioContextType context_type,
1548     const types::BidirectionalPair<AudioContexts>& metadata_context_types,
1549     const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists) {
1550   bool reuse_cis_id =
1551       GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
1552 
1553   /* TODO For now: set ase if matching with first pac.
1554    * 1) We assume as well that devices will match requirements in order
1555    *    e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc.
1556    * 2) ASEs should be active only if best (according to priority list) full
1557    *    scenarion will be covered.
1558    * 3) ASEs should be filled according to performance profile.
1559    */
1560 
1561   // WARNING: This may look like the results stored here are unused, but it
1562   //          actually shares the intermediate values between the multiple
1563   //          configuration calls within the configuration loop.
1564   BidirectionalPair<types::AudioLocations> group_audio_locations_memo = {
1565       .sink = 0, .source = 0};
1566 
1567   for (auto direction :
1568        {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) {
1569     auto direction_str =
1570         (direction == types::kLeAudioDirectionSink ? "Sink" : "Source");
1571     log::debug("{}: Looking for requirements: {}", direction_str,
1572                audio_set_conf->name);
1573 
1574     if (audio_set_conf->confs.get(direction).empty()) {
1575       log::warn("No {} configuration available.", direction_str);
1576       continue;
1577     }
1578 
1579     auto const max_required_device_cnt = NumOfAvailableForDirection(direction);
1580     auto required_device_cnt = max_required_device_cnt;
1581     uint8_t active_ase_cnt = 0;
1582 
1583     auto configuration_closure = [&](LeAudioDevice* dev) -> void {
1584       /* For the moment, we configure only connected devices and when it is
1585        * ready to stream i.e. All ASEs are discovered and dev is reported as
1586        * connected
1587        */
1588       if (dev->GetConnectionState() != DeviceConnectState::CONNECTED) {
1589         log::warn("Device {}, in the state {}", dev->address_,
1590                   bluetooth::common::ToString(dev->GetConnectionState()));
1591         return;
1592       }
1593 
1594       if (!dev->ConfigureAses(audio_set_conf, max_required_device_cnt,
1595                               direction, context_type, &active_ase_cnt,
1596                               group_audio_locations_memo.get(direction),
1597                               metadata_context_types.get(direction),
1598                               ccid_lists.get(direction), reuse_cis_id)) {
1599         return;
1600       }
1601 
1602       required_device_cnt--;
1603     };
1604 
1605     // First use the devices claiming proper support
1606     for (auto* device = GetFirstDeviceWithAvailableContext(context_type);
1607          device != nullptr && required_device_cnt > 0;
1608          device = GetNextDeviceWithAvailableContext(device, context_type)) {
1609       configuration_closure(device);
1610     }
1611     // In case some devices do not support this scenario - us them anyway if
1612     // they are required for the scenario - we will not put this context into
1613     // their metadata anyway
1614     if (required_device_cnt > 0) {
1615       for (auto* device = GetFirstDevice();
1616            device != nullptr && required_device_cnt > 0;
1617            device = GetNextDevice(device)) {
1618         configuration_closure(device);
1619       }
1620     }
1621 
1622     if (required_device_cnt > 0) {
1623       /* Don't left any active devices if requirements are not met */
1624       log::error("could not configure all the devices");
1625       Deactivate();
1626       return false;
1627     }
1628   }
1629 
1630   log::info("Choosed ASE Configuration for group: {}, configuration: {}",
1631             group_id_, audio_set_conf->name);
1632 
1633   configuration_context_type_ = context_type;
1634   metadata_context_type_ = metadata_context_types;
1635   return true;
1636 }
1637 
1638 std::shared_ptr<const set_configurations::AudioSetConfiguration>
GetCachedConfiguration(LeAudioContextType context_type) const1639 LeAudioDeviceGroup::GetCachedConfiguration(
1640     LeAudioContextType context_type) const {
1641   if (context_to_configuration_cache_map.count(context_type) != 0) {
1642     return context_to_configuration_cache_map.at(context_type).second;
1643   }
1644   return nullptr;
1645 }
1646 
1647 std::shared_ptr<const set_configurations::AudioSetConfiguration>
GetActiveConfiguration(void) const1648 LeAudioDeviceGroup::GetActiveConfiguration(void) const {
1649   return GetCachedConfiguration(configuration_context_type_);
1650 }
1651 
1652 std::shared_ptr<const set_configurations::AudioSetConfiguration>
GetConfiguration(LeAudioContextType context_type) const1653 LeAudioDeviceGroup::GetConfiguration(LeAudioContextType context_type) const {
1654   if (context_type == LeAudioContextType::UNINITIALIZED) {
1655     return nullptr;
1656   }
1657 
1658   const set_configurations::AudioSetConfiguration* conf = nullptr;
1659   bool is_valid = false;
1660 
1661   /* Refresh the cache if there is no valid configuration */
1662   if (context_to_configuration_cache_map.count(context_type) != 0) {
1663     auto& valid_config_pair =
1664         context_to_configuration_cache_map.at(context_type);
1665     is_valid = valid_config_pair.first;
1666     conf = valid_config_pair.second.get();
1667   }
1668   if (!is_valid || (conf == nullptr)) {
1669     UpdateAudioSetConfigurationCache(context_type);
1670   }
1671 
1672   return GetCachedConfiguration(context_type);
1673 }
1674 
1675 LeAudioCodecConfiguration
GetAudioSessionCodecConfigForDirection(LeAudioContextType context_type,uint8_t direction) const1676 LeAudioDeviceGroup::GetAudioSessionCodecConfigForDirection(
1677     LeAudioContextType context_type, uint8_t direction) const {
1678   const set_configurations::AudioSetConfiguration* conf = nullptr;
1679   bool is_valid = false;
1680 
1681   /* Refresh the cache if there is no valid configuration */
1682   if (context_to_configuration_cache_map.count(context_type) != 0) {
1683     auto& valid_config_pair =
1684         context_to_configuration_cache_map.at(context_type);
1685     is_valid = valid_config_pair.first;
1686     conf = valid_config_pair.second.get();
1687   }
1688   if (!is_valid || (conf == nullptr)) {
1689     UpdateAudioSetConfigurationCache(context_type);
1690   }
1691 
1692   auto audio_set_conf = GetCachedConfiguration(context_type);
1693   if (!audio_set_conf) return {0, 0, 0, 0};
1694 
1695   auto group_config =
1696       utils::GetAudioSessionCodecConfigFromAudioSetConfiguration(
1697           *audio_set_conf.get(), direction);
1698   return group_config;
1699 }
1700 
HasCodecConfigurationForDirection(types::LeAudioContextType context_type,uint8_t direction) const1701 bool LeAudioDeviceGroup::HasCodecConfigurationForDirection(
1702     types::LeAudioContextType context_type, uint8_t direction) const {
1703   auto audio_set_conf = GetConfiguration(context_type);
1704   return audio_set_conf ? !audio_set_conf->confs.get(direction).empty() : false;
1705 }
1706 
IsAudioSetConfigurationAvailable(LeAudioContextType group_context_type)1707 bool LeAudioDeviceGroup::IsAudioSetConfigurationAvailable(
1708     LeAudioContextType group_context_type) {
1709   return GetConfiguration(group_context_type) != nullptr;
1710 }
1711 
IsMetadataChanged(const BidirectionalPair<AudioContexts> & context_types,const BidirectionalPair<std::vector<uint8_t>> & ccid_lists) const1712 bool LeAudioDeviceGroup::IsMetadataChanged(
1713     const BidirectionalPair<AudioContexts>& context_types,
1714     const BidirectionalPair<std::vector<uint8_t>>& ccid_lists) const {
1715   for (auto* leAudioDevice = GetFirstActiveDevice(); leAudioDevice;
1716        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
1717     if (leAudioDevice->IsMetadataChanged(context_types, ccid_lists))
1718       return true;
1719   }
1720 
1721   return false;
1722 }
1723 
IsCisPartOfCurrentStream(uint16_t cis_conn_hdl) const1724 bool LeAudioDeviceGroup::IsCisPartOfCurrentStream(uint16_t cis_conn_hdl) const {
1725   auto& sink_stream_locations = stream_conf.stream_params.sink.stream_locations;
1726   auto iter = std::find_if(
1727       sink_stream_locations.begin(), sink_stream_locations.end(),
1728       [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });
1729 
1730   if (iter != sink_stream_locations.end()) return true;
1731 
1732   auto& source_stream_locations =
1733       stream_conf.stream_params.source.stream_locations;
1734   iter = std::find_if(
1735       source_stream_locations.begin(), source_stream_locations.end(),
1736       [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });
1737 
1738   return (iter != source_stream_locations.end());
1739 }
1740 
RemoveCisFromStreamIfNeeded(LeAudioDevice * leAudioDevice,uint16_t cis_conn_hdl)1741 void LeAudioDeviceGroup::RemoveCisFromStreamIfNeeded(
1742     LeAudioDevice* leAudioDevice, uint16_t cis_conn_hdl) {
1743   log::info("CIS Connection Handle: {}", cis_conn_hdl);
1744 
1745   if (!IsCisPartOfCurrentStream(cis_conn_hdl)) return;
1746 
1747   /* Cache the old values for comparison */
1748   auto old_sink_channels = stream_conf.stream_params.sink.num_of_channels;
1749   auto old_source_channels = stream_conf.stream_params.source.num_of_channels;
1750 
1751   for (auto dir :
1752        {types::kLeAudioDirectionSink, types::kLeAudioDirectionSource}) {
1753     auto& params = stream_conf.stream_params.get(dir);
1754     params.stream_locations.erase(
1755         std::remove_if(
1756             params.stream_locations.begin(), params.stream_locations.end(),
1757             [leAudioDevice, &cis_conn_hdl, &params, dir](auto& pair) {
1758               if (!cis_conn_hdl) {
1759                 cis_conn_hdl = pair.first;
1760               }
1761               auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(cis_conn_hdl);
1762               if (ases_pair.get(dir) && cis_conn_hdl == pair.first) {
1763                 params.num_of_devices--;
1764                 params.num_of_channels -= ases_pair.get(dir)->channel_count;
1765                 params.audio_channel_allocation &= ~pair.second;
1766               }
1767               return (ases_pair.get(dir) && cis_conn_hdl == pair.first);
1768             }),
1769         params.stream_locations.end());
1770   }
1771 
1772   log::info(
1773       "Sink Number Of Devices: {}, Sink Number Of Channels: {}, Source Number "
1774       "Of Devices: {}, Source Number Of Channels: {}",
1775       stream_conf.stream_params.sink.num_of_devices,
1776       stream_conf.stream_params.sink.num_of_channels,
1777       stream_conf.stream_params.source.num_of_devices,
1778       stream_conf.stream_params.source.num_of_channels);
1779 
1780   if (stream_conf.stream_params.sink.num_of_channels == 0) {
1781     ClearSinksFromConfiguration();
1782   }
1783 
1784   if (stream_conf.stream_params.source.num_of_channels == 0) {
1785     ClearSourcesFromConfiguration();
1786   }
1787 
1788   /* Update CodecManager CIS configuration */
1789   if (old_sink_channels > stream_conf.stream_params.sink.num_of_channels) {
1790     CodecManager::GetInstance()->UpdateCisConfiguration(
1791         cig.cises,
1792         stream_conf.stream_params.get(
1793             bluetooth::le_audio::types::kLeAudioDirectionSink),
1794         bluetooth::le_audio::types::kLeAudioDirectionSink);
1795   }
1796   if (old_source_channels > stream_conf.stream_params.source.num_of_channels) {
1797     CodecManager::GetInstance()->UpdateCisConfiguration(
1798         cig.cises,
1799         stream_conf.stream_params.get(
1800             bluetooth::le_audio::types::kLeAudioDirectionSource),
1801         bluetooth::le_audio::types::kLeAudioDirectionSource);
1802   }
1803 
1804   cig.UnassignCis(leAudioDevice);
1805 }
1806 
IsPendingConfiguration(void) const1807 bool LeAudioDeviceGroup::IsPendingConfiguration(void) const {
1808   return stream_conf.pending_configuration;
1809 }
1810 
SetPendingConfiguration(void)1811 void LeAudioDeviceGroup::SetPendingConfiguration(void) {
1812   stream_conf.pending_configuration = true;
1813 }
1814 
ClearPendingConfiguration(void)1815 void LeAudioDeviceGroup::ClearPendingConfiguration(void) {
1816   stream_conf.pending_configuration = false;
1817 }
1818 
Disable(int gatt_if)1819 void LeAudioDeviceGroup::Disable(int gatt_if) {
1820   is_enabled_ = false;
1821 
1822   for (auto& device_iter : leAudioDevices_) {
1823     if (!device_iter.lock()->autoconnect_flag_) {
1824       continue;
1825     }
1826 
1827     auto connection_state = device_iter.lock()->GetConnectionState();
1828     auto address = device_iter.lock()->address_;
1829 
1830     btif_storage_set_leaudio_autoconnect(address, false);
1831     device_iter.lock()->autoconnect_flag_ = false;
1832 
1833     log::info("Group {} in state {}. Removing {} from background connect",
1834               group_id_, bluetooth::common::ToString(GetState()), address);
1835 
1836     BTA_GATTC_CancelOpen(gatt_if, address, false);
1837 
1838     if (connection_state == DeviceConnectState::CONNECTING_AUTOCONNECT) {
1839       device_iter.lock()->SetConnectionState(DeviceConnectState::DISCONNECTED);
1840     }
1841   }
1842 }
1843 
Enable(int gatt_if,tBTM_BLE_CONN_TYPE reconnection_mode)1844 void LeAudioDeviceGroup::Enable(int gatt_if,
1845                                 tBTM_BLE_CONN_TYPE reconnection_mode) {
1846   is_enabled_ = true;
1847   for (auto& device_iter : leAudioDevices_) {
1848     if (device_iter.lock()->autoconnect_flag_) {
1849       continue;
1850     }
1851 
1852     auto address = device_iter.lock()->address_;
1853     auto connection_state = device_iter.lock()->GetConnectionState();
1854 
1855     btif_storage_set_leaudio_autoconnect(address, true);
1856     device_iter.lock()->autoconnect_flag_ = true;
1857 
1858     log::info("Group {} in state {}. Adding {} from background connect",
1859               group_id_, bluetooth::common::ToString(GetState()), address);
1860 
1861     if (connection_state == DeviceConnectState::DISCONNECTED) {
1862       BTA_GATTC_Open(gatt_if, address, reconnection_mode, false);
1863       device_iter.lock()->SetConnectionState(
1864           DeviceConnectState::CONNECTING_AUTOCONNECT);
1865     }
1866   }
1867 }
1868 
IsEnabled(void) const1869 bool LeAudioDeviceGroup::IsEnabled(void) const { return is_enabled_; };
1870 
AddToAllowListNotConnectedGroupMembers(int gatt_if)1871 void LeAudioDeviceGroup::AddToAllowListNotConnectedGroupMembers(int gatt_if) {
1872   for (const auto& device_iter : leAudioDevices_) {
1873     auto connection_state = device_iter.lock()->GetConnectionState();
1874     if (connection_state == DeviceConnectState::CONNECTED ||
1875         connection_state == DeviceConnectState::CONNECTING_BY_USER ||
1876         connection_state ==
1877             DeviceConnectState::CONNECTED_BY_USER_GETTING_READY ||
1878         connection_state ==
1879             DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY) {
1880       continue;
1881     }
1882 
1883     auto address = device_iter.lock()->address_;
1884     log::info("Group {} in state {}. Adding {} to allow list", group_id_,
1885               bluetooth::common::ToString(GetState()), address);
1886 
1887     /* When adding set members to allow list, let use direct connect first.
1888      * When it fails (i.e. device is not advertising), it will go to background
1889      * connect. We are doing that because for background connect, stack is using
1890      * slow scan parameters for connection which might delay connecting
1891      * available members.
1892      */
1893     BTA_GATTC_CancelOpen(gatt_if, address, false);
1894     BTA_GATTC_Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, false);
1895     device_iter.lock()->SetConnectionState(
1896         DeviceConnectState::CONNECTING_AUTOCONNECT);
1897   }
1898 }
1899 
ApplyReconnectionMode(int gatt_if,tBTM_BLE_CONN_TYPE reconnection_mode)1900 void LeAudioDeviceGroup::ApplyReconnectionMode(
1901     int gatt_if, tBTM_BLE_CONN_TYPE reconnection_mode) {
1902   for (const auto& device_iter : leAudioDevices_) {
1903     BTA_GATTC_CancelOpen(gatt_if, device_iter.lock()->address_, false);
1904     BTA_GATTC_Open(gatt_if, device_iter.lock()->address_, reconnection_mode,
1905                    false);
1906     log::info("Group {} in state {}. Adding {} to default reconnection mode",
1907               group_id_, bluetooth::common::ToString(GetState()),
1908               device_iter.lock()->address_);
1909     device_iter.lock()->SetConnectionState(
1910         DeviceConnectState::CONNECTING_AUTOCONNECT);
1911   }
1912 }
1913 
IsConfiguredForContext(LeAudioContextType context_type) const1914 bool LeAudioDeviceGroup::IsConfiguredForContext(
1915     LeAudioContextType context_type) const {
1916   /* Check if all connected group members are configured */
1917   if (GetConfigurationContextType() != context_type) {
1918     return false;
1919   }
1920 
1921   if (!stream_conf.conf) return false;
1922 
1923   /* Check if used configuration is same as the active one.*/
1924   return (stream_conf.conf.get() == GetActiveConfiguration().get());
1925 }
1926 
1927 const set_configurations::AudioSetConfiguration*
FindFirstSupportedConfiguration(const CodecManager::UnicastConfigurationRequirements & requirements,const set_configurations::AudioSetConfigurations * confs) const1928 LeAudioDeviceGroup::FindFirstSupportedConfiguration(
1929     const CodecManager::UnicastConfigurationRequirements& requirements,
1930     const set_configurations::AudioSetConfigurations* confs) const {
1931   log::assert_that(confs != nullptr, "confs should not be null");
1932 
1933   log::debug("context type: {},  number of connected devices: {}",
1934              bluetooth::common::ToString(requirements.audio_context_type),
1935              NumOfConnected());
1936 
1937   /* Filter out device set for each end every scenario */
1938   for (const auto& conf : *confs) {
1939     log::assert_that(conf != nullptr, "confs should not be null");
1940     if (IsAudioSetConfigurationSupported(requirements, conf)) {
1941       log::debug("found: {}", conf->name);
1942       return conf;
1943     }
1944   }
1945 
1946   return nullptr;
1947 }
1948 
1949 /* This method should choose aproperiate ASEs to be active and set a cached
1950  * configuration for codec and qos.
1951  */
Configure(LeAudioContextType context_type,const types::BidirectionalPair<AudioContexts> & metadata_context_types,types::BidirectionalPair<std::vector<uint8_t>> ccid_lists)1952 bool LeAudioDeviceGroup::Configure(
1953     LeAudioContextType context_type,
1954     const types::BidirectionalPair<AudioContexts>& metadata_context_types,
1955     types::BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
1956   auto conf = GetConfiguration(context_type);
1957   if (!conf) {
1958     log::error(
1959         ", requested context type: {} , is in mismatch with cached available "
1960         "contexts",
1961         bluetooth::common::ToString(context_type));
1962     return false;
1963   }
1964 
1965   log::debug("setting context type: {}",
1966              bluetooth::common::ToString(context_type));
1967 
1968   if (!ConfigureAses(conf.get(), context_type, metadata_context_types,
1969                      ccid_lists)) {
1970     log::error(
1971         ", requested context type: {}, is in mismatch with cached available "
1972         "contexts",
1973         bluetooth::common::ToString(context_type));
1974     return false;
1975   }
1976 
1977   /* Store selected configuration at once it is chosen.
1978    * It might happen it will get unavailable in some point of time
1979    */
1980   stream_conf.conf = conf;
1981   return true;
1982 }
1983 
~LeAudioDeviceGroup(void)1984 LeAudioDeviceGroup::~LeAudioDeviceGroup(void) { this->Cleanup(); }
1985 
PrintDebugState(void) const1986 void LeAudioDeviceGroup::PrintDebugState(void) const {
1987   auto active_conf = GetActiveConfiguration();
1988   std::stringstream debug_str;
1989 
1990   debug_str << "\n Groupd id: " << group_id_
1991             << (is_enabled_ ? " enabled" : " disabled")
1992             << ", state: " << bluetooth::common::ToString(GetState())
1993             << ", target state: "
1994             << bluetooth::common::ToString(GetTargetState())
1995             << ", cig state: " << bluetooth::common::ToString(cig.GetState())
1996             << ", \n group supported contexts: "
1997             << bluetooth::common::ToString(GetSupportedContexts())
1998             << ", \n group available contexts: "
1999             << bluetooth::common::ToString(GetAvailableContexts())
2000             << ", \n group allowed contexts: "
2001             << bluetooth::common::ToString(GetAllowedContextMask())
2002             << ", \n configuration context type: "
2003             << bluetooth::common::ToString(GetConfigurationContextType())
2004             << ", \n active configuration name: "
2005             << (active_conf ? active_conf->name : " not set");
2006 
2007   if (cig.cises.size() > 0) {
2008     log::info("\n Allocated CISes: {}", static_cast<int>(cig.cises.size()));
2009     for (auto cis : cig.cises) {
2010       log::info("\n cis id: {}, type: {}, conn_handle {}, addr: {}", cis.id,
2011                 cis.type, cis.conn_handle, cis.addr.ToString());
2012     }
2013   }
2014 
2015   if (GetFirstActiveDevice() != nullptr) {
2016     uint32_t sink_delay = 0;
2017     uint32_t source_delay = 0;
2018     GetPresentationDelay(&sink_delay,
2019                          bluetooth::le_audio::types::kLeAudioDirectionSink);
2020     GetPresentationDelay(&source_delay,
2021                          bluetooth::le_audio::types::kLeAudioDirectionSource);
2022     auto phy_mtos =
2023         GetPhyBitmask(bluetooth::le_audio::types::kLeAudioDirectionSink);
2024     auto phy_stom =
2025         GetPhyBitmask(bluetooth::le_audio::types::kLeAudioDirectionSource);
2026     auto max_transport_latency_mtos = GetMaxTransportLatencyMtos();
2027     auto max_transport_latency_stom = GetMaxTransportLatencyStom();
2028     auto sdu_mts =
2029         GetSduInterval(bluetooth::le_audio::types::kLeAudioDirectionSink);
2030     auto sdu_stom =
2031         GetSduInterval(bluetooth::le_audio::types::kLeAudioDirectionSource);
2032 
2033     debug_str << "\n presentation_delay for sink (speaker): " << +sink_delay
2034               << " us, presentation_delay for source (microphone): "
2035               << +source_delay << "us, \n MtoS transport latency:  "
2036               << +max_transport_latency_mtos
2037               << ", StoM transport latency: " << +max_transport_latency_stom
2038               << ", \n MtoS Phy: " << loghex(phy_mtos)
2039               << ", MtoS sdu: " << loghex(phy_stom)
2040               << " \n MtoS sdu: " << +sdu_mts << ", StoM sdu: " << +sdu_stom;
2041   }
2042 
2043   log::info("{}", debug_str.str());
2044 
2045   for (const auto& device_iter : leAudioDevices_) {
2046     device_iter.lock()->PrintDebugState();
2047   }
2048 }
2049 
Dump(int fd,int active_group_id) const2050 void LeAudioDeviceGroup::Dump(int fd, int active_group_id) const {
2051   bool is_active = (group_id_ == active_group_id);
2052   std::stringstream stream, stream_pacs;
2053   auto active_conf = GetActiveConfiguration();
2054 
2055   stream << "\n    == Group id: " << group_id_
2056          << (is_enabled_ ? " enabled" : " disabled")
2057          << " == " << (is_active ? ",\tActive\n" : ",\tInactive\n")
2058          << "      state: " << GetState()
2059          << ",\ttarget state: " << GetTargetState()
2060          << ",\tcig state: " << cig.GetState() << "\n"
2061          << "      group supported contexts: " << GetSupportedContexts() << "\n"
2062          << "      group available contexts: " << GetAvailableContexts() << "\n"
2063          << "      group allowed contexts: " << GetAllowedContextMask() << "\n"
2064          << "      configuration context type: "
2065          << bluetooth::common::ToString(GetConfigurationContextType()).c_str()
2066          << "\n"
2067          << "      active configuration name: "
2068          << (active_conf ? active_conf->name : " not set") << "\n"
2069          << "      stream configuration: "
2070          << (stream_conf.conf != nullptr ? stream_conf.conf->name : " unknown ")
2071          << "\n"
2072          << "      codec id: " << +(stream_conf.codec_id.coding_format)
2073          << ",\tpending_configuration: " << stream_conf.pending_configuration
2074          << "\n"
2075          << "      num of devices(connected): " << Size() << "("
2076          << NumOfConnected() << ")\n"
2077          << ",     num of sinks(connected): "
2078          << stream_conf.stream_params.sink.num_of_devices << "("
2079          << stream_conf.stream_params.sink.stream_locations.size() << ")\n"
2080          << "      num of sources(connected): "
2081          << stream_conf.stream_params.source.num_of_devices << "("
2082          << stream_conf.stream_params.source.stream_locations.size() << ")\n"
2083          << "      allocated CISes: " << static_cast<int>(cig.cises.size());
2084 
2085   if (cig.cises.size() > 0) {
2086     stream << "\n\t == CISes == ";
2087     for (auto cis : cig.cises) {
2088       stream << "\n\t cis id: " << static_cast<int>(cis.id)
2089              << ",\ttype: " << static_cast<int>(cis.type)
2090              << ",\tconn_handle: " << static_cast<int>(cis.conn_handle)
2091              << ",\taddr: " << ADDRESS_TO_LOGGABLE_STR(cis.addr);
2092     }
2093     stream << "\n\t ====";
2094   }
2095 
2096   if (GetFirstActiveDevice() != nullptr) {
2097     uint32_t sink_delay;
2098     if (GetPresentationDelay(
2099             &sink_delay, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
2100       stream << "\n      presentation_delay for sink (speaker): " << sink_delay
2101              << " us";
2102     }
2103 
2104     uint32_t source_delay;
2105     if (GetPresentationDelay(
2106             &source_delay,
2107             bluetooth::le_audio::types::kLeAudioDirectionSource)) {
2108       stream << "\n      presentation_delay for source (microphone): "
2109              << source_delay << " us";
2110     }
2111   }
2112 
2113   stream << "\n      == devices: ==";
2114 
2115   dprintf(fd, "%s", stream.str().c_str());
2116 
2117   for (const auto& device_iter : leAudioDevices_) {
2118     device_iter.lock()->Dump(fd);
2119   }
2120 
2121   for (const auto& device_iter : leAudioDevices_) {
2122     auto device = device_iter.lock();
2123     stream_pacs << "\n\taddress: " << device->address_;
2124     device->DumpPacsDebugState(stream_pacs);
2125   }
2126   dprintf(fd, "%s", stream_pacs.str().c_str());
2127 }
2128 
Add(int group_id)2129 LeAudioDeviceGroup* LeAudioDeviceGroups::Add(int group_id) {
2130   /* Get first free group id */
2131   if (FindById(group_id)) {
2132     log::error("group already exists, id: 0x{:x}", group_id);
2133     return nullptr;
2134   }
2135 
2136   return (groups_.emplace_back(std::make_unique<LeAudioDeviceGroup>(group_id)))
2137       .get();
2138 }
2139 
Remove(int group_id)2140 void LeAudioDeviceGroups::Remove(int group_id) {
2141   auto iter = std::find_if(
2142       groups_.begin(), groups_.end(),
2143       [&group_id](auto const& group) { return group->group_id_ == group_id; });
2144 
2145   if (iter == groups_.end()) {
2146     log::error("no such group_id: {}", group_id);
2147     return;
2148   }
2149 
2150   groups_.erase(iter);
2151 }
2152 
FindById(int group_id) const2153 LeAudioDeviceGroup* LeAudioDeviceGroups::FindById(int group_id) const {
2154   auto iter = std::find_if(
2155       groups_.begin(), groups_.end(),
2156       [&group_id](auto const& group) { return group->group_id_ == group_id; });
2157 
2158   return (iter == groups_.end()) ? nullptr : iter->get();
2159 }
2160 
Cleanup(void)2161 void LeAudioDeviceGroups::Cleanup(void) {
2162   for (auto& g : groups_) {
2163     g->Cleanup();
2164   }
2165 
2166   groups_.clear();
2167 }
2168 
Dump(int fd,int active_group_id) const2169 void LeAudioDeviceGroups::Dump(int fd, int active_group_id) const {
2170   /* Dump first active group */
2171   for (auto& g : groups_) {
2172     if (g->group_id_ == active_group_id) {
2173       g->Dump(fd, active_group_id);
2174       break;
2175     }
2176   }
2177 
2178   /* Dump non active group */
2179   for (auto& g : groups_) {
2180     if (g->group_id_ != active_group_id) {
2181       g->Dump(fd, active_group_id);
2182     }
2183   }
2184 }
2185 
IsAnyInTransition(void) const2186 bool LeAudioDeviceGroups::IsAnyInTransition(void) const {
2187   for (auto& g : groups_) {
2188     if (g->IsInTransition()) {
2189       log::debug("group: {} is in transition", g->group_id_);
2190       return true;
2191     }
2192   }
2193   return false;
2194 }
2195 
Size() const2196 size_t LeAudioDeviceGroups::Size() const { return (groups_.size()); }
2197 
GetGroupsIds(void) const2198 std::vector<int> LeAudioDeviceGroups::GetGroupsIds(void) const {
2199   std::vector<int> result;
2200 
2201   for (auto const& group : groups_) {
2202     result.push_back(group->group_id_);
2203   }
2204 
2205   return result;
2206 }
2207 
2208 }  // namespace bluetooth::le_audio
2209