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