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