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 #include <bluetooth/log.h>
22 #include <com_android_bluetooth_flags.h>
23 
24 #include "acl_api.h"
25 #include "bta_gatt_queue.h"
26 #include "btif/include/btif_storage.h"
27 #include "common/strings.h"
28 #include "hci/controller_interface.h"
29 #include "internal_include/bt_trace.h"
30 #include "le_audio/codec_manager.h"
31 #include "le_audio/le_audio_types.h"
32 #include "le_audio_log_history.h"
33 #include "le_audio_utils.h"
34 #include "main/shim/entry.h"
35 #include "os/log.h"
36 #include "osi/include/properties.h"
37 
38 using bluetooth::hci::kIsoCigPhy1M;
39 using bluetooth::hci::kIsoCigPhy2M;
40 using bluetooth::le_audio::DeviceConnectState;
41 using bluetooth::le_audio::set_configurations::CodecConfigSetting;
42 using bluetooth::le_audio::types::ase;
43 using bluetooth::le_audio::types::AseState;
44 using bluetooth::le_audio::types::AudioContexts;
45 using bluetooth::le_audio::types::AudioLocations;
46 using bluetooth::le_audio::types::BidirectionalPair;
47 using bluetooth::le_audio::types::CisState;
48 using bluetooth::le_audio::types::DataPathState;
49 using bluetooth::le_audio::types::LeAudioContextType;
50 using bluetooth::le_audio::types::LeAudioCoreCodecConfig;
51 
52 namespace bluetooth::le_audio {
operator <<(std::ostream & os,const DeviceConnectState & state)53 std::ostream& operator<<(std::ostream& os, const DeviceConnectState& state) {
54   const char* char_value_ = "UNKNOWN";
55 
56   switch (state) {
57     case DeviceConnectState::CONNECTED:
58       char_value_ = "CONNECTED";
59       break;
60     case DeviceConnectState::DISCONNECTED:
61       char_value_ = "DISCONNECTED";
62       break;
63     case DeviceConnectState::REMOVING:
64       char_value_ = "REMOVING";
65       break;
66     case DeviceConnectState::DISCONNECTING:
67       char_value_ = "DISCONNECTING";
68       break;
69     case DeviceConnectState::DISCONNECTING_AND_RECOVER:
70       char_value_ = "DISCONNECTING_AND_RECOVER";
71       break;
72     case DeviceConnectState::CONNECTING_BY_USER:
73       char_value_ = "CONNECTING_BY_USER";
74       break;
75     case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
76       char_value_ = "CONNECTED_BY_USER_GETTING_READY";
77       break;
78     case DeviceConnectState::CONNECTING_AUTOCONNECT:
79       char_value_ = "CONNECTING_AUTOCONNECT";
80       break;
81     case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
82       char_value_ = "CONNECTED_AUTOCONNECT_GETTING_READY";
83       break;
84   }
85 
86   os << char_value_ << " ("
87      << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
88      << ")";
89   return os;
90 }
91 
GetFirstLeft(const AudioLocations & audio_locations)92 static uint32_t GetFirstLeft(const AudioLocations& audio_locations) {
93   uint32_t audio_location_ulong = audio_locations.to_ulong();
94 
95   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeft)
96     return codec_spec_conf::kLeAudioLocationFrontLeft;
97 
98   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackLeft)
99     return codec_spec_conf::kLeAudioLocationBackLeft;
100 
101   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftOfCenter)
102     return codec_spec_conf::kLeAudioLocationFrontLeftOfCenter;
103 
104   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideLeft)
105     return codec_spec_conf::kLeAudioLocationSideLeft;
106 
107   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontLeft)
108     return codec_spec_conf::kLeAudioLocationTopFrontLeft;
109 
110   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackLeft)
111     return codec_spec_conf::kLeAudioLocationTopBackLeft;
112 
113   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideLeft)
114     return codec_spec_conf::kLeAudioLocationTopSideLeft;
115 
116   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontLeft)
117     return codec_spec_conf::kLeAudioLocationBottomFrontLeft;
118 
119   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftWide)
120     return codec_spec_conf::kLeAudioLocationFrontLeftWide;
121 
122   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationLeftSurround)
123     return codec_spec_conf::kLeAudioLocationLeftSurround;
124 
125   return 0;
126 }
127 
GetFirstRight(const AudioLocations & audio_locations)128 static uint32_t GetFirstRight(const AudioLocations& audio_locations) {
129   uint32_t audio_location_ulong = audio_locations.to_ulong();
130 
131   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRight)
132     return codec_spec_conf::kLeAudioLocationFrontRight;
133 
134   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackRight)
135     return codec_spec_conf::kLeAudioLocationBackRight;
136 
137   if (audio_location_ulong &
138       codec_spec_conf::kLeAudioLocationFrontRightOfCenter)
139     return codec_spec_conf::kLeAudioLocationFrontRightOfCenter;
140 
141   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideRight)
142     return codec_spec_conf::kLeAudioLocationSideRight;
143 
144   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontRight)
145     return codec_spec_conf::kLeAudioLocationTopFrontRight;
146 
147   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackRight)
148     return codec_spec_conf::kLeAudioLocationTopBackRight;
149 
150   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideRight)
151     return codec_spec_conf::kLeAudioLocationTopSideRight;
152 
153   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontRight)
154     return codec_spec_conf::kLeAudioLocationBottomFrontRight;
155 
156   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRightWide)
157     return codec_spec_conf::kLeAudioLocationFrontRightWide;
158 
159   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationRightSurround)
160     return codec_spec_conf::kLeAudioLocationRightSurround;
161 
162   return 0;
163 }
164 
PickAudioLocation(types::LeAudioConfigurationStrategy strategy,const AudioLocations & device_locations,AudioLocations & group_locations)165 uint32_t PickAudioLocation(types::LeAudioConfigurationStrategy strategy,
166                            const AudioLocations& device_locations,
167                            AudioLocations& group_locations) {
168   log::debug("strategy: {}, locations: 0x{:x}, input group locations: 0x{:x}",
169              (int)strategy, device_locations.to_ulong(),
170              group_locations.to_ulong());
171 
172   auto is_left_not_yet_assigned =
173       !(group_locations.to_ulong() & codec_spec_conf::kLeAudioLocationAnyLeft);
174   auto is_right_not_yet_assigned =
175       !(group_locations.to_ulong() & codec_spec_conf::kLeAudioLocationAnyRight);
176   uint32_t left_device_loc = GetFirstLeft(device_locations);
177   uint32_t right_device_loc = GetFirstRight(device_locations);
178 
179   if (left_device_loc == 0 && right_device_loc == 0) {
180     log::warn("Can't find device able to render left  and right audio channel");
181   }
182 
183   switch (strategy) {
184     case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
185     case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
186       if (left_device_loc && is_left_not_yet_assigned) {
187         group_locations |= left_device_loc;
188         return left_device_loc;
189       }
190 
191       if (right_device_loc && is_right_not_yet_assigned) {
192         group_locations |= right_device_loc;
193         return right_device_loc;
194       }
195       break;
196 
197     case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
198       if (left_device_loc && right_device_loc) {
199         group_locations |= left_device_loc | right_device_loc;
200         return left_device_loc | right_device_loc;
201       }
202       break;
203     default:
204       log::fatal("Unknown strategy: {}", strategy);
205       return 0;
206   }
207 
208   log::error(
209       "Can't find device for left/right channel. Strategy: {}, "
210       "device_locations: {:x}, output group_locations: {:x}.",
211       strategy, device_locations.to_ulong(), group_locations.to_ulong());
212 
213   /* Return either any left or any right audio location. It might result with
214    * multiple devices within the group having the same location.
215    */
216   return left_device_loc ? left_device_loc : right_device_loc;
217 }
218 
IsAudioSetConfigurationSupported(const set_configurations::AudioSetConfiguration * audio_set_conf) const219 bool LeAudioDevice::IsAudioSetConfigurationSupported(
220     const set_configurations::AudioSetConfiguration* audio_set_conf) const {
221   for (auto direction : {le_audio::types::kLeAudioDirectionSink,
222                          le_audio::types::kLeAudioDirectionSource}) {
223     const auto& confs = audio_set_conf->confs.get(direction);
224     if (confs.size() == 0) continue;
225 
226     log::info("Looking for requirements: {} - {}", audio_set_conf->name,
227               direction == 1 ? "snk" : "src");
228 
229     auto const& pacs =
230         (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;
231     for (const auto& ent : confs) {
232       if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
233         log::info("Configuration is NOT supported by device {}", address_);
234         return false;
235       }
236     }
237   }
238 
239   log::info("Configuration is supported by device {}", address_);
240   return true;
241 }
242 
ConfigureAses(const set_configurations::AudioSetConfiguration * audio_set_conf,uint8_t num_of_devices,uint8_t direction,LeAudioContextType context_type,uint8_t * number_of_already_active_group_ase,AudioLocations & group_audio_locations_memo,const AudioContexts & metadata_context_types,const std::vector<uint8_t> & ccid_lists,bool reuse_cis_id)243 bool LeAudioDevice::ConfigureAses(
244     const set_configurations::AudioSetConfiguration* audio_set_conf,
245     uint8_t num_of_devices, uint8_t direction, LeAudioContextType context_type,
246     uint8_t* number_of_already_active_group_ase,
247     AudioLocations& group_audio_locations_memo,
248     const AudioContexts& metadata_context_types,
249     const std::vector<uint8_t>& ccid_lists, bool reuse_cis_id) {
250   /* First try to use the already configured ASE */
251   auto ase = GetFirstActiveAseByDirection(direction);
252   if (ase) {
253     log::info("{}, using an already active ASE id={}", address_, ase->id);
254   } else {
255     ase = GetFirstInactiveAse(direction, reuse_cis_id);
256   }
257 
258   if (!ase) {
259     log::error("{}, unable to find an ASE to configure", address_);
260     PrintDebugState();
261     return false;
262   }
263 
264   auto audio_locations = (direction == types::kLeAudioDirectionSink)
265                              ? snk_audio_locations_
266                              : src_audio_locations_;
267 
268   auto const& group_ase_configs = audio_set_conf->confs.get(direction);
269   std::vector<set_configurations::AseConfiguration> ase_configs;
270   std::copy_if(group_ase_configs.cbegin(), group_ase_configs.cend(),
271                std::back_inserter(ase_configs),
272                [&audio_locations](auto const& cfg) {
273                  /* Pass as matching if config has no allocation to match
274                   * (the legacy json config provider). Otherwise, with the codec
275                   * extensibility feature enabled, we receive ASE configurations
276                   * for the whole group and we should filter them by audio
277                   * allocations to match with the locations supported by a
278                   * particular device.
279                   */
280                  auto config = cfg.codec.params.GetAsCoreCodecConfig();
281                  if (!config.audio_channel_allocation.has_value()) return true;
282 
283                  // Filter-out not matching audio locations
284                  return (cfg.codec.params.GetAsCoreCodecConfig()
285                              .audio_channel_allocation.value() &
286                          audio_locations.to_ulong()) != 0;
287                });
288 
289   auto const& pacs =
290       (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;
291   for (size_t i = 0; i < ase_configs.size() && ase; ++i) {
292     auto const& ase_cfg = ase_configs.at(i);
293     if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) &&
294         !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
295       return false;
296     }
297   }
298 
299   /* The number_of_already_active_group_ase keeps all the active ases
300    * in other devices in the group for the given direction.
301    * This function counts active ases only for this device, and we count here
302    * new active ases and already active ases which we want to reuse in the
303    * scenario
304    */
305   uint8_t active_ases = *number_of_already_active_group_ase;
306 
307   // Before we activate the ASEs, make sure we have the right configuration
308   // Check for matching PACs only if we know that the LTV format is being used.
309   uint8_t max_required_ase_per_dev = ase_configs.size() / num_of_devices +
310                                      (ase_configs.size() % num_of_devices);
311   int needed_ase =
312       std::min((int)(max_required_ase_per_dev), (int)(ase_configs.size()));
313 
314   for (int i = 0; i < needed_ase; ++i) {
315     auto const& ase_cfg = ase_configs.at(i);
316     if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) &&
317         !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
318       log::error("{}, no matching PAC found. Stop the activation.", address_);
319       return false;
320     }
321   }
322 
323   auto strategy =
324       utils::GetStrategyForAseConfig(group_ase_configs, num_of_devices);
325 
326   // Make sure we configure a single microphone if Dual Bidir SWB is not
327   // supported.
328   if (direction == types::kLeAudioDirectionSource &&
329       !CodecManager::GetInstance()->IsDualBiDirSwbSupported() &&
330       (active_ases != 0)) {
331     if (CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(
332             *audio_set_conf)) {
333       log::error(
334           "{}, trying to configure the dual bidir SWB, but the feature is "
335           "disabled. This should not happen! Skipping ASE activation.",
336           address_);
337       return true;
338     }
339   }
340 
341   for (int i = 0; i < needed_ase && ase; ++i) {
342     auto const& ase_cfg = ase_configs.at(i);
343     ase->active = true;
344     ase->configured_for_context_type = context_type;
345     ase->data_path_configuration = ase_cfg.data_path_configuration;
346     active_ases++;
347 
348     /* In case of late connect, we could be here for STREAMING ase.
349      * in such case, it is needed to mark ase as known active ase which
350      * is important to validate scenario and is done already few lines above.
351      * Nothing more to do is needed here.
352      */
353     if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
354       if (ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED)
355         ase->reconfigure = true;
356 
357       ase->target_latency = ase_cfg.qos.target_latency;
358       ase->codec_id = ase_cfg.codec.id;
359       ase->codec_config = ase_cfg.codec.params;
360       ase->vendor_codec_config = ase_cfg.codec.vendor_params;
361       ase->channel_count = ase_cfg.codec.channel_count_per_iso_stream;
362 
363       /* Let's choose audio channel allocation if not set */
364       ase->codec_config.Add(
365           codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
366           PickAudioLocation(strategy, audio_locations,
367                             group_audio_locations_memo));
368 
369       /* Get default value if no requirement for specific frame blocks per sdu
370        */
371       if (utils::IsCodecUsingLtvFormat(ase->codec_id) &&
372           !ase->codec_config.Find(
373               codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu)) {
374         ase->codec_config.Add(
375             codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
376             GetMaxCodecFramesPerSduFromPac(
377                 utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)));
378       }
379 
380       ase->qos_config.sdu_interval = ase_cfg.qos.sduIntervalUs;
381       ase->qos_config.max_sdu_size = ase_cfg.qos.maxSdu;
382       ase->qos_config.retrans_nb = ase_cfg.qos.retransmission_number;
383       ase->qos_config.max_transport_latency = ase_cfg.qos.max_transport_latency;
384 
385       SetMetadataToAse(ase, metadata_context_types, ccid_lists);
386     }
387 
388     log::debug(
389         "device={}, activated ASE id={}, direction={}, max_sdu_size={}, "
390         "cis_id={}, target_latency={}",
391         address_, ase->id, direction == 1 ? "snk" : "src",
392         ase->qos_config.max_sdu_size, ase->cis_id, ase_cfg.qos.target_latency);
393 
394     /* Try to use the already active ASE */
395     ase = GetNextActiveAseWithSameDirection(ase);
396     if (ase == nullptr) {
397       ase = GetFirstInactiveAse(direction, reuse_cis_id);
398     }
399   }
400 
401   *number_of_already_active_group_ase = active_ases;
402   return true;
403 }
404 
405 /* LeAudioDevice Class methods implementation */
SetConnectionState(DeviceConnectState state)406 void LeAudioDevice::SetConnectionState(DeviceConnectState state) {
407   log::debug("{}, {} --> {}", address_,
408              bluetooth::common::ToString(connection_state_),
409              bluetooth::common::ToString(state));
410   LeAudioLogHistory::Get()->AddLogHistory(
411       kLogConnectionTag, group_id_, address_,
412       bluetooth::common::ToString(connection_state_) + " -> ",
413       "->" + bluetooth::common::ToString(state));
414   connection_state_ = state;
415 }
416 
GetConnectionState(void)417 DeviceConnectState LeAudioDevice::GetConnectionState(void) {
418   return connection_state_;
419 }
420 
ClearPACs(void)421 void LeAudioDevice::ClearPACs(void) {
422   snk_pacs_.clear();
423   src_pacs_.clear();
424 }
425 
~LeAudioDevice(void)426 LeAudioDevice::~LeAudioDevice(void) {
427   alarm_free(link_quality_timer);
428   for (auto& ase : ases_) {
429     alarm_free(ase.autonomous_operation_timer_);
430   }
431   this->ClearPACs();
432 }
433 
ParseHeadtrackingCodec(const struct types::acs_ac_record & pac)434 void LeAudioDevice::ParseHeadtrackingCodec(
435     const struct types::acs_ac_record& pac) {
436   if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
437     return;
438   }
439 
440   if (pac.codec_id == types::kLeAudioCodecHeadtracking) {
441     log::info("Headtracking supported");
442 
443     // Assume LE-ISO is supported if metadata is not available
444     dsa_.modes = {
445         DsaMode::DISABLED,
446         DsaMode::ISO_SW,
447         DsaMode::ISO_HW,
448     };
449 
450     if (!com::android::bluetooth::flags::headtracker_codec_capability()) {
451       return;
452     }
453 
454     /*
455      * Android Headtracker Codec Metadata description
456      *   length: 5
457      *   type: 0xFF
458      *   value: {
459      *     vendorId: 0x00E0 (Google)
460      *     vendorSpecificMetadata: {
461      *       length: 1
462      *       type: 1 (Headtracker supported transports)
463      *       value: x
464      *     }
465      *   }
466      */
467     std::vector<uint8_t> ltv = pac.metadata;
468     if (ltv.size() < 7) {
469       log::info("{}, headtracker codec does not have metadata", address_);
470       return;
471     }
472 
473     if (ltv[0] < 5 || ltv[1] != types::kLeAudioMetadataTypeVendorSpecific ||
474         ltv[2] != (types::kLeAudioVendorCompanyIdGoogle & 0xFF) ||
475         ltv[3] != (types::kLeAudioVendorCompanyIdGoogle >> 8) ||
476         ltv[4] != types::kLeAudioMetadataHeadtrackerTransportLen ||
477         ltv[5] != types::kLeAudioMetadataHeadtrackerTransportVal) {
478       log::warn("{}, headtracker codec metadata invalid", address_);
479       return;
480     }
481 
482     uint8_t supported_transports = ltv[6];
483     DsaModes dsa_modes = {DsaMode::DISABLED};
484 
485     if ((supported_transports &
486          types::kLeAudioMetadataHeadtrackerTransportLeAcl) != 0) {
487       log::debug("{}, headtracking supported over LE-ACL", address_);
488       dsa_modes.push_back(DsaMode::ACL);
489     }
490 
491     if ((supported_transports &
492          types::kLeAudioMetadataHeadtrackerTransportLeIso) != 0) {
493       log::debug("{}, headtracking supported over LE-ISO", address_);
494       dsa_modes.push_back(DsaMode::ISO_SW);
495       dsa_modes.push_back(DsaMode::ISO_HW);
496     }
497 
498     dsa_.modes = dsa_modes;
499   }
500 }
501 
RegisterPACs(std::vector<struct types::acs_ac_record> * pac_db,std::vector<struct types::acs_ac_record> * pac_recs)502 void LeAudioDevice::RegisterPACs(
503     std::vector<struct types::acs_ac_record>* pac_db,
504     std::vector<struct types::acs_ac_record>* pac_recs) {
505   /* Clear PAC database for characteristic in case if re-read, indicated */
506   if (!pac_db->empty()) {
507     log::debug("{}, upgrade PACs for characteristic", address_);
508     pac_db->clear();
509   }
510 
511   dsa_.modes = {DsaMode::DISABLED};
512 
513   /* TODO wrap this logging part with debug flag */
514   for (const struct types::acs_ac_record& pac : *pac_recs) {
515     std::stringstream debug_str;
516     debug_str << "Registering PAC"
517               << "\n\tCoding format: " << loghex(pac.codec_id.coding_format)
518               << "\n\tVendor codec company ID: "
519               << loghex(pac.codec_id.vendor_company_id)
520               << "\n\tVendor codec ID: " << loghex(pac.codec_id.vendor_codec_id)
521               << "\n\tCodec spec caps:\n";
522     if (utils::IsCodecUsingLtvFormat(pac.codec_id) &&
523         !pac.codec_spec_caps.IsEmpty()) {
524       debug_str << pac.codec_spec_caps.ToString(
525           "", types::CodecCapabilitiesLtvFormat);
526     } else {
527       debug_str << base::HexEncode(pac.codec_spec_caps_raw.data(),
528                                    pac.codec_spec_caps_raw.size());
529     }
530     debug_str << "\n\tMetadata: "
531               << base::HexEncode(pac.metadata.data(), pac.metadata.size());
532     log::debug("{}", debug_str.str());
533 
534     ParseHeadtrackingCodec(pac);
535   }
536 
537   pac_db->insert(pac_db->begin(), pac_recs->begin(), pac_recs->end());
538 }
539 
GetAseByValHandle(uint16_t val_hdl)540 struct ase* LeAudioDevice::GetAseByValHandle(uint16_t val_hdl) {
541   auto iter = std::find_if(
542       ases_.begin(), ases_.end(),
543       [&val_hdl](const auto& ase) { return ase.hdls.val_hdl == val_hdl; });
544 
545   return (iter == ases_.end()) ? nullptr : &(*iter);
546 }
547 
GetAseCount(uint8_t direction)548 int LeAudioDevice::GetAseCount(uint8_t direction) {
549   return std::count_if(ases_.begin(), ases_.end(), [direction](const auto& a) {
550     return a.direction == direction;
551   });
552 }
553 
GetFirstAseWithState(uint8_t direction,AseState state)554 struct ase* LeAudioDevice::GetFirstAseWithState(uint8_t direction,
555                                                 AseState state) {
556   auto iter = std::find_if(
557       ases_.begin(), ases_.end(), [direction, state](const auto& ase) {
558         return ((ase.direction == direction) && (ase.state == state));
559       });
560 
561   return (iter == ases_.end()) ? nullptr : &(*iter);
562 }
563 
GetFirstActiveAse(void)564 struct ase* LeAudioDevice::GetFirstActiveAse(void) {
565   auto iter = std::find_if(ases_.begin(), ases_.end(),
566                            [](const auto& ase) { return ase.active; });
567 
568   return (iter == ases_.end()) ? nullptr : &(*iter);
569 }
570 
GetFirstActiveAseByDirection(uint8_t direction)571 struct ase* LeAudioDevice::GetFirstActiveAseByDirection(uint8_t direction) {
572   auto iter =
573       std::find_if(ases_.begin(), ases_.end(), [direction](const auto& ase) {
574         return (ase.active && (ase.direction == direction));
575       });
576 
577   return (iter == ases_.end()) ? nullptr : &(*iter);
578 }
579 
GetNextActiveAseWithSameDirection(struct ase * base_ase)580 struct ase* LeAudioDevice::GetNextActiveAseWithSameDirection(
581     struct ase* base_ase) {
582   auto iter = std::find_if(ases_.begin(), ases_.end(),
583                            [&base_ase](auto& ase) { return base_ase == &ase; });
584 
585   /* Invalid ase given */
586   if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1)
587     return nullptr;
588 
589   iter =
590       std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
591         return ase.active && (*iter).direction == ase.direction;
592       });
593 
594   return (iter == ases_.end()) ? nullptr : &(*iter);
595 }
596 
GetNextActiveAseWithDifferentDirection(struct ase * base_ase)597 struct ase* LeAudioDevice::GetNextActiveAseWithDifferentDirection(
598     struct ase* base_ase) {
599   auto iter = std::find_if(ases_.begin(), ases_.end(),
600                            [&base_ase](auto& ase) { return base_ase == &ase; });
601 
602   /* Invalid ase given */
603   if (std::distance(iter, ases_.end()) < 1) {
604     log::debug("{}, ASE {} does not use bidirectional CIS", address_,
605                base_ase->id);
606     return nullptr;
607   }
608 
609   iter =
610       std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
611         return ase.active && iter->direction != ase.direction;
612       });
613 
614   if (iter == ases_.end()) {
615     return nullptr;
616   }
617 
618   return &(*iter);
619 }
620 
GetFirstActiveAseByCisAndDataPathState(CisState cis_state,DataPathState data_path_state)621 struct ase* LeAudioDevice::GetFirstActiveAseByCisAndDataPathState(
622     CisState cis_state, DataPathState data_path_state) {
623   auto iter = std::find_if(ases_.begin(), ases_.end(),
624                            [cis_state, data_path_state](const auto& ase) {
625                              return (ase.active &&
626                                      (ase.data_path_state == data_path_state) &&
627                                      (ase.cis_state == cis_state));
628                            });
629 
630   return (iter == ases_.end()) ? nullptr : &(*iter);
631 }
632 
GetFirstInactiveAse(uint8_t direction,bool reuse_cis_id)633 struct ase* LeAudioDevice::GetFirstInactiveAse(uint8_t direction,
634                                                bool reuse_cis_id) {
635   auto iter = std::find_if(ases_.begin(), ases_.end(),
636                            [direction, reuse_cis_id](const auto& ase) {
637                              if (ase.active || (ase.direction != direction))
638                                return false;
639 
640                              if (!reuse_cis_id) return true;
641 
642                              return (ase.cis_id != kInvalidCisId);
643                            });
644   /* If ASE is found, return it */
645   if (iter != ases_.end()) return &(*iter);
646 
647   /* If reuse was not set, that means there is no inactive ASE available. */
648   if (!reuse_cis_id) return nullptr;
649 
650   /* Since there is no ASE with assigned CIS ID, it means new configuration
651    * needs more ASEs then it was configured before.
652    * Let's find just inactive one */
653   iter = std::find_if(ases_.begin(), ases_.end(),
654                       [direction](const auto& ase) {
655                         if (ase.active || (ase.direction != direction))
656                           return false;
657                         return true;
658                       });
659 
660   return (iter == ases_.end()) ? nullptr : &(*iter);
661 }
662 
GetNextActiveAse(struct ase * base_ase)663 struct ase* LeAudioDevice::GetNextActiveAse(struct ase* base_ase) {
664   auto iter = std::find_if(ases_.begin(), ases_.end(),
665                            [&base_ase](auto& ase) { return base_ase == &ase; });
666 
667   /* Invalid ase given */
668   if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1)
669     return nullptr;
670 
671   iter = std::find_if(std::next(iter, 1), ases_.end(),
672                       [](const auto& ase) { return ase.active; });
673 
674   return (iter == ases_.end()) ? nullptr : &(*iter);
675 }
676 
GetAseToMatchBidirectionCis(struct ase * base_ase)677 struct ase* LeAudioDevice::GetAseToMatchBidirectionCis(struct ase* base_ase) {
678   auto iter = std::find_if(ases_.begin(), ases_.end(), [&base_ase](auto& ase) {
679     return (base_ase->cis_conn_hdl == ase.cis_conn_hdl) &&
680            (base_ase->direction != ase.direction);
681   });
682   return (iter == ases_.end()) ? nullptr : &(*iter);
683 }
684 
GetAsesByCisConnHdl(uint16_t conn_hdl)685 BidirectionalPair<struct ase*> LeAudioDevice::GetAsesByCisConnHdl(
686     uint16_t conn_hdl) {
687   BidirectionalPair<struct ase*> ases = {nullptr, nullptr};
688 
689   for (auto& ase : ases_) {
690     if (ase.cis_conn_hdl == conn_hdl) {
691       if (ase.direction == types::kLeAudioDirectionSink) {
692         ases.sink = &ase;
693       } else {
694         ases.source = &ase;
695       }
696     }
697   }
698 
699   return ases;
700 }
701 
GetAsesByCisId(uint8_t cis_id)702 BidirectionalPair<struct ase*> LeAudioDevice::GetAsesByCisId(uint8_t cis_id) {
703   BidirectionalPair<struct ase*> ases = {nullptr, nullptr};
704 
705   for (auto& ase : ases_) {
706     if (ase.cis_id == cis_id) {
707       if (ase.direction == types::kLeAudioDirectionSink) {
708         ases.sink = &ase;
709       } else {
710         ases.source = &ase;
711       }
712     }
713   }
714 
715   return ases;
716 }
717 
HaveActiveAse(void)718 bool LeAudioDevice::HaveActiveAse(void) {
719   auto iter = std::find_if(ases_.begin(), ases_.end(),
720                            [](const auto& ase) { return ase.active; });
721 
722   return iter != ases_.end();
723 }
724 
HaveAnyUnconfiguredAses(void)725 bool LeAudioDevice::HaveAnyUnconfiguredAses(void) {
726   /* In configuring state when active in Idle or Configured and reconfigure */
727   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
728     if (!ase.active) return false;
729 
730     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE ||
731         ((ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) &&
732          ase.reconfigure))
733       return true;
734 
735     return false;
736   });
737 
738   return iter != ases_.end();
739 }
740 
HaveAllActiveAsesSameState(AseState state)741 bool LeAudioDevice::HaveAllActiveAsesSameState(AseState state) {
742   log::verbose("{}", address_);
743   auto iter =
744       std::find_if(ases_.begin(), ases_.end(), [&state](const auto& ase) {
745         log::verbose("ASE id: {}, active: {}, state: {}", ase.id, ase.active,
746                      bluetooth::common::ToString(ase.state));
747         return ase.active && (ase.state != state);
748       });
749 
750   return iter == ases_.end();
751 }
752 
HaveAllActiveAsesSameDataPathState(types::DataPathState state) const753 bool LeAudioDevice::HaveAllActiveAsesSameDataPathState(
754     types::DataPathState state) const {
755   log::verbose("{}", address_);
756   auto iter =
757       std::find_if(ases_.begin(), ases_.end(), [&state](const auto& ase) {
758         log::verbose("ASE id: {}, active: {}, state: {}", ase.id, ase.active,
759                      bluetooth::common::ToString(ase.data_path_state));
760         return ase.active && (ase.data_path_state != state);
761       });
762 
763   return iter == ases_.end();
764 }
765 
IsReadyToCreateStream(void)766 bool LeAudioDevice::IsReadyToCreateStream(void) {
767   log::verbose("{}", address_);
768   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
769     if (!ase.active) return false;
770 
771     log::verbose("ASE id: {}, state: {}, direction: {}", ase.id,
772                  bluetooth::common::ToString(ase.state), ase.direction);
773     if (ase.direction == types::kLeAudioDirectionSink &&
774         (ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING &&
775          ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING))
776       return true;
777 
778     if (ase.direction == types::kLeAudioDirectionSource &&
779         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING)
780       return true;
781 
782     return false;
783   });
784 
785   return iter == ases_.end();
786 }
787 
IsReadyToSuspendStream(void)788 bool LeAudioDevice::IsReadyToSuspendStream(void) {
789   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
790     if (!ase.active) return false;
791 
792     if (ase.direction == types::kLeAudioDirectionSink &&
793         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED)
794       return true;
795 
796     if (ase.direction == types::kLeAudioDirectionSource &&
797         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING)
798       return true;
799 
800     return false;
801   });
802 
803   return iter == ases_.end();
804 }
805 
HaveAllActiveAsesCisEst(void) const806 bool LeAudioDevice::HaveAllActiveAsesCisEst(void) const {
807   if (ases_.empty()) {
808     log::warn("No ases for device {}", address_);
809     /* If there is no ASEs at all, it means we are good here - meaning, it is
810      * not waiting for any CIS to be established.
811      */
812     return true;
813   }
814 
815   log::verbose("{}", address_);
816 
817   bool has_active_ase = false;
818   auto iter = std::find_if(ases_.begin(), ases_.end(), [&](const auto& ase) {
819     if (!has_active_ase && ase.active) {
820       has_active_ase = true;
821     }
822     log::verbose("ASE id: {}, cis_state: {}, direction: {}", ase.id,
823                  bluetooth::common::ToString(ase.cis_state), ase.direction);
824 
825     return ase.active && (ase.cis_state != CisState::CONNECTED);
826   });
827 
828   return iter == ases_.end() && has_active_ase;
829 }
830 
HaveAnyCisConnected(void)831 bool LeAudioDevice::HaveAnyCisConnected(void) {
832   /* Pending and Disconnecting is considered as connected in this function */
833   for (auto const ase : ases_) {
834     if (ase.cis_state == CisState::CONNECTED ||
835         ase.cis_state == CisState::CONNECTING ||
836         ase.cis_state == CisState::DISCONNECTING) {
837       return true;
838     }
839   }
840   return false;
841 }
842 
GetSupportedAudioChannelCounts(uint8_t direction) const843 uint8_t LeAudioDevice::GetSupportedAudioChannelCounts(uint8_t direction) const {
844   auto& pacs =
845       direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;
846 
847   if (pacs.size() == 0) {
848     log::error("{}, missing PAC for direction {}", address_, direction);
849     return 0;
850   }
851 
852   for (const auto& pac_tuple : pacs) {
853     /* Get PAC records from tuple as second element from tuple */
854     auto& pac_recs = std::get<1>(pac_tuple);
855 
856     for (const auto pac : pac_recs) {
857       if (!utils::IsCodecUsingLtvFormat(pac.codec_id)) {
858         log::warn(" {} Unknown codec PAC record for codec: {}", address_,
859                   bluetooth::common::ToString(pac.codec_id));
860         continue;
861       }
862       log::assert_that(
863           !pac.codec_spec_caps.IsEmpty(),
864           "Codec specific capabilities are not parsed approprietly.");
865 
866       auto supported_channel_count_ltv = pac.codec_spec_caps.Find(
867           codec_spec_caps::kLeAudioLtvTypeSupportedAudioChannelCounts);
868 
869       if (supported_channel_count_ltv == std::nullopt ||
870           supported_channel_count_ltv->size() == 0L) {
871         return 1;
872       }
873 
874       return VEC_UINT8_TO_UINT8(supported_channel_count_ltv.value());
875     };
876   }
877 
878   return 0;
879 }
880 
881 /**
882  * Returns supported PHY's bitfield
883  */
GetPhyBitmask(void) const884 uint8_t LeAudioDevice::GetPhyBitmask(void) const {
885   uint8_t phy_bitfield = kIsoCigPhy1M;
886 
887   if (BTM_IsPhy2mSupported(address_, BT_TRANSPORT_LE))
888     phy_bitfield |= kIsoCigPhy2M;
889 
890   return phy_bitfield;
891 }
892 
PrintDebugState(void)893 void LeAudioDevice::PrintDebugState(void) {
894   std::stringstream debug_str;
895 
896   debug_str << " address: " << address_ << ", "
897             << bluetooth::common::ToString(connection_state_)
898             << ", conn_id: " << +conn_id_ << ", mtu: " << +mtu_
899             << ", num_of_ase: " << static_cast<int>(ases_.size());
900 
901   if (ases_.size() > 0) {
902     debug_str << "\n  == ASEs == ";
903     for (auto& ase : ases_) {
904       debug_str
905           << "\n  id: " << +ase.id << ", active: " << ase.active << ", dir: "
906           << (ase.direction == types::kLeAudioDirectionSink ? "sink" : "source")
907           << ", state: " << bluetooth::common::ToString(ase.state)
908           << ", cis_id: " << +ase.cis_id
909           << ", cis_handle: " << +ase.cis_conn_hdl
910           << ", cis_state: " << bluetooth::common::ToString(ase.cis_state)
911           << ", data_path_state: "
912           << bluetooth::common::ToString(ase.data_path_state)
913           << "\n ase max_latency: " << +ase.qos_config.max_transport_latency
914           << ", rtn: " << +ase.qos_config.retrans_nb
915           << ", max_sdu: " << +ase.qos_config.max_sdu_size
916           << ", sdu_interval: " << +ase.qos_config.sdu_interval
917           << ", presentation_delay: " << +ase.qos_config.presentation_delay
918           << ", framing: " << +ase.qos_config.framing
919           << ", phy: " << +ase.qos_config.phy
920           << ", target latency: " << +ase.target_latency
921           << ", reconfigure: " << ase.reconfigure << "\n";
922     }
923   }
924 
925   log::info("{}", debug_str.str());
926 }
927 
GetPreferredPhyBitmask(uint8_t preferred_phy) const928 uint8_t LeAudioDevice::GetPreferredPhyBitmask(uint8_t preferred_phy) const {
929   // Start with full local phy support
930   uint8_t phy_bitmask = bluetooth::hci::kIsoCigPhy1M;
931   if (bluetooth::shim::GetController()->SupportsBle2mPhy())
932     phy_bitmask |= bluetooth::hci::kIsoCigPhy2M;
933   if (bluetooth::shim::GetController()->SupportsBleCodedPhy())
934     phy_bitmask |= bluetooth::hci::kIsoCigPhyC;
935 
936   // Check against the remote device support
937   phy_bitmask &= GetPhyBitmask();
938 
939   // Take the preferences if possible
940   if (preferred_phy && (phy_bitmask & preferred_phy)) {
941     phy_bitmask &= preferred_phy;
942     log::debug("{},  using ASE preferred phy 0x{:02x}", address_,
943                static_cast<int>(phy_bitmask));
944   } else {
945     log::warn(
946         " {}, ASE preferred 0x{:02x} has nothing common with phy_bitfield  "
947         "0x{:02x}",
948         address_, static_cast<int>(preferred_phy),
949         static_cast<int>(phy_bitmask));
950   }
951   return phy_bitmask;
952 }
953 
DumpPacsDebugState(std::stringstream & stream,types::PublishedAudioCapabilities pacs)954 void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream,
955                                        types::PublishedAudioCapabilities pacs) {
956   if (pacs.size() > 0) {
957     for (auto& pac : pacs) {
958       stream << "\n\t\tvalue handle: " << loghex(std::get<0>(pac).val_hdl)
959              << " / CCC handle: " << loghex(std::get<0>(pac).ccc_hdl);
960 
961       for (auto& record : std::get<1>(pac)) {
962         stream << "\n\n\t\tCodecId(Coding format: "
963                << static_cast<int>(record.codec_id.coding_format)
964                << ", Vendor company ID: "
965                << static_cast<int>(record.codec_id.vendor_company_id)
966                << ", Vendor codec ID: "
967                << static_cast<int>(record.codec_id.vendor_codec_id) << ")";
968         stream << "\n\t\tCodec specific capabilities:\n";
969         if (utils::IsCodecUsingLtvFormat(record.codec_id)) {
970           stream << record.codec_spec_caps.ToString(
971               "\t\t\t", types::CodecCapabilitiesLtvFormat);
972         } else {
973           stream << "\t\t\t"
974                  << base::HexEncode(record.codec_spec_caps_raw.data(),
975                                     record.codec_spec_caps_raw.size());
976         }
977         stream << "\t\tMetadata: "
978                << base::HexEncode(record.metadata.data(),
979                                   record.metadata.size());
980       }
981     }
982   }
983 }
984 
DumpPacsDebugState(std::stringstream & stream)985 void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream) {
986   stream << "\n\tSink PACs";
987   DumpPacsDebugState(stream, snk_pacs_);
988   stream << "\n\tSource PACs";
989   DumpPacsDebugState(stream, src_pacs_);
990 }
991 
locationToString(uint32_t location)992 static std::string locationToString(uint32_t location) {
993   std::string result_str = "unknown location";
994 
995   if (location & codec_spec_conf::kLeAudioLocationAnyLeft &&
996       location & codec_spec_conf::kLeAudioLocationAnyRight) {
997     std::string location_left_right = "left/right";
998     result_str.swap(location_left_right);
999   } else if (location & codec_spec_conf::kLeAudioLocationAnyLeft) {
1000     std::string location_left = "left";
1001     result_str.swap(location_left);
1002   } else if (location & codec_spec_conf::kLeAudioLocationAnyRight) {
1003     std::string location_right = "right";
1004     result_str.swap(location_right);
1005   }
1006 
1007   return result_str;
1008 }
1009 
Dump(int fd)1010 void LeAudioDevice::Dump(int fd) {
1011   uint16_t acl_handle = BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
1012   std::string snk_location = locationToString(snk_audio_locations_.to_ulong());
1013   std::string src_location = locationToString(src_audio_locations_.to_ulong());
1014 
1015   std::stringstream stream;
1016   stream << "\n\taddress: " << ADDRESS_TO_LOGGABLE_STR(address_) << ": "
1017          << connection_state_ << ": "
1018          << (conn_id_ == GATT_INVALID_CONN_ID ? "" : std::to_string(conn_id_))
1019          << ", acl_handle: " << std::to_string(acl_handle)
1020          << ", snk_location: " << snk_location
1021          << ", src_location: " << src_location << ",\t"
1022          << (encrypted_ ? "Encrypted" : "Unecrypted")
1023          << ",mtu: " << std::to_string(mtu_)
1024          << "\n\tnumber of ases_: " << static_cast<int>(ases_.size());
1025 
1026   if (ases_.size() > 0) {
1027     stream << "\n\t== ASEs == \n\t";
1028     stream << "id  active dir     cis_id  cis_handle  sdu  latency rtn  "
1029               "cis_state data_path_state";
1030     for (auto& ase : ases_) {
1031       stream << std::setfill('\x20') << "\n\t" << std::left << std::setw(4)
1032              << static_cast<int>(ase.id) << std::left << std::setw(7)
1033              << (ase.active ? "true" : "false") << std::left << std::setw(8)
1034              << (ase.direction == types::kLeAudioDirectionSink ? "sink"
1035                                                                : "source")
1036              << std::left << std::setw(8) << static_cast<int>(ase.cis_id)
1037              << std::left << std::setw(12) << ase.cis_conn_hdl << std::left
1038              << std::setw(5) << ase.qos_config.max_sdu_size << std::left
1039              << std::setw(8) << ase.qos_config.max_transport_latency
1040              << std::left << std::setw(5)
1041              << static_cast<int>(ase.qos_config.retrans_nb) << std::left
1042              << std::setw(10) << bluetooth::common::ToString(ase.cis_state)
1043              << std::setw(12)
1044              << bluetooth::common::ToString(ase.data_path_state);
1045     }
1046   }
1047 
1048   stream << "\n\t====";
1049 
1050   dprintf(fd, "%s", stream.str().c_str());
1051 }
1052 
DisconnectAcl(void)1053 void LeAudioDevice::DisconnectAcl(void) {
1054   if (conn_id_ == GATT_INVALID_CONN_ID) return;
1055 
1056   uint16_t acl_handle =
1057       BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
1058   if (acl_handle != HCI_INVALID_HANDLE) {
1059     acl_disconnect_from_handle(acl_handle, HCI_ERR_PEER_USER,
1060                                "bta::bluetooth::le_audio::client disconnect");
1061   }
1062 }
1063 
SetAvailableContexts(BidirectionalPair<AudioContexts> contexts)1064 void LeAudioDevice::SetAvailableContexts(
1065     BidirectionalPair<AudioContexts> contexts) {
1066   log::debug(
1067       "{}: \n\t previous_contexts_.sink: {} \n\t previous_contexts_.source: {} "
1068       " "
1069       "\n\t new_contexts.sink: {} \n\t new_contexts.source: {} \n\t",
1070       address_, avail_contexts_.sink.to_string(),
1071       avail_contexts_.source.to_string(), contexts.sink.to_string(),
1072       contexts.source.to_string());
1073 
1074   avail_contexts_.sink = contexts.sink;
1075   avail_contexts_.source = contexts.source;
1076 }
1077 
SetMetadataToAse(struct types::ase * ase,const AudioContexts & metadata_context_types,const std::vector<uint8_t> & ccid_lists)1078 void LeAudioDevice::SetMetadataToAse(
1079     struct types::ase* ase, const AudioContexts& metadata_context_types,
1080     const std::vector<uint8_t>& ccid_lists) {
1081   /* Filter multidirectional audio context for each ase direction */
1082   auto directional_audio_context =
1083       metadata_context_types & GetAvailableContexts(ase->direction);
1084   if (directional_audio_context.any()) {
1085     ase->metadata = GetMetadata(directional_audio_context, ccid_lists);
1086   } else {
1087     ase->metadata = GetMetadata(AudioContexts(LeAudioContextType::UNSPECIFIED),
1088                                 std::vector<uint8_t>());
1089   }
1090 }
1091 
ActivateConfiguredAses(LeAudioContextType context_type,const BidirectionalPair<AudioContexts> & metadata_context_types,BidirectionalPair<std::vector<uint8_t>> ccid_lists)1092 bool LeAudioDevice::ActivateConfiguredAses(
1093     LeAudioContextType context_type,
1094     const BidirectionalPair<AudioContexts>& metadata_context_types,
1095     BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
1096   if (conn_id_ == GATT_INVALID_CONN_ID) {
1097     log::warn("Device {} is not connected", address_);
1098     return false;
1099   }
1100 
1101   bool ret = false;
1102 
1103   log::info("Configuring device {}", address_);
1104   for (auto& ase : ases_) {
1105     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED &&
1106         ase.configured_for_context_type == context_type) {
1107       log::info(
1108           "conn_id: {}, ase id {}, cis id {}, cis_handle 0x{:04x} is "
1109           "activated.",
1110           conn_id_, ase.id, ase.cis_id, ase.cis_conn_hdl);
1111       ase.active = true;
1112       ret = true;
1113       /* update metadata */
1114       SetMetadataToAse(&ase, metadata_context_types.get(ase.direction),
1115                        ccid_lists.get(ase.direction));
1116     }
1117   }
1118 
1119   return ret;
1120 }
1121 
DeactivateAllAses(void)1122 void LeAudioDevice::DeactivateAllAses(void) {
1123   for (auto& ase : ases_) {
1124     if (ase.active == false && ase.cis_state != CisState::IDLE &&
1125         ase.data_path_state != DataPathState::IDLE) {
1126       log::warn(
1127           "{}, ase_id: {}, ase.cis_id: {}, cis_handle: 0x{:02x}, "
1128           "ase.cis_state={}, ase.data_path_state={}",
1129           address_, ase.id, ase.cis_id, ase.cis_conn_hdl,
1130           bluetooth::common::ToString(ase.cis_state),
1131           bluetooth::common::ToString(ase.data_path_state));
1132     }
1133     if (alarm_is_scheduled(ase.autonomous_operation_timer_)) {
1134       alarm_free(ase.autonomous_operation_timer_);
1135       ase.autonomous_operation_timer_ = NULL;
1136       ase.autonomous_target_state_ = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1137     }
1138     ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1139     ase.cis_state = CisState::IDLE;
1140     ase.data_path_state = DataPathState::IDLE;
1141     ase.active = false;
1142     ase.reconfigure = 0;
1143     ase.cis_id = bluetooth::le_audio::kInvalidCisId;
1144     ase.cis_conn_hdl = 0;
1145   }
1146 }
1147 
GetMetadata(AudioContexts context_type,const std::vector<uint8_t> & ccid_list)1148 std::vector<uint8_t> LeAudioDevice::GetMetadata(
1149     AudioContexts context_type, const std::vector<uint8_t>& ccid_list) {
1150   std::vector<uint8_t> metadata;
1151 
1152   AppendMetadataLtvEntryForStreamingContext(metadata, context_type);
1153   AppendMetadataLtvEntryForCcidList(metadata, ccid_list);
1154 
1155   return std::move(metadata);
1156 }
1157 
IsMetadataChanged(const BidirectionalPair<AudioContexts> & context_types,const BidirectionalPair<std::vector<uint8_t>> & ccid_lists)1158 bool LeAudioDevice::IsMetadataChanged(
1159     const BidirectionalPair<AudioContexts>& context_types,
1160     const BidirectionalPair<std::vector<uint8_t>>& ccid_lists) {
1161   for (auto* ase = this->GetFirstActiveAse(); ase;
1162        ase = this->GetNextActiveAse(ase)) {
1163     if (this->GetMetadata(context_types.get(ase->direction),
1164                           ccid_lists.get(ase->direction)) != ase->metadata)
1165       return true;
1166   }
1167 
1168   return false;
1169 }
1170 
GetDeviceModelName(void)1171 void LeAudioDevice::GetDeviceModelName(void) {
1172   bt_property_t prop_name;
1173   bt_bdname_t prop_value = {0};
1174   // Retrieve model name from storage
1175   BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_REMOTE_MODEL_NUM,
1176                              sizeof(bt_bdname_t), &prop_value);
1177   if (btif_storage_get_remote_device_property(&address_, &prop_name) ==
1178       BT_STATUS_SUCCESS) {
1179     model_name_.assign((char*)prop_value.name);
1180   }
1181 }
1182 
UpdateDeviceAllowlistFlag(void)1183 void LeAudioDevice::UpdateDeviceAllowlistFlag(void) {
1184   char allow_list[PROPERTY_VALUE_MAX] = {0};
1185   GetDeviceModelName();
1186   osi_property_get(kLeAudioDeviceAllowListProp, allow_list, "");
1187   if (allow_list[0] == '\0' || model_name_ == "") {
1188     // if device allow list is empty or no remote model name available
1189     // return allowlist_flag_ as default false
1190     return;
1191   }
1192 
1193   std::istringstream stream(allow_list);
1194   std::string token;
1195   while (std::getline(stream, token, ',')) {
1196     if (token.compare(model_name_) == 0) {
1197       allowlist_flag_ = true;
1198       return;
1199     }
1200   }
1201 }
1202 
GetDsaModes(void)1203 DsaModes LeAudioDevice::GetDsaModes(void) { return dsa_.modes; }
1204 
GetDsaDataPathState(void)1205 types::DataPathState LeAudioDevice::GetDsaDataPathState(void) {
1206   return dsa_.state;
1207 }
1208 
SetDsaDataPathState(types::DataPathState state)1209 void LeAudioDevice::SetDsaDataPathState(types::DataPathState state) {
1210   dsa_.state = state;
1211 }
1212 
GetDsaCisHandle(void)1213 uint16_t LeAudioDevice::GetDsaCisHandle(void) { return dsa_.cis_handle; }
1214 
SetDsaCisHandle(uint16_t cis_handle)1215 void LeAudioDevice::SetDsaCisHandle(uint16_t cis_handle) {
1216   dsa_.cis_handle = cis_handle;
1217 }
1218 
1219 /* LeAudioDevices Class methods implementation */
Add(const RawAddress & address,DeviceConnectState state,int group_id)1220 void LeAudioDevices::Add(const RawAddress& address, DeviceConnectState state,
1221                          int group_id) {
1222   auto device = FindByAddress(address);
1223   if (device != nullptr) {
1224     log::error("address: {} is already assigned to group: {}", address,
1225                device->group_id_);
1226     return;
1227   }
1228 
1229   leAudioDevices_.emplace_back(
1230       std::make_shared<LeAudioDevice>(address, state, group_id));
1231 }
1232 
Remove(const RawAddress & address)1233 void LeAudioDevices::Remove(const RawAddress& address) {
1234   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1235                            [&address](auto const& leAudioDevice) {
1236                              return leAudioDevice->address_ == address;
1237                            });
1238 
1239   if (iter == leAudioDevices_.end()) {
1240     log::error("no such address: {}", address);
1241     return;
1242   }
1243 
1244   leAudioDevices_.erase(iter);
1245 }
1246 
FindByAddress(const RawAddress & address) const1247 LeAudioDevice* LeAudioDevices::FindByAddress(const RawAddress& address) const {
1248   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1249                            [&address](auto const& leAudioDevice) {
1250                              return leAudioDevice->address_ == address;
1251                            });
1252 
1253   return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
1254 }
1255 
GetByAddress(const RawAddress & address) const1256 std::shared_ptr<LeAudioDevice> LeAudioDevices::GetByAddress(
1257     const RawAddress& address) const {
1258   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1259                            [&address](auto const& leAudioDevice) {
1260                              return leAudioDevice->address_ == address;
1261                            });
1262 
1263   return (iter == leAudioDevices_.end()) ? nullptr : *iter;
1264 }
1265 
FindByConnId(uint16_t conn_id) const1266 LeAudioDevice* LeAudioDevices::FindByConnId(uint16_t conn_id) const {
1267   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1268                            [&conn_id](auto const& leAudioDevice) {
1269                              return leAudioDevice->conn_id_ == conn_id;
1270                            });
1271 
1272   return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
1273 }
1274 
FindByCisConnHdl(uint8_t cig_id,uint16_t conn_hdl) const1275 LeAudioDevice* LeAudioDevices::FindByCisConnHdl(uint8_t cig_id,
1276                                                 uint16_t conn_hdl) const {
1277   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1278                            [&conn_hdl, &cig_id](auto& d) {
1279                              LeAudioDevice* dev;
1280                              BidirectionalPair<struct ase*> ases;
1281 
1282                              dev = d.get();
1283                              if (dev->group_id_ != cig_id) {
1284                                return false;
1285                              }
1286 
1287                              ases = dev->GetAsesByCisConnHdl(conn_hdl);
1288                              if (ases.sink || ases.source)
1289                                return true;
1290                              else
1291                                return false;
1292                            });
1293 
1294   if (iter == leAudioDevices_.end()) return nullptr;
1295 
1296   return iter->get();
1297 }
1298 
SetInitialGroupAutoconnectState(int group_id,int gatt_if,tBTM_BLE_CONN_TYPE reconnection_mode,bool current_dev_autoconnect_flag)1299 void LeAudioDevices::SetInitialGroupAutoconnectState(
1300     int group_id, int gatt_if, tBTM_BLE_CONN_TYPE reconnection_mode,
1301     bool current_dev_autoconnect_flag) {
1302   if (!current_dev_autoconnect_flag) {
1303     /* If current device autoconnect flag is false, check if there is other
1304      * device in the group which is in autoconnect mode.
1305      * If yes, assume whole group is in autoconnect.
1306      */
1307     auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1308                              [&group_id](auto& d) {
1309                                LeAudioDevice* dev;
1310                                dev = d.get();
1311                                if (dev->group_id_ != group_id) {
1312                                  return false;
1313                                }
1314                                return dev->autoconnect_flag_;
1315                              });
1316 
1317     current_dev_autoconnect_flag = !(iter == leAudioDevices_.end());
1318   }
1319 
1320   if (!current_dev_autoconnect_flag) {
1321     return;
1322   }
1323 
1324   /* This function is called when bluetooth started, therefore here we will
1325    * try direct connection, if that failes, we fallback to background connection
1326    */
1327   for (auto dev : leAudioDevices_) {
1328     if ((dev->group_id_ == group_id) &&
1329         (dev->GetConnectionState() == DeviceConnectState::DISCONNECTED)) {
1330       dev->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
1331       dev->autoconnect_flag_ = true;
1332       btif_storage_set_leaudio_autoconnect(dev->address_, true);
1333       BTA_GATTC_Open(gatt_if, dev->address_, BTM_BLE_DIRECT_CONNECTION, false);
1334     }
1335   }
1336 }
1337 
Size() const1338 size_t LeAudioDevices::Size() const { return (leAudioDevices_.size()); }
1339 
Dump(int fd,int group_id) const1340 void LeAudioDevices::Dump(int fd, int group_id) const {
1341   std::stringstream stream, stream_pacs;
1342 
1343   for (auto const& device : leAudioDevices_) {
1344     if (device->group_id_ == group_id) {
1345       device->Dump(fd);
1346 
1347       stream_pacs << "\n\taddress: " << device->address_;
1348       device->DumpPacsDebugState(stream_pacs);
1349       dprintf(fd, "%s", stream_pacs.str().c_str());
1350     }
1351   }
1352 }
1353 
Cleanup(tGATT_IF client_if)1354 void LeAudioDevices::Cleanup(tGATT_IF client_if) {
1355   for (auto const& device : leAudioDevices_) {
1356     auto connection_state = device->GetConnectionState();
1357     if (connection_state == DeviceConnectState::DISCONNECTED ||
1358         connection_state == DeviceConnectState::DISCONNECTING) {
1359       continue;
1360     }
1361 
1362     if (connection_state == DeviceConnectState::CONNECTING_AUTOCONNECT) {
1363       BTA_GATTC_CancelOpen(client_if, device->address_, false);
1364     } else {
1365       BtaGattQueue::Clean(device->conn_id_);
1366       BTA_GATTC_Close(device->conn_id_);
1367       device->DisconnectAcl();
1368     }
1369   }
1370   leAudioDevices_.clear();
1371 }
1372 
1373 }  // namespace bluetooth::le_audio
1374