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