• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA
3  * - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "devices.h"
19 
20 #include <base/strings/string_number_conversions.h>
21 
22 #include <map>
23 
24 #include "audio_hal_client/audio_hal_client.h"
25 #include "bta_csis_api.h"
26 #include "bta_gatt_queue.h"
27 #include "bta_groups.h"
28 #include "bta_le_audio_api.h"
29 #include "btif_storage.h"
30 #include "btm_iso_api.h"
31 #include "btm_iso_api_types.h"
32 #include "device/include/controller.h"
33 #include "gd/common/strings.h"
34 #include "le_audio_set_configuration_provider.h"
35 #include "metrics_collector.h"
36 #include "osi/include/log.h"
37 #include "stack/include/acl_api.h"
38 
39 using bluetooth::hci::kIsoCigFramingFramed;
40 using bluetooth::hci::kIsoCigFramingUnframed;
41 using bluetooth::hci::kIsoCigPackingSequential;
42 using bluetooth::hci::kIsoCigPhy1M;
43 using bluetooth::hci::kIsoCigPhy2M;
44 using bluetooth::hci::iso_manager::kIsoSca0To20Ppm;
45 using le_audio::AudioSetConfigurationProvider;
46 using le_audio::DeviceConnectState;
47 using le_audio::set_configurations::CodecCapabilitySetting;
48 using le_audio::types::ase;
49 using le_audio::types::AseState;
50 using le_audio::types::AudioContexts;
51 using le_audio::types::AudioLocations;
52 using le_audio::types::AudioStreamDataPathState;
53 using le_audio::types::BidirectAsesPair;
54 using le_audio::types::CisType;
55 using le_audio::types::LeAudioCodecId;
56 using le_audio::types::LeAudioContextType;
57 using le_audio::types::LeAudioLc3Config;
58 
59 namespace le_audio {
operator <<(std::ostream & os,const DeviceConnectState & state)60 std::ostream& operator<<(std::ostream& os, const DeviceConnectState& state) {
61   const char* char_value_ = "UNKNOWN";
62 
63   switch (state) {
64     case DeviceConnectState::CONNECTED:
65       char_value_ = "CONNECTED";
66       break;
67     case DeviceConnectState::DISCONNECTED:
68       char_value_ = "DISCONNECTED";
69       break;
70     case DeviceConnectState::REMOVING:
71       char_value_ = "REMOVING";
72       break;
73     case DeviceConnectState::DISCONNECTING:
74       char_value_ = "DISCONNECTING";
75       break;
76     case DeviceConnectState::PENDING_REMOVAL:
77       char_value_ = "PENDING_REMOVAL";
78       break;
79     case DeviceConnectState::CONNECTING_BY_USER:
80       char_value_ = "CONNECTING_BY_USER";
81       break;
82     case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
83       char_value_ = "CONNECTED_BY_USER_GETTING_READY";
84       break;
85     case DeviceConnectState::CONNECTING_AUTOCONNECT:
86       char_value_ = "CONNECTING_AUTOCONNECT";
87       break;
88     case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
89       char_value_ = "CONNECTED_AUTOCONNECT_GETTING_READY";
90       break;
91   }
92 
93   os << char_value_ << " ("
94      << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
95      << ")";
96   return os;
97 }
98 
99 /* LeAudioDeviceGroup Class methods implementation */
AddNode(const std::shared_ptr<LeAudioDevice> & leAudioDevice)100 void LeAudioDeviceGroup::AddNode(
101     const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
102   leAudioDevice->group_id_ = group_id_;
103   leAudioDevices_.push_back(std::weak_ptr<LeAudioDevice>(leAudioDevice));
104   MetricsCollector::Get()->OnGroupSizeUpdate(group_id_, leAudioDevices_.size());
105 }
106 
RemoveNode(const std::shared_ptr<LeAudioDevice> & leAudioDevice)107 void LeAudioDeviceGroup::RemoveNode(
108     const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
109   /* Group information cleaning in the device. */
110   leAudioDevice->group_id_ = bluetooth::groups::kGroupUnknown;
111   for (auto ase : leAudioDevice->ases_) {
112     ase.active = false;
113     ase.cis_conn_hdl = 0;
114   }
115 
116   leAudioDevices_.erase(
117       std::remove_if(
118           leAudioDevices_.begin(), leAudioDevices_.end(),
119           [&leAudioDevice](auto& d) { return d.lock() == leAudioDevice; }),
120       leAudioDevices_.end());
121   MetricsCollector::Get()->OnGroupSizeUpdate(group_id_, leAudioDevices_.size());
122 }
123 
IsEmpty(void)124 bool LeAudioDeviceGroup::IsEmpty(void) { return leAudioDevices_.size() == 0; }
125 
IsAnyDeviceConnected(void)126 bool LeAudioDeviceGroup::IsAnyDeviceConnected(void) {
127   return (NumOfConnected() != 0);
128 }
129 
Size(void)130 int LeAudioDeviceGroup::Size(void) { return leAudioDevices_.size(); }
131 
NumOfConnected(types::LeAudioContextType context_type)132 int LeAudioDeviceGroup::NumOfConnected(types::LeAudioContextType context_type) {
133   if (leAudioDevices_.empty()) return 0;
134 
135   bool check_context_type = (context_type != LeAudioContextType::RFU);
136   AudioContexts type_set(context_type);
137 
138   /* return number of connected devices from the set*/
139   return std::count_if(
140       leAudioDevices_.begin(), leAudioDevices_.end(),
141       [type_set, check_context_type](auto& iter) {
142         if (iter.expired()) return false;
143         if (iter.lock()->conn_id_ == GATT_INVALID_CONN_ID) return false;
144 
145         if (!check_context_type) return true;
146 
147         return iter.lock()->GetAvailableContexts().test_any(type_set);
148       });
149 }
150 
ClearSinksFromConfiguration(void)151 void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
152   LOG_INFO("Group %p, group_id %d", this, group_id_);
153   stream_conf.sink_streams.clear();
154   stream_conf.sink_offloader_streams_target_allocation.clear();
155   stream_conf.sink_offloader_streams_current_allocation.clear();
156   stream_conf.sink_audio_channel_allocation = 0;
157   stream_conf.sink_num_of_channels = 0;
158   stream_conf.sink_num_of_devices = 0;
159   stream_conf.sink_sample_frequency_hz = 0;
160   stream_conf.sink_codec_frames_blocks_per_sdu = 0;
161   stream_conf.sink_octets_per_codec_frame = 0;
162   stream_conf.sink_frame_duration_us = 0;
163 }
164 
ClearSourcesFromConfiguration(void)165 void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
166   LOG_INFO("Group %p, group_id %d", this, group_id_);
167   stream_conf.source_streams.clear();
168   stream_conf.source_offloader_streams_target_allocation.clear();
169   stream_conf.source_offloader_streams_current_allocation.clear();
170   stream_conf.source_audio_channel_allocation = 0;
171   stream_conf.source_num_of_channels = 0;
172   stream_conf.source_num_of_devices = 0;
173   stream_conf.source_sample_frequency_hz = 0;
174   stream_conf.source_codec_frames_blocks_per_sdu = 0;
175   stream_conf.source_octets_per_codec_frame = 0;
176   stream_conf.source_frame_duration_us = 0;
177 }
178 
CigClearCis(void)179 void LeAudioDeviceGroup::CigClearCis(void) {
180   LOG_INFO("group_id: %d", group_id_);
181   cises_.clear();
182   ClearSinksFromConfiguration();
183   ClearSourcesFromConfiguration();
184 }
185 
Cleanup(void)186 void LeAudioDeviceGroup::Cleanup(void) {
187   /* Bluetooth is off while streaming - disconnect CISes and remove CIG */
188   if (GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
189     if (!stream_conf.sink_streams.empty()) {
190       for (auto [cis_handle, audio_location] : stream_conf.sink_streams) {
191         bluetooth::hci::IsoManager::GetInstance()->DisconnectCis(
192             cis_handle, HCI_ERR_PEER_USER);
193 
194         if (stream_conf.source_streams.empty()) {
195           continue;
196         }
197         uint16_t cis_hdl = cis_handle;
198         stream_conf.source_streams.erase(
199             std::remove_if(
200                 stream_conf.source_streams.begin(),
201                 stream_conf.source_streams.end(),
202                 [cis_hdl](auto& pair) { return pair.first == cis_hdl; }),
203             stream_conf.source_streams.end());
204       }
205     }
206 
207     if (!stream_conf.source_streams.empty()) {
208       for (auto [cis_handle, audio_location] : stream_conf.source_streams) {
209         bluetooth::hci::IsoManager::GetInstance()->DisconnectCis(
210             cis_handle, HCI_ERR_PEER_USER);
211       }
212     }
213   }
214 
215   /* Note: CIG will stay in the controller. We cannot remove it here, because
216    * Cises are not yet disconnected.
217    * When user start Bluetooth, HCI Reset should remove it
218    */
219 
220   leAudioDevices_.clear();
221   this->CigClearCis();
222 }
223 
Deactivate(void)224 void LeAudioDeviceGroup::Deactivate(void) {
225   for (auto* leAudioDevice = GetFirstActiveDevice(); leAudioDevice;
226        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
227     for (auto* ase = leAudioDevice->GetFirstActiveAse(); ase;
228          ase = leAudioDevice->GetNextActiveAse(ase)) {
229       ase->active = false;
230     }
231   }
232 }
233 
GetCigState(void)234 le_audio::types::CigState LeAudioDeviceGroup::GetCigState(void) {
235   return cig_state_;
236 }
237 
SetCigState(le_audio::types::CigState state)238 void LeAudioDeviceGroup::SetCigState(le_audio::types::CigState state) {
239   LOG_VERBOSE("%s -> %s", bluetooth::common::ToString(cig_state_).c_str(),
240               bluetooth::common::ToString(state).c_str());
241   cig_state_ = state;
242 }
243 
Activate(LeAudioContextType context_type)244 bool LeAudioDeviceGroup::Activate(LeAudioContextType context_type) {
245   bool is_activate = false;
246   for (auto leAudioDevice : leAudioDevices_) {
247     if (leAudioDevice.expired()) continue;
248 
249     bool activated = leAudioDevice.lock()->ActivateConfiguredAses(context_type);
250     LOG_INFO("Device %s is %s",
251              leAudioDevice.lock().get()->address_.ToString().c_str(),
252              activated ? "activated" : " not activated");
253     if (activated) {
254       if (!CigAssignCisIds(leAudioDevice.lock().get())) {
255         return false;
256       }
257       is_activate = true;
258     }
259   }
260   return is_activate;
261 }
262 
GetFirstDevice(void)263 LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) {
264   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
265                            [](auto& iter) { return !iter.expired(); });
266 
267   if (iter == leAudioDevices_.end()) return nullptr;
268 
269   return (iter->lock()).get();
270 }
271 
GetFirstDeviceWithActiveContext(types::LeAudioContextType context_type)272 LeAudioDevice* LeAudioDeviceGroup::GetFirstDeviceWithActiveContext(
273     types::LeAudioContextType context_type) {
274   auto iter = std::find_if(
275       leAudioDevices_.begin(), leAudioDevices_.end(),
276       [&context_type](auto& iter) {
277         if (iter.expired()) return false;
278         return iter.lock()->GetAvailableContexts().test(context_type);
279       });
280 
281   if ((iter == leAudioDevices_.end()) || (iter->expired())) return nullptr;
282 
283   return (iter->lock()).get();
284 }
285 
GetNextDevice(LeAudioDevice * leAudioDevice)286 LeAudioDevice* LeAudioDeviceGroup::GetNextDevice(LeAudioDevice* leAudioDevice) {
287   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
288                            [&leAudioDevice](auto& d) {
289                              if (d.expired())
290                                return false;
291                              else
292                                return (d.lock()).get() == leAudioDevice;
293                            });
294 
295   /* If reference device not found */
296   if (iter == leAudioDevices_.end()) return nullptr;
297 
298   std::advance(iter, 1);
299   /* If reference device is last in group */
300   if (iter == leAudioDevices_.end()) return nullptr;
301 
302   if (iter->expired()) return nullptr;
303 
304   return (iter->lock()).get();
305 }
306 
GetNextDeviceWithActiveContext(LeAudioDevice * leAudioDevice,types::LeAudioContextType context_type)307 LeAudioDevice* LeAudioDeviceGroup::GetNextDeviceWithActiveContext(
308     LeAudioDevice* leAudioDevice, types::LeAudioContextType context_type) {
309   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
310                            [&leAudioDevice](auto& d) {
311                              if (d.expired())
312                                return false;
313                              else
314                                return (d.lock()).get() == leAudioDevice;
315                            });
316 
317   /* If reference device not found */
318   if (iter == leAudioDevices_.end()) return nullptr;
319 
320   std::advance(iter, 1);
321   /* If reference device is last in group */
322   if (iter == leAudioDevices_.end()) return nullptr;
323 
324   iter = std::find_if(iter, leAudioDevices_.end(), [&context_type](auto& d) {
325     if (d.expired())
326       return false;
327     else
328       return d.lock()->GetAvailableContexts().test(context_type);
329     ;
330   });
331 
332   return (iter == leAudioDevices_.end()) ? nullptr : (iter->lock()).get();
333 }
334 
IsDeviceInTheGroup(LeAudioDevice * leAudioDevice)335 bool LeAudioDeviceGroup::IsDeviceInTheGroup(LeAudioDevice* leAudioDevice) {
336   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
337                            [&leAudioDevice](auto& d) {
338                              if (d.expired())
339                                return false;
340                              else
341                                return (d.lock()).get() == leAudioDevice;
342                            });
343 
344   if ((iter == leAudioDevices_.end()) || (iter->expired())) return false;
345 
346   return true;
347 }
348 
HaveAllActiveDevicesAsesTheSameState(AseState state)349 bool LeAudioDeviceGroup::HaveAllActiveDevicesAsesTheSameState(AseState state) {
350   auto iter = std::find_if(
351       leAudioDevices_.begin(), leAudioDevices_.end(), [&state](auto& d) {
352         if (d.expired())
353           return false;
354         else
355           return !(((d.lock()).get())->HaveAllActiveAsesSameState(state));
356       });
357 
358   return iter == leAudioDevices_.end();
359 }
360 
GetFirstActiveDevice(void)361 LeAudioDevice* LeAudioDeviceGroup::GetFirstActiveDevice(void) {
362   auto iter =
363       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
364         if (d.expired())
365           return false;
366         else
367           return ((d.lock()).get())->HaveActiveAse();
368       });
369 
370   if (iter == leAudioDevices_.end() || iter->expired()) return nullptr;
371 
372   return (iter->lock()).get();
373 }
374 
GetNextActiveDevice(LeAudioDevice * leAudioDevice)375 LeAudioDevice* LeAudioDeviceGroup::GetNextActiveDevice(
376     LeAudioDevice* leAudioDevice) {
377   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
378                            [&leAudioDevice](auto& d) {
379                              if (d.expired())
380                                return false;
381                              else
382                                return (d.lock()).get() == leAudioDevice;
383                            });
384 
385   if (iter == leAudioDevices_.end() ||
386       std::distance(iter, leAudioDevices_.end()) < 1)
387     return nullptr;
388 
389   iter = std::find_if(std::next(iter, 1), leAudioDevices_.end(), [](auto& d) {
390     if (d.expired())
391       return false;
392     else
393       return ((d.lock()).get())->HaveActiveAse();
394   });
395 
396   return (iter == leAudioDevices_.end()) ? nullptr : (iter->lock()).get();
397 }
398 
GetFirstActiveDeviceByDataPathState(AudioStreamDataPathState data_path_state)399 LeAudioDevice* LeAudioDeviceGroup::GetFirstActiveDeviceByDataPathState(
400     AudioStreamDataPathState data_path_state) {
401   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
402                            [&data_path_state](auto& d) {
403                              if (d.expired()) {
404                                return false;
405                              }
406 
407                              return (((d.lock()).get())
408                                          ->GetFirstActiveAseByDataPathState(
409                                              data_path_state) != nullptr);
410                            });
411 
412   if (iter == leAudioDevices_.end()) {
413     return nullptr;
414   }
415 
416   return iter->lock().get();
417 }
418 
GetNextActiveDeviceByDataPathState(LeAudioDevice * leAudioDevice,AudioStreamDataPathState data_path_state)419 LeAudioDevice* LeAudioDeviceGroup::GetNextActiveDeviceByDataPathState(
420     LeAudioDevice* leAudioDevice, AudioStreamDataPathState data_path_state) {
421   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
422                            [&leAudioDevice](auto& d) {
423                              if (d.expired()) {
424                                return false;
425                              }
426 
427                              return d.lock().get() == leAudioDevice;
428                            });
429 
430   if (std::distance(iter, leAudioDevices_.end()) < 1) {
431     return nullptr;
432   }
433 
434   iter = std::find_if(
435       std::next(iter, 1), leAudioDevices_.end(), [&data_path_state](auto& d) {
436         if (d.expired()) {
437           return false;
438         }
439 
440         return (((d.lock()).get())
441                     ->GetFirstActiveAseByDataPathState(data_path_state) !=
442                 nullptr);
443       });
444 
445   if (iter == leAudioDevices_.end()) {
446     return nullptr;
447   }
448 
449   return iter->lock().get();
450 }
451 
GetSduInterval(uint8_t direction)452 uint32_t LeAudioDeviceGroup::GetSduInterval(uint8_t direction) {
453   for (LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
454        leAudioDevice != nullptr;
455        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
456     struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
457     if (!ase) continue;
458 
459     return ase->codec_config.GetFrameDurationUs();
460   }
461 
462   return 0;
463 }
464 
GetSCA(void)465 uint8_t LeAudioDeviceGroup::GetSCA(void) {
466   uint8_t sca = kIsoSca0To20Ppm;
467 
468   for (const auto& leAudioDevice : leAudioDevices_) {
469     uint8_t dev_sca =
470         BTM_GetPeerSCA(leAudioDevice.lock()->address_, BT_TRANSPORT_LE);
471 
472     /* If we could not read SCA from the peer device or sca is 0,
473      * then there is no reason to continue.
474      */
475     if ((dev_sca == 0xFF) || (dev_sca == 0)) return 0;
476 
477     /* The Slaves_Clock_Accuracy parameter shall be the worst-case sleep clock
478      *accuracy of all the slaves that will participate in the CIG.
479      */
480     if (dev_sca < sca) {
481       sca = dev_sca;
482     }
483   }
484 
485   return sca;
486 }
487 
GetPacking(void)488 uint8_t LeAudioDeviceGroup::GetPacking(void) {
489   /* TODO: Decide about packing */
490   return kIsoCigPackingSequential;
491 }
492 
GetFraming(void)493 uint8_t LeAudioDeviceGroup::GetFraming(void) {
494   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
495   LOG_ASSERT(leAudioDevice)
496       << __func__ << " Shouldn't be called without an active device.";
497 
498   do {
499     struct ase* ase = leAudioDevice->GetFirstActiveAse();
500     if (!ase) continue;
501 
502     do {
503       if (ase->framing == types::kFramingUnframedPduUnsupported)
504         return kIsoCigFramingFramed;
505     } while ((ase = leAudioDevice->GetNextActiveAse(ase)));
506   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
507 
508   return kIsoCigFramingUnframed;
509 }
510 
511 /* TODO: Preferred parameter may be other than minimum */
find_max_transport_latency(LeAudioDeviceGroup * group,uint8_t direction)512 static uint16_t find_max_transport_latency(LeAudioDeviceGroup* group,
513                                            uint8_t direction) {
514   uint16_t max_transport_latency = 0;
515 
516   for (LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice();
517        leAudioDevice != nullptr;
518        leAudioDevice = group->GetNextActiveDevice(leAudioDevice)) {
519     for (ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
520          ase != nullptr;
521          ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)) {
522       if (!ase) break;
523 
524       if (!max_transport_latency)
525         // first assignment
526         max_transport_latency = ase->max_transport_latency;
527       else if (ase->max_transport_latency < max_transport_latency)
528         max_transport_latency = ase->max_transport_latency;
529     }
530   }
531 
532   if (max_transport_latency < types::kMaxTransportLatencyMin)
533     max_transport_latency = types::kMaxTransportLatencyMin;
534   else if (max_transport_latency > types::kMaxTransportLatencyMax)
535     max_transport_latency = types::kMaxTransportLatencyMax;
536 
537   return max_transport_latency;
538 }
539 
GetMaxTransportLatencyStom(void)540 uint16_t LeAudioDeviceGroup::GetMaxTransportLatencyStom(void) {
541   return find_max_transport_latency(this, types::kLeAudioDirectionSource);
542 }
543 
GetMaxTransportLatencyMtos(void)544 uint16_t LeAudioDeviceGroup::GetMaxTransportLatencyMtos(void) {
545   return find_max_transport_latency(this, types::kLeAudioDirectionSink);
546 }
547 
GetTransportLatencyUs(uint8_t direction)548 uint32_t LeAudioDeviceGroup::GetTransportLatencyUs(uint8_t direction) {
549   if (direction == types::kLeAudioDirectionSink) {
550     return transport_latency_mtos_us_;
551   } else if (direction == types::kLeAudioDirectionSource) {
552     return transport_latency_stom_us_ ;
553   } else {
554     LOG(ERROR) << __func__ << ", invalid direction";
555     return 0;
556   }
557 }
558 
SetTransportLatency(uint8_t direction,uint32_t new_transport_latency_us)559 void LeAudioDeviceGroup::SetTransportLatency(uint8_t direction,
560                                              uint32_t new_transport_latency_us) {
561   uint32_t* transport_latency_us;
562 
563   if (direction == types::kLeAudioDirectionSink) {
564     transport_latency_us = &transport_latency_mtos_us_;
565   } else if (direction == types::kLeAudioDirectionSource) {
566     transport_latency_us = &transport_latency_stom_us_;
567   } else {
568     LOG(ERROR) << __func__ << ", invalid direction";
569     return;
570   }
571 
572   if (*transport_latency_us == new_transport_latency_us) return;
573 
574   if ((*transport_latency_us != 0) &&
575       (*transport_latency_us != new_transport_latency_us)) {
576     LOG(WARNING) << __func__ << ", Different transport latency for group: "
577                  << " old: " << static_cast<int>(*transport_latency_us)
578                  << " [us], new: " << static_cast<int>(new_transport_latency_us)
579                  << " [us]";
580     return;
581   }
582 
583   LOG(INFO) << __func__ << ", updated group " << static_cast<int>(group_id_)
584             << " transport latency: " << static_cast<int>(new_transport_latency_us)
585             << " [us]";
586   *transport_latency_us = new_transport_latency_us;
587 }
588 
GetRtn(uint8_t direction,uint8_t cis_id)589 uint8_t LeAudioDeviceGroup::GetRtn(uint8_t direction, uint8_t cis_id) {
590   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
591   LOG_ASSERT(leAudioDevice)
592       << __func__ << " Shouldn't be called without an active device.";
593 
594   do {
595     auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);
596 
597     if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
598       return ases_pair.sink->retrans_nb;
599     } else if (ases_pair.source &&
600                direction == types::kLeAudioDirectionSource) {
601       return ases_pair.source->retrans_nb;
602     }
603   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
604 
605   return 0;
606 }
607 
GetMaxSduSize(uint8_t direction,uint8_t cis_id)608 uint16_t LeAudioDeviceGroup::GetMaxSduSize(uint8_t direction, uint8_t cis_id) {
609   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
610   LOG_ASSERT(leAudioDevice)
611       << __func__ << " Shouldn't be called without an active device.";
612 
613   do {
614     auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);
615 
616     if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
617       return ases_pair.sink->max_sdu_size;
618     } else if (ases_pair.source &&
619                direction == types::kLeAudioDirectionSource) {
620       return ases_pair.source->max_sdu_size;
621     }
622   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
623 
624   return 0;
625 }
626 
GetPhyBitmask(uint8_t direction)627 uint8_t LeAudioDeviceGroup::GetPhyBitmask(uint8_t direction) {
628   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
629   LOG_ASSERT(leAudioDevice)
630       << __func__ << " Shouldn't be called without an active device.";
631 
632   // local supported PHY's
633   uint8_t phy_bitfield = kIsoCigPhy1M;
634   if (controller_get_interface()->supports_ble_2m_phy())
635     phy_bitfield |= kIsoCigPhy2M;
636 
637   if (!leAudioDevice) {
638     LOG(ERROR) << "No active leaudio device for direction?: " << +direction;
639     return phy_bitfield;
640   }
641 
642   do {
643     struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
644     if (!ase) return phy_bitfield;
645 
646     do {
647       if (direction == ase->direction) {
648         phy_bitfield &= leAudioDevice->GetPhyBitmask();
649 
650         // A value of 0x00 denotes no preference
651         if (ase->preferred_phy && (phy_bitfield & ase->preferred_phy)) {
652           phy_bitfield &= ase->preferred_phy;
653           LOG_DEBUG("Using ASE preferred phy 0x%02x",
654                     static_cast<int>(phy_bitfield));
655         } else {
656           LOG_WARN(
657               "ASE preferred 0x%02x has nothing common with phy_bitfield "
658               "0x%02x ",
659               static_cast<int>(ase->preferred_phy),
660               static_cast<int>(phy_bitfield));
661         }
662       }
663     } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
664   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
665 
666   return phy_bitfield;
667 }
668 
GetTargetPhy(uint8_t direction)669 uint8_t LeAudioDeviceGroup::GetTargetPhy(uint8_t direction) {
670   uint8_t phy_bitfield = GetPhyBitmask(direction);
671 
672   // prefer to use 2M if supported
673   if (phy_bitfield & kIsoCigPhy2M)
674     return types::kTargetPhy2M;
675   else if (phy_bitfield & kIsoCigPhy1M)
676     return types::kTargetPhy1M;
677   else
678     return 0;
679 }
680 
GetPresentationDelay(uint32_t * delay,uint8_t direction)681 bool LeAudioDeviceGroup::GetPresentationDelay(uint32_t* delay,
682                                               uint8_t direction) {
683   uint32_t delay_min = 0;
684   uint32_t delay_max = UINT32_MAX;
685   uint32_t preferred_delay_min = delay_min;
686   uint32_t preferred_delay_max = delay_max;
687 
688   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
689   LOG_ASSERT(leAudioDevice)
690       << __func__ << " Shouldn't be called without an active device.";
691 
692   do {
693     struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
694     if (!ase) continue;  // device has no active ASEs in this direction
695 
696     do {
697       /* No common range check */
698       if (ase->pres_delay_min > delay_max || ase->pres_delay_max < delay_min)
699         return false;
700 
701       if (ase->pres_delay_min > delay_min) delay_min = ase->pres_delay_min;
702       if (ase->pres_delay_max < delay_max) delay_max = ase->pres_delay_max;
703       if (ase->preferred_pres_delay_min > preferred_delay_min)
704         preferred_delay_min = ase->preferred_pres_delay_min;
705       if (ase->preferred_pres_delay_max < preferred_delay_max &&
706           ase->preferred_pres_delay_max != types::kPresDelayNoPreference)
707         preferred_delay_max = ase->preferred_pres_delay_max;
708     } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
709   } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
710 
711   if (preferred_delay_min <= preferred_delay_max &&
712       preferred_delay_min > delay_min && preferred_delay_min < delay_max) {
713     *delay = preferred_delay_min;
714   } else {
715     *delay = delay_min;
716   }
717 
718   return true;
719 }
720 
GetRemoteDelay(uint8_t direction)721 uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) {
722   uint16_t remote_delay_ms = 0;
723   uint32_t presentation_delay;
724 
725   if (!GetPresentationDelay(&presentation_delay, direction)) {
726     /* This should never happens at stream request time but to be safe return
727      * some sample value to not break streaming
728      */
729     return 100;
730   }
731 
732   /* us to ms */
733   remote_delay_ms = presentation_delay / 1000;
734   remote_delay_ms += GetTransportLatencyUs(direction) / 1000;
735 
736   return remote_delay_ms;
737 }
738 
UpdateAudioContextTypeAvailability(void)739 void LeAudioDeviceGroup::UpdateAudioContextTypeAvailability(void) {
740   LOG_DEBUG(" group id: %d, available contexts: %s", group_id_,
741             group_available_contexts_.to_string().c_str());
742   UpdateAudioContextTypeAvailability(group_available_contexts_);
743 }
744 
745 /* Returns true if support for any type in the whole group has changed,
746  * otherwise false. */
UpdateAudioContextTypeAvailability(AudioContexts update_contexts)747 bool LeAudioDeviceGroup::UpdateAudioContextTypeAvailability(
748     AudioContexts update_contexts) {
749   auto new_contexts = AudioContexts();
750   bool active_contexts_has_been_modified = false;
751 
752   if (update_contexts.none()) {
753     LOG_DEBUG("No context updated");
754     return false;
755   }
756 
757   LOG_DEBUG("Updated context: %s", update_contexts.to_string().c_str());
758 
759   for (LeAudioContextType ctx_type : types::kLeAudioContextAllTypesArray) {
760     LOG_DEBUG("Checking context: %s", ToHexString(ctx_type).c_str());
761 
762     if (!update_contexts.test(ctx_type)) {
763       LOG_DEBUG("Configuration not in updated context");
764       /* Fill context bitset for possible returned value if updated */
765       if (available_context_to_configuration_map.count(ctx_type) > 0)
766         new_contexts.set(ctx_type);
767 
768       continue;
769     }
770 
771     auto new_conf = FindFirstSupportedConfiguration(ctx_type);
772 
773     bool ctx_previously_not_supported =
774         (available_context_to_configuration_map.count(ctx_type) == 0 ||
775          available_context_to_configuration_map[ctx_type] == nullptr);
776     /* Check if support for context type has changed */
777     if (ctx_previously_not_supported) {
778       /* Current configuration for context type is empty */
779       if (new_conf == nullptr) {
780         /* Configuration remains empty */
781         continue;
782       } else {
783         /* Configuration changes from empty to some */
784         new_contexts.set(ctx_type);
785         active_contexts_has_been_modified = true;
786       }
787     } else {
788       /* Current configuration for context type is not empty */
789       if (new_conf == nullptr) {
790         /* Configuration changed to empty */
791         new_contexts.unset(ctx_type);
792         active_contexts_has_been_modified = true;
793       } else if (new_conf != available_context_to_configuration_map[ctx_type]) {
794         /* Configuration changed to any other */
795         new_contexts.set(ctx_type);
796         active_contexts_has_been_modified = true;
797       } else {
798         /* Configuration is the same */
799         new_contexts.set(ctx_type);
800         continue;
801       }
802     }
803 
804     LOG_INFO(
805         "updated context: %s, %s -> %s", ToHexString(ctx_type).c_str(),
806         (ctx_previously_not_supported
807              ? "empty"
808              : available_context_to_configuration_map[ctx_type]->name.c_str()),
809         (new_conf != nullptr ? new_conf->name.c_str() : "empty"));
810 
811     available_context_to_configuration_map[ctx_type] = new_conf;
812   }
813 
814   /* Some contexts have changed, return new available context bitset */
815   if (active_contexts_has_been_modified) {
816     group_available_contexts_ = new_contexts;
817   }
818 
819   return active_contexts_has_been_modified;
820 }
821 
ReloadAudioLocations(void)822 bool LeAudioDeviceGroup::ReloadAudioLocations(void) {
823   AudioLocations updated_snk_audio_locations_ =
824       codec_spec_conf::kLeAudioLocationNotAllowed;
825   AudioLocations updated_src_audio_locations_ =
826       codec_spec_conf::kLeAudioLocationNotAllowed;
827 
828   for (const auto& device : leAudioDevices_) {
829     if (device.expired() || (device.lock().get()->GetConnectionState() !=
830                              DeviceConnectState::CONNECTED))
831       continue;
832     updated_snk_audio_locations_ |= device.lock().get()->snk_audio_locations_;
833     updated_src_audio_locations_ |= device.lock().get()->src_audio_locations_;
834   }
835 
836   /* Nothing has changed */
837   if ((updated_snk_audio_locations_ == snk_audio_locations_) &&
838       (updated_src_audio_locations_ == src_audio_locations_))
839     return false;
840 
841   snk_audio_locations_ = updated_snk_audio_locations_;
842   src_audio_locations_ = updated_src_audio_locations_;
843 
844   return true;
845 }
846 
ReloadAudioDirections(void)847 bool LeAudioDeviceGroup::ReloadAudioDirections(void) {
848   uint8_t updated_audio_directions = 0x00;
849 
850   for (const auto& device : leAudioDevices_) {
851     if (device.expired() || (device.lock().get()->GetConnectionState() !=
852                              DeviceConnectState::CONNECTED))
853       continue;
854     updated_audio_directions |= device.lock().get()->audio_directions_;
855   }
856 
857   /* Nothing has changed */
858   if (updated_audio_directions == audio_directions_) return false;
859 
860   audio_directions_ = updated_audio_directions;
861 
862   return true;
863 }
864 
IsInTransition(void)865 bool LeAudioDeviceGroup::IsInTransition(void) {
866   return target_state_ != current_state_;
867 }
868 
IsReleasingOrIdle(void)869 bool LeAudioDeviceGroup::IsReleasingOrIdle(void) {
870   return (target_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) ||
871          (current_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
872 }
873 
IsGroupStreamReady(void)874 bool LeAudioDeviceGroup::IsGroupStreamReady(void) {
875   auto iter =
876       std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
877         if (d.expired())
878           return false;
879         else
880           return !(((d.lock()).get())->HaveAllActiveAsesCisEst());
881       });
882 
883   return iter == leAudioDevices_.end();
884 }
885 
HaveAllCisesDisconnected(void)886 bool LeAudioDeviceGroup::HaveAllCisesDisconnected(void) {
887   for (auto const dev : leAudioDevices_) {
888     if (dev.expired()) continue;
889     if (dev.lock().get()->HaveAnyCisConnected()) return false;
890   }
891   return true;
892 }
893 
GetFirstFreeCisId(void)894 uint8_t LeAudioDeviceGroup::GetFirstFreeCisId(void) {
895   for (uint8_t id = 0; id < UINT8_MAX; id++) {
896     auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
897                              [id](auto& d) {
898                                if (d.expired())
899                                  return false;
900                                else
901                                  return ((d.lock()).get())->HasCisId(id);
902                              });
903 
904     if (iter == leAudioDevices_.end()) return id;
905   }
906 
907   return kInvalidCisId;
908 }
909 
GetFirstFreeCisId(CisType cis_type)910 uint8_t LeAudioDeviceGroup::GetFirstFreeCisId(CisType cis_type) {
911   LOG_DEBUG("Group: %p, group_id: %d cis_type: %d", this, group_id_,
912             static_cast<int>(cis_type));
913   for (size_t id = 0; id < cises_.size(); id++) {
914     if (cises_[id].addr.IsEmpty() && cises_[id].type == cis_type) {
915       return id;
916     }
917   }
918   return kInvalidCisId;
919 }
920 
GetGroupStrategy(void)921 types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupStrategy(void) {
922   /* Simple strategy picker */
923   LOG_INFO(" Group %d size %d", group_id_, Size());
924   if (Size() > 1) {
925     return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
926   }
927 
928   LOG_INFO("audio location 0x%04lx", snk_audio_locations_.to_ulong());
929   if (!(snk_audio_locations_.to_ulong() &
930         codec_spec_conf::kLeAudioLocationAnyLeft) ||
931       !(snk_audio_locations_.to_ulong() &
932         codec_spec_conf::kLeAudioLocationAnyRight)) {
933     return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
934   }
935 
936   auto device = GetFirstDevice();
937   auto channel_cnt =
938       device->GetLc3SupportedChannelCount(types::kLeAudioDirectionSink);
939   LOG_INFO("Channel count for group %d is %d (device %s)", group_id_,
940            channel_cnt, device->address_.ToString().c_str());
941   if (channel_cnt == 1) {
942     return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE;
943   }
944 
945   return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE;
946 }
947 
GetAseCount(uint8_t direction)948 int LeAudioDeviceGroup::GetAseCount(uint8_t direction) {
949   int result = 0;
950   for (const auto& device_iter : leAudioDevices_) {
951     result += device_iter.lock()->GetAseCount(direction);
952   }
953 
954   return result;
955 }
956 
CigGenerateCisIds(types::LeAudioContextType context_type)957 void LeAudioDeviceGroup::CigGenerateCisIds(
958     types::LeAudioContextType context_type) {
959   LOG_INFO("Group %p, group_id: %d, context_type: %s", this, group_id_,
960            bluetooth::common::ToString(context_type).c_str());
961 
962   if (cises_.size() > 0) {
963     LOG_INFO("CIS IDs already generated");
964     return;
965   }
966 
967   const set_configurations::AudioSetConfigurations* confs =
968       AudioSetConfigurationProvider::Get()->GetConfigurations(context_type);
969 
970   uint8_t cis_count_bidir = 0;
971   uint8_t cis_count_unidir_sink = 0;
972   uint8_t cis_count_unidir_source = 0;
973   int csis_group_size =
974       bluetooth::csis::CsisClient::Get()->GetDesiredSize(group_id_);
975   /* If this is CSIS group, the csis_group_size will be > 0, otherwise -1.
976    * If the last happen it means, group size is 1 */
977   int group_size = csis_group_size > 0 ? csis_group_size : 1;
978 
979   get_cis_count(*confs, group_size, GetGroupStrategy(),
980                 GetAseCount(types::kLeAudioDirectionSink),
981                 GetAseCount(types::kLeAudioDirectionSource), cis_count_bidir,
982                 cis_count_unidir_sink, cis_count_unidir_source);
983 
984   uint8_t idx = 0;
985   while (cis_count_bidir > 0) {
986     struct le_audio::types::cis cis_entry = {
987         .id = idx,
988         .addr = RawAddress::kEmpty,
989         .type = CisType::CIS_TYPE_BIDIRECTIONAL,
990         .conn_handle = 0,
991     };
992     cises_.push_back(cis_entry);
993     cis_count_bidir--;
994     idx++;
995   }
996 
997   while (cis_count_unidir_sink > 0) {
998     struct le_audio::types::cis cis_entry = {
999         .id = idx,
1000         .addr = RawAddress::kEmpty,
1001         .type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK,
1002         .conn_handle = 0,
1003     };
1004     cises_.push_back(cis_entry);
1005     cis_count_unidir_sink--;
1006     idx++;
1007   }
1008 
1009   while (cis_count_unidir_source > 0) {
1010     struct le_audio::types::cis cis_entry = {
1011         .id = idx,
1012         .addr = RawAddress::kEmpty,
1013         .type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE,
1014         .conn_handle = 0,
1015     };
1016     cises_.push_back(cis_entry);
1017     cis_count_unidir_source--;
1018     idx++;
1019   }
1020 }
1021 
CigAssignCisIds(LeAudioDevice * leAudioDevice)1022 bool LeAudioDeviceGroup::CigAssignCisIds(LeAudioDevice* leAudioDevice) {
1023   ASSERT_LOG(leAudioDevice, "invalid device");
1024   LOG_INFO("device: %s", leAudioDevice->address_.ToString().c_str());
1025 
1026   struct ase* ase = leAudioDevice->GetFirstActiveAse();
1027   if (!ase) {
1028     LOG_ERROR(" Device %s shouldn't be called without an active ASE",
1029               leAudioDevice->address_.ToString().c_str());
1030     return false;
1031   }
1032 
1033   for (; ase != nullptr; ase = leAudioDevice->GetNextActiveAse(ase)) {
1034     uint8_t cis_id = kInvalidCisId;
1035     /* CIS ID already set */
1036     if (ase->cis_id != kInvalidCisId) {
1037       LOG_INFO("ASE ID: %d, is already assigned CIS ID: %d, type %d", ase->id,
1038                ase->cis_id, cises_[ase->cis_id].type);
1039       if (!cises_[ase->cis_id].addr.IsEmpty()) {
1040         LOG_INFO("Bidirectional ASE already assigned");
1041         continue;
1042       }
1043       /* Reuse existing CIS ID if available*/
1044       cis_id = ase->cis_id;
1045     }
1046 
1047     /* First check if we have bidirectional ASEs. If so, assign same CIS ID.*/
1048     struct ase* matching_bidir_ase =
1049         leAudioDevice->GetNextActiveAseWithDifferentDirection(ase);
1050 
1051     if (matching_bidir_ase) {
1052       if (cis_id == kInvalidCisId) {
1053         cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1054       }
1055 
1056       if (cis_id != kInvalidCisId) {
1057         ase->cis_id = cis_id;
1058         matching_bidir_ase->cis_id = cis_id;
1059         cises_[cis_id].addr = leAudioDevice->address_;
1060 
1061         LOG_INFO(
1062             " ASE ID: %d and ASE ID: %d, assigned Bi-Directional CIS ID: %d",
1063             +ase->id, +matching_bidir_ase->id, +ase->cis_id);
1064         continue;
1065       }
1066 
1067       LOG_WARN(
1068           " ASE ID: %d, unable to get free Bi-Directional CIS ID but maybe "
1069           "thats fine. Try using unidirectional.",
1070           ase->id);
1071     }
1072 
1073     if (ase->direction == types::kLeAudioDirectionSink) {
1074       if (cis_id == kInvalidCisId) {
1075         cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_UNIDIRECTIONAL_SINK);
1076       }
1077 
1078       if (cis_id == kInvalidCisId) {
1079         LOG_WARN(
1080             " Unable to get free Uni-Directional Sink CIS ID - maybe there is "
1081             "bi-directional available");
1082         /* This could happen when scenarios for given context type allows for
1083          * Sink and Source configuration but also only Sink configuration.
1084          */
1085         cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1086         if (cis_id == kInvalidCisId) {
1087           LOG_ERROR("Unable to get free Uni-Directional Sink CIS ID");
1088           return false;
1089         }
1090       }
1091 
1092       ase->cis_id = cis_id;
1093       cises_[cis_id].addr = leAudioDevice->address_;
1094       LOG_INFO("ASE ID: %d, assigned Uni-Directional Sink CIS ID: %d", ase->id,
1095                ase->cis_id);
1096       continue;
1097     }
1098 
1099     /* Source direction */
1100     ASSERT_LOG(ase->direction == types::kLeAudioDirectionSource,
1101                "Expected Source direction, actual=%d", ase->direction);
1102 
1103     if (cis_id == kInvalidCisId) {
1104       cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE);
1105     }
1106 
1107     if (cis_id == kInvalidCisId) {
1108       /* This could happen when scenarios for given context type allows for
1109        * Sink and Source configuration but also only Sink configuration.
1110        */
1111       LOG_WARN(
1112           "Unable to get free Uni-Directional Source CIS ID - maybe there "
1113           "is bi-directional available");
1114       cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1115       if (cis_id == kInvalidCisId) {
1116         LOG_ERROR("Unable to get free Uni-Directional Source CIS ID");
1117         return false;
1118       }
1119     }
1120 
1121     ase->cis_id = cis_id;
1122     cises_[cis_id].addr = leAudioDevice->address_;
1123     LOG_INFO("ASE ID: %d, assigned Uni-Directional Source CIS ID: %d", ase->id,
1124              ase->cis_id);
1125   }
1126 
1127   return true;
1128 }
1129 
CigAssignCisConnHandles(const std::vector<uint16_t> & conn_handles)1130 void LeAudioDeviceGroup::CigAssignCisConnHandles(
1131     const std::vector<uint16_t>& conn_handles) {
1132   LOG_INFO("num of cis handles %d", static_cast<int>(conn_handles.size()));
1133   for (size_t i = 0; i < cises_.size(); i++) {
1134     cises_[i].conn_handle = conn_handles[i];
1135     LOG_INFO("assigning cis[%d] conn_handle: %d", cises_[i].id,
1136              cises_[i].conn_handle);
1137   }
1138 }
1139 
CigAssignCisConnHandlesToAses(LeAudioDevice * leAudioDevice)1140 void LeAudioDeviceGroup::CigAssignCisConnHandlesToAses(
1141     LeAudioDevice* leAudioDevice) {
1142   ASSERT_LOG(leAudioDevice, "Invalid device");
1143   LOG_INFO("group: %p, group_id: %d, device: %s", this, group_id_,
1144            leAudioDevice->address_.ToString().c_str());
1145 
1146   /* Assign all CIS connection handles to ases */
1147   struct le_audio::types::ase* ase =
1148       leAudioDevice->GetFirstActiveAseByDataPathState(
1149           AudioStreamDataPathState::IDLE);
1150   if (!ase) {
1151     LOG_WARN("No active ASE with AudioStreamDataPathState IDLE");
1152     return;
1153   }
1154 
1155   for (; ase != nullptr; ase = leAudioDevice->GetFirstActiveAseByDataPathState(
1156                              AudioStreamDataPathState::IDLE)) {
1157     auto ases_pair = leAudioDevice->GetAsesByCisId(ase->cis_id);
1158 
1159     if (ases_pair.sink && ases_pair.sink->active) {
1160       ases_pair.sink->cis_conn_hdl = cises_[ase->cis_id].conn_handle;
1161       ases_pair.sink->data_path_state = AudioStreamDataPathState::CIS_ASSIGNED;
1162     }
1163     if (ases_pair.source && ases_pair.source->active) {
1164       ases_pair.source->cis_conn_hdl = cises_[ase->cis_id].conn_handle;
1165       ases_pair.source->data_path_state =
1166           AudioStreamDataPathState::CIS_ASSIGNED;
1167     }
1168   }
1169 }
1170 
CigAssignCisConnHandlesToAses(void)1171 void LeAudioDeviceGroup::CigAssignCisConnHandlesToAses(void) {
1172   LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
1173   ASSERT_LOG(leAudioDevice, "Shouldn't be called without an active device.");
1174 
1175   LOG_INFO("Group %p, group_id %d", this, group_id_);
1176 
1177   /* Assign all CIS connection handles to ases */
1178   for (; leAudioDevice != nullptr;
1179        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
1180     CigAssignCisConnHandlesToAses(leAudioDevice);
1181   }
1182 }
1183 
CigUnassignCis(LeAudioDevice * leAudioDevice)1184 void LeAudioDeviceGroup::CigUnassignCis(LeAudioDevice* leAudioDevice) {
1185   ASSERT_LOG(leAudioDevice, "Invalid device");
1186 
1187   LOG_INFO("Group %p, group_id %d, device: %s", this, group_id_,
1188            leAudioDevice->address_.ToString().c_str());
1189 
1190   for (struct le_audio::types::cis& cis_entry : cises_) {
1191     if (cis_entry.addr == leAudioDevice->address_) {
1192       cis_entry.addr = RawAddress::kEmpty;
1193     }
1194   }
1195 }
1196 
CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,types::AudioLocations audio_locations,uint8_t requested_channel_count,uint8_t channel_count_mask)1197 bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,
1198                               types::AudioLocations audio_locations,
1199                               uint8_t requested_channel_count,
1200                               uint8_t channel_count_mask) {
1201   DLOG(INFO) << __func__ << " strategy: " << (int)strategy
1202              << " locations: " << +audio_locations.to_ulong();
1203 
1204   switch (strategy) {
1205     case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
1206       return audio_locations.any();
1207     case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
1208       if ((audio_locations.to_ulong() &
1209            codec_spec_conf::kLeAudioLocationAnyLeft) &&
1210           (audio_locations.to_ulong() &
1211            codec_spec_conf::kLeAudioLocationAnyRight))
1212         return true;
1213       else
1214         return false;
1215     case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
1216       if (!(audio_locations.to_ulong() &
1217             codec_spec_conf::kLeAudioLocationAnyLeft) ||
1218           !(audio_locations.to_ulong() &
1219             codec_spec_conf::kLeAudioLocationAnyRight))
1220         return false;
1221 
1222       DLOG(INFO) << __func__ << " requested chan cnt "
1223                  << +requested_channel_count
1224                  << " chan mask: " << loghex(channel_count_mask);
1225 
1226       /* Return true if requested channel count is set in the channel count
1227        * mask. In the channel_count_mask, bit0 is set when 1 channel is
1228        * supported.
1229        */
1230       return ((1 << (requested_channel_count - 1)) & channel_count_mask);
1231     default:
1232       return false;
1233   }
1234 
1235   return false;
1236 }
1237 
1238 /* This method check if group support given audio configuration
1239  * requirement for connected devices in the group and available ASEs
1240  * (no matter on the ASE state) and for given context type
1241  */
IsConfigurationSupported(const set_configurations::AudioSetConfiguration * audio_set_conf,types::LeAudioContextType context_type)1242 bool LeAudioDeviceGroup::IsConfigurationSupported(
1243     const set_configurations::AudioSetConfiguration* audio_set_conf,
1244     types::LeAudioContextType context_type) {
1245   if (!set_configurations::check_if_may_cover_scenario(
1246           audio_set_conf, NumOfConnected(context_type))) {
1247     LOG_DEBUG(" cannot cover scenario  %s: size of for context type %d",
1248               bluetooth::common::ToString(context_type).c_str(),
1249               +NumOfConnected(context_type));
1250     return false;
1251   }
1252 
1253   auto required_snk_strategy = GetGroupStrategy();
1254 
1255   /* TODO For now: set ase if matching with first pac.
1256    * 1) We assume as well that devices will match requirements in order
1257    *    e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc.
1258    * 2) ASEs should be active only if best (according to priority list) full
1259    *    scenarion will be covered.
1260    * 3) ASEs should be filled according to performance profile.
1261    */
1262   for (const auto& ent : (*audio_set_conf).confs) {
1263     LOG_DEBUG(" Looking for configuration: %s - %s",
1264               audio_set_conf->name.c_str(),
1265               (ent.direction == types::kLeAudioDirectionSink ? "snk" : "src"));
1266 
1267     uint8_t required_device_cnt = ent.device_cnt;
1268     uint8_t max_required_ase_per_dev =
1269         ent.ase_cnt / ent.device_cnt + (ent.ase_cnt % ent.device_cnt);
1270     uint8_t active_ase_num = 0;
1271     auto strategy = ent.strategy;
1272 
1273     LOG_DEBUG(
1274         " Number of devices: %d, number of ASEs: %d,  Max ASE per device: %d "
1275         "strategy: %d",
1276         +required_device_cnt, +ent.ase_cnt, +max_required_ase_per_dev,
1277         static_cast<int>(strategy));
1278 
1279     if (ent.direction == types::kLeAudioDirectionSink &&
1280         strategy != required_snk_strategy) {
1281       LOG_INFO(" Sink strategy mismatch group!=cfg.entry (%d!=%d)",
1282                static_cast<int>(required_snk_strategy),
1283                static_cast<int>(strategy));
1284       return false;
1285     }
1286 
1287     for (auto* device = GetFirstDeviceWithActiveContext(context_type);
1288          device != nullptr && required_device_cnt > 0;
1289          device = GetNextDeviceWithActiveContext(device, context_type)) {
1290       /* Skip if device has ASE configured in this direction already */
1291 
1292       if (device->ases_.empty()) continue;
1293 
1294       if (!device->GetCodecConfigurationSupportedPac(ent.direction, ent.codec))
1295         continue;
1296 
1297       int needed_ase = std::min(static_cast<int>(max_required_ase_per_dev),
1298                                 static_cast<int>(ent.ase_cnt - active_ase_num));
1299 
1300       /* If we required more ASEs per device which means we would like to
1301        * create more CISes to one device, we should also check the allocation
1302        * if it allows us to do this.
1303        */
1304 
1305       types::AudioLocations audio_locations = 0;
1306       /* Check direction and if audio location allows to create more cise */
1307       if (ent.direction == types::kLeAudioDirectionSink)
1308         audio_locations = device->snk_audio_locations_;
1309       else
1310         audio_locations = device->src_audio_locations_;
1311 
1312       /* TODO Make it no Lc3 specific */
1313       if (!CheckIfStrategySupported(
1314               strategy, audio_locations,
1315               std::get<LeAudioLc3Config>(ent.codec.config).GetChannelCount(),
1316               device->GetLc3SupportedChannelCount(ent.direction))) {
1317         LOG_DEBUG(" insufficient device audio allocation: %lu",
1318                   audio_locations.to_ulong());
1319         continue;
1320       }
1321 
1322       for (auto& ase : device->ases_) {
1323         if (ase.direction != ent.direction) continue;
1324 
1325         active_ase_num++;
1326         needed_ase--;
1327 
1328         if (needed_ase == 0) break;
1329       }
1330 
1331       if (needed_ase > 0) {
1332         LOG_DEBUG("Device has too less ASEs. Still needed ases %d", needed_ase);
1333         return false;
1334       }
1335 
1336       required_device_cnt--;
1337     }
1338 
1339     if (required_device_cnt > 0) {
1340       /* Don't left any active devices if requirements are not met */
1341       LOG_DEBUG(" could not configure all the devices");
1342       return false;
1343     }
1344   }
1345 
1346   LOG_DEBUG("Chosen ASE Configuration for group: %d, configuration: %s",
1347             this->group_id_, audio_set_conf->name.c_str());
1348   return true;
1349 }
1350 
GetFirstLeft(const types::AudioLocations & audio_locations)1351 static uint32_t GetFirstLeft(const types::AudioLocations& audio_locations) {
1352   uint32_t audio_location_ulong = audio_locations.to_ulong();
1353 
1354   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeft)
1355     return codec_spec_conf::kLeAudioLocationFrontLeft;
1356 
1357   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackLeft)
1358     return codec_spec_conf::kLeAudioLocationBackLeft;
1359 
1360   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftOfCenter)
1361     return codec_spec_conf::kLeAudioLocationFrontLeftOfCenter;
1362 
1363   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideLeft)
1364     return codec_spec_conf::kLeAudioLocationSideLeft;
1365 
1366   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontLeft)
1367     return codec_spec_conf::kLeAudioLocationTopFrontLeft;
1368 
1369   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackLeft)
1370     return codec_spec_conf::kLeAudioLocationTopBackLeft;
1371 
1372   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideLeft)
1373     return codec_spec_conf::kLeAudioLocationTopSideLeft;
1374 
1375   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontLeft)
1376     return codec_spec_conf::kLeAudioLocationBottomFrontLeft;
1377 
1378   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftWide)
1379     return codec_spec_conf::kLeAudioLocationFrontLeftWide;
1380 
1381   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationLeftSurround)
1382     return codec_spec_conf::kLeAudioLocationLeftSurround;
1383 
1384   return 0;
1385 }
1386 
GetFirstRight(const types::AudioLocations & audio_locations)1387 static uint32_t GetFirstRight(const types::AudioLocations& audio_locations) {
1388   uint32_t audio_location_ulong = audio_locations.to_ulong();
1389 
1390   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRight)
1391     return codec_spec_conf::kLeAudioLocationFrontRight;
1392 
1393   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackRight)
1394     return codec_spec_conf::kLeAudioLocationBackRight;
1395 
1396   if (audio_location_ulong &
1397       codec_spec_conf::kLeAudioLocationFrontRightOfCenter)
1398     return codec_spec_conf::kLeAudioLocationFrontRightOfCenter;
1399 
1400   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideRight)
1401     return codec_spec_conf::kLeAudioLocationSideRight;
1402 
1403   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontRight)
1404     return codec_spec_conf::kLeAudioLocationTopFrontRight;
1405 
1406   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackRight)
1407     return codec_spec_conf::kLeAudioLocationTopBackRight;
1408 
1409   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideRight)
1410     return codec_spec_conf::kLeAudioLocationTopSideRight;
1411 
1412   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontRight)
1413     return codec_spec_conf::kLeAudioLocationBottomFrontRight;
1414 
1415   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRightWide)
1416     return codec_spec_conf::kLeAudioLocationFrontRightWide;
1417 
1418   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationRightSurround)
1419     return codec_spec_conf::kLeAudioLocationRightSurround;
1420 
1421   return 0;
1422 }
1423 
PickAudioLocation(types::LeAudioConfigurationStrategy strategy,types::AudioLocations device_locations,types::AudioLocations * group_locations)1424 uint32_t PickAudioLocation(types::LeAudioConfigurationStrategy strategy,
1425                            types::AudioLocations device_locations,
1426                            types::AudioLocations* group_locations) {
1427   LOG_DEBUG("strategy: %d, locations: 0x%lx, group locations: 0x%lx",
1428             (int)strategy, device_locations.to_ulong(),
1429             group_locations->to_ulong());
1430 
1431   auto is_left_not_yet_assigned =
1432       !(group_locations->to_ulong() & codec_spec_conf::kLeAudioLocationAnyLeft);
1433   auto is_right_not_yet_assigned = !(group_locations->to_ulong() &
1434                                      codec_spec_conf::kLeAudioLocationAnyRight);
1435   uint32_t left_device_loc = GetFirstLeft(device_locations);
1436   uint32_t right_device_loc = GetFirstRight(device_locations);
1437 
1438   if (left_device_loc == 0 && right_device_loc == 0) {
1439     LOG_WARN("Can't find device able to render left  and right audio channel");
1440   }
1441 
1442   switch (strategy) {
1443     case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
1444     case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
1445       if (left_device_loc && is_left_not_yet_assigned) {
1446         *group_locations |= left_device_loc;
1447         return left_device_loc;
1448       }
1449 
1450       if (right_device_loc && is_right_not_yet_assigned) {
1451         *group_locations |= right_device_loc;
1452         return right_device_loc;
1453       }
1454       break;
1455 
1456     case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
1457       if (left_device_loc && right_device_loc) {
1458         *group_locations |= left_device_loc | right_device_loc;
1459         return left_device_loc | right_device_loc;
1460       }
1461       break;
1462     default:
1463       LOG_ALWAYS_FATAL("%s: Unknown strategy: %hhu", __func__, strategy);
1464       return 0;
1465   }
1466 
1467   LOG_ERROR(
1468       "Can't find device for left/right channel. Strategy: %hhu, "
1469       "device_locations: %lx, group_locations: %lx.",
1470       strategy, device_locations.to_ulong(), group_locations->to_ulong());
1471 
1472   /* Return either any left or any right audio location. It might result with
1473    * multiple devices within the group having the same location.
1474    */
1475   return left_device_loc ? left_device_loc : right_device_loc;
1476 }
1477 
ConfigureAses(const le_audio::set_configurations::SetConfiguration & ent,types::LeAudioContextType context_type,uint8_t * number_of_already_active_group_ase,types::AudioLocations & group_snk_audio_locations,types::AudioLocations & group_src_audio_locations,bool reuse_cis_id,AudioContexts metadata_context_type,const std::vector<uint8_t> & ccid_list)1478 bool LeAudioDevice::ConfigureAses(
1479     const le_audio::set_configurations::SetConfiguration& ent,
1480     types::LeAudioContextType context_type,
1481     uint8_t* number_of_already_active_group_ase,
1482     types::AudioLocations& group_snk_audio_locations,
1483     types::AudioLocations& group_src_audio_locations, bool reuse_cis_id,
1484     AudioContexts metadata_context_type,
1485     const std::vector<uint8_t>& ccid_list) {
1486   /* First try to use the already configured ASE */
1487   auto ase = GetFirstActiveAseByDirection(ent.direction);
1488   if (ase) {
1489     LOG_INFO("Using an already active ASE id=%d", ase->id);
1490   } else {
1491     ase = GetFirstInactiveAse(ent.direction, reuse_cis_id);
1492   }
1493 
1494   if (!ase) {
1495     LOG_ERROR("Unable to find an ASE to configure");
1496     return false;
1497   }
1498 
1499   /* The number_of_already_active_group_ase keeps all the active ases
1500    * in other devices in the group.
1501    * This function counts active ases only for this device, and we count here
1502    * new active ases and already active ases which we want to reuse in the
1503    * scenario
1504    */
1505   uint8_t active_ases = *number_of_already_active_group_ase;
1506   uint8_t max_required_ase_per_dev =
1507       ent.ase_cnt / ent.device_cnt + (ent.ase_cnt % ent.device_cnt);
1508   le_audio::types::LeAudioConfigurationStrategy strategy = ent.strategy;
1509 
1510   auto pac = GetCodecConfigurationSupportedPac(ent.direction, ent.codec);
1511   if (!pac) return false;
1512 
1513   int needed_ase = std::min((int)(max_required_ase_per_dev),
1514                             (int)(ent.ase_cnt - active_ases));
1515 
1516   types::AudioLocations audio_locations = 0;
1517   types::AudioLocations* group_audio_locations;
1518   /* Check direction and if audio location allows to create more cise */
1519   if (ent.direction == types::kLeAudioDirectionSink) {
1520     audio_locations = snk_audio_locations_;
1521     group_audio_locations = &group_snk_audio_locations;
1522   } else {
1523     audio_locations = src_audio_locations_;
1524     group_audio_locations = &group_src_audio_locations;
1525   }
1526 
1527   for (; needed_ase && ase; needed_ase--) {
1528     ase->active = true;
1529     ase->configured_for_context_type = context_type;
1530     active_ases++;
1531 
1532     /* In case of late connect, we could be here for STREAMING ase.
1533      * in such case, it is needed to mark ase as known active ase which
1534      * is important to validate scenario and is done already few lines above.
1535      * Nothing more to do is needed here.
1536      */
1537     if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1538       if (ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED)
1539         ase->reconfigure = true;
1540 
1541       ase->target_latency = ent.target_latency;
1542       ase->codec_id = ent.codec.id;
1543       /* TODO: find better way to not use LC3 explicitly */
1544       ase->codec_config = std::get<LeAudioLc3Config>(ent.codec.config);
1545 
1546       /*Let's choose audio channel allocation if not set */
1547       ase->codec_config.audio_channel_allocation =
1548           PickAudioLocation(strategy, audio_locations, group_audio_locations);
1549 
1550       /* Get default value if no requirement for specific frame blocks per sdu
1551        */
1552       if (!ase->codec_config.codec_frames_blocks_per_sdu) {
1553         ase->codec_config.codec_frames_blocks_per_sdu =
1554             GetMaxCodecFramesPerSduFromPac(pac);
1555       }
1556       ase->max_sdu_size = codec_spec_caps::GetAudioChannelCounts(
1557                               *ase->codec_config.audio_channel_allocation) *
1558                           *ase->codec_config.octets_per_codec_frame *
1559                           *ase->codec_config.codec_frames_blocks_per_sdu;
1560 
1561       ase->retrans_nb = ent.qos.retransmission_number;
1562       ase->max_transport_latency = ent.qos.max_transport_latency;
1563 
1564       /* Filter multidirectional audio context for each ase direction */
1565       auto directional_audio_context =
1566           metadata_context_type & GetAvailableContexts(ase->direction);
1567       if (directional_audio_context.any()) {
1568         ase->metadata = GetMetadata(directional_audio_context, ccid_list);
1569       } else {
1570         ase->metadata =
1571             GetMetadata(AudioContexts(LeAudioContextType::UNSPECIFIED),
1572                         std::vector<uint8_t>());
1573       }
1574     }
1575 
1576     LOG_DEBUG(
1577         "device=%s, activated ASE id=%d, direction=%s, max_sdu_size=%d, "
1578         "cis_id=%d, target_latency=%d",
1579         address_.ToString().c_str(), ase->id,
1580         (ent.direction == 1 ? "snk" : "src"), ase->max_sdu_size, ase->cis_id,
1581         ent.target_latency);
1582 
1583     /* Try to use the already active ASE */
1584     ase = GetNextActiveAseWithSameDirection(ase);
1585     if (ase == nullptr) {
1586       ase = GetFirstInactiveAse(ent.direction, reuse_cis_id);
1587     }
1588   }
1589 
1590   *number_of_already_active_group_ase = active_ases;
1591   return true;
1592 }
1593 
1594 /* This method should choose aproperiate ASEs to be active and set a cached
1595  * configuration for codec and qos.
1596  */
ConfigureAses(const set_configurations::AudioSetConfiguration * audio_set_conf,types::LeAudioContextType context_type,AudioContexts metadata_context_type,const std::vector<uint8_t> & ccid_list)1597 bool LeAudioDeviceGroup::ConfigureAses(
1598     const set_configurations::AudioSetConfiguration* audio_set_conf,
1599     types::LeAudioContextType context_type, AudioContexts metadata_context_type,
1600     const std::vector<uint8_t>& ccid_list) {
1601   if (!set_configurations::check_if_may_cover_scenario(
1602           audio_set_conf, NumOfConnected(context_type)))
1603     return false;
1604 
1605   bool reuse_cis_id =
1606       GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
1607 
1608   /* TODO For now: set ase if matching with first pac.
1609    * 1) We assume as well that devices will match requirements in order
1610    *    e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc.
1611    * 2) ASEs should be active only if best (according to priority list) full
1612    *    scenarion will be covered.
1613    * 3) ASEs should be filled according to performance profile.
1614    */
1615 
1616   types::AudioLocations group_snk_audio_locations = 0;
1617   types::AudioLocations group_src_audio_locations = 0;
1618 
1619   for (const auto& ent : (*audio_set_conf).confs) {
1620     LOG_DEBUG(" Looking for requirements: %s,  - %s",
1621               audio_set_conf->name.c_str(),
1622               (ent.direction == 1 ? "snk" : "src"));
1623 
1624     uint8_t required_device_cnt = ent.device_cnt;
1625     uint8_t max_required_ase_per_dev =
1626         ent.ase_cnt / ent.device_cnt + (ent.ase_cnt % ent.device_cnt);
1627     uint8_t active_ase_num = 0;
1628     le_audio::types::LeAudioConfigurationStrategy strategy = ent.strategy;
1629 
1630     LOG_DEBUG(
1631         "Number of devices: %d number of ASEs: %d, Max ASE per device: %d "
1632         "strategy: %d",
1633         required_device_cnt, ent.ase_cnt, max_required_ase_per_dev,
1634         (int)strategy);
1635 
1636     for (auto* device = GetFirstDeviceWithActiveContext(context_type);
1637          device != nullptr && required_device_cnt > 0;
1638          device = GetNextDeviceWithActiveContext(device, context_type)) {
1639       /* For the moment, we configure only connected devices and when it is
1640        * ready to stream i.e. All ASEs are discovered and device is reported as
1641        * connected
1642        */
1643       if (device->GetConnectionState() != DeviceConnectState::CONNECTED) {
1644         LOG_WARN(
1645             "Device %s, in the state %s", device->address_.ToString().c_str(),
1646             bluetooth::common::ToString(device->GetConnectionState()).c_str());
1647         continue;
1648       }
1649 
1650       if (!device->ConfigureAses(ent, context_type, &active_ase_num,
1651                                  group_snk_audio_locations,
1652                                  group_src_audio_locations, reuse_cis_id,
1653                                  metadata_context_type, ccid_list))
1654         continue;
1655 
1656       required_device_cnt--;
1657     }
1658 
1659     if (required_device_cnt > 0) {
1660       /* Don't left any active devices if requirements are not met */
1661       LOG_ERROR(" could not configure all the devices");
1662       Deactivate();
1663       return false;
1664     }
1665   }
1666 
1667   LOG_INFO("Choosed ASE Configuration for group: %d, configuration: %s",
1668            group_id_, audio_set_conf->name.c_str());
1669 
1670   configuration_context_type_ = context_type;
1671   metadata_context_type_ = metadata_context_type;
1672   return true;
1673 }
1674 
1675 const set_configurations::AudioSetConfiguration*
GetActiveConfiguration(void)1676 LeAudioDeviceGroup::GetActiveConfiguration(void) {
1677   return available_context_to_configuration_map[configuration_context_type_];
1678 }
1679 
1680 std::optional<LeAudioCodecConfiguration>
GetCodecConfigurationByDirection(types::LeAudioContextType group_context_type,uint8_t direction) const1681 LeAudioDeviceGroup::GetCodecConfigurationByDirection(
1682     types::LeAudioContextType group_context_type, uint8_t direction) const {
1683   if (available_context_to_configuration_map.count(group_context_type) == 0) {
1684     LOG_DEBUG("Context type %s, not supported",
1685               bluetooth::common::ToString(group_context_type).c_str());
1686     return std::nullopt;
1687   }
1688 
1689   const set_configurations::AudioSetConfiguration* audio_set_conf =
1690       available_context_to_configuration_map.at(group_context_type);
1691   LeAudioCodecConfiguration group_config = {0, 0, 0, 0};
1692   if (!audio_set_conf) return std::nullopt;
1693 
1694   for (const auto& conf : audio_set_conf->confs) {
1695     if (conf.direction != direction) continue;
1696 
1697     if (group_config.sample_rate != 0 &&
1698         conf.codec.GetConfigSamplingFrequency() != group_config.sample_rate) {
1699       LOG(WARNING) << __func__
1700                    << ", stream configuration could not be "
1701                       "determined (sampling frequency differs) for direction: "
1702                    << loghex(direction);
1703       return std::nullopt;
1704     }
1705     group_config.sample_rate = conf.codec.GetConfigSamplingFrequency();
1706 
1707     if (group_config.data_interval_us != 0 &&
1708         conf.codec.GetConfigDataIntervalUs() != group_config.data_interval_us) {
1709       LOG(WARNING) << __func__
1710                    << ", stream configuration could not be "
1711                       "determined (data interval differs) for direction: "
1712                    << loghex(direction);
1713       return std::nullopt;
1714     }
1715     group_config.data_interval_us = conf.codec.GetConfigDataIntervalUs();
1716 
1717     if (group_config.bits_per_sample != 0 &&
1718         conf.codec.GetConfigBitsPerSample() != group_config.bits_per_sample) {
1719       LOG(WARNING) << __func__
1720                    << ", stream configuration could not be "
1721                       "determined (bits per sample differs) for direction: "
1722                    << loghex(direction);
1723       return std::nullopt;
1724     }
1725     group_config.bits_per_sample = conf.codec.GetConfigBitsPerSample();
1726 
1727     group_config.num_channels +=
1728         conf.codec.GetConfigChannelCount() * conf.device_cnt;
1729   }
1730 
1731   if (group_config.IsInvalid()) return std::nullopt;
1732 
1733   return group_config;
1734 }
1735 
IsContextSupported(types::LeAudioContextType group_context_type)1736 bool LeAudioDeviceGroup::IsContextSupported(
1737     types::LeAudioContextType group_context_type) {
1738   auto iter = available_context_to_configuration_map.find(group_context_type);
1739   if (iter == available_context_to_configuration_map.end()) return false;
1740 
1741   return available_context_to_configuration_map[group_context_type] != nullptr;
1742 }
1743 
IsMetadataChanged(types::AudioContexts context_type,const std::vector<uint8_t> & ccid_list)1744 bool LeAudioDeviceGroup::IsMetadataChanged(
1745     types::AudioContexts context_type, const std::vector<uint8_t>& ccid_list) {
1746   for (auto* leAudioDevice = GetFirstActiveDevice(); leAudioDevice;
1747        leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
1748     if (leAudioDevice->IsMetadataChanged(context_type, ccid_list)) return true;
1749   }
1750 
1751   return false;
1752 }
1753 
StreamOffloaderUpdated(uint8_t direction)1754 void LeAudioDeviceGroup::StreamOffloaderUpdated(uint8_t direction) {
1755   if (direction == le_audio::types::kLeAudioDirectionSource) {
1756     stream_conf.source_is_initial = false;
1757   } else {
1758     stream_conf.sink_is_initial = false;
1759   }
1760 }
1761 
CreateStreamVectorForOffloader(uint8_t direction)1762 void LeAudioDeviceGroup::CreateStreamVectorForOffloader(uint8_t direction) {
1763   if (CodecManager::GetInstance()->GetCodecLocation() !=
1764       le_audio::types::CodecLocation::ADSP) {
1765     return;
1766   }
1767 
1768   CisType cis_type;
1769   std::vector<std::pair<uint16_t, uint32_t>>* streams;
1770   std::vector<std::pair<uint16_t, uint32_t>>*
1771       offloader_streams_target_allocation;
1772   std::vector<std::pair<uint16_t, uint32_t>>*
1773       offloader_streams_current_allocation;
1774   std::string tag;
1775   uint32_t available_allocations = 0;
1776   bool* changed_flag;
1777   bool* is_initial;
1778   if (direction == le_audio::types::kLeAudioDirectionSource) {
1779     changed_flag = &stream_conf.source_offloader_changed;
1780     is_initial = &stream_conf.source_is_initial;
1781     cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE;
1782     streams = &stream_conf.source_streams;
1783     offloader_streams_target_allocation =
1784         &stream_conf.source_offloader_streams_target_allocation;
1785     offloader_streams_current_allocation =
1786         &stream_conf.source_offloader_streams_current_allocation;
1787     tag = "Source";
1788     available_allocations = AdjustAllocationForOffloader(
1789         stream_conf.source_audio_channel_allocation);
1790   } else {
1791     changed_flag = &stream_conf.sink_offloader_changed;
1792     is_initial = &stream_conf.sink_is_initial;
1793     cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK;
1794     streams = &stream_conf.sink_streams;
1795     offloader_streams_target_allocation =
1796         &stream_conf.sink_offloader_streams_target_allocation;
1797     offloader_streams_current_allocation =
1798         &stream_conf.sink_offloader_streams_current_allocation;
1799     tag = "Sink";
1800     available_allocations =
1801         AdjustAllocationForOffloader(stream_conf.sink_audio_channel_allocation);
1802   }
1803 
1804   if (available_allocations == 0) {
1805     LOG_ERROR("There is no CIS connected");
1806     return;
1807   }
1808 
1809   if (offloader_streams_target_allocation->size() == 0) {
1810     *is_initial = true;
1811   } else if (*is_initial) {
1812     // As multiple CISes phone call case, the target_allocation already have the
1813     // previous data, but the is_initial flag not be cleared. We need to clear
1814     // here to avoid make duplicated target allocation stream map.
1815     offloader_streams_target_allocation->clear();
1816   }
1817 
1818   offloader_streams_current_allocation->clear();
1819   *changed_flag = true;
1820   bool not_all_cises_connected = false;
1821   if (available_allocations != codec_spec_conf::kLeAudioLocationStereo) {
1822     not_all_cises_connected = true;
1823   }
1824 
1825   /* If the all cises are connected as stream started, reset changed_flag that
1826    * the bt stack wouldn't send another audio configuration for the connection
1827    * status */
1828   if (*is_initial && !not_all_cises_connected) {
1829     *changed_flag = false;
1830   }
1831 
1832   /* Note: For the offloader case we simplify allocation to only Left and Right.
1833    * If we need 2 CISes and only one is connected, the connected one will have
1834    * allocation set to stereo (left | right) and other one will have allocation
1835    * set to 0. Offloader in this case shall mix left and right and send it on
1836    * connected CIS. If there is only single CIS with stereo allocation, it means
1837    * that peer device support channel count 2 and offloader shall send two
1838    * channels in the single CIS.
1839    */
1840 
1841   for (auto& cis_entry : cises_) {
1842     if ((cis_entry.type == CisType::CIS_TYPE_BIDIRECTIONAL ||
1843          cis_entry.type == cis_type) &&
1844         cis_entry.conn_handle != 0) {
1845       uint32_t target_allocation = 0;
1846       uint32_t current_allocation = 0;
1847       for (const auto& s : *streams) {
1848         if (s.first == cis_entry.conn_handle) {
1849           target_allocation = AdjustAllocationForOffloader(s.second);
1850           current_allocation = target_allocation;
1851           if (not_all_cises_connected) {
1852             /* Tell offloader to mix on this CIS.*/
1853             current_allocation = codec_spec_conf::kLeAudioLocationStereo;
1854           }
1855           break;
1856         }
1857       }
1858 
1859       if (target_allocation == 0) {
1860         /* Take missing allocation for that one .*/
1861         target_allocation =
1862             codec_spec_conf::kLeAudioLocationStereo & ~available_allocations;
1863       }
1864 
1865       LOG_INFO(
1866           "%s: Cis handle 0x%04x, target allocation  0x%08x, current "
1867           "allocation 0x%08x",
1868           tag.c_str(), cis_entry.conn_handle, target_allocation,
1869           current_allocation);
1870       if (*is_initial) {
1871         offloader_streams_target_allocation->emplace_back(
1872             std::make_pair(cis_entry.conn_handle, target_allocation));
1873       }
1874       offloader_streams_current_allocation->emplace_back(
1875           std::make_pair(cis_entry.conn_handle, current_allocation));
1876     }
1877   }
1878 }
1879 
IsPendingConfiguration(void)1880 bool LeAudioDeviceGroup::IsPendingConfiguration(void) {
1881   return stream_conf.pending_configuration;
1882 }
1883 
SetPendingConfiguration(void)1884 void LeAudioDeviceGroup::SetPendingConfiguration(void) {
1885   stream_conf.pending_configuration = true;
1886 }
1887 
ClearPendingConfiguration(void)1888 void LeAudioDeviceGroup::ClearPendingConfiguration(void) {
1889   stream_conf.pending_configuration = false;
1890 }
1891 
IsConfigurationSupported(LeAudioDevice * leAudioDevice,const set_configurations::AudioSetConfiguration * audio_set_conf)1892 bool LeAudioDeviceGroup::IsConfigurationSupported(
1893     LeAudioDevice* leAudioDevice,
1894     const set_configurations::AudioSetConfiguration* audio_set_conf) {
1895   for (const auto& ent : (*audio_set_conf).confs) {
1896     LOG_INFO("Looking for requirements: %s - %s", audio_set_conf->name.c_str(),
1897              (ent.direction == 1 ? "snk" : "src"));
1898     auto pac = leAudioDevice->GetCodecConfigurationSupportedPac(ent.direction,
1899                                                                 ent.codec);
1900     if (pac != nullptr) {
1901       LOG_INFO("Configuration is supported by device %s",
1902                leAudioDevice->address_.ToString().c_str());
1903       return true;
1904     }
1905   }
1906 
1907   LOG_INFO("Configuration is NOT supported by device %s",
1908            leAudioDevice->address_.ToString().c_str());
1909   return false;
1910 }
1911 
1912 const set_configurations::AudioSetConfiguration*
FindFirstSupportedConfiguration(LeAudioContextType context_type)1913 LeAudioDeviceGroup::FindFirstSupportedConfiguration(
1914     LeAudioContextType context_type) {
1915   const set_configurations::AudioSetConfigurations* confs =
1916       AudioSetConfigurationProvider::Get()->GetConfigurations(context_type);
1917 
1918   LOG_DEBUG("context type: %s,  number of connected devices: %d",
1919             bluetooth::common::ToString(context_type).c_str(),
1920             +NumOfConnected());
1921 
1922   /* Filter out device set for all scenarios */
1923   if (!set_configurations::check_if_may_cover_scenario(confs,
1924                                                        NumOfConnected())) {
1925     LOG_ERROR(", group is unable to cover scenario");
1926     return nullptr;
1927   }
1928 
1929   /* Filter out device set for each end every scenario */
1930 
1931   for (const auto& conf : *confs) {
1932     if (IsConfigurationSupported(conf, context_type)) {
1933       LOG_DEBUG("found: %s", conf->name.c_str());
1934       return conf;
1935     }
1936   }
1937 
1938   return nullptr;
1939 }
1940 
1941 /* This method should choose aproperiate ASEs to be active and set a cached
1942  * configuration for codec and qos.
1943  */
Configure(LeAudioContextType context_type,AudioContexts metadata_context_type,std::vector<uint8_t> ccid_list)1944 bool LeAudioDeviceGroup::Configure(LeAudioContextType context_type,
1945                                    AudioContexts metadata_context_type,
1946                                    std::vector<uint8_t> ccid_list) {
1947   const set_configurations::AudioSetConfiguration* conf =
1948       available_context_to_configuration_map[context_type];
1949 
1950   if (!conf) {
1951     LOG_ERROR(
1952         ", requested context type: %s , is in mismatch with cached available "
1953         "contexts ",
1954         bluetooth::common::ToString(context_type).c_str());
1955     return false;
1956   }
1957 
1958   LOG_DEBUG(" setting context type: %s",
1959             bluetooth::common::ToString(context_type).c_str());
1960 
1961   if (!ConfigureAses(conf, context_type, metadata_context_type, ccid_list)) {
1962     LOG_ERROR(
1963         ", requested context type: %s , is in mismatch with cached available "
1964         "contexts",
1965         bluetooth::common::ToString(context_type).c_str());
1966     return false;
1967   }
1968 
1969   /* Store selected configuration at once it is chosen.
1970    * It might happen it will get unavailable in some point of time
1971    */
1972   stream_conf.conf = conf;
1973   return true;
1974 }
1975 
~LeAudioDeviceGroup(void)1976 LeAudioDeviceGroup::~LeAudioDeviceGroup(void) { this->Cleanup(); }
1977 
PrintDebugState(void)1978 void LeAudioDeviceGroup::PrintDebugState(void) {
1979   auto* active_conf = GetActiveConfiguration();
1980   std::stringstream debug_str;
1981 
1982   debug_str << "\n Groupd id: " << group_id_
1983             << ", state: " << bluetooth::common::ToString(GetState())
1984             << ", target state: "
1985             << bluetooth::common::ToString(GetTargetState())
1986             << ", cig state: " << bluetooth::common::ToString(cig_state_)
1987             << ", \n group available contexts: "
1988             << bluetooth::common::ToString(GetAvailableContexts())
1989             << ", \n configuration context type: "
1990             << bluetooth::common::ToString(GetConfigurationContextType())
1991             << ", \n active configuration name: "
1992             << (active_conf ? active_conf->name : " not set");
1993 
1994   if (cises_.size() > 0) {
1995     LOG_INFO("\n Allocated CISes: %d", static_cast<int>(cises_.size()));
1996     for (auto cis : cises_) {
1997       LOG_INFO("\n cis id: %d, type: %d, conn_handle %d, addr: %s", cis.id,
1998                cis.type, cis.conn_handle, cis.addr.ToString().c_str());
1999     }
2000   }
2001 
2002   if (GetFirstActiveDevice() != nullptr) {
2003     uint32_t sink_delay = 0;
2004     uint32_t source_delay = 0;
2005     GetPresentationDelay(&sink_delay, le_audio::types::kLeAudioDirectionSink);
2006     GetPresentationDelay(&source_delay,
2007                          le_audio::types::kLeAudioDirectionSource);
2008     auto phy_mtos = GetPhyBitmask(le_audio::types::kLeAudioDirectionSink);
2009     auto phy_stom = GetPhyBitmask(le_audio::types::kLeAudioDirectionSource);
2010     auto max_transport_latency_mtos = GetMaxTransportLatencyMtos();
2011     auto max_transport_latency_stom = GetMaxTransportLatencyStom();
2012     auto sdu_mts = GetSduInterval(le_audio::types::kLeAudioDirectionSink);
2013     auto sdu_stom = GetSduInterval(le_audio::types::kLeAudioDirectionSource);
2014 
2015     debug_str << "\n resentation_delay for sink (speaker): " << +sink_delay
2016               << " us, presentation_delay for source (microphone): "
2017               << +source_delay << "us, \n MtoS transport latency:  "
2018               << +max_transport_latency_mtos
2019               << ", StoM transport latency: " << +max_transport_latency_stom
2020               << ", \n MtoS Phy: " << loghex(phy_mtos)
2021               << ", MtoS sdu: " << loghex(phy_stom)
2022               << " \n MtoS sdu: " << +sdu_mts << ", StoM sdu: " << +sdu_stom;
2023   }
2024 
2025   LOG_INFO("%s", debug_str.str().c_str());
2026 
2027   for (const auto& device_iter : leAudioDevices_) {
2028     device_iter.lock()->PrintDebugState();
2029   }
2030 }
2031 
Dump(int fd,int active_group_id)2032 void LeAudioDeviceGroup::Dump(int fd, int active_group_id) {
2033   bool is_active = (group_id_ == active_group_id);
2034   std::stringstream stream;
2035   auto* active_conf = GetActiveConfiguration();
2036 
2037   stream << "\n    == Group id: " << group_id_
2038          << " == " << (is_active ? ",\tActive\n" : ",\tInactive\n")
2039          << "      state: " << GetState()
2040          << ",\ttarget state: " << GetTargetState()
2041          << ",\tcig state: " << cig_state_ << "\n"
2042          << "      group available contexts: " << GetAvailableContexts()
2043          << "      configuration context type: "
2044          << bluetooth::common::ToString(GetConfigurationContextType()).c_str()
2045          << "      active configuration name: "
2046          << (active_conf ? active_conf->name : " not set") << "\n"
2047          << "      stream configuration: "
2048          << (stream_conf.conf != nullptr ? stream_conf.conf->name : " unknown ")
2049          << "\n"
2050          << "      codec id: " << +(stream_conf.id.coding_format)
2051          << ",\tpending_configuration: " << stream_conf.pending_configuration
2052          << "\n"
2053          << "      num of devices(connected): " << Size() << "("
2054          << NumOfConnected() << ")\n"
2055          << ",     num of sinks(connected): " << stream_conf.sink_num_of_devices
2056          << "(" << stream_conf.sink_streams.size() << ")\n"
2057          << "      num of sources(connected): "
2058          << stream_conf.source_num_of_devices << "("
2059          << stream_conf.source_streams.size() << ")\n"
2060          << "      allocated CISes: " << static_cast<int>(cises_.size());
2061 
2062   if (cises_.size() > 0) {
2063     stream << "\n\t == CISes == ";
2064     for (auto cis : cises_) {
2065       stream << "\n\t cis id: " << static_cast<int>(cis.id)
2066              << ",\ttype: " << static_cast<int>(cis.type)
2067              << ",\tconn_handle: " << static_cast<int>(cis.conn_handle)
2068              << ",\taddr: " << cis.addr;
2069     }
2070     stream << "\n\t ====";
2071   }
2072 
2073   if (GetFirstActiveDevice() != nullptr) {
2074     uint32_t sink_delay;
2075     if (GetPresentationDelay(&sink_delay,
2076                              le_audio::types::kLeAudioDirectionSink)) {
2077       stream << "\n      presentation_delay for sink (speaker): " << sink_delay
2078              << " us";
2079     }
2080 
2081     uint32_t source_delay;
2082     if (GetPresentationDelay(&source_delay,
2083                              le_audio::types::kLeAudioDirectionSource)) {
2084       stream << "\n      presentation_delay for source (microphone): "
2085              << source_delay << " us";
2086     }
2087   }
2088 
2089   stream << "\n      == devices: ==";
2090 
2091   dprintf(fd, "%s", stream.str().c_str());
2092 
2093   for (const auto& device_iter : leAudioDevices_) {
2094     device_iter.lock()->Dump(fd);
2095   }
2096 }
2097 
2098 /* LeAudioDevice Class methods implementation */
SetConnectionState(DeviceConnectState state)2099 void LeAudioDevice::SetConnectionState(DeviceConnectState state) {
2100   LOG_DEBUG(" %s --> %s",
2101             bluetooth::common::ToString(connection_state_).c_str(),
2102             bluetooth::common::ToString(state).c_str());
2103   connection_state_ = state;
2104 }
2105 
GetConnectionState(void)2106 DeviceConnectState LeAudioDevice::GetConnectionState(void) {
2107   return connection_state_;
2108 }
2109 
ClearPACs(void)2110 void LeAudioDevice::ClearPACs(void) {
2111   snk_pacs_.clear();
2112   src_pacs_.clear();
2113 }
2114 
~LeAudioDevice(void)2115 LeAudioDevice::~LeAudioDevice(void) {
2116   alarm_free(link_quality_timer);
2117   this->ClearPACs();
2118 }
2119 
RegisterPACs(std::vector<struct types::acs_ac_record> * pac_db,std::vector<struct types::acs_ac_record> * pac_recs)2120 void LeAudioDevice::RegisterPACs(
2121     std::vector<struct types::acs_ac_record>* pac_db,
2122     std::vector<struct types::acs_ac_record>* pac_recs) {
2123   /* Clear PAC database for characteristic in case if re-read, indicated */
2124   if (!pac_db->empty()) {
2125     DLOG(INFO) << __func__ << ", upgrade PACs for characteristic";
2126     pac_db->clear();
2127   }
2128 
2129   /* TODO wrap this logging part with debug flag */
2130   for (const struct types::acs_ac_record& pac : *pac_recs) {
2131     LOG(INFO) << "Registering PAC"
2132               << "\n\tCoding format: " << loghex(pac.codec_id.coding_format)
2133               << "\n\tVendor codec company ID: "
2134               << loghex(pac.codec_id.vendor_company_id)
2135               << "\n\tVendor codec ID: " << loghex(pac.codec_id.vendor_codec_id)
2136               << "\n\tCodec spec caps:\n"
2137               << pac.codec_spec_caps.ToString() << "\n\tMetadata: "
2138               << base::HexEncode(pac.metadata.data(), pac.metadata.size());
2139   }
2140 
2141   pac_db->insert(pac_db->begin(), pac_recs->begin(), pac_recs->end());
2142 }
2143 
GetAseByValHandle(uint16_t val_hdl)2144 struct ase* LeAudioDevice::GetAseByValHandle(uint16_t val_hdl) {
2145   auto iter = std::find_if(
2146       ases_.begin(), ases_.end(),
2147       [&val_hdl](const auto& ase) { return ase.hdls.val_hdl == val_hdl; });
2148 
2149   return (iter == ases_.end()) ? nullptr : &(*iter);
2150 }
2151 
GetAseCount(uint8_t direction)2152 int LeAudioDevice::GetAseCount(uint8_t direction) {
2153   return std::count_if(ases_.begin(), ases_.end(), [direction](const auto& a) {
2154     return a.direction == direction;
2155   });
2156 }
2157 
GetFirstAseWithState(uint8_t direction,AseState state)2158 struct ase* LeAudioDevice::GetFirstAseWithState(uint8_t direction,
2159                                                 AseState state) {
2160   auto iter = std::find_if(
2161       ases_.begin(), ases_.end(), [direction, state](const auto& ase) {
2162         return ((ase.direction == direction) && (ase.state == state));
2163       });
2164 
2165   return (iter == ases_.end()) ? nullptr : &(*iter);
2166 }
2167 
GetFirstActiveAse(void)2168 struct ase* LeAudioDevice::GetFirstActiveAse(void) {
2169   auto iter = std::find_if(ases_.begin(), ases_.end(),
2170                            [](const auto& ase) { return ase.active; });
2171 
2172   return (iter == ases_.end()) ? nullptr : &(*iter);
2173 }
2174 
GetFirstActiveAseByDirection(uint8_t direction)2175 struct ase* LeAudioDevice::GetFirstActiveAseByDirection(uint8_t direction) {
2176   auto iter =
2177       std::find_if(ases_.begin(), ases_.end(), [direction](const auto& ase) {
2178         return (ase.active && (ase.direction == direction));
2179       });
2180 
2181   return (iter == ases_.end()) ? nullptr : &(*iter);
2182 }
2183 
GetNextActiveAseWithSameDirection(struct ase * base_ase)2184 struct ase* LeAudioDevice::GetNextActiveAseWithSameDirection(
2185     struct ase* base_ase) {
2186   auto iter = std::find_if(ases_.begin(), ases_.end(),
2187                            [&base_ase](auto& ase) { return base_ase == &ase; });
2188 
2189   /* Invalid ase given */
2190   if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1)
2191     return nullptr;
2192 
2193   iter =
2194       std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
2195         return ase.active && (*iter).direction == ase.direction;
2196       });
2197 
2198   return (iter == ases_.end()) ? nullptr : &(*iter);
2199 }
2200 
GetNextActiveAseWithDifferentDirection(struct ase * base_ase)2201 struct ase* LeAudioDevice::GetNextActiveAseWithDifferentDirection(
2202     struct ase* base_ase) {
2203   auto iter = std::find_if(ases_.begin(), ases_.end(),
2204                            [&base_ase](auto& ase) { return base_ase == &ase; });
2205 
2206   /* Invalid ase given */
2207   if (std::distance(iter, ases_.end()) < 1) {
2208     LOG_DEBUG("ASE %d does not use bidirectional CIS", base_ase->id);
2209     return nullptr;
2210   }
2211 
2212   iter =
2213       std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
2214         return ase.active && iter->direction != ase.direction;
2215       });
2216 
2217   if (iter == ases_.end()) {
2218     return nullptr;
2219   }
2220 
2221   return &(*iter);
2222 }
2223 
GetFirstActiveAseByDataPathState(types::AudioStreamDataPathState state)2224 struct ase* LeAudioDevice::GetFirstActiveAseByDataPathState(
2225     types::AudioStreamDataPathState state) {
2226   auto iter =
2227       std::find_if(ases_.begin(), ases_.end(), [state](const auto& ase) {
2228         return (ase.active && (ase.data_path_state == state));
2229       });
2230 
2231   return (iter == ases_.end()) ? nullptr : &(*iter);
2232 }
2233 
GetFirstInactiveAse(uint8_t direction,bool reuse_cis_id)2234 struct ase* LeAudioDevice::GetFirstInactiveAse(uint8_t direction,
2235                                                bool reuse_cis_id) {
2236   auto iter = std::find_if(ases_.begin(), ases_.end(),
2237                            [direction, reuse_cis_id](const auto& ase) {
2238                              if (ase.active || (ase.direction != direction))
2239                                return false;
2240 
2241                              if (!reuse_cis_id) return true;
2242 
2243                              return (ase.cis_id != kInvalidCisId);
2244                            });
2245   /* If ASE is found, return it */
2246   if (iter != ases_.end()) return &(*iter);
2247 
2248   /* If reuse was not set, that means there is no inactive ASE available. */
2249   if (!reuse_cis_id) return nullptr;
2250 
2251   /* Since there is no ASE with assigned CIS ID, it means new configuration
2252    * needs more ASEs then it was configured before.
2253    * Let's find just inactive one */
2254   iter = std::find_if(ases_.begin(), ases_.end(),
2255                       [direction](const auto& ase) {
2256                         if (ase.active || (ase.direction != direction))
2257                           return false;
2258                         return true;
2259                       });
2260 
2261   return (iter == ases_.end()) ? nullptr : &(*iter);
2262 }
2263 
GetNextActiveAse(struct ase * base_ase)2264 struct ase* LeAudioDevice::GetNextActiveAse(struct ase* base_ase) {
2265   auto iter = std::find_if(ases_.begin(), ases_.end(),
2266                            [&base_ase](auto& ase) { return base_ase == &ase; });
2267 
2268   /* Invalid ase given */
2269   if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1)
2270     return nullptr;
2271 
2272   iter = std::find_if(std::next(iter, 1), ases_.end(),
2273                       [](const auto& ase) { return ase.active; });
2274 
2275   return (iter == ases_.end()) ? nullptr : &(*iter);
2276 }
2277 
GetAseToMatchBidirectionCis(struct ase * base_ase)2278 struct ase* LeAudioDevice::GetAseToMatchBidirectionCis(struct ase* base_ase) {
2279   auto iter = std::find_if(ases_.begin(), ases_.end(), [&base_ase](auto& ase) {
2280     return (base_ase->cis_conn_hdl == ase.cis_conn_hdl) &&
2281            (base_ase->direction != ase.direction);
2282   });
2283   return (iter == ases_.end()) ? nullptr : &(*iter);
2284 }
2285 
GetAsesByCisConnHdl(uint16_t conn_hdl)2286 BidirectAsesPair LeAudioDevice::GetAsesByCisConnHdl(uint16_t conn_hdl) {
2287   BidirectAsesPair ases = {nullptr, nullptr};
2288 
2289   for (auto& ase : ases_) {
2290     if (ase.cis_conn_hdl == conn_hdl) {
2291       if (ase.direction == types::kLeAudioDirectionSink) {
2292         ases.sink = &ase;
2293       } else {
2294         ases.source = &ase;
2295       }
2296     }
2297   }
2298 
2299   return ases;
2300 }
2301 
GetAsesByCisId(uint8_t cis_id)2302 BidirectAsesPair LeAudioDevice::GetAsesByCisId(uint8_t cis_id) {
2303   BidirectAsesPair ases = {nullptr, nullptr};
2304 
2305   for (auto& ase : ases_) {
2306     if (ase.cis_id == cis_id) {
2307       if (ase.direction == types::kLeAudioDirectionSink) {
2308         ases.sink = &ase;
2309       } else {
2310         ases.source = &ase;
2311       }
2312     }
2313   }
2314 
2315   return ases;
2316 }
2317 
HaveActiveAse(void)2318 bool LeAudioDevice::HaveActiveAse(void) {
2319   auto iter = std::find_if(ases_.begin(), ases_.end(),
2320                            [](const auto& ase) { return ase.active; });
2321 
2322   return iter != ases_.end();
2323 }
2324 
HaveAnyUnconfiguredAses(void)2325 bool LeAudioDevice::HaveAnyUnconfiguredAses(void) {
2326   /* In configuring state when active in Idle or Configured and reconfigure */
2327   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2328     if (!ase.active) return false;
2329 
2330     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE ||
2331         ((ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) &&
2332          ase.reconfigure))
2333       return true;
2334 
2335     return false;
2336   });
2337 
2338   return iter != ases_.end();
2339 }
2340 
HaveAllActiveAsesSameState(AseState state)2341 bool LeAudioDevice::HaveAllActiveAsesSameState(AseState state) {
2342   auto iter = std::find_if(
2343       ases_.begin(), ases_.end(),
2344       [&state](const auto& ase) { return ase.active && (ase.state != state); });
2345 
2346   return iter == ases_.end();
2347 }
2348 
IsReadyToCreateStream(void)2349 bool LeAudioDevice::IsReadyToCreateStream(void) {
2350   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2351     if (!ase.active) return false;
2352 
2353     if (ase.direction == types::kLeAudioDirectionSink &&
2354         (ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING &&
2355          ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING))
2356       return true;
2357 
2358     if (ase.direction == types::kLeAudioDirectionSource &&
2359         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING)
2360       return true;
2361 
2362     return false;
2363   });
2364 
2365   return iter == ases_.end();
2366 }
2367 
IsReadyToSuspendStream(void)2368 bool LeAudioDevice::IsReadyToSuspendStream(void) {
2369   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2370     if (!ase.active) return false;
2371 
2372     if (ase.direction == types::kLeAudioDirectionSink &&
2373         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED)
2374       return true;
2375 
2376     if (ase.direction == types::kLeAudioDirectionSource &&
2377         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING)
2378       return true;
2379 
2380     return false;
2381   });
2382 
2383   return iter == ases_.end();
2384 }
2385 
HaveAllActiveAsesCisEst(void)2386 bool LeAudioDevice::HaveAllActiveAsesCisEst(void) {
2387   if (ases_.empty()) {
2388     LOG_WARN("No ases for device %s", address_.ToString().c_str());
2389     return false;
2390   }
2391 
2392   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2393     return ase.active &&
2394            (ase.data_path_state != AudioStreamDataPathState::CIS_ESTABLISHED);
2395   });
2396 
2397   return iter == ases_.end();
2398 }
2399 
HaveAnyCisConnected(void)2400 bool LeAudioDevice::HaveAnyCisConnected(void) {
2401   /* Pending and Disconnecting is considered as connected in this function */
2402   for (auto const ase : ases_) {
2403     if (ase.data_path_state != AudioStreamDataPathState::CIS_ASSIGNED &&
2404         ase.data_path_state != AudioStreamDataPathState::IDLE) {
2405       return true;
2406     }
2407   }
2408   return false;
2409 }
2410 
HasCisId(uint8_t id)2411 bool LeAudioDevice::HasCisId(uint8_t id) {
2412   struct ase* ase = GetFirstActiveAse();
2413 
2414   while (ase) {
2415     if (ase->cis_id == id) return true;
2416     ase = GetNextActiveAse(ase);
2417   }
2418 
2419   return false;
2420 }
2421 
GetMatchingBidirectionCisId(const struct types::ase * base_ase)2422 uint8_t LeAudioDevice::GetMatchingBidirectionCisId(
2423     const struct types::ase* base_ase) {
2424   for (auto& ase : ases_) {
2425     auto& cis = ase.cis_id;
2426     if (!ase.active) continue;
2427 
2428     int num_cises =
2429         std::count_if(ases_.begin(), ases_.end(), [&cis](const auto& iter_ase) {
2430           return iter_ase.active && iter_ase.cis_id == cis;
2431         });
2432 
2433     /*
2434      * If there is only one ASE for device with unique CIS ID and opposite to
2435      * direction - it may be bi-directional/completive.
2436      */
2437     if (num_cises == 1 &&
2438         ((base_ase->direction == types::kLeAudioDirectionSink &&
2439           ase.direction == types::kLeAudioDirectionSource) ||
2440          (base_ase->direction == types::kLeAudioDirectionSource &&
2441           ase.direction == types::kLeAudioDirectionSink))) {
2442       return ase.cis_id;
2443     }
2444   }
2445 
2446   return kInvalidCisId;
2447 }
2448 
GetLc3SupportedChannelCount(uint8_t direction)2449 uint8_t LeAudioDevice::GetLc3SupportedChannelCount(uint8_t direction) {
2450   auto& pacs =
2451       direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;
2452 
2453   if (pacs.size() == 0) {
2454     LOG(ERROR) << __func__ << " missing PAC for direction " << +direction;
2455     return 0;
2456   }
2457 
2458   for (const auto& pac_tuple : pacs) {
2459     /* Get PAC records from tuple as second element from tuple */
2460     auto& pac_recs = std::get<1>(pac_tuple);
2461 
2462     for (const auto pac : pac_recs) {
2463       if (pac.codec_id.coding_format != types::kLeAudioCodingFormatLC3)
2464         continue;
2465 
2466       auto supported_channel_count_ltv = pac.codec_spec_caps.Find(
2467           codec_spec_caps::kLeAudioCodecLC3TypeAudioChannelCounts);
2468 
2469       if (supported_channel_count_ltv == std::nullopt ||
2470           supported_channel_count_ltv->size() == 0L) {
2471         return 1;
2472       }
2473 
2474       return VEC_UINT8_TO_UINT8(supported_channel_count_ltv.value());
2475     };
2476   }
2477 
2478   return 0;
2479 }
2480 
2481 const struct types::acs_ac_record*
GetCodecConfigurationSupportedPac(uint8_t direction,const CodecCapabilitySetting & codec_capability_setting)2482 LeAudioDevice::GetCodecConfigurationSupportedPac(
2483     uint8_t direction, const CodecCapabilitySetting& codec_capability_setting) {
2484   auto& pacs =
2485       direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;
2486 
2487   if (pacs.size() == 0) {
2488     LOG_ERROR("missing PAC for direction %d", direction);
2489     return nullptr;
2490   }
2491 
2492   /* TODO: Validate channel locations */
2493 
2494   for (const auto& pac_tuple : pacs) {
2495     /* Get PAC records from tuple as second element from tuple */
2496     auto& pac_recs = std::get<1>(pac_tuple);
2497 
2498     for (const auto& pac : pac_recs) {
2499       if (!IsCodecCapabilitySettingSupported(pac, codec_capability_setting))
2500         continue;
2501 
2502       return &pac;
2503     };
2504   }
2505 
2506   /* Doesn't match required configuration with any PAC */
2507   return nullptr;
2508 }
2509 
2510 /**
2511  * Returns supported PHY's bitfield
2512  */
GetPhyBitmask(void)2513 uint8_t LeAudioDevice::GetPhyBitmask(void) {
2514   uint8_t phy_bitfield = kIsoCigPhy1M;
2515 
2516   if (BTM_IsPhy2mSupported(address_, BT_TRANSPORT_LE))
2517     phy_bitfield |= kIsoCigPhy2M;
2518 
2519   return phy_bitfield;
2520 }
2521 
SetSupportedContexts(AudioContexts snk_contexts,AudioContexts src_contexts)2522 void LeAudioDevice::SetSupportedContexts(AudioContexts snk_contexts,
2523                                          AudioContexts src_contexts) {
2524   supp_contexts_.sink = snk_contexts;
2525   supp_contexts_.source = src_contexts;
2526 }
2527 
PrintDebugState(void)2528 void LeAudioDevice::PrintDebugState(void) {
2529   std::stringstream debug_str;
2530 
2531   debug_str << " address: " << address_ << ", "
2532             << bluetooth::common::ToString(connection_state_)
2533             << ", conn_id: " << +conn_id_ << ", mtu: " << +mtu_
2534             << ", num_of_ase: " << static_cast<int>(ases_.size());
2535 
2536   if (ases_.size() > 0) {
2537     debug_str << "\n  == ASEs == ";
2538     for (auto& ase : ases_) {
2539       debug_str << "\n  id: " << +ase.id << ", active: " << ase.active
2540                 << ", dir: "
2541                 << (ase.direction == types::kLeAudioDirectionSink ? "sink"
2542                                                                   : "source")
2543                 << ", cis_id: " << +ase.cis_id
2544                 << ", cis_handle: " << +ase.cis_conn_hdl << ", state: "
2545                 << bluetooth::common::ToString(ase.data_path_state)
2546                 << "\n ase max_latency: " << +ase.max_transport_latency
2547                 << ", rtn: " << +ase.retrans_nb
2548                 << ", max_sdu: " << +ase.max_sdu_size
2549                 << ", target latency: " << +ase.target_latency;
2550     }
2551   }
2552 
2553   LOG_INFO("%s", debug_str.str().c_str());
2554 }
2555 
Dump(int fd)2556 void LeAudioDevice::Dump(int fd) {
2557   uint16_t acl_handle = BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
2558   std::string location = "unknown location";
2559 
2560   if (snk_audio_locations_.to_ulong() &
2561       codec_spec_conf::kLeAudioLocationAnyLeft) {
2562     std::string location_left = "left";
2563     location.swap(location_left);
2564   } else if (snk_audio_locations_.to_ulong() &
2565              codec_spec_conf::kLeAudioLocationAnyRight) {
2566     std::string location_right = "right";
2567     location.swap(location_right);
2568   }
2569 
2570   std::stringstream stream;
2571   stream << "\n\taddress: " << address_ << ": " << connection_state_ << ": "
2572          << (conn_id_ == GATT_INVALID_CONN_ID ? "" : std::to_string(conn_id_))
2573          << ", acl_handle: " << std::to_string(acl_handle) << ", " << location
2574          << ",\t" << (encrypted_ ? "Encrypted" : "Unecrypted")
2575          << ",mtu: " << std::to_string(mtu_)
2576          << "\n\tnumber of ases_: " << static_cast<int>(ases_.size());
2577 
2578   if (ases_.size() > 0) {
2579     stream << "\n\t== ASEs == \n\t";
2580     stream
2581         << "id  active dir     cis_id  cis_handle  sdu  latency rtn  state";
2582     for (auto& ase : ases_) {
2583       stream << std::setfill('\xA0') << "\n\t" << std::left << std::setw(4)
2584              << static_cast<int>(ase.id) << std::left << std::setw(7)
2585              << (ase.active ? "true" : "false") << std::left << std::setw(8)
2586              << (ase.direction == types::kLeAudioDirectionSink ? "sink"
2587                                                                : "source")
2588              << std::left << std::setw(8) << static_cast<int>(ase.cis_id)
2589              << std::left << std::setw(12) << ase.cis_conn_hdl << std::left
2590              << std::setw(5) << ase.max_sdu_size << std::left << std::setw(8)
2591              << ase.max_transport_latency << std::left << std::setw(5)
2592              << static_cast<int>(ase.retrans_nb) << std::left << std::setw(12)
2593              << bluetooth::common::ToString(ase.data_path_state);
2594     }
2595   }
2596   stream << "\n\t====";
2597 
2598   dprintf(fd, "%s", stream.str().c_str());
2599 }
2600 
DisconnectAcl(void)2601 void LeAudioDevice::DisconnectAcl(void) {
2602   if (conn_id_ == GATT_INVALID_CONN_ID) return;
2603 
2604   uint16_t acl_handle =
2605       BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
2606   if (acl_handle != HCI_INVALID_HANDLE) {
2607     acl_disconnect_from_handle(acl_handle, HCI_ERR_PEER_USER,
2608                                "bta::le_audio::client disconnect");
2609   }
2610 }
2611 
GetAvailableContexts(int direction)2612 types::AudioContexts LeAudioDevice::GetAvailableContexts(int direction) {
2613   if (direction ==
2614       (types::kLeAudioDirectionSink | types::kLeAudioDirectionSource)) {
2615     return get_bidirectional(avail_contexts_);
2616   } else if (direction == types::kLeAudioDirectionSink) {
2617     return avail_contexts_.sink;
2618   }
2619   return avail_contexts_.source;
2620 }
2621 
2622 /* Returns XOR of updated sink and source bitset context types */
SetAvailableContexts(AudioContexts snk_contexts,AudioContexts src_contexts)2623 AudioContexts LeAudioDevice::SetAvailableContexts(AudioContexts snk_contexts,
2624                                                   AudioContexts src_contexts) {
2625   AudioContexts updated_contexts;
2626 
2627   updated_contexts = snk_contexts ^ avail_contexts_.sink;
2628   updated_contexts |= src_contexts ^ avail_contexts_.source;
2629 
2630   LOG_DEBUG(
2631       "\n\t avail_contexts_.sink: %s \n\t avail_contexts_.source: %s  \n\t "
2632       "snk_contexts: %s \n\t src_contexts: %s \n\t updated_contexts: %s",
2633       avail_contexts_.sink.to_string().c_str(),
2634       avail_contexts_.source.to_string().c_str(),
2635       snk_contexts.to_string().c_str(), src_contexts.to_string().c_str(),
2636       updated_contexts.to_string().c_str());
2637 
2638   avail_contexts_.sink = snk_contexts;
2639   avail_contexts_.source = src_contexts;
2640 
2641   return updated_contexts;
2642 }
2643 
ActivateConfiguredAses(LeAudioContextType context_type)2644 bool LeAudioDevice::ActivateConfiguredAses(LeAudioContextType context_type) {
2645   if (conn_id_ == GATT_INVALID_CONN_ID) {
2646     LOG_WARN(" Device %s is not connected ", address_.ToString().c_str());
2647     return false;
2648   }
2649 
2650   bool ret = false;
2651 
2652   LOG_INFO(" Configuring device %s", address_.ToString().c_str());
2653   for (auto& ase : ases_) {
2654     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED &&
2655         ase.configured_for_context_type == context_type) {
2656       LOG_INFO(
2657           " conn_id: %d, ase id %d, cis id %d, cis_handle 0x%04x is activated.",
2658           conn_id_, ase.id, ase.cis_id, ase.cis_conn_hdl);
2659       ase.active = true;
2660       ret = true;
2661     }
2662   }
2663 
2664   return ret;
2665 }
2666 
DeactivateAllAses(void)2667 void LeAudioDevice::DeactivateAllAses(void) {
2668   for (auto& ase : ases_) {
2669     if (ase.active == false &&
2670         ase.data_path_state != AudioStreamDataPathState::IDLE) {
2671       LOG_WARN(
2672           " %s, ase_id: %d, ase.cis_id: %d, cis_handle: 0x%02x, "
2673           "ase.data_path=%s",
2674           address_.ToString().c_str(), ase.id, ase.cis_id, ase.cis_conn_hdl,
2675           bluetooth::common::ToString(ase.data_path_state).c_str());
2676     }
2677     ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
2678     ase.data_path_state = AudioStreamDataPathState::IDLE;
2679     ase.active = false;
2680     ase.cis_id = le_audio::kInvalidCisId;
2681     ase.cis_conn_hdl = 0;
2682   }
2683 }
2684 
GetMetadata(AudioContexts context_type,const std::vector<uint8_t> & ccid_list)2685 std::vector<uint8_t> LeAudioDevice::GetMetadata(
2686     AudioContexts context_type, const std::vector<uint8_t>& ccid_list) {
2687   std::vector<uint8_t> metadata;
2688 
2689   AppendMetadataLtvEntryForStreamingContext(metadata, context_type);
2690   AppendMetadataLtvEntryForCcidList(metadata, ccid_list);
2691 
2692   return std::move(metadata);
2693 }
2694 
IsMetadataChanged(AudioContexts context_type,const std::vector<uint8_t> & ccid_list)2695 bool LeAudioDevice::IsMetadataChanged(AudioContexts context_type,
2696                                       const std::vector<uint8_t>& ccid_list) {
2697   for (auto* ase = this->GetFirstActiveAse(); ase;
2698        ase = this->GetNextActiveAse(ase)) {
2699     if (this->GetMetadata(context_type, ccid_list) != ase->metadata)
2700       return true;
2701   }
2702 
2703   return false;
2704 }
2705 
Add(int group_id)2706 LeAudioDeviceGroup* LeAudioDeviceGroups::Add(int group_id) {
2707   /* Get first free group id */
2708   if (FindById(group_id)) {
2709     LOG(ERROR) << __func__
2710                << ", group already exists, id: " << loghex(group_id);
2711     return nullptr;
2712   }
2713 
2714   return (groups_.emplace_back(std::make_unique<LeAudioDeviceGroup>(group_id)))
2715       .get();
2716 }
2717 
Remove(int group_id)2718 void LeAudioDeviceGroups::Remove(int group_id) {
2719   auto iter = std::find_if(
2720       groups_.begin(), groups_.end(),
2721       [&group_id](auto const& group) { return group->group_id_ == group_id; });
2722 
2723   if (iter == groups_.end()) {
2724     LOG(ERROR) << __func__ << ", no such group_id: " << group_id;
2725     return;
2726   }
2727 
2728   groups_.erase(iter);
2729 }
2730 
FindById(int group_id)2731 LeAudioDeviceGroup* LeAudioDeviceGroups::FindById(int group_id) {
2732   auto iter = std::find_if(
2733       groups_.begin(), groups_.end(),
2734       [&group_id](auto const& group) { return group->group_id_ == group_id; });
2735 
2736   return (iter == groups_.end()) ? nullptr : iter->get();
2737 }
2738 
Cleanup(void)2739 void LeAudioDeviceGroups::Cleanup(void) {
2740   for (auto& g : groups_) {
2741     g->Cleanup();
2742   }
2743 
2744   groups_.clear();
2745 }
2746 
Dump(int fd,int active_group_id)2747 void LeAudioDeviceGroups::Dump(int fd, int active_group_id) {
2748   for (auto& g : groups_) {
2749     g->Dump(fd, active_group_id);
2750   }
2751 }
2752 
IsAnyInTransition(void)2753 bool LeAudioDeviceGroups::IsAnyInTransition(void) {
2754   for (auto& g : groups_) {
2755     if (g->IsInTransition()) {
2756       DLOG(INFO) << __func__ << " group: " << g->group_id_
2757                  << " is in transition";
2758       return true;
2759     }
2760   }
2761   return false;
2762 }
2763 
Size()2764 size_t LeAudioDeviceGroups::Size() { return (groups_.size()); }
2765 
GetGroupsIds(void)2766 std::vector<int> LeAudioDeviceGroups::GetGroupsIds(void) {
2767   std::vector<int> result;
2768 
2769   for (auto const& group : groups_) {
2770     result.push_back(group->group_id_);
2771   }
2772 
2773   return result;
2774 }
2775 
2776 /* LeAudioDevices Class methods implementation */
Add(const RawAddress & address,DeviceConnectState state,int group_id)2777 void LeAudioDevices::Add(const RawAddress& address, DeviceConnectState state,
2778                          int group_id) {
2779   auto device = FindByAddress(address);
2780   if (device != nullptr) {
2781     LOG(ERROR) << __func__ << ", address: " << address
2782                << " is already assigned to group: " << device->group_id_;
2783     return;
2784   }
2785 
2786   leAudioDevices_.emplace_back(
2787       std::make_shared<LeAudioDevice>(address, state, group_id));
2788 }
2789 
Remove(const RawAddress & address)2790 void LeAudioDevices::Remove(const RawAddress& address) {
2791   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2792                            [&address](auto const& leAudioDevice) {
2793                              return leAudioDevice->address_ == address;
2794                            });
2795 
2796   if (iter == leAudioDevices_.end()) {
2797     LOG(ERROR) << __func__ << ", no such address: " << address;
2798     return;
2799   }
2800 
2801   leAudioDevices_.erase(iter);
2802 }
2803 
FindByAddress(const RawAddress & address)2804 LeAudioDevice* LeAudioDevices::FindByAddress(const RawAddress& address) {
2805   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2806                            [&address](auto const& leAudioDevice) {
2807                              return leAudioDevice->address_ == address;
2808                            });
2809 
2810   return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
2811 }
2812 
GetByAddress(const RawAddress & address)2813 std::shared_ptr<LeAudioDevice> LeAudioDevices::GetByAddress(
2814     const RawAddress& address) {
2815   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2816                            [&address](auto const& leAudioDevice) {
2817                              return leAudioDevice->address_ == address;
2818                            });
2819 
2820   return (iter == leAudioDevices_.end()) ? nullptr : *iter;
2821 }
2822 
FindByConnId(uint16_t conn_id)2823 LeAudioDevice* LeAudioDevices::FindByConnId(uint16_t conn_id) {
2824   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2825                            [&conn_id](auto const& leAudioDevice) {
2826                              return leAudioDevice->conn_id_ == conn_id;
2827                            });
2828 
2829   return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
2830 }
2831 
FindByCisConnHdl(uint8_t cig_id,uint16_t conn_hdl)2832 LeAudioDevice* LeAudioDevices::FindByCisConnHdl(uint8_t cig_id,
2833                                                 uint16_t conn_hdl) {
2834   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2835                            [&conn_hdl, &cig_id](auto& d) {
2836                              LeAudioDevice* dev;
2837                              BidirectAsesPair ases;
2838 
2839                              dev = d.get();
2840                              if (dev->group_id_ != cig_id) {
2841                                return false;
2842                              }
2843 
2844                              ases = dev->GetAsesByCisConnHdl(conn_hdl);
2845                              if (ases.sink || ases.source)
2846                                return true;
2847                              else
2848                                return false;
2849                            });
2850 
2851   if (iter == leAudioDevices_.end()) return nullptr;
2852 
2853   return iter->get();
2854 }
2855 
SetInitialGroupAutoconnectState(int group_id,int gatt_if,tBTM_BLE_CONN_TYPE reconnection_mode,bool current_dev_autoconnect_flag)2856 void LeAudioDevices::SetInitialGroupAutoconnectState(
2857     int group_id, int gatt_if, tBTM_BLE_CONN_TYPE reconnection_mode,
2858     bool current_dev_autoconnect_flag) {
2859   if (!current_dev_autoconnect_flag) {
2860     /* If current device autoconnect flag is false, check if there is other
2861      * device in the group which is in autoconnect mode.
2862      * If yes, assume whole group is in autoconnect.
2863      */
2864     auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2865                              [&group_id](auto& d) {
2866                                LeAudioDevice* dev;
2867                                dev = d.get();
2868                                if (dev->group_id_ != group_id) {
2869                                  return false;
2870                                }
2871                                return dev->autoconnect_flag_;
2872                              });
2873 
2874     current_dev_autoconnect_flag = !(iter == leAudioDevices_.end());
2875   }
2876 
2877   if (!current_dev_autoconnect_flag) {
2878     return;
2879   }
2880 
2881   for (auto dev : leAudioDevices_) {
2882     if ((dev->group_id_ == group_id) &&
2883         (dev->GetConnectionState() == DeviceConnectState::DISCONNECTED)) {
2884       dev->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2885       dev->autoconnect_flag_ = true;
2886       btif_storage_set_leaudio_autoconnect(dev->address_, true);
2887       BTA_GATTC_Open(gatt_if, dev->address_, reconnection_mode, false);
2888     }
2889   }
2890 }
2891 
Size()2892 size_t LeAudioDevices::Size() { return (leAudioDevices_.size()); }
2893 
Dump(int fd,int group_id)2894 void LeAudioDevices::Dump(int fd, int group_id) {
2895   for (auto const& device : leAudioDevices_) {
2896     if (device->group_id_ == group_id) {
2897       device->Dump(fd);
2898     }
2899   }
2900 }
2901 
Cleanup(tGATT_IF client_if)2902 void LeAudioDevices::Cleanup(tGATT_IF client_if) {
2903   for (auto const& device : leAudioDevices_) {
2904     auto connection_state = device->GetConnectionState();
2905     if (connection_state == DeviceConnectState::DISCONNECTED) {
2906       continue;
2907     }
2908 
2909     if (connection_state == DeviceConnectState::CONNECTING_AUTOCONNECT) {
2910       BTA_GATTC_CancelOpen(client_if, device->address_, false);
2911     } else {
2912       BtaGattQueue::Clean(device->conn_id_);
2913       BTA_GATTC_Close(device->conn_id_);
2914       device->DisconnectAcl();
2915     }
2916   }
2917   leAudioDevices_.clear();
2918 }
2919 
2920 }  // namespace le_audio
2921