1 /*
2 * Copyright 2021 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 <base/functional/bind.h>
19 #include <base/strings/string_number_conversions.h>
20 #include <bluetooth/log.h>
21 #include <com_android_bluetooth_flags.h>
22 #include <stdio.h>
23
24 #include <algorithm>
25 #include <bitset>
26 #include <chrono>
27 #include <cstddef>
28 #include <cstdint>
29 #include <cstring>
30 #include <deque>
31 #include <functional>
32 #include <list>
33 #include <map>
34 #include <memory>
35 #include <mutex>
36 #include <optional>
37 #include <ostream>
38 #include <sstream>
39 #include <tuple>
40 #include <utility>
41 #include <vector>
42
43 #include "audio_hal_client/audio_hal_client.h"
44 #include "audio_hal_interface/le_audio_software.h"
45 #include "bt_types.h"
46 #include "bta/csis/csis_types.h"
47 #include "bta_csis_api.h"
48 #include "bta_gatt_api.h"
49 #include "bta_gatt_queue.h"
50 #include "bta_groups.h"
51 #include "bta_le_audio_api.h"
52 #include "bta_le_audio_broadcaster_api.h"
53 #include "btif/include/btif_profile_storage.h"
54 #include "btm_api_types.h"
55 #include "btm_ble_api_types.h"
56 #include "btm_iso_api.h"
57 #include "btm_iso_api_types.h"
58 #include "btm_sec_api_types.h"
59 #include "client_parser.h"
60 #include "codec_interface.h"
61 #include "codec_manager.h"
62 #include "common/strings.h"
63 #include "common/time_util.h"
64 #include "content_control_id_keeper.h"
65 #include "devices.h"
66 #include "gatt/database.h"
67 #include "gatt_api.h"
68 #include "gattdefs.h"
69 #include "gmap_client.h"
70 #include "gmap_server.h"
71 #include "hardware/bt_le_audio.h"
72 #include "hci/controller_interface.h"
73 #include "hci_error_code.h"
74 #include "include/hardware/bt_gmap.h"
75 #include "internal_include/bt_trace.h"
76 #include "internal_include/stack_config.h"
77 #include "le_audio/device_groups.h"
78 #include "le_audio/le_audio_log_history.h"
79 #include "le_audio_health_status.h"
80 #include "le_audio_set_configuration_provider.h"
81 #include "le_audio_types.h"
82 #include "le_audio_utils.h"
83 #include "main/shim/entry.h"
84 #include "metrics_collector.h"
85 #include "osi/include/alarm.h"
86 #include "osi/include/osi.h"
87 #include "osi/include/properties.h"
88 #include "stack/btm/btm_sec.h"
89 #include "stack/include/bt_types.h"
90 #include "stack/include/btm_client_interface.h"
91 #include "stack/include/btm_status.h"
92 #include "stack/include/l2cap_interface.h"
93 #include "stack/include/main_thread.h"
94 #include "state_machine.h"
95 #include "storage_helper.h"
96 #include "types/bluetooth/uuid.h"
97 #include "types/bt_transport.h"
98 #include "types/raw_address.h"
99
100 #ifdef TARGET_FLOSS
101 #include <audio_hal_interface/audio_linux.h>
102 #else
103 #include <hardware/audio.h>
104 #endif // TARGET_FLOSS
105
106 // TODO(b/369381361) Enfore -Wmissing-prototypes
107 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
108
109 using base::Closure;
110 using bluetooth::Uuid;
111 using bluetooth::common::ToString;
112 using bluetooth::groups::DeviceGroups;
113 using bluetooth::groups::DeviceGroupsCallbacks;
114 using bluetooth::hci::IsoManager;
115 using bluetooth::hci::iso_manager::cig_create_cmpl_evt;
116 using bluetooth::hci::iso_manager::cig_remove_cmpl_evt;
117 using bluetooth::hci::iso_manager::CigCallbacks;
118 using bluetooth::le_audio::CodecManager;
119 using bluetooth::le_audio::ConnectionState;
120 using bluetooth::le_audio::ContentControlIdKeeper;
121 using bluetooth::le_audio::DeviceConnectState;
122 using bluetooth::le_audio::DsaMode;
123 using bluetooth::le_audio::DsaModes;
124 using bluetooth::le_audio::GmapClient;
125 using bluetooth::le_audio::GmapServer;
126 using bluetooth::le_audio::GroupNodeStatus;
127 using bluetooth::le_audio::GroupStatus;
128 using bluetooth::le_audio::GroupStreamStatus;
129 using bluetooth::le_audio::LeAudioCodecConfiguration;
130 using bluetooth::le_audio::LeAudioDevice;
131 using bluetooth::le_audio::LeAudioDeviceGroup;
132 using bluetooth::le_audio::LeAudioDeviceGroups;
133 using bluetooth::le_audio::LeAudioDevices;
134 using bluetooth::le_audio::LeAudioGroupStateMachine;
135 using bluetooth::le_audio::LeAudioHealthBasedAction;
136 using bluetooth::le_audio::LeAudioHealthDeviceStatType;
137 using bluetooth::le_audio::LeAudioHealthGroupStatType;
138 using bluetooth::le_audio::LeAudioHealthStatus;
139 using bluetooth::le_audio::LeAudioRecommendationActionCb;
140 using bluetooth::le_audio::LeAudioSinkAudioHalClient;
141 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
142 using bluetooth::le_audio::UnicastMonitorModeStatus;
143 using bluetooth::le_audio::types::ase;
144 using bluetooth::le_audio::types::AseState;
145 using bluetooth::le_audio::types::AudioContexts;
146 using bluetooth::le_audio::types::AudioLocations;
147 using bluetooth::le_audio::types::BidirectionalPair;
148 using bluetooth::le_audio::types::DataPathState;
149 using bluetooth::le_audio::types::hdl_pair;
150 using bluetooth::le_audio::types::kLeAudioContextAllRemoteSource;
151 using bluetooth::le_audio::types::kLeAudioContextAllTypesArray;
152 using bluetooth::le_audio::types::LeAudioContextType;
153 using bluetooth::le_audio::types::PublishedAudioCapabilities;
154 using bluetooth::le_audio::utils::GetAudioContextsFromSinkMetadata;
155 using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata;
156
157 using namespace bluetooth;
158
159 /* Enums */
160 enum class AudioReconfigurationResult {
161 RECONFIGURATION_NEEDED = 0x00,
162 RECONFIGURATION_NOT_NEEDED,
163 RECONFIGURATION_NOT_POSSIBLE
164 };
165
166 enum class AudioState {
167 IDLE = 0x00,
168 READY_TO_START,
169 STARTED,
170 READY_TO_RELEASE,
171 RELEASING,
172 };
173
operator <<(std::ostream & os,const AudioReconfigurationResult & state)174 std::ostream& operator<<(std::ostream& os, const AudioReconfigurationResult& state) {
175 switch (state) {
176 case AudioReconfigurationResult::RECONFIGURATION_NEEDED:
177 os << "RECONFIGURATION_NEEDED";
178 break;
179 case AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED:
180 os << "RECONFIGURATION_NOT_NEEDED";
181 break;
182 case AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE:
183 os << "RECONFIGRATION_NOT_POSSIBLE";
184 break;
185 default:
186 os << "UNKNOWN";
187 break;
188 }
189 return os;
190 }
191
operator <<(std::ostream & os,const AudioState & audio_state)192 std::ostream& operator<<(std::ostream& os, const AudioState& audio_state) {
193 switch (audio_state) {
194 case AudioState::IDLE:
195 os << "IDLE";
196 break;
197 case AudioState::READY_TO_START:
198 os << "READY_TO_START";
199 break;
200 case AudioState::STARTED:
201 os << "STARTED";
202 break;
203 case AudioState::READY_TO_RELEASE:
204 os << "READY_TO_RELEASE";
205 break;
206 case AudioState::RELEASING:
207 os << "RELEASING";
208 break;
209 default:
210 os << "UNKNOWN";
211 break;
212 }
213 return os;
214 }
215
216 namespace std {
217 template <>
218 struct formatter<AudioState> : ostream_formatter {};
219 } // namespace std
220
221 namespace {
222 void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
223
224 static void le_audio_health_status_callback(const RawAddress& addr, int group_id,
225 LeAudioHealthBasedAction action);
226
227 class LeAudioClientImpl;
228 LeAudioClientImpl* instance;
229 std::mutex instance_mutex;
230 LeAudioSourceAudioHalClient::Callbacks* audioSinkReceiver;
231 LeAudioSinkAudioHalClient::Callbacks* audioSourceReceiver;
232 CigCallbacks* stateMachineHciCallbacks;
233 LeAudioGroupStateMachine::Callbacks* stateMachineCallbacks;
234 DeviceGroupsCallbacks* device_group_callbacks;
235 LeAudioIsoDataCallback* iso_data_callback;
236
237 class StreamSpeedTracker {
238 public:
StreamSpeedTracker(void)239 StreamSpeedTracker(void)
240 : is_started_(false),
241 group_id_(bluetooth::groups::kGroupUnknown),
242 num_of_devices_(0),
243 context_type_(LeAudioContextType::UNSPECIFIED),
244 reconfig_start_ts_(0),
245 setup_start_ts_(0),
246 total_time_(0),
247 reconfig_time_(0),
248 stream_setup_time_(0) {}
249
Init(int group_id,LeAudioContextType context_type,int num_of_devices)250 void Init(int group_id, LeAudioContextType context_type, int num_of_devices) {
251 Reset();
252 group_id_ = group_id;
253 context_type_ = context_type;
254 num_of_devices_ = num_of_devices;
255 log::verbose("StreamSpeedTracker group_id: {}, context: {} #{}", group_id_,
256 ToString(context_type_), num_of_devices);
257 }
258
Reset(void)259 void Reset(void) {
260 log::verbose("StreamSpeedTracker group_id: {}", group_id_);
261 is_started_ = false;
262 group_id_ = bluetooth::groups::kGroupUnknown;
263 reconfig_start_ts_ = setup_start_ts_ = total_time_ = reconfig_time_ = stream_setup_time_ =
264 num_of_devices_ = 0;
265 context_type_ = LeAudioContextType::UNSPECIFIED;
266 }
267
ReconfigStarted(void)268 void ReconfigStarted(void) {
269 log::verbose("StreamSpeedTracker group_id: {}", group_id_);
270 reconfig_time_ = 0;
271 is_started_ = true;
272 reconfig_start_ts_ = bluetooth::common::time_get_os_boottime_us();
273 }
274
StartStream(void)275 void StartStream(void) {
276 log::verbose("StreamSpeedTracker group_id: {}", group_id_);
277 setup_start_ts_ = bluetooth::common::time_get_os_boottime_us();
278 is_started_ = true;
279 }
280
ReconfigurationComplete(void)281 void ReconfigurationComplete(void) {
282 reconfig_time_ = (bluetooth::common::time_get_os_boottime_us() - reconfig_start_ts_) / 1000;
283 log::verbose("StreamSpeedTracker group_id: {}, {} reconfig time {} ms", group_id_,
284 ToString(context_type_), reconfig_time_);
285 }
286
StreamCreated(void)287 void StreamCreated(void) {
288 stream_setup_time_ = (bluetooth::common::time_get_os_boottime_us() - setup_start_ts_) / 1000;
289 log::verbose("StreamSpeedTracker group_id: {}, {} stream create time {} ms", group_id_,
290 ToString(context_type_), stream_setup_time_);
291 }
292
StopStreamSetup(void)293 void StopStreamSetup(void) {
294 is_started_ = false;
295 uint64_t start_ts = reconfig_time_ != 0 ? reconfig_start_ts_ : setup_start_ts_;
296 total_time_ = (bluetooth::common::time_get_os_boottime_us() - start_ts) / 1000;
297 clock_gettime(CLOCK_REALTIME, &end_ts_);
298 log::verbose("StreamSpeedTracker group_id: {}, {} setup time {} ms", group_id_,
299 ToString(context_type_), total_time_);
300 }
301
IsStarted(void)302 bool IsStarted(void) {
303 if (is_started_) {
304 log::verbose("StreamSpeedTracker group_id: {}, {} is_started_: {} ", group_id_,
305 ToString(context_type_), is_started_);
306 } else {
307 log::verbose("StreamSpeedTracker not started ");
308 }
309 return is_started_;
310 }
311
Dump(std::stringstream & stream)312 void Dump(std::stringstream& stream) {
313 char ts[20];
314 std::strftime(ts, sizeof(ts), "%T", std::gmtime(&end_ts_.tv_sec));
315
316 if (total_time_ < 900) {
317 stream << "[ ";
318 } else if (total_time_ < 1500) {
319 stream << "[ ";
320 } else if (total_time_ < 2500) {
321 stream << "[ ";
322 } else {
323 stream << "[ ❗ ";
324 }
325
326 stream << ts << ": Gid: " << group_id_ << "(#" << num_of_devices_ << "), " << context_type_
327 << ", ";
328 auto hal_idle = total_time_ - stream_setup_time_ - reconfig_time_;
329 if (reconfig_time_ != 0) {
330 stream << "t:" << total_time_ << "ms (r:" << reconfig_time_ << "/s:" << stream_setup_time_
331 << "/hal:" << hal_idle << ")";
332 } else {
333 stream << "t:" << total_time_ << "ms (hal:" << hal_idle << ")";
334 }
335 stream << "]";
336 }
337
338 private:
339 bool is_started_;
340 int group_id_;
341 int num_of_devices_;
342 LeAudioContextType context_type_;
343 struct timespec end_ts_;
344 uint64_t reconfig_start_ts_;
345 uint64_t setup_start_ts_;
346 uint64_t total_time_;
347 uint64_t reconfig_time_;
348 uint64_t stream_setup_time_;
349 };
350
351 /*
352 * Coordinatet Set Identification Profile (CSIP) based on CSIP 1.0
353 * and Coordinatet Set Identification Service (CSIS) 1.0
354 *
355 * CSIP allows to organize audio servers into sets e.g. Stereo Set, 5.1 Set
356 * and speed up connecting it.
357 *
358 * Since leaudio has already grouping API it was decided to integrate here CSIS
359 * and allow it to group devices semi-automatically.
360 *
361 * Flow:
362 * If connected device contains CSIS services, and it is included into CAP
363 * service, implementation marks device as a set member and waits for the
364 * bta/csis to learn about groups and notify implementation about assigned
365 * group id.
366 *
367 */
368 /* LeAudioClientImpl class represents main implementation class for le audio
369 * feature in stack. This class implements GATT, le audio and ISO related parts.
370 *
371 * This class is represented in single instance and manages a group of devices,
372 * and devices. All devices calls back static method from it and are dispatched
373 * to target receivers (e.g. ASEs, devices).
374 *
375 * This instance also implements a LeAudioClient which is a upper layer API.
376 * Also LeAudioClientCallbacks are callbacks for upper layer.
377 *
378 * This class may be bonded with Test socket which allows to drive an instance
379 * for test purposes.
380 */
381 class LeAudioClientImpl : public LeAudioClient {
382 public:
~LeAudioClientImpl()383 ~LeAudioClientImpl() {
384 alarm_free(close_vbc_timeout_);
385 alarm_free(disable_timer_);
386 alarm_free(suspend_timeout_);
387 alarm_free(reconfiguration_timeout_);
388 }
389
LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks * callbacks,LeAudioGroupStateMachine::Callbacks * state_machine_callbacks,base::Closure initCb)390 LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks* callbacks,
391 LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
392 base::Closure initCb)
393 : gatt_if_(0),
394 callbacks_(callbacks),
395 active_group_id_(bluetooth::groups::kGroupUnknown),
396 configuration_context_type_(LeAudioContextType::UNINITIALIZED),
397 in_call_metadata_context_types_({.sink = AudioContexts(), .source = AudioContexts()}),
398 local_metadata_context_types_({.sink = AudioContexts(), .source = AudioContexts()}),
399 audio_receiver_state_(AudioState::IDLE),
400 audio_sender_state_(AudioState::IDLE),
401 in_call_(false),
402 in_voip_call_(false),
403 sink_monitor_mode_(false),
404 sink_monitor_notified_status_(std::nullopt),
405 source_monitor_mode_(false),
406 source_monitor_notified_status_(std::nullopt),
407 le_audio_source_hal_client_(nullptr),
408 le_audio_sink_hal_client_(nullptr),
409 close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")),
410 suspend_timeout_(alarm_new("LeAudioSuspendTimeout")),
411 reconfiguration_timeout_(alarm_new("LeAudioReconfigurationTimeout")),
412 disable_timer_(alarm_new("LeAudioDisableTimer")) {
413 LeAudioGroupStateMachine::Initialize(state_machine_callbacks);
414 groupStateMachine_ = LeAudioGroupStateMachine::Get();
415
416 log::info("Reconnection mode: TARGETED_ANNOUNCEMENTS");
417 reconnection_mode_ = BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS;
418
419 log::info("Loading health status module");
420 leAudioHealthStatus_ = LeAudioHealthStatus::Get();
421 leAudioHealthStatus_->RegisterCallback(base::BindRepeating(le_audio_health_status_callback));
422
423 BTA_GATTC_AppRegister(
424 le_audio_gattc_callback,
425 base::Bind(
__anon6840174e0202(base::Closure initCb, uint8_t client_id, uint8_t status) 426 [](base::Closure initCb, uint8_t client_id, uint8_t status) {
427 if (status != GATT_SUCCESS) {
428 log::error("Can't start LeAudio profile - no gatt clients left!");
429 return;
430 }
431 instance->gatt_if_ = client_id;
432 initCb.Run();
433 },
434 initCb),
435 true);
436
437 DeviceGroups::Get()->Initialize(device_group_callbacks);
438 }
439
ReconfigureAfterVbcClose()440 void ReconfigureAfterVbcClose() {
441 log::debug("VBC close timeout");
442
443 if (IsInVoipCall()) {
444 SetInVoipCall(false);
445 }
446
447 auto group = aseGroups_.FindById(active_group_id_);
448 if (!group) {
449 log::error("Invalid group: {}", active_group_id_);
450 return;
451 }
452
453 /* Reconfiguration to non requiring source scenario */
454 if (sink_monitor_mode_) {
455 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
456 }
457
458 /* For sonification events we don't really need to reconfigure to HQ
459 * configuration, but if the previous configuration was for HQ Media,
460 * we might want to go back to that scenario.
461 */
462
463 if ((configuration_context_type_ != LeAudioContextType::MEDIA) &&
464 (configuration_context_type_ != LeAudioContextType::GAME)) {
465 log::info("Keeping the old configuration as no HQ Media playback is needed right now.");
466 return;
467 }
468
469 /* Test the existing metadata against the recent availability */
470 local_metadata_context_types_.source &=
471 group->GetAvailableContexts(bluetooth::le_audio::types::kLeAudioDirectionSink);
472 if (local_metadata_context_types_.source.none()) {
473 log::warn("invalid/unknown context metadata, using 'MEDIA' instead");
474 local_metadata_context_types_.source = AudioContexts(LeAudioContextType::MEDIA);
475 }
476
477 /* Choose the right configuration context */
478 auto new_configuration_context =
479 ChooseConfigurationContextType(local_metadata_context_types_.source);
480
481 log::debug("new_configuration_context= {}", ToString(new_configuration_context));
482 ReconfigureOrUpdateMetadata(group, new_configuration_context,
483 {.sink = local_metadata_context_types_.source,
484 .source = local_metadata_context_types_.sink});
485 }
486
StartVbcCloseTimeout()487 void StartVbcCloseTimeout() {
488 if (alarm_is_scheduled(close_vbc_timeout_)) {
489 StopVbcCloseTimeout();
490 }
491
492 static const uint64_t timeoutMs = 2000;
493 log::debug("Start VBC close timeout with {} ms", timeoutMs);
494
495 alarm_set_on_mloop(
496 close_vbc_timeout_, timeoutMs,
497 [](void*) {
498 if (instance) {
499 log::debug("Reconfigure after VBC close");
500 instance->ReconfigureAfterVbcClose();
501 }
502 },
503 nullptr);
504 }
505
StopVbcCloseTimeout()506 void StopVbcCloseTimeout() {
507 if (alarm_is_scheduled(close_vbc_timeout_)) {
508 log::debug("Cancel VBC close timeout");
509 alarm_cancel(close_vbc_timeout_);
510 }
511 }
512
IsReconfigurationTimeoutRunning(int group_id,uint8_t direction=bluetooth::le_audio::types::kLeAudioDirectionBoth)513 bool IsReconfigurationTimeoutRunning(
514 int group_id, uint8_t direction = bluetooth::le_audio::types::kLeAudioDirectionBoth) {
515 if (alarm_is_scheduled(reconfiguration_timeout_)) {
516 log::debug(" is {} group_id: {}, to check: {}, scheduled: {}",
517 group_id == reconfiguration_group_ ? "running" : " not running", group_id,
518 direction, reconfiguration_local_directions_);
519 return group_id == reconfiguration_group_ && (direction & reconfiguration_local_directions_);
520 }
521 return false;
522 }
523
StartReconfigurationTimeout(int group_id)524 void StartReconfigurationTimeout(int group_id) {
525 log::debug("group_id: {}", group_id);
526
527 /* This is called when Reconfiguration has been completed. This function starts
528 * timer which is a guard for unwanted reconfiguration which might happen when Audio HAL
529 * is sending to Bluetooth stack multiple metadata updates and suspends/resume commands.
530 * What we want to achieve with this timeout, that BT stack will resume the stream with
531 * configuration picked up when ReconfigurationComplete command was sent out to Audio HAL.
532 */
533
534 if (alarm_is_scheduled(reconfiguration_timeout_)) {
535 log::info("Is already running for group {}", reconfiguration_group_);
536 return;
537 }
538
539 auto group = aseGroups_.FindById(group_id);
540 if (group == nullptr) {
541 log::warn("This shall not happen, group_id: {} is not available.", group_id);
542 return;
543 }
544
545 if (IsDirectionAvailableForCurrentConfiguration(
546 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
547 reconfiguration_local_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource;
548 }
549 if (IsDirectionAvailableForCurrentConfiguration(
550 group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
551 reconfiguration_local_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink;
552 }
553
554 log::debug("reconfiguration_local_directions_ : {}", reconfiguration_local_directions_);
555
556 reconfiguration_group_ = group_id;
557 alarm_set_on_mloop(
558 reconfiguration_timeout_, kAudioReconfigurationTimeoutMs,
559 [](void* data) {
560 if (instance) {
561 instance->StopReconfigurationTimeout(
562 PTR_TO_INT(data), bluetooth::le_audio::types::kLeAudioDirectionBoth);
563 }
564 },
565 INT_TO_PTR(group_id));
566 }
567
StopReconfigurationTimeout(int group_id,uint8_t local_direction)568 void StopReconfigurationTimeout(int group_id, uint8_t local_direction) {
569 log::debug("group_id: {}, local_direction {}, reconfiguration directions {}", group_id,
570 local_direction, reconfiguration_local_directions_);
571
572 reconfiguration_local_directions_ &= ~local_direction;
573
574 if (reconfiguration_local_directions_ != 0) {
575 log::debug("Wait for remaining directions: {} ", reconfiguration_local_directions_);
576 return;
577 }
578
579 if (alarm_is_scheduled(reconfiguration_timeout_)) {
580 log::debug("Canceling for group_id {}", reconfiguration_group_);
581 alarm_cancel(reconfiguration_timeout_);
582 }
583 reconfiguration_group_ = bluetooth::groups::kGroupUnknown;
584 }
585
StartSuspendTimeout(void)586 void StartSuspendTimeout(void) {
587 StopSuspendTimeout();
588
589 /* Group should tie in time to get requested status */
590 uint64_t timeoutMs = kAudioSuspentKeepIsoAliveTimeoutMs;
591 timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp, timeoutMs);
592
593 if (stack_config_get_interface()->get_pts_le_audio_disable_ases_before_stopping()) {
594 timeoutMs += kAudioDisableTimeoutMs;
595 }
596
597 log::debug("Stream suspend_timeout_ started: {} ms", static_cast<int>(timeoutMs));
598
599 alarm_set_on_mloop(
600 suspend_timeout_, timeoutMs,
601 [](void* data) {
602 if (instance) {
603 auto const group_id = PTR_TO_INT(data);
604 log::debug("No resume request received. Stop the group ID: {}", group_id);
605 instance->GroupStop(group_id);
606 }
607 },
608 INT_TO_PTR(active_group_id_));
609 }
610
StopSuspendTimeout(void)611 void StopSuspendTimeout(void) {
612 if (alarm_is_scheduled(suspend_timeout_)) {
613 log::debug("Cancel suspend timeout");
614 alarm_cancel(suspend_timeout_);
615 }
616 }
617
AseInitialStateReadRequest(LeAudioDevice * leAudioDevice)618 void AseInitialStateReadRequest(LeAudioDevice* leAudioDevice) {
619 int ases_num = leAudioDevice->ases_.size();
620 void* notify_flag_ptr = NULL;
621
622 tBTA_GATTC_MULTI multi_read{};
623
624 for (int i = 0; i < ases_num; i++) {
625 /* Last read ase characteristic should issue connected state callback
626 * to upper layer
627 */
628
629 if (leAudioDevice->notify_connected_after_read_ && (i == (ases_num - 1))) {
630 notify_flag_ptr = INT_TO_PTR(leAudioDevice->notify_connected_after_read_);
631 }
632
633 if (!com::android::bluetooth::flags::le_ase_read_multiple_variable()) {
634 BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
635 leAudioDevice->ases_[i].hdls.val_hdl, OnGattReadRspStatic,
636 notify_flag_ptr);
637 continue;
638 }
639
640 if (i != 0 && (i % GATT_MAX_READ_MULTI_HANDLES == 0)) {
641 multi_read.num_attr = GATT_MAX_READ_MULTI_HANDLES;
642 BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
643 OnGattReadMultiRspStatic, notify_flag_ptr);
644 memset(multi_read.handles, 0, GATT_MAX_READ_MULTI_HANDLES * sizeof(uint16_t));
645 }
646 multi_read.handles[i % GATT_MAX_READ_MULTI_HANDLES] = leAudioDevice->ases_[i].hdls.val_hdl;
647 }
648
649 if (com::android::bluetooth::flags::le_ase_read_multiple_variable() &&
650 (ases_num % GATT_MAX_READ_MULTI_HANDLES != 0)) {
651 multi_read.num_attr = ases_num % GATT_MAX_READ_MULTI_HANDLES;
652 BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
653 OnGattReadMultiRspStatic, notify_flag_ptr);
654 }
655 }
656
OnGroupAddedCb(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)657 void OnGroupAddedCb(const RawAddress& address, const bluetooth::Uuid& uuid, int group_id) {
658 log::info("address: {} group uuid {} group_id: {}", address, uuid, group_id);
659
660 /* We are interested in the groups which are in the context of CAP */
661 if (uuid != bluetooth::le_audio::uuid::kCapServiceUuid) {
662 return;
663 }
664
665 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
666 if (!leAudioDevice) {
667 return;
668 }
669 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
670 log::info("group already set: {}", leAudioDevice->group_id_);
671 return;
672 }
673
674 group_add_node(group_id, address);
675 }
676
677 /* If device participates in streaming the group, it has to be stopped and
678 * group needs to be reconfigured if needed to new configuration without
679 * considering this removing device.
680 */
SetDeviceAsRemovePendingAndStopGroup(LeAudioDevice * leAudioDevice)681 void SetDeviceAsRemovePendingAndStopGroup(LeAudioDevice* leAudioDevice) {
682 log::info("device {}", leAudioDevice->address_);
683 leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
684 leAudioDevice->closing_stream_for_disconnection_ = true;
685 GroupStop(leAudioDevice->group_id_);
686 }
687
OnGroupMemberAddedCb(const RawAddress & address,int group_id)688 void OnGroupMemberAddedCb(const RawAddress& address, int group_id) {
689 log::info("address: {} group_id: {}", address, group_id);
690
691 auto group = aseGroups_.FindById(group_id);
692 if (!group) {
693 log::error("Not interested in group id: {}", group_id);
694 return;
695 }
696
697 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
698 if (!leAudioDevice) {
699 return;
700 }
701 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
702 log::info("group already set: {}", leAudioDevice->group_id_);
703 return;
704 }
705
706 if (leAudioHealthStatus_) {
707 leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice,
708 LeAudioHealthDeviceStatType::VALID_CSIS);
709 }
710
711 group_add_node(group_id, address);
712 }
713
OnGroupMemberRemovedCb(const RawAddress & address,int group_id)714 void OnGroupMemberRemovedCb(const RawAddress& address, int group_id) {
715 log::info("address: {} group_id: {}", address, group_id);
716
717 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
718 if (!leAudioDevice) {
719 return;
720 }
721 if (leAudioDevice->group_id_ != group_id) {
722 log::warn("Device: {} not assigned to the group.", leAudioDevice->address_);
723 return;
724 }
725
726 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
727 if (group == NULL) {
728 log::info("device not in the group: {}, {}", leAudioDevice->address_, group_id);
729 return;
730 }
731
732 if (leAudioHealthStatus_) {
733 leAudioHealthStatus_->RemoveStatistics(address, group->group_id_);
734 }
735
736 if (leAudioDevice->HaveActiveAse()) {
737 SetDeviceAsRemovePendingAndStopGroup(leAudioDevice);
738 return;
739 }
740
741 group_remove_node(group, address);
742 }
743
744 /* This callback happens if kLeAudioDeviceSetStateTimeoutMs timeout happens
745 * during transition from origin to target state
746 */
OnLeAudioDeviceSetStateTimeout(int group_id)747 void OnLeAudioDeviceSetStateTimeout(int group_id) {
748 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
749
750 if (!group) {
751 /* Group removed */
752 return;
753 }
754
755 bool check_if_recovery_needed =
756 group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
757
758 if (leAudioHealthStatus_) {
759 leAudioHealthStatus_->AddStatisticForGroup(
760 group, LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED);
761 }
762
763 log::error(
764 "State not achieved on time for group: group id {}, current state {}, "
765 "target state: {}, check_if_recovery_needed: {}",
766 group_id, ToString(group->GetState()), ToString(group->GetTargetState()),
767 check_if_recovery_needed);
768 group->PrintDebugState();
769 group->SetTargetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
770 group->ClearAllCises();
771
772 /* There is an issue with a setting up stream or any other operation which
773 * are gatt operations. It means peer is not responsible. Lets close ACL
774 */
775 CancelStreamingRequest();
776 LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice();
777 if (leAudioDevice == nullptr) {
778 log::error("Shouldn't be called without an active device.");
779 leAudioDevice = group->GetFirstDevice();
780 if (leAudioDevice == nullptr) {
781 log::error("Front device is null. Number of devices: {}", group->Size());
782 return;
783 }
784 }
785
786 /* If Timeout happens on stream close and stream is closing just for the
787 * purpose of device disconnection, do not bother with recovery mode
788 */
789 bool recovery = true;
790 if (check_if_recovery_needed) {
791 for (auto tmpDevice = leAudioDevice; tmpDevice != nullptr;
792 tmpDevice = group->GetNextActiveDevice(tmpDevice)) {
793 if (tmpDevice->closing_stream_for_disconnection_) {
794 recovery = false;
795 break;
796 }
797 }
798 }
799
800 do {
801 DisconnectDevice(leAudioDevice, true, recovery);
802 leAudioDevice = group->GetNextActiveDevice(leAudioDevice);
803 } while (leAudioDevice);
804
805 if (recovery) {
806 /* Both devices will be disconnected soon. Notify upper layer that group
807 * is inactive */
808 groupSetAndNotifyInactive();
809 }
810 }
811
UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup * group,bool force=false)812 void UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup* group, bool force = false) {
813 bool group_conf_changed = group->ReloadAudioLocations();
814 group_conf_changed |= group->ReloadAudioDirections();
815 group_conf_changed |= group->UpdateAudioContextAvailability();
816 if (group_conf_changed || force) {
817 /* All the configurations should be recalculated for the new conditions */
818 group->InvalidateCachedConfigurations();
819 group->InvalidateGroupStrategy();
820 callbacks_->OnAudioConf(
821 group->audio_directions_, group->group_id_, group->snk_audio_locations_.to_ulong(),
822 group->src_audio_locations_.to_ulong(), group->GetAvailableContexts().value());
823 }
824 }
825
SuspendedForReconfiguration()826 void SuspendedForReconfiguration() {
827 if (audio_sender_state_ > AudioState::IDLE) {
828 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
829 kLogAfSuspendForReconfig + "LocalSource",
830 "r_state: " + ToString(audio_receiver_state_) +
831 "s_state: " + ToString(audio_sender_state_));
832 le_audio_source_hal_client_->SuspendedForReconfiguration();
833 }
834 if (audio_receiver_state_ > AudioState::IDLE) {
835 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
836 kLogAfSuspendForReconfig + "LocalSink",
837 "r_state: " + ToString(audio_receiver_state_) +
838 "s_state: " + ToString(audio_sender_state_));
839 le_audio_sink_hal_client_->SuspendedForReconfiguration();
840 }
841 StartReconfigurationTimeout(active_group_id_);
842 }
843
ReconfigurationComplete(uint8_t directions)844 void ReconfigurationComplete(uint8_t directions) {
845 if (directions & bluetooth::le_audio::types::kLeAudioDirectionSink) {
846 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
847 kLogAfReconfigComplete + "LocalSource",
848 "r_state: " + ToString(audio_receiver_state_) +
849 "s_state: " + ToString(audio_sender_state_));
850
851 le_audio_source_hal_client_->ReconfigurationComplete();
852 }
853 if (directions & bluetooth::le_audio::types::kLeAudioDirectionSource) {
854 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
855 kLogAfReconfigComplete + "LocalSink",
856 "r_state: " + ToString(audio_receiver_state_) +
857 "s_state: " + ToString(audio_sender_state_));
858
859 le_audio_sink_hal_client_->ReconfigurationComplete();
860 }
861 }
862
CancelLocalAudioSourceStreamingRequest()863 void CancelLocalAudioSourceStreamingRequest() {
864 le_audio_source_hal_client_->CancelStreamingRequest();
865
866 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
867 kLogAfCancel + "LocalSource",
868 "s_state: " + ToString(audio_sender_state_));
869
870 audio_sender_state_ = AudioState::IDLE;
871 }
872
CancelLocalAudioSinkStreamingRequest()873 void CancelLocalAudioSinkStreamingRequest() {
874 le_audio_sink_hal_client_->CancelStreamingRequest();
875
876 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
877 kLogAfCancel + "LocalSink",
878 "s_state: " + ToString(audio_receiver_state_));
879
880 audio_receiver_state_ = AudioState::IDLE;
881 }
882
CancelStreamingRequest()883 void CancelStreamingRequest() {
884 if (audio_sender_state_ >= AudioState::READY_TO_START) {
885 CancelLocalAudioSourceStreamingRequest();
886 }
887
888 if (audio_receiver_state_ >= AudioState::READY_TO_START) {
889 CancelLocalAudioSinkStreamingRequest();
890 }
891 }
892
group_add_node(const int group_id,const RawAddress & address,bool update_group_module=false)893 void group_add_node(const int group_id, const RawAddress& address,
894 bool update_group_module = false) {
895 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
896 LeAudioDeviceGroup* new_group;
897 LeAudioDeviceGroup* old_group = nullptr;
898
899 if (!leAudioDevice) {
900 /* TODO This part possible to remove as this is to handle adding device to
901 * the group which is unknown and not connected.
902 */
903 log::info("leAudioDevice unknown , address: {} group: 0x{:x}", address, group_id);
904
905 if (group_id == bluetooth::groups::kGroupUnknown) {
906 return;
907 }
908
909 log::info("Set member adding ...");
910 leAudioDevices_.Add(address, DeviceConnectState::CONNECTING_BY_USER);
911 leAudioDevice = leAudioDevices_.FindByAddress(address);
912 } else {
913 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
914 old_group = aseGroups_.FindById(leAudioDevice->group_id_);
915 }
916 }
917
918 auto id = DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
919 if (group_id == bluetooth::groups::kGroupUnknown) {
920 if (id == bluetooth::groups::kGroupUnknown) {
921 DeviceGroups::Get()->AddDevice(address, bluetooth::le_audio::uuid::kCapServiceUuid);
922 /* We will get back here when group will be created */
923 return;
924 }
925
926 new_group = aseGroups_.Add(id);
927 if (!new_group) {
928 log::error("can't create group - group is already there?");
929 return;
930 }
931 } else {
932 log::assert_that(id == group_id, "group id missmatch? leaudio id: {}, groups module {}",
933 group_id, id);
934 new_group = aseGroups_.FindById(group_id);
935 if (!new_group) {
936 new_group = aseGroups_.Add(group_id);
937 } else {
938 if (new_group->IsDeviceInTheGroup(leAudioDevice)) {
939 return;
940 }
941 }
942 }
943
944 log::debug("New group {}, id: {}", std::format_ptr(new_group), new_group->group_id_);
945
946 /* If device was in the group and it was not removed by the application,
947 * lets do it now
948 */
949 if (old_group) {
950 group_remove_node(old_group, address, update_group_module);
951 }
952
953 new_group->AddNode(leAudioDevices_.GetByAddress(address));
954
955 callbacks_->OnGroupNodeStatus(address, new_group->group_id_, GroupNodeStatus::ADDED);
956
957 /* If device is connected and added to the group, lets read ASE states */
958 if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
959 AseInitialStateReadRequest(leAudioDevice);
960 }
961
962 if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
963 UpdateLocationsAndContextsAvailability(new_group);
964 }
965 }
966
GroupAddNode(const int group_id,const RawAddress & address)967 void GroupAddNode(const int group_id, const RawAddress& address) override {
968 auto id = DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
969 if (id == group_id) {
970 return;
971 }
972
973 if (id != bluetooth::groups::kGroupUnknown) {
974 DeviceGroups::Get()->RemoveDevice(address, id);
975 }
976
977 DeviceGroups::Get()->AddDevice(address, bluetooth::le_audio::uuid::kCapServiceUuid, group_id);
978 }
979
remove_group_if_possible(LeAudioDeviceGroup * group)980 void remove_group_if_possible(LeAudioDeviceGroup* group) {
981 if (!group) {
982 log::debug("group is null");
983 return;
984 }
985 log::debug("Group {}, id: {}, size: {}, is cig_state {}", std::format_ptr(group),
986 group->group_id_, group->Size(), ToString(group->cig.GetState()));
987 if (group->IsEmpty() && (group->cig.GetState() == bluetooth::le_audio::types::CigState::NONE)) {
988 lastNotifiedGroupStreamStatusMap_.erase(group->group_id_);
989 aseGroups_.Remove(group->group_id_);
990 }
991 }
992
group_remove_node(LeAudioDeviceGroup * group,const RawAddress & address,bool update_group_module=false)993 void group_remove_node(LeAudioDeviceGroup* group, const RawAddress& address,
994 bool update_group_module = false) {
995 int group_id = group->group_id_;
996 group->RemoveNode(leAudioDevices_.GetByAddress(address));
997
998 if (update_group_module) {
999 int groups_group_id =
1000 DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
1001 if (groups_group_id == group_id) {
1002 DeviceGroups::Get()->RemoveDevice(address, group_id);
1003 }
1004 }
1005
1006 callbacks_->OnGroupNodeStatus(address, group_id, GroupNodeStatus::REMOVED);
1007
1008 /* Remove group if this was the last leAudioDevice in this group */
1009 if (group->IsEmpty()) {
1010 remove_group_if_possible(group);
1011 return;
1012 }
1013
1014 /* Removing node from group requires updating group context availability */
1015 UpdateLocationsAndContextsAvailability(group);
1016 }
1017
GroupRemoveNode(const int group_id,const RawAddress & address)1018 void GroupRemoveNode(const int group_id, const RawAddress& address) override {
1019 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1020 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1021
1022 log::info("group_id: {} address: {}", group_id, address);
1023
1024 if (!leAudioDevice) {
1025 log::error("Skipping unknown leAudioDevice, address: {}", address);
1026 return;
1027 }
1028
1029 if (leAudioDevice->group_id_ != group_id) {
1030 log::error("Device is not in group_id: {}, but in group_id: {}", group_id,
1031 leAudioDevice->group_id_);
1032 return;
1033 }
1034
1035 if (group == NULL) {
1036 log::error("device not in the group ?!");
1037 return;
1038 }
1039
1040 if (leAudioDevice->HaveActiveAse()) {
1041 SetDeviceAsRemovePendingAndStopGroup(leAudioDevice);
1042 return;
1043 }
1044
1045 group_remove_node(group, address, true);
1046 }
1047
ChooseMetadataContextType(AudioContexts metadata_context_type)1048 AudioContexts ChooseMetadataContextType(AudioContexts metadata_context_type) {
1049 /* This function takes already filtered contexts which we are plannig to use
1050 * in the Enable or UpdateMetadata command.
1051 * Note we are not changing stream configuration here, but just the list of
1052 * the contexts in the Metadata which will be provide to remote side.
1053 * Ideally, we should send all the bits we have, but not all headsets like
1054 * it.
1055 */
1056 if (osi_property_get_bool(kAllowMultipleContextsInMetadata, true)) {
1057 return metadata_context_type;
1058 }
1059
1060 log::debug("Converting to single context type: {}", metadata_context_type.to_string());
1061
1062 /* Mini policy */
1063 if (metadata_context_type.any()) {
1064 LeAudioContextType context_priority_list[] = {
1065 /* Highest priority first */
1066 LeAudioContextType::CONVERSATIONAL, LeAudioContextType::RINGTONE,
1067 LeAudioContextType::LIVE, LeAudioContextType::VOICEASSISTANTS,
1068 LeAudioContextType::GAME, LeAudioContextType::MEDIA,
1069 LeAudioContextType::EMERGENCYALARM, LeAudioContextType::ALERTS,
1070 LeAudioContextType::INSTRUCTIONAL, LeAudioContextType::NOTIFICATIONS,
1071 LeAudioContextType::SOUNDEFFECTS,
1072 };
1073 for (auto ct : context_priority_list) {
1074 if (metadata_context_type.test(ct)) {
1075 log::debug("Converted to single context type: {}", ToString(ct));
1076 return AudioContexts(ct);
1077 }
1078 }
1079 }
1080
1081 /* Fallback to BAP mandated context type */
1082 log::warn("Invalid/unknown context, using 'UNSPECIFIED'");
1083 return AudioContexts(LeAudioContextType::UNSPECIFIED);
1084 }
1085
1086 /* Return true if stream is started */
GroupStream(int group_id,LeAudioContextType configuration_context_type,BidirectionalPair<AudioContexts> remote_contexts)1087 bool GroupStream(int group_id, LeAudioContextType configuration_context_type,
1088 BidirectionalPair<AudioContexts> remote_contexts) {
1089 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1090
1091 log::debug(
1092 "configuration_context_type= {}, remote sink contexts= {}, remote source contexts= {}",
1093 ToString(configuration_context_type), ToString(remote_contexts.sink),
1094 ToString(remote_contexts.source));
1095
1096 log::debug("");
1097 if (configuration_context_type >= LeAudioContextType::RFU) {
1098 log::error("stream context type is not supported: {}",
1099 ToHexString(configuration_context_type));
1100 return false;
1101 }
1102
1103 if (!group) {
1104 log::error("unknown group id: {}", group_id);
1105 return false;
1106 }
1107
1108 log::debug("group state={}, target_state={}", ToString(group->GetState()),
1109 ToString(group->GetTargetState()));
1110
1111 if (!group->IsAnyDeviceConnected()) {
1112 log::error("group {} is not connected", group_id);
1113 return false;
1114 }
1115
1116 /* Check if any group is in the transition state. If so, we don't allow to
1117 * start new group to stream
1118 */
1119 if (group->IsInTransition()) {
1120 /* WARNING: Due to group state machine limitations, we should not
1121 * interrupt any ongoing transition. We will check if another
1122 * reconfiguration is needed once the group reaches streaming state.
1123 */
1124 log::warn(
1125 "Group is already in the transition state. Waiting for the target "
1126 "state to be reached.");
1127 return false;
1128 }
1129
1130 /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
1131 auto ccid_contexts = remote_contexts;
1132 if (IsInVoipCall() && !IsInCall()) {
1133 ccid_contexts.sink.unset(LeAudioContextType::CONVERSATIONAL);
1134 ccid_contexts.source.unset(LeAudioContextType::CONVERSATIONAL);
1135 }
1136
1137 bool group_is_streaming = group->IsStreaming();
1138
1139 BidirectionalPair<std::vector<uint8_t>> ccids = {
1140 .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.sink),
1141 .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.source)};
1142 if (group->IsPendingConfiguration()) {
1143 return groupStateMachine_->ConfigureStream(group, configuration_context_type_,
1144 remote_contexts, ccids);
1145 } else if (!group_is_streaming) {
1146 speed_start_setup(group->group_id_, configuration_context_type, group->NumOfConnected());
1147 }
1148
1149 /* If assistant have some connected delegators that needs to be informed
1150 * when there would be request to stream unicast.
1151 */
1152 if (!sink_monitor_mode_ && source_monitor_mode_ && !group_is_streaming) {
1153 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_REQUESTED);
1154 }
1155
1156 bool result = groupStateMachine_->StartStream(group, configuration_context_type,
1157 remote_contexts, ccids);
1158
1159 if (result && !group_is_streaming) {
1160 /* Notify Java about new configuration when start stream has been accepted and
1161 * it is not metadata update
1162 */
1163 SendAudioGroupCurrentCodecConfigChanged(group);
1164 }
1165
1166 return result;
1167 }
1168
GroupStream(const int group_id,uint16_t context_type)1169 void GroupStream(const int group_id, uint16_t context_type) override {
1170 BidirectionalPair<AudioContexts> initial_contexts = {AudioContexts(context_type),
1171 AudioContexts(context_type)};
1172 GroupStream(group_id, LeAudioContextType(context_type), initial_contexts);
1173 }
1174
GroupSuspend(const int group_id)1175 void GroupSuspend(const int group_id) override {
1176 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1177
1178 if (!group) {
1179 log::error("unknown group id: {}", group_id);
1180 return;
1181 }
1182
1183 if (!group->IsAnyDeviceConnected()) {
1184 log::error("group is not connected");
1185 return;
1186 }
1187
1188 if (group->IsInTransition()) {
1189 log::info(", group is in transition from: {} to: {}", ToString(group->GetState()),
1190 ToString(group->GetTargetState()));
1191 return;
1192 }
1193
1194 if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1195 log::error(", invalid current state of group: {}", ToString(group->GetState()));
1196 return;
1197 }
1198
1199 groupStateMachine_->SuspendStream(group);
1200 }
1201
GroupStop(const int group_id)1202 void GroupStop(const int group_id) override {
1203 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1204
1205 if (!group) {
1206 log::error("unknown group id: {}", group_id);
1207 return;
1208 }
1209
1210 if (group->IsEmpty()) {
1211 log::error("group is empty");
1212 return;
1213 }
1214
1215 groupStateMachine_->StopStream(group);
1216 }
1217
GroupDestroy(const int group_id)1218 void GroupDestroy(const int group_id) override {
1219 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1220
1221 if (!group) {
1222 log::error("unknown group id: {}", group_id);
1223 return;
1224 }
1225
1226 // Disconnect and remove each device within the group
1227 auto* dev = group->GetFirstDevice();
1228 while (dev) {
1229 auto* next_dev = group->GetNextDevice(dev);
1230 RemoveDevice(dev->address_);
1231 dev = next_dev;
1232 }
1233 }
1234
SetCodecConfigPreference(int group_id,bluetooth::le_audio::btle_audio_codec_config_t input_codec_config,bluetooth::le_audio::btle_audio_codec_config_t output_codec_config)1235 void SetCodecConfigPreference(
1236 int group_id, bluetooth::le_audio::btle_audio_codec_config_t input_codec_config,
1237 bluetooth::le_audio::btle_audio_codec_config_t output_codec_config) override {
1238 if (!com::android::bluetooth::flags::leaudio_set_codec_config_preference()) {
1239 log::debug("leaudio_set_codec_config_preference flag is not enabled");
1240 return;
1241 }
1242
1243 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1244
1245 if (!group) {
1246 log::error("Unknown group id: %d", group_id);
1247 }
1248
1249 if (group->SetPreferredAudioSetConfiguration(input_codec_config, output_codec_config)) {
1250 log::info("group id: {}, setting preferred codec is successful.", group_id);
1251 } else {
1252 log::warn("group id: {}, setting preferred codec is failed.", group_id);
1253 return;
1254 }
1255
1256 if (group_id != active_group_id_) {
1257 log::warn("Selected group is not active.");
1258 return;
1259 }
1260
1261 if (SetConfigurationAndStopStreamWhenNeeded(group, group->GetConfigurationContextType())) {
1262 log::debug("Group id {} do the reconfiguration based on preferred codec config", group_id);
1263 } else {
1264 log::debug("Group id {} preferred codec config is not changed", group_id);
1265 }
1266 }
1267
IsUsingPreferredCodecConfig(int group_id,int context_type)1268 bool IsUsingPreferredCodecConfig(int group_id, int context_type) {
1269 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1270 if (!group) {
1271 log::error("Unknown group id: %d", group_id);
1272 return false;
1273 }
1274
1275 return group->IsUsingPreferredAudioSetConfiguration(
1276 static_cast<LeAudioContextType>(context_type));
1277 }
1278
SetCcidInformation(int ccid,int context_type)1279 void SetCcidInformation(int ccid, int context_type) override {
1280 log::debug("Ccid: {}, context type {}", ccid, context_type);
1281
1282 ContentControlIdKeeper::GetInstance()->SetCcid(AudioContexts(context_type), ccid);
1283 }
1284
initReconfiguration(LeAudioDeviceGroup * group,LeAudioContextType previous_context_type)1285 void initReconfiguration(LeAudioDeviceGroup* group, LeAudioContextType previous_context_type) {
1286 log::debug(" group_id: {}, previous context_type {}", group->group_id_,
1287 ToString(previous_context_type));
1288 pre_configuration_context_type_ = previous_context_type;
1289 group->SetPendingConfiguration();
1290 groupStateMachine_->StopStream(group);
1291 speed_start_setup(group->group_id_, configuration_context_type_, group->NumOfConnected(), true);
1292 }
1293
SetInCall(bool in_call)1294 void SetInCall(bool in_call) override {
1295 log::debug("in_call: {}", in_call);
1296 if (in_call == in_call_) {
1297 log::verbose("no state change {}", in_call);
1298 return;
1299 }
1300
1301 in_call_ = in_call;
1302
1303 if (!com::android::bluetooth::flags::leaudio_speed_up_reconfiguration_between_call()) {
1304 log::debug("leaudio_speed_up_reconfiguration_between_call flag is not enabled");
1305 return;
1306 }
1307
1308 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1309 log::debug("There is no active group");
1310 return;
1311 }
1312
1313 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1314 if (!group || !group->IsStreaming()) {
1315 log::debug("{} is not streaming", active_group_id_);
1316 return;
1317 }
1318
1319 bool reconfigure = false;
1320
1321 if (in_call_) {
1322 in_call_metadata_context_types_ = local_metadata_context_types_;
1323
1324 log::debug("in_call_metadata_context_types_ sink: {} source: {}",
1325 in_call_metadata_context_types_.sink.to_string(),
1326 in_call_metadata_context_types_.source.to_string());
1327
1328 auto audio_set_conf = group->GetConfiguration(LeAudioContextType::CONVERSATIONAL);
1329 if (audio_set_conf && group->IsGroupConfiguredTo(*audio_set_conf)) {
1330 log::info("Call is coming, but CIG already set for a call");
1331 return;
1332 }
1333 log::info("Call is coming, speed up reconfiguration for a call");
1334 local_metadata_context_types_.sink.clear();
1335 local_metadata_context_types_.source.clear();
1336 reconfigure = true;
1337 } else {
1338 if (configuration_context_type_ == LeAudioContextType::CONVERSATIONAL) {
1339 log::info("Call is ended, speed up reconfiguration for media");
1340 local_metadata_context_types_ = in_call_metadata_context_types_;
1341 log::debug("restored local_metadata_context_types_ sink: {} source: {}",
1342 local_metadata_context_types_.sink.to_string(),
1343 local_metadata_context_types_.source.to_string());
1344 in_call_metadata_context_types_.sink.clear();
1345 in_call_metadata_context_types_.source.clear();
1346 reconfigure = true;
1347 }
1348 }
1349
1350 if (reconfigure) {
1351 ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSink);
1352 }
1353 }
1354
IsInCall()1355 bool IsInCall() override { return in_call_; }
1356
SetInVoipCall(bool in_call)1357 void SetInVoipCall(bool in_call) override {
1358 log::debug("in_voip_call: {}", in_call);
1359 in_voip_call_ = in_call;
1360 }
1361
IsInVoipCall()1362 bool IsInVoipCall() override { return in_voip_call_; }
1363
IsInStreaming()1364 bool IsInStreaming() override {
1365 return audio_sender_state_ == AudioState::STARTED ||
1366 audio_receiver_state_ == AudioState::STARTED;
1367 }
1368
SetUnicastMonitorMode(uint8_t direction,bool enable)1369 void SetUnicastMonitorMode(uint8_t direction, bool enable) override {
1370 if (direction == bluetooth::le_audio::types::kLeAudioDirectionSink) {
1371 /* Cleanup Sink HAL client interface if listening mode is toggled off
1372 * before group activation (active group context would take care of
1373 * Sink HAL client cleanup).
1374 */
1375 if (sink_monitor_mode_ && !enable && le_audio_sink_hal_client_ &&
1376 active_group_id_ == bluetooth::groups::kGroupUnknown) {
1377 local_metadata_context_types_.sink.clear();
1378 le_audio_sink_hal_client_->Stop();
1379 le_audio_sink_hal_client_.reset();
1380 }
1381
1382 log::debug("enable: {}", enable);
1383 sink_monitor_mode_ = enable;
1384 } else if (direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
1385 log::debug("enable: {}", enable);
1386 source_monitor_mode_ = enable;
1387
1388 if (!enable) {
1389 return;
1390 }
1391
1392 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1393 if (!group) {
1394 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
1395
1396 return;
1397 }
1398
1399 if (group->IsStreaming()) {
1400 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING);
1401 } else {
1402 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
1403 }
1404 } else {
1405 log::error("invalid direction: 0x{:02x} monitor mode set", direction);
1406 }
1407 }
1408
SendAudioProfilePreferences(const int group_id,bool is_output_preference_le_audio,bool is_duplex_preference_le_audio)1409 void SendAudioProfilePreferences(const int group_id, bool is_output_preference_le_audio,
1410 bool is_duplex_preference_le_audio) override {
1411 log::info(
1412 "group_id: {}, is_output_preference_le_audio: {}, "
1413 "is_duplex_preference_le_audio: {}",
1414 group_id, is_output_preference_le_audio, is_duplex_preference_le_audio);
1415 if (group_id == bluetooth::groups::kGroupUnknown) {
1416 log::warn("Unknown group_id");
1417 return;
1418 }
1419 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1420 if (!group) {
1421 log::warn("group_id {} does not exist", group_id);
1422 return;
1423 }
1424
1425 group->is_output_preference_le_audio = is_output_preference_le_audio;
1426 group->is_duplex_preference_le_audio = is_duplex_preference_le_audio;
1427 }
1428
SetGroupAllowedContextMask(int group_id,int sink_context_types,int source_context_types)1429 void SetGroupAllowedContextMask(int group_id, int sink_context_types,
1430 int source_context_types) override {
1431 log::info("group_id: {}, sink context types: {}, source context types: {}", group_id,
1432 sink_context_types, source_context_types);
1433
1434 if (group_id == bluetooth::groups::kGroupUnknown) {
1435 log::warn("Unknown group_id");
1436 return;
1437 }
1438 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1439 if (!group) {
1440 log::warn("group_id {} does not exist", group_id);
1441 return;
1442 }
1443
1444 BidirectionalPair<AudioContexts> allowed_contexts = {
1445 .sink = AudioContexts(sink_context_types),
1446 .source = AudioContexts(source_context_types),
1447 };
1448
1449 group->SetAllowedContextMask(allowed_contexts);
1450 }
1451
StartAudioSession(LeAudioDeviceGroup * group)1452 void StartAudioSession(LeAudioDeviceGroup* group) {
1453 /* This function is called when group is not yet set to active.
1454 * This is why we don't have to check if session is started already.
1455 * Just check if it is acquired.
1456 */
1457 log::assert_that(active_group_id_ == bluetooth::groups::kGroupUnknown,
1458 "Active group is not set.");
1459 log::assert_that(le_audio_source_hal_client_ != nullptr, "Source session not acquired");
1460 log::assert_that(le_audio_sink_hal_client_ != nullptr, "Sink session not acquired");
1461
1462 DsaModes dsa_modes = {DsaMode::DISABLED};
1463 if (com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
1464 dsa_modes = group->GetAllowedDsaModes();
1465 }
1466
1467 /* We assume that peer device always use same frame duration */
1468 uint32_t frame_duration_us = 0;
1469 if (!current_encoder_config_.IsInvalid()) {
1470 frame_duration_us = current_encoder_config_.data_interval_us;
1471 } else if (!current_decoder_config_.IsInvalid()) {
1472 frame_duration_us = current_decoder_config_.data_interval_us;
1473 } else {
1474 log::assert_that(true, "Both configs are invalid");
1475 }
1476
1477 stack::l2cap::get_interface().L2CA_SetEcosystemBaseInterval(frame_duration_us / 1250);
1478
1479 // Scale by the codec frame blocks per SDU if set
1480 uint8_t codec_frame_blocks_per_sdu =
1481 group->stream_conf.stream_params.source.codec_frames_blocks_per_sdu ?: 1;
1482 audio_framework_source_config.data_interval_us = frame_duration_us * codec_frame_blocks_per_sdu;
1483
1484 le_audio_source_hal_client_->Start(audio_framework_source_config, audioSinkReceiver, dsa_modes);
1485
1486 /* We use same frame duration for sink/source */
1487 audio_framework_sink_config.data_interval_us = frame_duration_us * codec_frame_blocks_per_sdu;
1488
1489 /* If group supports more than 16kHz for the microphone in converstional
1490 * case let's use that also for Audio Framework.
1491 */
1492 auto sink_configuration = group->GetAudioSessionCodecConfigForDirection(
1493 LeAudioContextType::CONVERSATIONAL,
1494 bluetooth::le_audio::types::kLeAudioDirectionSource);
1495 if (!sink_configuration.IsInvalid() &&
1496 sink_configuration.sample_rate > bluetooth::audio::le_audio::kSampleRate16000) {
1497 audio_framework_sink_config.sample_rate = sink_configuration.sample_rate;
1498 }
1499
1500 le_audio_sink_hal_client_->Start(audio_framework_sink_config, audioSourceReceiver, dsa_modes);
1501 }
1502
isOutputPreferenceLeAudio(const RawAddress & address)1503 bool isOutputPreferenceLeAudio(const RawAddress& address) {
1504 log::info("address: {}, active_group_id_: {}", address.ToStringForLogging(), active_group_id_);
1505 std::vector<RawAddress> active_leaudio_devices = GetGroupDevices(active_group_id_);
1506 if (std::find(active_leaudio_devices.begin(), active_leaudio_devices.end(), address) ==
1507 active_leaudio_devices.end()) {
1508 log::info("Device {} is not active for LE Audio", address.ToStringForLogging());
1509 return false;
1510 }
1511
1512 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1513 log::info("active_group_id: {}, is_output_preference_le_audio_: {}", group->group_id_,
1514 group->is_output_preference_le_audio);
1515 return group->is_output_preference_le_audio;
1516 }
1517
isDuplexPreferenceLeAudio(const RawAddress & address)1518 bool isDuplexPreferenceLeAudio(const RawAddress& address) {
1519 log::info("address: {}, active_group_id_: {}", address.ToStringForLogging(), active_group_id_);
1520 std::vector<RawAddress> active_leaudio_devices = GetGroupDevices(active_group_id_);
1521 if (std::find(active_leaudio_devices.begin(), active_leaudio_devices.end(), address) ==
1522 active_leaudio_devices.end()) {
1523 log::info("Device {} is not active for LE Audio", address.ToStringForLogging());
1524 return false;
1525 }
1526
1527 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1528 log::info("active_group_id: {}, is_duplex_preference_le_audio: {}", group->group_id_,
1529 group->is_duplex_preference_le_audio);
1530 return group->is_duplex_preference_le_audio;
1531 }
1532
groupSetAndNotifyInactive(void)1533 void groupSetAndNotifyInactive(void) {
1534 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1535 return;
1536 }
1537 sink_monitor_notified_status_ = std::nullopt;
1538 source_monitor_notified_status_ = std::nullopt;
1539 log::info("Group id: {}", active_group_id_);
1540
1541 StopSuspendTimeout();
1542
1543 StopAudio();
1544 ClientAudioInterfaceRelease();
1545
1546 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::INACTIVE);
1547 active_group_id_ = bluetooth::groups::kGroupUnknown;
1548 }
1549
PrepareStreamForAConversational(LeAudioDeviceGroup * group)1550 void PrepareStreamForAConversational(LeAudioDeviceGroup* group) {
1551 if (!com::android::bluetooth::flags::leaudio_improve_switch_during_phone_call()) {
1552 log::info("Flag leaudio_improve_switch_during_phone_call is not enabled");
1553 return;
1554 }
1555
1556 log::debug("group_id: {}", group->group_id_);
1557
1558 auto remote_direction = bluetooth::le_audio::types::kLeAudioDirectionSink;
1559 ReconfigureOrUpdateRemote(group, remote_direction);
1560
1561 if (configuration_context_type_ != LeAudioContextType::CONVERSATIONAL) {
1562 log::error("Something went wrong {} != {} ", ToString(configuration_context_type_),
1563 ToString(LeAudioContextType::CONVERSATIONAL));
1564 return;
1565 }
1566
1567 BidirectionalPair<std::vector<uint8_t>> ccids = {
1568 .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(
1569 local_metadata_context_types_.sink),
1570 .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(
1571 local_metadata_context_types_.source)};
1572 if (!groupStateMachine_->ConfigureStream(group, configuration_context_type_,
1573 local_metadata_context_types_, ccids, true)) {
1574 log::info("Reconfiguration is needed for group {}", group->group_id_);
1575 initReconfiguration(group, LeAudioContextType::UNSPECIFIED);
1576 }
1577 }
1578
GroupSetActive(const int group_id)1579 void GroupSetActive(const int group_id) override {
1580 log::info("group_id: {}", group_id);
1581
1582 if (group_id == bluetooth::groups::kGroupUnknown) {
1583 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1584 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1585 /* Nothing to do */
1586 return;
1587 }
1588
1589 log::info("Active group_id changed {} -> {}", active_group_id_, group_id);
1590 auto group_id_to_close = active_group_id_;
1591 groupSetAndNotifyInactive();
1592 GroupStop(group_id_to_close);
1593
1594 return;
1595 }
1596
1597 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1598 if (!group) {
1599 log::error("Invalid group: {}", static_cast<int>(group_id));
1600 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1601 return;
1602 }
1603
1604 if (group->NumOfConnected() == 0) {
1605 log::error("Group: {} is not connected anymore", static_cast<int>(group_id));
1606 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1607 return;
1608 }
1609
1610 if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
1611 if (active_group_id_ == group_id) {
1612 log::info("Group is already active: {}", static_cast<int>(active_group_id_));
1613 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1614 return;
1615 }
1616 log::info("switching active group to: {}", group_id);
1617
1618 auto result = CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
1619 le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(), false);
1620 log::assert_that(result, "Could not update session to codec manager");
1621 }
1622
1623 if (!le_audio_source_hal_client_) {
1624 le_audio_source_hal_client_ = LeAudioSourceAudioHalClient::AcquireUnicast();
1625 if (!le_audio_source_hal_client_) {
1626 log::error("could not acquire audio source interface");
1627 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1628 return;
1629 }
1630 }
1631
1632 if (!le_audio_sink_hal_client_) {
1633 le_audio_sink_hal_client_ = LeAudioSinkAudioHalClient::AcquireUnicast();
1634 if (!le_audio_sink_hal_client_) {
1635 log::error("could not acquire audio sink interface");
1636 callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1637 return;
1638 }
1639 }
1640
1641 auto result = CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
1642 le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(), true);
1643 log::assert_that(result, "Could not update session to codec manager");
1644
1645 /* Mini policy: Try configure audio HAL sessions with most recent context.
1646 * If reconfiguration is not needed it means, context type is not supported.
1647 * If most recent scenario is not supported, try to find first supported.
1648 */
1649 LeAudioContextType default_context_type = configuration_context_type_;
1650 if (!group->IsAudioSetConfigurationAvailable(default_context_type)) {
1651 if (group->IsAudioSetConfigurationAvailable(LeAudioContextType::UNSPECIFIED)) {
1652 default_context_type = LeAudioContextType::UNSPECIFIED;
1653 default_context_type = LeAudioContextType::UNSPECIFIED;
1654 } else {
1655 for (LeAudioContextType context_type : kLeAudioContextAllTypesArray) {
1656 if (group->IsAudioSetConfigurationAvailable(context_type)) {
1657 default_context_type = context_type;
1658 break;
1659 }
1660 }
1661 }
1662 }
1663
1664 /* Only update the configuration audio context and audio coding session
1665 * parameters if needed.
1666 */
1667 UpdateConfigAndCheckIfReconfigurationIsNeeded(group, default_context_type);
1668
1669 auto previous_active_group = active_group_id_;
1670 log::info("Active group_id changed {} -> {}", previous_active_group, group_id);
1671
1672 if (previous_active_group == bluetooth::groups::kGroupUnknown) {
1673 /* Expose audio sessions if there was no previous active group */
1674 StartAudioSession(group);
1675 active_group_id_ = group_id;
1676 } else {
1677 /* In case there was an active group. Stop the stream, but before that, set
1678 * the new group so the group change is correctly handled in OnStateMachineStatusReportCb
1679 */
1680 active_group_id_ = group_id;
1681 SuspendedForReconfiguration();
1682 GroupStop(previous_active_group);
1683 /* Note: On purpose we are not sending INACTIVE status up to Java, because previous active
1684 * group will be provided in ACTIVE status. This is in order to have single call to audio
1685 * framework
1686 */
1687 }
1688
1689 /* Reset sink and source listener notified status */
1690 sink_monitor_notified_status_ = std::nullopt;
1691 source_monitor_notified_status_ = std::nullopt;
1692 if (com::android::bluetooth::flags::leaudio_codec_config_callback_order_fix()) {
1693 SendAudioGroupSelectableCodecConfigChanged(group);
1694 SendAudioGroupCurrentCodecConfigChanged(group);
1695 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1696 } else {
1697 callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1698 SendAudioGroupSelectableCodecConfigChanged(group);
1699 }
1700
1701 /* If group become active while phone call, let's configure it right away,
1702 * so when audio framework resumes the stream, it will be almost there.
1703 */
1704 if (IsInCall()) {
1705 PrepareStreamForAConversational(group);
1706 }
1707 }
1708
SetEnableState(const RawAddress & address,bool enabled)1709 void SetEnableState(const RawAddress& address, bool enabled) override {
1710 log::info("{}: {}", address, enabled ? "enabled" : "disabled");
1711 auto leAudioDevice = leAudioDevices_.FindByAddress(address);
1712 if (leAudioDevice == nullptr) {
1713 log::warn("{} is null", address);
1714 return;
1715 }
1716
1717 auto group_id = leAudioDevice->group_id_;
1718 auto group = aseGroups_.FindById(group_id);
1719 if (group == nullptr) {
1720 log::warn("Group {} is not available", group_id);
1721 return;
1722 }
1723
1724 if (enabled) {
1725 group->Enable(gatt_if_, reconnection_mode_);
1726 } else {
1727 group->Disable(gatt_if_);
1728 }
1729 }
1730
RemoveDevice(const RawAddress & address)1731 void RemoveDevice(const RawAddress& address) override {
1732 log::info(": {}", address);
1733 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1734 if (!leAudioDevice) {
1735 return;
1736 }
1737
1738 /* Remove device from the background connect if it is there */
1739 BTA_GATTC_CancelOpen(gatt_if_, address, false);
1740 btif_storage_set_leaudio_autoconnect(address, false);
1741
1742 log::info("{}, state: {}", address,
1743 bluetooth::common::ToString(leAudioDevice->GetConnectionState()));
1744 auto connection_state = leAudioDevice->GetConnectionState();
1745 switch (connection_state) {
1746 case DeviceConnectState::REMOVING:
1747 /* Just return, and let device disconnect */
1748 return;
1749 case DeviceConnectState::CONNECTED:
1750 case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
1751 case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
1752 /* ACL exist in this case, disconnect and mark as removing */
1753 Disconnect(address);
1754 [[fallthrough]];
1755 case DeviceConnectState::DISCONNECTING:
1756 case DeviceConnectState::DISCONNECTING_AND_RECOVER:
1757 /* Device is disconnecting, just mark it shall be removed after all. */
1758 leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
1759 return;
1760 case DeviceConnectState::CONNECTING_AUTOCONNECT:
1761 /* Fallthrough as for AUTOCONNECT it might be that device is doing direct connect
1762 * in case of previous connection timeout.
1763 */
1764 case DeviceConnectState::CONNECTING_BY_USER:
1765 BTA_GATTC_CancelOpen(gatt_if_, address, true);
1766 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
1767 break;
1768 case DeviceConnectState::DISCONNECTED:
1769 /* Do nothing, just remove device */
1770 break;
1771 }
1772
1773 /* Remove the group assignment if not yet removed. It might happen that the
1774 * group module has already called the appropriate callback and we have
1775 * already removed the group assignment.
1776 */
1777 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
1778 auto group = aseGroups_.FindById(leAudioDevice->group_id_);
1779 group_remove_node(group, address, true);
1780 }
1781
1782 leAudioDevices_.Remove(address);
1783 }
1784
Connect(const RawAddress & address)1785 void Connect(const RawAddress& address) override {
1786 log::info(": {}", address);
1787
1788 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1789 if (!leAudioDevice) {
1790 if (!BTM_IsLinkKeyKnown(address, BT_TRANSPORT_LE)) {
1791 log::error("Connecting {} when not bonded", address);
1792 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1793 return;
1794 }
1795 leAudioDevices_.Add(address, DeviceConnectState::CONNECTING_BY_USER);
1796 } else {
1797 auto current_connect_state = leAudioDevice->GetConnectionState();
1798 if ((current_connect_state == DeviceConnectState::CONNECTED) ||
1799 (current_connect_state == DeviceConnectState::CONNECTING_BY_USER)) {
1800 log::error("Device {} is in invalid state: {}", leAudioDevice->address_,
1801 bluetooth::common::ToString(current_connect_state));
1802
1803 return;
1804 }
1805
1806 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
1807 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
1808 if (!group) {
1809 log::warn("{}, trying to connect to disabled group id {}", address,
1810 leAudioDevice->group_id_);
1811 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1812 return;
1813 }
1814 }
1815
1816 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_BY_USER);
1817
1818 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
1819 leAudioDevice->group_id_, address, ConnectionState::CONNECTING,
1820 bluetooth::le_audio::ConnectionStatus::SUCCESS);
1821 }
1822
1823 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
1824 }
1825
GetGroupDevices(const int group_id)1826 std::vector<RawAddress> GetGroupDevices(const int group_id) override {
1827 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1828 std::vector<RawAddress> all_group_device_addrs;
1829
1830 if (group != nullptr) {
1831 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
1832 while (leAudioDevice) {
1833 all_group_device_addrs.push_back(leAudioDevice->address_);
1834 leAudioDevice = group->GetNextDevice(leAudioDevice);
1835 };
1836 }
1837
1838 return all_group_device_addrs;
1839 }
1840
1841 /* Restore paired device from storage to recreate groups */
AddFromStorage(const RawAddress & address,bool autoconnect,int sink_audio_location,int source_audio_location,int sink_supported_context_types,int source_supported_context_types,const std::vector<uint8_t> & handles,const std::vector<uint8_t> & sink_pacs,const std::vector<uint8_t> & source_pacs,const std::vector<uint8_t> & ases)1842 void AddFromStorage(const RawAddress& address, bool autoconnect, int sink_audio_location,
1843 int source_audio_location, int sink_supported_context_types,
1844 int source_supported_context_types, const std::vector<uint8_t>& handles,
1845 const std::vector<uint8_t>& sink_pacs,
1846 const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases) {
1847 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1848
1849 if (leAudioDevice) {
1850 log::error("Device is already loaded. Nothing to do.");
1851 return;
1852 }
1853
1854 log::info(
1855 "restoring: {}, autoconnect {}, sink_audio_location: {}, "
1856 "source_audio_location: {}, sink_supported_context_types : 0x{:04x}, "
1857 "source_supported_context_types 0x{:04x}",
1858 address, autoconnect, sink_audio_location, source_audio_location,
1859 sink_supported_context_types, source_supported_context_types);
1860
1861 leAudioDevices_.Add(address, DeviceConnectState::DISCONNECTED);
1862 leAudioDevice = leAudioDevices_.FindByAddress(address);
1863
1864 int group_id =
1865 DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
1866 if (group_id != bluetooth::groups::kGroupUnknown) {
1867 group_add_node(group_id, address);
1868 }
1869
1870 leAudioDevice->src_audio_locations_ = source_audio_location;
1871 leAudioDevice->snk_audio_locations_ = sink_audio_location;
1872 callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_,
1873 leAudioDevice->snk_audio_locations_.to_ulong());
1874
1875 BidirectionalPair<AudioContexts> supported_contexts = {
1876 .sink = AudioContexts(sink_supported_context_types),
1877 .source = AudioContexts(source_supported_context_types),
1878 };
1879
1880 leAudioDevice->SetSupportedContexts(supported_contexts);
1881
1882 /* Use same as supported ones for now. */
1883 leAudioDevice->SetAvailableContexts(supported_contexts);
1884
1885 if (!DeserializeHandles(leAudioDevice, handles)) {
1886 log::warn("Could not load Handles");
1887 }
1888
1889 /* Presence of PAC characteristic for a direction means support for that direction */
1890 if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0) {
1891 leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource;
1892 }
1893 if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0) {
1894 leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink;
1895 }
1896
1897 if (!DeserializeSinkPacs(leAudioDevice, sink_pacs)) {
1898 /* If PACs are invalid, just say whole cache is invalid */
1899 leAudioDevice->known_service_handles_ = false;
1900 log::warn("Could not load sink pacs");
1901 }
1902
1903 if (!DeserializeSourcePacs(leAudioDevice, source_pacs)) {
1904 /* If PACs are invalid, just say whole cache is invalid */
1905 leAudioDevice->known_service_handles_ = false;
1906 log::warn("Could not load source pacs");
1907 }
1908
1909 if (!DeserializeAses(leAudioDevice, ases)) {
1910 /* If ASEs are invalid, just say whole cache is invalid */
1911 leAudioDevice->known_service_handles_ = false;
1912 log::warn("Could not load ases");
1913 }
1914
1915 leAudioDevice->autoconnect_flag_ = autoconnect;
1916 /* When adding from storage, make sure that autoconnect is used
1917 * by all the devices in the group.
1918 */
1919 leAudioDevices_.SetInitialGroupAutoconnectState(group_id, gatt_if_, reconnection_mode_,
1920 autoconnect);
1921 }
1922
GetHandlesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1923 bool GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
1924 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1925 return SerializeHandles(leAudioDevice, out);
1926 }
1927
GetSinkPacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1928 bool GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
1929 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1930 return SerializeSinkPacs(leAudioDevice, out);
1931 }
1932
GetSourcePacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1933 bool GetSourcePacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
1934 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1935 return SerializeSourcePacs(leAudioDevice, out);
1936 }
1937
GetAsesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)1938 bool GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
1939 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
1940
1941 return SerializeAses(leAudioDevice, out);
1942 }
1943
BackgroundConnectIfNeeded(LeAudioDevice * leAudioDevice)1944 void BackgroundConnectIfNeeded(LeAudioDevice* leAudioDevice) {
1945 if (!leAudioDevice->autoconnect_flag_) {
1946 log::debug("Device {} not in the background connect", leAudioDevice->address_);
1947 return;
1948 }
1949 AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
1950 }
1951
Disconnect(const RawAddress & address)1952 void Disconnect(const RawAddress& address) override {
1953 log::info(": {}", address);
1954 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1955
1956 if (!leAudioDevice) {
1957 log::warn("leAudioDevice not connected ( {} )", address);
1958 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1959 return;
1960 }
1961
1962 auto connection_state = leAudioDevice->GetConnectionState();
1963 log::info("{}, state: {}", address, bluetooth::common::ToString(connection_state));
1964
1965 switch (connection_state) {
1966 case DeviceConnectState::CONNECTING_BY_USER:
1967 /* Timeout happen on the Java layer. Device probably not in the range.
1968 * Cancel just direct connection and keep background if it is there.
1969 */
1970 BTA_GATTC_CancelOpen(gatt_if_, address, true);
1971 /* If this is a device which is a part of the group which is connected,
1972 * lets start backgroup connect
1973 */
1974 BackgroundConnectIfNeeded(leAudioDevice);
1975 return;
1976 case DeviceConnectState::CONNECTED: {
1977 /* User is disconnecting the device, we shall remove the autoconnect
1978 * flag for this device and all others if not TA is used
1979 */
1980 /* If target announcement is used, do not remove autoconnect
1981 */
1982 bool remove_from_autoconnect =
1983 (reconnection_mode_ != BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS);
1984
1985 if (leAudioDevice->autoconnect_flag_ && remove_from_autoconnect) {
1986 log::info("Removing autoconnect flag for group_id {}", leAudioDevice->group_id_);
1987
1988 /* Removes device from background connect */
1989 BTA_GATTC_CancelOpen(gatt_if_, address, false);
1990 btif_storage_set_leaudio_autoconnect(address, false);
1991 leAudioDevice->autoconnect_flag_ = false;
1992 }
1993
1994 /* Make sure ACL is disconnected to avoid reconnecting immediately
1995 * when autoconnect with TA reconnection mechanism is used.
1996 */
1997 bool force_acl_disconnect = leAudioDevice->autoconnect_flag_;
1998
1999 auto group = aseGroups_.FindById(leAudioDevice->group_id_);
2000 if (group) {
2001 /* Remove devices from auto connect mode */
2002 for (auto dev = group->GetFirstDevice(); dev; dev = group->GetNextDevice(dev)) {
2003 if (remove_from_autoconnect &&
2004 (dev->GetConnectionState() == DeviceConnectState::CONNECTING_AUTOCONNECT)) {
2005 btif_storage_set_leaudio_autoconnect(dev->address_, false);
2006 dev->autoconnect_flag_ = false;
2007 BTA_GATTC_CancelOpen(gatt_if_, dev->address_, false);
2008 dev->SetConnectionState(DeviceConnectState::DISCONNECTED);
2009 }
2010 }
2011
2012 /* If group is Streaming or is in transition for Streaming - lets stop it
2013 * and mark device to disconnect when stream is closed
2014 */
2015 if (group->IsStreaming() || !group->IsReleasingOrIdle()) {
2016 log::debug("group_id {} needs to stop streaming before {} disconnection",
2017 group->group_id_, leAudioDevice->address_);
2018 leAudioDevice->closing_stream_for_disconnection_ = true;
2019 groupStateMachine_->StopStream(group);
2020 return;
2021 }
2022
2023 if (group->IsReleasing()) {
2024 log::debug("group_id {} needs to stop streaming before {} disconnection",
2025 group->group_id_, leAudioDevice->address_);
2026 /* Stream is releasing, wait till it is completed and then disconnect ACL. */
2027 leAudioDevice->closing_stream_for_disconnection_ = true;
2028 return;
2029 }
2030
2031 force_acl_disconnect &= group->IsEnabled();
2032 }
2033
2034 DisconnectDevice(leAudioDevice, force_acl_disconnect);
2035 }
2036 return;
2037 case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
2038 /* Timeout happen on the Java layer before native got ready with the
2039 * device */
2040 DisconnectDevice(leAudioDevice);
2041 return;
2042 case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
2043 /* Java is not aware about autoconnect actions,
2044 * therefore this should not happen.
2045 */
2046 log::warn("Should not happen - disconnect device");
2047 DisconnectDevice(leAudioDevice);
2048 return;
2049 case DeviceConnectState::DISCONNECTED:
2050 case DeviceConnectState::DISCONNECTING:
2051 case DeviceConnectState::DISCONNECTING_AND_RECOVER:
2052 case DeviceConnectState::CONNECTING_AUTOCONNECT:
2053 case DeviceConnectState::REMOVING:
2054 log::warn("{}, invalid state {}", address, bluetooth::common::ToString(connection_state));
2055 return;
2056 }
2057 }
2058
DisconnectDevice(LeAudioDevice * leAudioDevice,bool acl_force_disconnect=false,bool recover=false)2059 void DisconnectDevice(LeAudioDevice* leAudioDevice, bool acl_force_disconnect = false,
2060 bool recover = false) {
2061 if (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID) {
2062 return;
2063 }
2064
2065 if (leAudioDevice->GetConnectionState() != DeviceConnectState::REMOVING) {
2066 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING);
2067 }
2068
2069 BtaGattQueue::Clean(leAudioDevice->conn_id_);
2070
2071 /* Remote in bad state, force ACL Disconnection. */
2072 if (acl_force_disconnect) {
2073 leAudioDevice->DisconnectAcl();
2074 if (recover) {
2075 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING_AND_RECOVER);
2076 }
2077 } else {
2078 BTA_GATTC_Close(leAudioDevice->conn_id_);
2079 }
2080 }
2081
DeregisterNotifications(LeAudioDevice * leAudioDevice)2082 void DeregisterNotifications(LeAudioDevice* leAudioDevice) {
2083 /* GATTC will omit not registered previously handles */
2084 for (auto pac_tuple : leAudioDevice->snk_pacs_) {
2085 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2086 std::get<0>(pac_tuple).val_hdl);
2087 }
2088 for (auto pac_tuple : leAudioDevice->src_pacs_) {
2089 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2090 std::get<0>(pac_tuple).val_hdl);
2091 }
2092
2093 if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0) {
2094 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2095 leAudioDevice->snk_audio_locations_hdls_.val_hdl);
2096 }
2097 if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0) {
2098 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2099 leAudioDevice->src_audio_locations_hdls_.val_hdl);
2100 }
2101 if (leAudioDevice->audio_avail_hdls_.val_hdl != 0) {
2102 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2103 leAudioDevice->audio_avail_hdls_.val_hdl);
2104 }
2105 if (leAudioDevice->audio_supp_cont_hdls_.val_hdl != 0) {
2106 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2107 leAudioDevice->audio_supp_cont_hdls_.val_hdl);
2108 }
2109 if (leAudioDevice->ctp_hdls_.val_hdl != 0) {
2110 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2111 leAudioDevice->ctp_hdls_.val_hdl);
2112 }
2113
2114 for (struct ase& ase : leAudioDevice->ases_) {
2115 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_, ase.hdls.val_hdl);
2116 }
2117 }
2118
handleInitialCtpCccRead(LeAudioDevice * leAudioDevice,uint16_t len,uint8_t * value)2119 void handleInitialCtpCccRead(LeAudioDevice* leAudioDevice, uint16_t len, uint8_t* value) {
2120 if (len != 2) {
2121 log::error("Could not read CCC for {}, disconnecting", leAudioDevice->address_);
2122 instance->Disconnect(leAudioDevice->address_);
2123 return;
2124 }
2125
2126 uint16_t val = *(uint16_t*)value;
2127 if (val == 0) {
2128 log::warn("{} forgot CCC values. Re-subscribing", leAudioDevice->address_);
2129 RegisterKnownNotifications(leAudioDevice, false, true);
2130 return;
2131 }
2132
2133 log::verbose("{}, ASCS ctp ccc: {:#x}", leAudioDevice->address_, val);
2134 connectionReady(leAudioDevice);
2135 }
2136
2137 /* This is a generic read/notify/indicate handler for gatt. Here messages
2138 * are dispatched to correct elements e.g. ASEs, PACs, audio locations etc.
2139 */
LeAudioCharValueHandle(tCONN_ID conn_id,uint16_t hdl,uint16_t len,uint8_t * value,bool notify=false)2140 void LeAudioCharValueHandle(tCONN_ID conn_id, uint16_t hdl, uint16_t len, uint8_t* value,
2141 bool notify = false) {
2142 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2143 struct ase* ase;
2144
2145 if (!leAudioDevice) {
2146 log::error("no leAudioDevice assigned to connection id: {}", conn_id);
2147 return;
2148 }
2149
2150 ase = leAudioDevice->GetAseByValHandle(hdl);
2151 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
2152 if (ase) {
2153 groupStateMachine_->ProcessGattNotifEvent(value, len, ase, leAudioDevice, group);
2154 return;
2155 }
2156
2157 /* Initial CCC read to check if remote device properly keeps CCC values */
2158 if (hdl == leAudioDevice->ctp_hdls_.ccc_hdl) {
2159 handleInitialCtpCccRead(leAudioDevice, len, value);
2160 return;
2161 }
2162
2163 auto snk_pac_ent =
2164 std::find_if(leAudioDevice->snk_pacs_.begin(), leAudioDevice->snk_pacs_.end(),
2165 [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
2166 if (snk_pac_ent != leAudioDevice->snk_pacs_.end()) {
2167 std::vector<struct bluetooth::le_audio::types::acs_ac_record> pac_recs;
2168
2169 /* Guard consistency of PAC records structure */
2170 if (!bluetooth::le_audio::client_parser::pacs::ParsePacs(pac_recs, len, value)) {
2171 return;
2172 }
2173
2174 log::info("Registering sink PACs");
2175 leAudioDevice->RegisterPACs(&std::get<1>(*snk_pac_ent), &pac_recs);
2176
2177 /* Cached audio set configurations should be considered invalid when
2178 * PACs are updated.
2179 */
2180 if (group) {
2181 /* Changes in PAC record channel counts may change the strategy */
2182 group->InvalidateGroupStrategy();
2183 group->InvalidateCachedConfigurations();
2184 }
2185 if (notify) {
2186 btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
2187 }
2188 return;
2189 }
2190
2191 auto src_pac_ent =
2192 std::find_if(leAudioDevice->src_pacs_.begin(), leAudioDevice->src_pacs_.end(),
2193 [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
2194 if (src_pac_ent != leAudioDevice->src_pacs_.end()) {
2195 std::vector<struct bluetooth::le_audio::types::acs_ac_record> pac_recs;
2196
2197 /* Guard consistency of PAC records structure */
2198 if (!bluetooth::le_audio::client_parser::pacs::ParsePacs(pac_recs, len, value)) {
2199 return;
2200 }
2201
2202 log::info("Registering source PACs");
2203 leAudioDevice->RegisterPACs(&std::get<1>(*src_pac_ent), &pac_recs);
2204
2205 /* Cached audio set configurations should be considered invalid when
2206 * PACs are updated.
2207 */
2208 if (group) {
2209 /* Changes in PAC record channel counts may change the strategy */
2210 group->InvalidateGroupStrategy();
2211 group->InvalidateCachedConfigurations();
2212 }
2213 if (notify) {
2214 btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
2215 }
2216 return;
2217 }
2218
2219 if (hdl == leAudioDevice->snk_audio_locations_hdls_.val_hdl) {
2220 AudioLocations snk_audio_locations;
2221
2222 bluetooth::le_audio::client_parser::pacs::ParseAudioLocations(snk_audio_locations, len,
2223 value);
2224
2225 /* Value may not change */
2226 if ((leAudioDevice->audio_directions_ & bluetooth::le_audio::types::kLeAudioDirectionSink) &&
2227 (leAudioDevice->snk_audio_locations_ ^ snk_audio_locations).none()) {
2228 return;
2229 }
2230
2231 /* Presence of PAC characteristic for source means support for source
2232 * audio location. Value of 0x00000000 means mono/unspecified
2233 */
2234 leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink;
2235 leAudioDevice->snk_audio_locations_ = snk_audio_locations;
2236
2237 callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_,
2238 snk_audio_locations.to_ulong());
2239
2240 if (notify) {
2241 btif_storage_set_leaudio_audio_location(leAudioDevice->address_,
2242 leAudioDevice->snk_audio_locations_.to_ulong(),
2243 leAudioDevice->src_audio_locations_.to_ulong());
2244 if (group && group->IsReleasingOrIdle()) {
2245 UpdateLocationsAndContextsAvailability(group);
2246 }
2247 }
2248 } else if (hdl == leAudioDevice->src_audio_locations_hdls_.val_hdl) {
2249 AudioLocations src_audio_locations;
2250
2251 bluetooth::le_audio::client_parser::pacs::ParseAudioLocations(src_audio_locations, len,
2252 value);
2253
2254 /* Value may not change */
2255 if ((leAudioDevice->audio_directions_ &
2256 bluetooth::le_audio::types::kLeAudioDirectionSource) &&
2257 (leAudioDevice->src_audio_locations_ ^ src_audio_locations).none()) {
2258 return;
2259 }
2260
2261 /* Presence of PAC characteristic for source means support for source
2262 * audio location. Value of 0x00000000 means mono/unspecified
2263 */
2264 leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource;
2265 leAudioDevice->src_audio_locations_ = src_audio_locations;
2266
2267 if (notify) {
2268 btif_storage_set_leaudio_audio_location(leAudioDevice->address_,
2269 leAudioDevice->snk_audio_locations_.to_ulong(),
2270 leAudioDevice->src_audio_locations_.to_ulong());
2271 if (group && group->IsReleasingOrIdle()) {
2272 UpdateLocationsAndContextsAvailability(group);
2273 }
2274 }
2275 } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) {
2276 BidirectionalPair<AudioContexts> contexts;
2277 if (!bluetooth::le_audio::client_parser::pacs::ParseAvailableAudioContexts(contexts, len,
2278 value)) {
2279 return;
2280 }
2281
2282 leAudioDevice->SetAvailableContexts(contexts);
2283
2284 if (!group) {
2285 return;
2286 }
2287
2288 if (group->IsInTransition()) {
2289 /* Group is in transition.
2290 * if group is going to stream, schedule attaching the device to the
2291 * group.
2292 */
2293
2294 if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
2295 AttachToStreamingGroupIfNeeded(leAudioDevice);
2296 }
2297 return;
2298 }
2299
2300 if (!group->IsStreaming()) {
2301 /* Group is not streaming. Device does not have to be attach to the
2302 * stream, and we can update context availability for the group
2303 */
2304 UpdateLocationsAndContextsAvailability(group);
2305 return;
2306 }
2307
2308 AttachToStreamingGroupIfNeeded(leAudioDevice);
2309
2310 } else if (hdl == leAudioDevice->audio_supp_cont_hdls_.val_hdl) {
2311 BidirectionalPair<AudioContexts> supp_audio_contexts;
2312 if (bluetooth::le_audio::client_parser::pacs::ParseSupportedAudioContexts(supp_audio_contexts,
2313 len, value)) {
2314 /* Just store if for now */
2315 leAudioDevice->SetSupportedContexts(supp_audio_contexts);
2316
2317 btif_storage_set_leaudio_supported_context_types(leAudioDevice->address_,
2318 supp_audio_contexts.sink.value(),
2319 supp_audio_contexts.source.value());
2320 }
2321 } else if (hdl == leAudioDevice->ctp_hdls_.val_hdl) {
2322 groupStateMachine_->ProcessGattCtpNotification(group, value, len);
2323 } else if (hdl == leAudioDevice->tmap_role_hdl_) {
2324 bluetooth::le_audio::client_parser::tmap::ParseTmapRole(leAudioDevice->tmap_role_, len,
2325 value);
2326 } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() &&
2327 hdl == leAudioDevice->gmap_client_->getRoleHandle()) {
2328 leAudioDevice->gmap_client_->parseAndSaveGmapRole(len, value);
2329 } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() &&
2330 hdl == leAudioDevice->gmap_client_->getUGTFeatureHandle()) {
2331 leAudioDevice->gmap_client_->parseAndSaveUGTFeature(len, value);
2332 } else {
2333 log::error("Unknown attribute read: 0x{:x}", hdl);
2334 }
2335 }
2336
OnGattReadRsp(tCONN_ID conn_id,tGATT_STATUS,uint16_t hdl,uint16_t len,uint8_t * value,void *)2337 void OnGattReadRsp(tCONN_ID conn_id, tGATT_STATUS /*status*/, uint16_t hdl, uint16_t len,
2338 uint8_t* value, void* /*data*/) {
2339 LeAudioCharValueHandle(conn_id, hdl, len, value);
2340 }
2341
GetGroupIfEnabled(int group_id)2342 LeAudioDeviceGroup* GetGroupIfEnabled(int group_id) {
2343 auto group = aseGroups_.FindById(group_id);
2344 if (group == nullptr) {
2345 log::info("Group {} does not exist", group_id);
2346 return nullptr;
2347 }
2348 if (!group->IsEnabled()) {
2349 log::info("Group {} is disabled", group_id);
2350 return nullptr;
2351 }
2352 return group;
2353 }
2354
AddToBackgroundConnectCheckGroupConnected(LeAudioDevice * leAudioDevice)2355 void AddToBackgroundConnectCheckGroupConnected(LeAudioDevice* leAudioDevice) {
2356 /* If device belongs to streaming group, add it on allow list */
2357 auto address = leAudioDevice->address_;
2358 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2359 if (group == nullptr) {
2360 log::info("Group {} is invalid or disabled", leAudioDevice->group_id_);
2361 return;
2362 }
2363
2364 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2365
2366 /* Cancel previous bakcground connect */
2367 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2368 if (group->IsAnyDeviceConnected()) {
2369 log::info("Group {} in connected state. Adding {} to allow list", leAudioDevice->group_id_,
2370 address);
2371 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
2372 } else {
2373 log::info("Adding {} to background connect (default reconnection_mode (0x{:02x}))", address,
2374 reconnection_mode_);
2375 BTA_GATTC_Open(gatt_if_, address, reconnection_mode_, false);
2376 }
2377 }
2378
OnGattConnected(tGATT_STATUS status,tCONN_ID conn_id,tGATT_IF,RawAddress address,tBT_TRANSPORT transport,uint16_t mtu)2379 void OnGattConnected(tGATT_STATUS status, tCONN_ID conn_id, tGATT_IF /*client_if*/,
2380 RawAddress address, tBT_TRANSPORT transport, uint16_t mtu) {
2381 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2382
2383 log::info("{}, conn_id=0x{:04x}, transport={}, status={} (0x{:02x})", address, conn_id,
2384 bt_transport_text(transport), gatt_status_text(status), status);
2385
2386 if (transport != BT_TRANSPORT_LE) {
2387 log::warn("Only LE connection is allowed (transport {})", bt_transport_text(transport));
2388 BTA_GATTC_Close(conn_id);
2389 return;
2390 }
2391
2392 if (!leAudioDevice) {
2393 return;
2394 }
2395
2396 if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
2397 log::debug("Already connected {}, conn_id=0x{:04x}", address, leAudioDevice->conn_id_);
2398 return;
2399 }
2400
2401 if (status != GATT_SUCCESS) {
2402 /* Clear current connection request and let it be set again if needed */
2403 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2404
2405 /* autoconnect connection failed, that's ok */
2406 if (status != GATT_ILLEGAL_PARAMETER &&
2407 (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTING_AUTOCONNECT ||
2408 leAudioDevice->autoconnect_flag_)) {
2409 log::info("Device not available now, do background connect.");
2410 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2411 AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
2412 return;
2413 }
2414
2415 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2416
2417 log::error("Failed to connect to LeAudio leAudioDevice, status: 0x{:02x}", status);
2418 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2419 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2420 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2421 bluetooth::le_audio::ConnectionStatus::FAILED);
2422 return;
2423 }
2424
2425 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
2426 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2427 if (group == nullptr) {
2428 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2429
2430 log::warn("LeAudio profile is disabled for group_id: {}. {} is not connected",
2431 leAudioDevice->group_id_, address);
2432 return;
2433 }
2434 }
2435
2436 leAudioDevice->conn_id_ = conn_id;
2437 leAudioDevice->mtu_ = mtu;
2438 if (com::android::bluetooth::flags::gatt_queue_cleanup_connected()) {
2439 BtaGattQueue::Clean(conn_id);
2440 }
2441
2442 /* Remove device from the background connect (it might be either Allow list
2443 * or TA) and add it again with reconnection_mode_. In case it is TA, we are
2444 * sure that device will not be in the allow list for other applications
2445 * which are using background connect.
2446 */
2447 BTA_GATTC_CancelOpen(gatt_if_, address, false);
2448 BTA_GATTC_Open(gatt_if_, address, reconnection_mode_, false);
2449
2450 if (bluetooth::shim::GetController()->SupportsBle2mPhy()) {
2451 log::info("{} set preferred PHY to 2M", address);
2452 get_btm_client_interface().ble.BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
2453 }
2454
2455 get_btm_client_interface().peer.BTM_RequestPeerSCA(leAudioDevice->address_, transport);
2456
2457 if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTING_AUTOCONNECT) {
2458 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
2459 } else {
2460 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
2461 }
2462
2463 /* Check if the device is in allow list and update the flag */
2464 leAudioDevice->UpdateDeviceAllowlistFlag();
2465 if (BTM_SecIsSecurityPending(address)) {
2466 /* if security collision happened, wait for encryption done
2467 * (BTA_GATTC_ENC_CMPL_CB_EVT) */
2468 return;
2469 }
2470
2471 /* verify bond */
2472 if (BTM_IsEncrypted(address, BT_TRANSPORT_LE)) {
2473 /* if link has been encrypted */
2474 OnEncryptionComplete(address, tBTM_STATUS::BTM_SUCCESS);
2475 return;
2476 }
2477
2478 tBTM_STATUS result =
2479 BTM_SetEncryption(address, BT_TRANSPORT_LE, nullptr, nullptr, BTM_BLE_SEC_ENCRYPT);
2480
2481 log::info("Encryption required for {}. Request result: 0x{:02x}", address, result);
2482
2483 if (result == tBTM_STATUS::BTM_ERR_KEY_MISSING) {
2484 log::error("Link key unknown for {}, disconnect profile", address);
2485 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2486 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2487 bluetooth::le_audio::ConnectionStatus::FAILED);
2488
2489 /* If link cannot be enctypted, disconnect profile */
2490 BTA_GATTC_Close(conn_id);
2491 }
2492 }
2493
RegisterKnownNotifications(LeAudioDevice * leAudioDevice,bool gatt_register,bool write_ccc)2494 void RegisterKnownNotifications(LeAudioDevice* leAudioDevice, bool gatt_register,
2495 bool write_ccc) {
2496 log::info("device: {}", leAudioDevice->address_);
2497
2498 if (leAudioDevice->ctp_hdls_.val_hdl == 0) {
2499 log::error("Control point characteristic is mandatory - disconnecting device {}",
2500 leAudioDevice->address_);
2501 DisconnectDevice(leAudioDevice);
2502 return;
2503 }
2504
2505 /* GATTC will omit not registered previously handles */
2506 for (auto pac_tuple : leAudioDevice->snk_pacs_) {
2507 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2508 std::get<0>(pac_tuple), gatt_register, write_ccc);
2509 }
2510 for (auto pac_tuple : leAudioDevice->src_pacs_) {
2511 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2512 std::get<0>(pac_tuple), gatt_register, write_ccc);
2513 }
2514
2515 if (leAudioDevice->snk_audio_locations_hdls_.val_hdl != 0) {
2516 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2517 leAudioDevice->snk_audio_locations_hdls_, gatt_register,
2518 write_ccc);
2519 }
2520 if (leAudioDevice->src_audio_locations_hdls_.val_hdl != 0) {
2521 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2522 leAudioDevice->src_audio_locations_hdls_, gatt_register,
2523 write_ccc);
2524 }
2525
2526 if (leAudioDevice->audio_avail_hdls_.val_hdl != 0) {
2527 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2528 leAudioDevice->audio_avail_hdls_, gatt_register, write_ccc);
2529 }
2530
2531 if (leAudioDevice->audio_supp_cont_hdls_.val_hdl != 0) {
2532 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2533 leAudioDevice->audio_supp_cont_hdls_, gatt_register, write_ccc);
2534 }
2535
2536 for (struct ase& ase : leAudioDevice->ases_) {
2537 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_, ase.hdls,
2538 gatt_register, write_ccc);
2539 }
2540
2541 subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2542 leAudioDevice->ctp_hdls_, gatt_register, write_ccc);
2543 }
2544
changeMtuIfPossible(LeAudioDevice * leAudioDevice)2545 void changeMtuIfPossible(LeAudioDevice* leAudioDevice) {
2546 if (leAudioDevice->mtu_ == GATT_DEF_BLE_MTU_SIZE) {
2547 log::info("Configure MTU");
2548 /* Use here kBapMinimumAttMtu, because we know that GATT will request
2549 * default ATT MTU anyways. We also know that GATT will use this
2550 * kBapMinimumAttMtu as an input for Data Length Update procedure in the controller.
2551 */
2552 BtaGattQueue::ConfigureMtu(leAudioDevice->conn_id_, kBapMinimumAttMtu);
2553 }
2554 }
2555
ReadMustHaveAttributesOnReconnect(LeAudioDevice * leAudioDevice)2556 void ReadMustHaveAttributesOnReconnect(LeAudioDevice* leAudioDevice) {
2557 log::verbose("{}", leAudioDevice->address_);
2558 /* Here we read
2559 * 1) ASCS Control Point CCC descriptor in order to validate proper
2560 * behavior of remote device which should store CCC values for bonded device.
2561 * 2) Available Context Types which normally should be notified by the server,
2562 * but since it is crucial for proper streaming experiance, and in the same time
2563 * it can change very often which, as we observed, might lead to not being sent by
2564 * remote devices
2565 */
2566 if (!com::android::bluetooth::flags::le_ase_read_multiple_variable()) {
2567 BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
2568 leAudioDevice->audio_avail_hdls_.val_hdl,
2569 OnGattReadRspStatic, NULL);
2570 BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.ccc_hdl,
2571 OnGattReadRspStatic, NULL);
2572 } else {
2573 tBTA_GATTC_MULTI multi_read = {.num_attr = 2,
2574 .handles = {leAudioDevice->audio_avail_hdls_.val_hdl,
2575 leAudioDevice->ctp_hdls_.ccc_hdl}};
2576
2577 BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
2578 OnGattReadMultiRspStatic, NULL);
2579 }
2580 }
2581
OnEncryptionComplete(const RawAddress & address,tBTM_STATUS status)2582 void OnEncryptionComplete(const RawAddress& address, tBTM_STATUS status) {
2583 log::info("{} status 0x{:02x}", address, status);
2584 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2585 if (leAudioDevice == NULL || (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) {
2586 log::warn("Skipping device which is {}",
2587 leAudioDevice ? " not connected by service." : " null");
2588 return;
2589 }
2590
2591 if (status != tBTM_STATUS::BTM_SUCCESS) {
2592 log::error("Encryption failed status: {}", btm_status_text(status));
2593 if (leAudioDevice->GetConnectionState() ==
2594 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY) {
2595 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2596 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2597 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2598 bluetooth::le_audio::ConnectionStatus::FAILED);
2599 }
2600
2601 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING);
2602
2603 BTA_GATTC_Close(leAudioDevice->conn_id_);
2604 return;
2605 }
2606
2607 if (leAudioDevice->encrypted_) {
2608 log::info("link already encrypted, nothing to do");
2609 return;
2610 }
2611
2612 /* If PHY update did not succeed after ACL connection, which can happen
2613 * when remote feature read was not that quick, lets try to change phy here
2614 * one more time
2615 */
2616 if (!leAudioDevice->acl_phy_update_done_ &&
2617 bluetooth::shim::GetController()->SupportsBle2mPhy()) {
2618 log::info("{} set preferred PHY to 2M", leAudioDevice->address_);
2619 get_btm_client_interface().ble.BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
2620 }
2621
2622 changeMtuIfPossible(leAudioDevice);
2623
2624 leAudioDevice->encrypted_ = true;
2625
2626 /* If we know services, register for notifications */
2627 if (leAudioDevice->known_service_handles_) {
2628 /* This registration will do subscribtion in local GATT as we
2629 * assume remote device keeps bonded CCC values.
2630 */
2631 RegisterKnownNotifications(leAudioDevice, true, false);
2632 ReadMustHaveAttributesOnReconnect(leAudioDevice);
2633 }
2634
2635 /* If we know services and read is not ongoing, this is reconnection and
2636 * just notify connected */
2637 if (leAudioDevice->known_service_handles_ && !leAudioDevice->notify_connected_after_read_) {
2638 log::info("Wait for CCC registration and MTU change request");
2639 return;
2640 }
2641
2642 BTA_GATTC_ServiceSearchRequest(leAudioDevice->conn_id_,
2643 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
2644 }
2645
checkGroupConnectionStateAfterMemberDisconnect(int group_id)2646 void checkGroupConnectionStateAfterMemberDisconnect(int group_id) {
2647 /* This is fired t=kGroupConnectedWatchDelayMs after group member
2648 * got disconnected while either group members were connected.
2649 * We want to check here if there is any group member connected.
2650 * If so we should add other group members to allow list for better
2651 * reconnection experience. If all group members are disconnected
2652 * i e.g. devices intentionally disconnected for other
2653 * purposes like pairing with other device, then we do nothing here and
2654 * device stay on the default reconnection policy (i.e. targeted
2655 * announcements)
2656 */
2657 auto group = aseGroups_.FindById(group_id);
2658 if (group == nullptr) {
2659 log::info("Group {} is destroyed.", group_id);
2660 return;
2661 }
2662
2663 if (!group->IsAnyDeviceConnected()) {
2664 log::info("Group {} is not connected", group_id);
2665 /* Make sure all devices are in the default reconnection mode */
2666 group->ApplyReconnectionMode(gatt_if_, reconnection_mode_);
2667 return;
2668 }
2669
2670 /* if group is still connected, make sure that other not connected
2671 * set members are in the allow list for the quick reconnect.
2672 * E.g. for the earbud case, probably one of the earbud is in the case now.
2673 */
2674 group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
2675 }
2676
scheduleGroupConnectedCheck(int group_id)2677 void scheduleGroupConnectedCheck(int group_id) {
2678 log::info("Schedule group_id {} connected check.", group_id);
2679 do_in_main_thread_delayed(
2680 base::BindOnce(&LeAudioClientImpl::checkGroupConnectionStateAfterMemberDisconnect,
2681 weak_factory_.GetWeakPtr(), group_id),
2682 std::chrono::milliseconds(kGroupConnectedWatchDelayMs));
2683 }
2684
autoConnect(RawAddress address)2685 void autoConnect(RawAddress address) {
2686 auto leAudioDevice = leAudioDevices_.FindByAddress(address);
2687 if (leAudioDevice == nullptr) {
2688 log::warn("Device {} not valid anymore", address);
2689 return;
2690 }
2691
2692 BackgroundConnectIfNeeded(leAudioDevice);
2693 }
2694
scheduleAutoConnect(RawAddress & address)2695 void scheduleAutoConnect(RawAddress& address) {
2696 log::info("Schedule auto connect {}", address);
2697 do_in_main_thread_delayed(
2698 base::BindOnce(&LeAudioClientImpl::autoConnect, weak_factory_.GetWeakPtr(), address),
2699 std::chrono::milliseconds(kAutoConnectAfterOwnDisconnectDelayMs));
2700 }
2701
recoveryReconnect(RawAddress address)2702 void recoveryReconnect(RawAddress address) {
2703 log::info("Reconnecting to {} after timeout on state machine.", address);
2704 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2705
2706 if (leAudioDevice == nullptr ||
2707 leAudioDevice->GetConnectionState() != DeviceConnectState::DISCONNECTING_AND_RECOVER) {
2708 log::warn("Device {}, not interested in recovery connect anymore", address);
2709 return;
2710 }
2711
2712 auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2713
2714 if (group != nullptr) {
2715 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2716 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
2717 } else {
2718 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2719 }
2720 }
2721
scheduleRecoveryReconnect(RawAddress & address)2722 void scheduleRecoveryReconnect(RawAddress& address) {
2723 log::info("Schedule reconnecting to {} after timeout on state machine.", address);
2724 do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::recoveryReconnect,
2725 weak_factory_.GetWeakPtr(), address),
2726 std::chrono::milliseconds(kRecoveryReconnectDelayMs));
2727 }
2728
checkIfGroupMember(RawAddress address)2729 void checkIfGroupMember(RawAddress address) {
2730 log::info("checking being a group member: {}", address);
2731 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2732
2733 if (leAudioDevice == nullptr) {
2734 log::warn("Device {}, probably removed", address);
2735 return;
2736 }
2737
2738 if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
2739 disconnectInvalidDevice(leAudioDevice, ", device not a valid group member",
2740 LeAudioHealthDeviceStatType::INVALID_CSIS);
2741 return;
2742 }
2743 }
2744
2745 /* This is called, when CSIS native module is about to add device to the
2746 * group once the CSIS service will be verified on the remote side.
2747 * After some time (kCsisGroupMemberDelayMs) a checkIfGroupMember will be
2748 * called and will verify if the remote device has a group_id properly set.
2749 * if not, it means there is something wrong with CSIS service on the remote
2750 * side.
2751 */
scheduleGuardForCsisAdd(RawAddress & address)2752 void scheduleGuardForCsisAdd(RawAddress& address) {
2753 log::info("Schedule reconnecting to {} after timeout on state machine.", address);
2754 do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::checkIfGroupMember,
2755 weak_factory_.GetWeakPtr(), address),
2756 std::chrono::milliseconds(kCsisGroupMemberDelayMs));
2757 }
2758
OnGattDisconnected(tCONN_ID conn_id,tGATT_IF,RawAddress address,tGATT_DISCONN_REASON reason)2759 void OnGattDisconnected(tCONN_ID conn_id, tGATT_IF /*client_if*/, RawAddress address,
2760 tGATT_DISCONN_REASON reason) {
2761 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2762
2763 if (!leAudioDevice) {
2764 log::error(", skipping unknown leAudioDevice, address: {}", address);
2765 return;
2766 }
2767
2768 leAudioDevice->acl_asymmetric_ = false;
2769 BtaGattQueue::Clean(leAudioDevice->conn_id_);
2770 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
2771
2772 DeregisterNotifications(leAudioDevice);
2773
2774 callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2775 leAudioDevice->conn_id_ = GATT_INVALID_CONN_ID;
2776 leAudioDevice->mtu_ = 0;
2777 leAudioDevice->closing_stream_for_disconnection_ = false;
2778 leAudioDevice->encrypted_ = false;
2779 leAudioDevice->acl_phy_update_done_ = false;
2780
2781 auto connection_state = leAudioDevice->GetConnectionState();
2782
2783 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2784
2785 groupStateMachine_->ProcessHciNotifAclDisconnected(group, leAudioDevice);
2786
2787 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2788 leAudioDevice->group_id_, address, ConnectionState::DISCONNECTED,
2789 bluetooth::le_audio::ConnectionStatus::SUCCESS);
2790
2791 if (connection_state == DeviceConnectState::REMOVING) {
2792 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
2793 auto group = aseGroups_.FindById(leAudioDevice->group_id_);
2794 group_remove_node(group, address, true);
2795 }
2796 leAudioDevices_.Remove(address);
2797 return;
2798 }
2799
2800 log::info("{}, autoconnect {}, reason 0x{:02x}, connection state {}", leAudioDevice->address_,
2801 leAudioDevice->autoconnect_flag_, reason,
2802 bluetooth::common::ToString(connection_state));
2803
2804 if (connection_state == DeviceConnectState::DISCONNECTING_AND_RECOVER) {
2805 /* We are back after disconnecting device which was in a bad state.
2806 * lets try to reconnected - 30 sec with direct connect and later fallback
2807 * to default background reconnection mode.
2808 * Since GATT notifies us before ACL was dropped, let's wait a bit
2809 * before we do reconnect.
2810 *
2811 * Also, make sure that device has state which allows to do recover
2812 */
2813 leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING_AND_RECOVER);
2814 scheduleRecoveryReconnect(address);
2815 return;
2816 }
2817
2818 /* Attempt background re-connect if disconnect was not initiated locally
2819 * or if autoconnect is set and device got disconnected because of some
2820 * issues
2821 */
2822 if (group == nullptr || !group->IsEnabled()) {
2823 log::error("Group id {} ({}) disabled or null", leAudioDevice->group_id_,
2824 std::format_ptr(group));
2825 return;
2826 }
2827
2828 if (reason == GATT_CONN_TERMINATE_LOCAL_HOST) {
2829 if (leAudioDevice->autoconnect_flag_) {
2830 /* In this case ACL might not yet been disconnected */
2831 scheduleAutoConnect(address);
2832 }
2833 return;
2834 }
2835
2836 /* Remote disconnects from us or Timeout happens */
2837 /* In this case ACL is disconnected */
2838 if (reason == GATT_CONN_TIMEOUT) {
2839 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2840
2841 /* If timeout try to reconnect for 30 sec.*/
2842 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
2843 return;
2844 }
2845
2846 /* In other disconnect resons we act based on the autoconnect_flag_ */
2847 if (leAudioDevice->autoconnect_flag_) {
2848 if (group->IsAnyDeviceConnected()) {
2849 /* If all set is disconnecting, let's give it some time.
2850 * If not all get disconnected, and there will be group member
2851 * connected we want to put disconnected devices to allow list
2852 */
2853 scheduleGroupConnectedCheck(leAudioDevice->group_id_);
2854 } else {
2855 group->ApplyReconnectionMode(gatt_if_, reconnection_mode_);
2856 }
2857 }
2858 }
2859
subscribe_for_notification(tCONN_ID conn_id,const RawAddress & address,struct bluetooth::le_audio::types::hdl_pair handle_pair,bool gatt_register=true,bool write_ccc=true)2860 bool subscribe_for_notification(tCONN_ID conn_id, const RawAddress& address,
2861 struct bluetooth::le_audio::types::hdl_pair handle_pair,
2862 bool gatt_register = true, bool write_ccc = true) {
2863 std::vector<uint8_t> value(2);
2864 uint8_t* ptr = value.data();
2865 uint16_t handle = handle_pair.val_hdl;
2866 uint16_t ccc_handle = handle_pair.ccc_hdl;
2867
2868 log::info("conn id {}, gatt_register: {}, write_ccc: {}", conn_id, gatt_register, write_ccc);
2869 if (gatt_register &&
2870 BTA_GATTC_RegisterForNotifications(gatt_if_, address, handle) != GATT_SUCCESS) {
2871 log::error("cannot register for notification: {}", static_cast<int>(handle));
2872 return false;
2873 }
2874
2875 if (write_ccc == false) {
2876 log::verbose("CCC is not written to {} (0x{:04x}), handle 0x{:04x}", address, conn_id,
2877 ccc_handle);
2878 return true;
2879 }
2880
2881 UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
2882
2883 BtaGattQueue::WriteDescriptor(
2884 conn_id, ccc_handle, std::move(value), GATT_WRITE,
2885 [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
2886 const uint8_t* /*value*/, void* data) {
2887 if (instance) {
2888 instance->OnGattWriteCcc(conn_id, status, handle, data);
2889 }
2890 },
2891 nullptr);
2892 return true;
2893 }
2894
2895 /* Find the handle for the client characteristics configuration of a given
2896 * characteristics.
2897 */
find_ccc_handle(const gatt::Characteristic & charac)2898 uint16_t find_ccc_handle(const gatt::Characteristic& charac) {
2899 auto iter = std::find_if(charac.descriptors.begin(), charac.descriptors.end(),
2900 [](const auto& desc) {
2901 return desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG);
2902 });
2903
2904 return iter == charac.descriptors.end() ? 0 : (*iter).handle;
2905 }
2906
ClearDeviceInformationAndStartSearch(LeAudioDevice * leAudioDevice)2907 void ClearDeviceInformationAndStartSearch(LeAudioDevice* leAudioDevice) {
2908 if (!leAudioDevice) {
2909 log::warn("leAudioDevice is null");
2910 return;
2911 }
2912
2913 log::info("{}", leAudioDevice->address_);
2914
2915 if (leAudioDevice->known_service_handles_ == false) {
2916 log::debug("Database already invalidated");
2917 return;
2918 }
2919
2920 leAudioDevice->known_service_handles_ = false;
2921 leAudioDevice->csis_member_ = false;
2922 BtaGattQueue::Clean(leAudioDevice->conn_id_);
2923 DeregisterNotifications(leAudioDevice);
2924
2925 if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
2926 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
2927 }
2928
2929 btif_storage_leaudio_clear_service_data(leAudioDevice->address_);
2930
2931 BTA_GATTC_ServiceSearchRequest(leAudioDevice->conn_id_,
2932 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
2933 }
2934
OnServiceChangeEvent(const RawAddress & address)2935 void OnServiceChangeEvent(const RawAddress& address) {
2936 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2937 if (!leAudioDevice) {
2938 log::warn("Skipping unknown leAudioDevice {} ({})", address, std::format_ptr(leAudioDevice));
2939 return;
2940 }
2941
2942 if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
2943 ClearDeviceInformationAndStartSearch(leAudioDevice);
2944 return;
2945 }
2946
2947 /* If device is not connected, just clear the handle information and this
2948 * will trigger service search onGattConnected */
2949 leAudioDevice->known_service_handles_ = false;
2950 btif_storage_leaudio_clear_service_data(address);
2951 }
2952
OnMtuChanged(tCONN_ID conn_id,uint16_t mtu)2953 void OnMtuChanged(tCONN_ID conn_id, uint16_t mtu) {
2954 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2955 if (!leAudioDevice) {
2956 log::debug("Unknown connectect id {}", conn_id);
2957 return;
2958 }
2959
2960 /**
2961 * BAP 1.01. 3.6.1
2962 * ATT and EATT transport requirements
2963 * The Unicast Client shall support a minimum ATT_MTU of 64 octets for one
2964 * Unenhanced ATT bearer, or for at least one Enhanced ATT bearer if the
2965 * Unicast Client supports Enhanced ATT bearers.
2966 *
2967 */
2968 if (mtu < 64) {
2969 log::error("Device {} MTU is too low ({}). Disconnecting from LE Audio",
2970 leAudioDevice->address_, mtu);
2971 Disconnect(leAudioDevice->address_);
2972 return;
2973 }
2974
2975 leAudioDevice->mtu_ = mtu;
2976 }
2977
OnPhyUpdate(tCONN_ID conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)2978 void OnPhyUpdate(tCONN_ID conn_id, uint8_t tx_phy, uint8_t rx_phy, tGATT_STATUS status) {
2979 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2980 if (leAudioDevice == nullptr) {
2981 log::debug("Unknown conn_id {:#x}", conn_id);
2982 return;
2983 }
2984
2985 log::info("{}, tx_phy: {:#x}, rx_phy: {:#x} , status: {:#x}", leAudioDevice->address_, tx_phy,
2986 rx_phy, status);
2987
2988 if (status == 0) {
2989 leAudioDevice->acl_phy_update_done_ = true;
2990 }
2991 }
2992
OnGattServiceDiscoveryDone(const RawAddress & address)2993 void OnGattServiceDiscoveryDone(const RawAddress& address) {
2994 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2995 if (!leAudioDevice || (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) {
2996 log::verbose("skipping unknown leAudioDevice, address {} ({})", address,
2997 std::format_ptr(leAudioDevice));
2998 return;
2999 }
3000
3001 if (!leAudioDevice->encrypted_) {
3002 log::debug("Wait for device to be encrypted");
3003 return;
3004 }
3005
3006 if (!leAudioDevice->known_service_handles_) {
3007 BTA_GATTC_ServiceSearchRequest(
3008 leAudioDevice->conn_id_,
3009 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
3010 }
3011 }
3012
disconnectInvalidDevice(LeAudioDevice * leAudioDevice,std::string error_string,LeAudioHealthDeviceStatType stat)3013 void disconnectInvalidDevice(LeAudioDevice* leAudioDevice, std::string error_string,
3014 LeAudioHealthDeviceStatType stat) {
3015 log::error("{}, {}", leAudioDevice->address_, error_string);
3016 if (leAudioHealthStatus_) {
3017 leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice, stat);
3018 }
3019 DisconnectDevice(leAudioDevice);
3020 }
3021
3022 /* This method is called after connection beginning to identify and initialize
3023 * a le audio device. Any missing mandatory attribute will result in reverting
3024 * and cleaning up device.
3025 */
OnServiceSearchComplete(tCONN_ID conn_id,tGATT_STATUS status)3026 void OnServiceSearchComplete(tCONN_ID conn_id, tGATT_STATUS status) {
3027 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3028
3029 if (!leAudioDevice) {
3030 log::error("skipping unknown leAudioDevice, conn_id: 0x{:x}", conn_id);
3031 return;
3032 }
3033
3034 log::info("test csis_member {}", leAudioDevice->csis_member_);
3035
3036 if (status != GATT_SUCCESS) {
3037 /* close connection and report service discovery complete with error */
3038 log::error("Service discovery failed");
3039
3040 DisconnectDevice(leAudioDevice);
3041 return;
3042 }
3043
3044 if (!leAudioDevice->encrypted_) {
3045 log::warn("Device not yet bonded - waiting for encryption");
3046 return;
3047 }
3048
3049 const std::list<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
3050
3051 const gatt::Service* pac_svc = nullptr;
3052 const gatt::Service* ase_svc = nullptr;
3053 const gatt::Service* tmas_svc = nullptr;
3054 const gatt::Service* gmap_svc = nullptr;
3055
3056 std::vector<uint16_t> csis_primary_handles;
3057 uint16_t cas_csis_included_handle = 0;
3058
3059 for (const gatt::Service& tmp : *services) {
3060 if (tmp.uuid == bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid) {
3061 log::info("Found Audio Capability service, handle: 0x{:04x}, device: {}", tmp.handle,
3062 leAudioDevice->address_);
3063 pac_svc = &tmp;
3064 } else if (tmp.uuid == bluetooth::le_audio::uuid::kAudioStreamControlServiceUuid) {
3065 log::info("Found Audio Stream Endpoint service, handle: 0x{:04x}, device: {}", tmp.handle,
3066 leAudioDevice->address_);
3067 ase_svc = &tmp;
3068 } else if (tmp.uuid == bluetooth::csis::kCsisServiceUuid) {
3069 log::info("Found CSIS service, handle: 0x{:04x}, is primary: {}, device: {}", tmp.handle,
3070 tmp.is_primary, leAudioDevice->address_);
3071 if (tmp.is_primary) {
3072 csis_primary_handles.push_back(tmp.handle);
3073 }
3074 } else if (tmp.uuid == bluetooth::le_audio::uuid::kCapServiceUuid) {
3075 log::info("Found CAP service, handle: 0x{:04x}, device: {}", tmp.handle,
3076 leAudioDevice->address_);
3077
3078 /* Try to find context for CSIS instances */
3079 for (auto& included_srvc : tmp.included_services) {
3080 if (included_srvc.uuid == bluetooth::csis::kCsisServiceUuid) {
3081 log::info("CSIS included into CAS");
3082 if (bluetooth::csis::CsisClient::IsCsisClientRunning()) {
3083 cas_csis_included_handle = included_srvc.start_handle;
3084 }
3085
3086 break;
3087 }
3088 }
3089 } else if (tmp.uuid == bluetooth::le_audio::uuid::kTelephonyMediaAudioServiceUuid) {
3090 log::info("Found Telephony and Media Audio service, handle: 0x{:04x}, device: {}",
3091 tmp.handle, leAudioDevice->address_);
3092 tmas_svc = &tmp;
3093 } else if (tmp.uuid == bluetooth::le_audio::uuid::kGamingAudioServiceUuid) {
3094 log::info("Found Gaming Audio service, handle: 0x{:04x}, device: {}", tmp.handle,
3095 leAudioDevice->address_);
3096 gmap_svc = &tmp;
3097 }
3098 }
3099
3100 /* Check if CAS includes primary CSIS service */
3101 if (!csis_primary_handles.empty() && cas_csis_included_handle) {
3102 auto iter = std::find(csis_primary_handles.begin(), csis_primary_handles.end(),
3103 cas_csis_included_handle);
3104 if (iter != csis_primary_handles.end()) {
3105 leAudioDevice->csis_member_ = true;
3106 }
3107 }
3108
3109 if (!pac_svc || !ase_svc) {
3110 disconnectInvalidDevice(leAudioDevice, "No mandatory le audio services found (pacs or ascs)",
3111 LeAudioHealthDeviceStatType::INVALID_DB);
3112 return;
3113 }
3114
3115 /* Refresh PACs handles */
3116 leAudioDevice->ClearPACs();
3117
3118 for (const gatt::Characteristic& charac : pac_svc->characteristics) {
3119 if (charac.uuid ==
3120 bluetooth::le_audio::uuid::kSinkPublishedAudioCapabilityCharacteristicUuid) {
3121 struct hdl_pair hdl_pair;
3122 hdl_pair.val_hdl = charac.value_handle;
3123 hdl_pair.ccc_hdl = find_ccc_handle(charac);
3124
3125 if (hdl_pair.ccc_hdl == 0) {
3126 log::info(", Sink PACs ccc not available");
3127 }
3128
3129 if (hdl_pair.ccc_hdl != 0 &&
3130 !subscribe_for_notification(conn_id, leAudioDevice->address_, hdl_pair)) {
3131 disconnectInvalidDevice(leAudioDevice, ", could not subscribe for snk pac char",
3132 LeAudioHealthDeviceStatType::INVALID_DB);
3133 return;
3134 }
3135
3136 /* Obtain initial state of sink PACs */
3137 BtaGattQueue::ReadCharacteristic(conn_id, hdl_pair.val_hdl, OnGattReadRspStatic, NULL);
3138
3139 leAudioDevice->snk_pacs_.push_back(std::make_tuple(
3140 hdl_pair, std::vector<struct bluetooth::le_audio::types::acs_ac_record>()));
3141
3142 log::info("Found Sink PAC characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
3143 charac.value_handle, hdl_pair.ccc_hdl, leAudioDevice->address_);
3144 } else if (charac.uuid ==
3145 bluetooth::le_audio::uuid::kSourcePublishedAudioCapabilityCharacteristicUuid) {
3146 struct hdl_pair hdl_pair;
3147 hdl_pair.val_hdl = charac.value_handle;
3148 hdl_pair.ccc_hdl = find_ccc_handle(charac);
3149
3150 if (hdl_pair.ccc_hdl == 0) {
3151 log::info(", Source PACs ccc not available");
3152 }
3153
3154 if (hdl_pair.ccc_hdl != 0 &&
3155 !subscribe_for_notification(conn_id, leAudioDevice->address_, hdl_pair)) {
3156 disconnectInvalidDevice(leAudioDevice, ", could not subscribe for src pac char",
3157 LeAudioHealthDeviceStatType::INVALID_DB);
3158 return;
3159 }
3160
3161 /* Obtain initial state of source PACs */
3162 BtaGattQueue::ReadCharacteristic(conn_id, hdl_pair.val_hdl, OnGattReadRspStatic, NULL);
3163
3164 leAudioDevice->src_pacs_.push_back(std::make_tuple(
3165 hdl_pair, std::vector<struct bluetooth::le_audio::types::acs_ac_record>()));
3166
3167 log::info(
3168 "Found Source PAC characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
3169 charac.value_handle, hdl_pair.ccc_hdl, leAudioDevice->address_);
3170 } else if (charac.uuid == bluetooth::le_audio::uuid::kSinkAudioLocationCharacteristicUuid) {
3171 leAudioDevice->snk_audio_locations_hdls_.val_hdl = charac.value_handle;
3172 leAudioDevice->snk_audio_locations_hdls_.ccc_hdl = find_ccc_handle(charac);
3173
3174 if (leAudioDevice->snk_audio_locations_hdls_.ccc_hdl == 0) {
3175 log::info(", snk audio locations char doesn't have ccc");
3176 }
3177
3178 if (leAudioDevice->snk_audio_locations_hdls_.ccc_hdl != 0 &&
3179 !subscribe_for_notification(conn_id, leAudioDevice->address_,
3180 leAudioDevice->snk_audio_locations_hdls_)) {
3181 disconnectInvalidDevice(leAudioDevice, ", could not subscribe for snk locations char",
3182 LeAudioHealthDeviceStatType::INVALID_DB);
3183 return;
3184 }
3185
3186 /* Obtain initial state of sink audio locations */
3187 BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->snk_audio_locations_hdls_.val_hdl,
3188 OnGattReadRspStatic, NULL);
3189
3190 log::info(
3191 "Found Sink audio locations characteristic, handle: 0x{:04x}, ccc "
3192 "handle: 0x{:04x}, addr: {}",
3193 charac.value_handle, leAudioDevice->snk_audio_locations_hdls_.ccc_hdl,
3194 leAudioDevice->address_);
3195 } else if (charac.uuid == bluetooth::le_audio::uuid::kSourceAudioLocationCharacteristicUuid) {
3196 leAudioDevice->src_audio_locations_hdls_.val_hdl = charac.value_handle;
3197 leAudioDevice->src_audio_locations_hdls_.ccc_hdl = find_ccc_handle(charac);
3198
3199 if (leAudioDevice->src_audio_locations_hdls_.ccc_hdl == 0) {
3200 log::info(", src audio locations char doesn't have ccc");
3201 }
3202
3203 if (leAudioDevice->src_audio_locations_hdls_.ccc_hdl != 0 &&
3204 !subscribe_for_notification(conn_id, leAudioDevice->address_,
3205 leAudioDevice->src_audio_locations_hdls_)) {
3206 disconnectInvalidDevice(leAudioDevice, ", could not subscribe for src locations char",
3207 LeAudioHealthDeviceStatType::INVALID_DB);
3208 return;
3209 }
3210
3211 /* Obtain initial state of source audio locations */
3212 BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->src_audio_locations_hdls_.val_hdl,
3213 OnGattReadRspStatic, NULL);
3214
3215 log::info(
3216 "Found Source audio locations characteristic, handle: 0x{:04x}, "
3217 "ccc handle: 0x{:04x}, addr: {}",
3218 charac.value_handle, leAudioDevice->src_audio_locations_hdls_.ccc_hdl,
3219 leAudioDevice->address_);
3220 } else if (charac.uuid ==
3221 bluetooth::le_audio::uuid::kAudioContextAvailabilityCharacteristicUuid) {
3222 leAudioDevice->audio_avail_hdls_.val_hdl = charac.value_handle;
3223 leAudioDevice->audio_avail_hdls_.ccc_hdl = find_ccc_handle(charac);
3224
3225 if (leAudioDevice->audio_avail_hdls_.ccc_hdl == 0) {
3226 disconnectInvalidDevice(leAudioDevice, ", audio avails char doesn't have ccc",
3227 LeAudioHealthDeviceStatType::INVALID_DB);
3228 return;
3229 }
3230
3231 if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3232 leAudioDevice->audio_avail_hdls_)) {
3233 disconnectInvalidDevice(leAudioDevice, ", could not subscribe for audio avails char",
3234 LeAudioHealthDeviceStatType::INVALID_DB);
3235 return;
3236 }
3237
3238 /* Obtain initial state */
3239 BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->audio_avail_hdls_.val_hdl,
3240 OnGattReadRspStatic, NULL);
3241
3242 log::info(
3243 "Found Audio Availability Context characteristic, handle: "
3244 "0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
3245 charac.value_handle, leAudioDevice->audio_avail_hdls_.ccc_hdl,
3246 leAudioDevice->address_);
3247 } else if (charac.uuid ==
3248 bluetooth::le_audio::uuid::kAudioSupportedContextCharacteristicUuid) {
3249 leAudioDevice->audio_supp_cont_hdls_.val_hdl = charac.value_handle;
3250 leAudioDevice->audio_supp_cont_hdls_.ccc_hdl = find_ccc_handle(charac);
3251
3252 if (leAudioDevice->audio_supp_cont_hdls_.ccc_hdl == 0) {
3253 log::info(", audio supported char doesn't have ccc");
3254 }
3255
3256 if (leAudioDevice->audio_supp_cont_hdls_.ccc_hdl != 0 &&
3257 !subscribe_for_notification(conn_id, leAudioDevice->address_,
3258 leAudioDevice->audio_supp_cont_hdls_)) {
3259 disconnectInvalidDevice(leAudioDevice,
3260 ", could not subscribe for audio supported ctx char",
3261 LeAudioHealthDeviceStatType::INVALID_DB);
3262 return;
3263 }
3264
3265 /* Obtain initial state */
3266 BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->audio_supp_cont_hdls_.val_hdl,
3267 OnGattReadRspStatic, NULL);
3268
3269 log::info(
3270 "Found Audio Supported Context characteristic, handle: 0x{:04x}, "
3271 "ccc handle: 0x{:04x}, addr: {}",
3272 charac.value_handle, leAudioDevice->audio_supp_cont_hdls_.ccc_hdl,
3273 leAudioDevice->address_);
3274 }
3275 }
3276
3277 /* Refresh ASE handles */
3278 leAudioDevice->ases_.clear();
3279
3280 for (const gatt::Characteristic& charac : ase_svc->characteristics) {
3281 log::info("Found characteristic, uuid: {}", charac.uuid.ToString());
3282 if (charac.uuid == bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid ||
3283 charac.uuid == bluetooth::le_audio::uuid::kSourceAudioStreamEndpointUuid) {
3284 uint16_t ccc_handle = find_ccc_handle(charac);
3285 if (ccc_handle == 0) {
3286 disconnectInvalidDevice(leAudioDevice, ", ASE char doesn't have ccc",
3287 LeAudioHealthDeviceStatType::INVALID_DB);
3288 return;
3289 }
3290 struct bluetooth::le_audio::types::hdl_pair hdls(charac.value_handle, ccc_handle);
3291 if (!subscribe_for_notification(conn_id, leAudioDevice->address_, hdls)) {
3292 disconnectInvalidDevice(leAudioDevice, ", could not subscribe ASE char",
3293 LeAudioHealthDeviceStatType::INVALID_DB);
3294 return;
3295 }
3296
3297 int direction = charac.uuid == bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid
3298 ? bluetooth::le_audio::types::kLeAudioDirectionSink
3299 : bluetooth::le_audio::types::kLeAudioDirectionSource;
3300
3301 leAudioDevice->ases_.emplace_back(charac.value_handle, ccc_handle, direction);
3302
3303 log::info(
3304 "Found ASE characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, "
3305 "direction: {}, addr: {}",
3306 charac.value_handle, ccc_handle, direction, leAudioDevice->address_);
3307 } else if (charac.uuid ==
3308 bluetooth::le_audio::uuid::kAudioStreamEndpointControlPointCharacteristicUuid) {
3309 leAudioDevice->ctp_hdls_.val_hdl = charac.value_handle;
3310 leAudioDevice->ctp_hdls_.ccc_hdl = find_ccc_handle(charac);
3311
3312 if (leAudioDevice->ctp_hdls_.ccc_hdl == 0) {
3313 disconnectInvalidDevice(leAudioDevice, ", ASE ctp doesn't have ccc",
3314 LeAudioHealthDeviceStatType::INVALID_DB);
3315 return;
3316 }
3317
3318 if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3319 leAudioDevice->ctp_hdls_)) {
3320 disconnectInvalidDevice(leAudioDevice, ", could not subscribe ASE char",
3321 LeAudioHealthDeviceStatType::INVALID_DB);
3322 return;
3323 }
3324
3325 log::info(
3326 "Found ASE Control Point characteristic, handle: 0x{:04x}, ccc "
3327 "handle: 0x{:04x}, addr: {}",
3328 charac.value_handle, leAudioDevice->ctp_hdls_.ccc_hdl, leAudioDevice->address_);
3329 }
3330 }
3331
3332 if (tmas_svc) {
3333 for (const gatt::Characteristic& charac : tmas_svc->characteristics) {
3334 if (charac.uuid ==
3335 bluetooth::le_audio::uuid::kTelephonyMediaAudioProfileRoleCharacteristicUuid) {
3336 leAudioDevice->tmap_role_hdl_ = charac.value_handle;
3337
3338 /* Obtain initial state of TMAP role */
3339 BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->tmap_role_hdl_,
3340 OnGattReadRspStatic, NULL);
3341
3342 log::info(
3343 "Found Telephony and Media Profile characteristic, handle: 0x{:04x}, device: {}",
3344 leAudioDevice->tmap_role_hdl_, leAudioDevice->address_);
3345 }
3346 }
3347 }
3348
3349 if (gmap_svc && GmapClient::IsGmapClientEnabled()) {
3350 leAudioDevice->gmap_client_ = std::make_unique<GmapClient>(leAudioDevice->address_);
3351 for (const gatt::Characteristic& charac : gmap_svc->characteristics) {
3352 if (charac.uuid == bluetooth::le_audio::uuid::kRoleCharacteristicUuid) {
3353 uint16_t handle = charac.value_handle;
3354 leAudioDevice->gmap_client_->setRoleHandle(handle);
3355 BtaGattQueue::ReadCharacteristic(conn_id, handle, OnGattReadRspStatic, NULL);
3356 log::info("Found Gmap Role characteristic, handle: 0x{:04x}, device: {}",
3357 leAudioDevice->gmap_client_->getRoleHandle(), leAudioDevice->address_);
3358 }
3359 if (charac.uuid == bluetooth::le_audio::uuid::kUnicastGameTerminalCharacteristicUuid) {
3360 uint16_t handle = charac.value_handle;
3361 leAudioDevice->gmap_client_->setUGTFeatureHandle(handle);
3362 BtaGattQueue::ReadCharacteristic(conn_id, handle, OnGattReadRspStatic, NULL);
3363 log::info("Found Gmap UGT Feature characteristic, handle: 0x{:04x}, device: {}",
3364 leAudioDevice->gmap_client_->getUGTFeatureHandle(), leAudioDevice->address_);
3365 }
3366 }
3367 }
3368
3369 leAudioDevice->known_service_handles_ = true;
3370 leAudioDevice->notify_connected_after_read_ = true;
3371 if (leAudioHealthStatus_) {
3372 leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice,
3373 LeAudioHealthDeviceStatType::VALID_DB);
3374 }
3375
3376 /* If already known group id */
3377 if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
3378 AseInitialStateReadRequest(leAudioDevice);
3379 return;
3380 }
3381
3382 /* If device does not belong to any group yet we either add it to the
3383 * group by our self now or wait for Csis to do it. In both cases, let's
3384 * check if group is already assigned.
3385 */
3386 int group_id = DeviceGroups::Get()->GetGroupId(leAudioDevice->address_,
3387 bluetooth::le_audio::uuid::kCapServiceUuid);
3388 if (group_id != bluetooth::groups::kGroupUnknown) {
3389 instance->group_add_node(group_id, leAudioDevice->address_);
3390 return;
3391 }
3392
3393 /* CSIS will trigger adding to group */
3394 if (leAudioDevice->csis_member_) {
3395 log::info("{}, waiting for CSIS to create group for device", leAudioDevice->address_);
3396 scheduleGuardForCsisAdd(leAudioDevice->address_);
3397 return;
3398 }
3399
3400 log::info("{} Not a CSIS member. Create group by our own", leAudioDevice->address_);
3401
3402 /* If there is no Csis just add device by our own */
3403 DeviceGroups::Get()->AddDevice(leAudioDevice->address_,
3404 bluetooth::le_audio::uuid::kCapServiceUuid);
3405 }
3406
OnGattWriteCcc(tCONN_ID conn_id,tGATT_STATUS status,uint16_t hdl,void *)3407 void OnGattWriteCcc(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, void* /*data*/) {
3408 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3409 std::vector<struct ase>::iterator ase_it;
3410
3411 if (!leAudioDevice) {
3412 log::error("unknown conn_id=0x{:x}", conn_id);
3413 return;
3414 }
3415
3416 if (status == GATT_DATABASE_OUT_OF_SYNC) {
3417 log::info("Database out of sync for {}, conn_id: 0x{:04x}", leAudioDevice->address_, conn_id);
3418 ClearDeviceInformationAndStartSearch(leAudioDevice);
3419 return;
3420 }
3421
3422 if (status == GATT_SUCCESS) {
3423 log::info("Successfully registered on ccc: 0x{:04x}, device: {}", hdl,
3424 leAudioDevice->address_);
3425
3426 if (leAudioDevice->ctp_hdls_.ccc_hdl == hdl && leAudioDevice->known_service_handles_ &&
3427 !leAudioDevice->notify_connected_after_read_) {
3428 /* Reconnection case. Control point is the last CCC LeAudio is
3429 * registering for on reconnection */
3430 connectionReady(leAudioDevice);
3431 }
3432
3433 return;
3434 }
3435
3436 log::error("Failed to register for notifications: 0x{:04x}, device: {}, status: 0x{:02x}", hdl,
3437 leAudioDevice->address_, status);
3438
3439 ase_it =
3440 std::find_if(leAudioDevice->ases_.begin(), leAudioDevice->ases_.end(),
3441 [&hdl](const struct ase& ase) -> bool { return ase.hdls.ccc_hdl == hdl; });
3442
3443 if (ase_it == leAudioDevice->ases_.end()) {
3444 log::error("Unknown ccc handle: 0x{:04x}, device: {}", hdl, leAudioDevice->address_);
3445 return;
3446 }
3447
3448 BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_, ase_it->hdls.val_hdl);
3449 }
3450
AttachToStreamingGroupIfNeeded(LeAudioDevice * leAudioDevice)3451 void AttachToStreamingGroupIfNeeded(LeAudioDevice* leAudioDevice) {
3452 if (leAudioDevice->group_id_ != active_group_id_) {
3453 log::info("group {} is not streaming. Nothing to do", leAudioDevice->group_id_);
3454 return;
3455 }
3456
3457 if (leAudioDevice->GetConnectionState() != DeviceConnectState::CONNECTED) {
3458 /* Do nothing, wait until device is connected */
3459 log::debug("{} is not yet connected", leAudioDevice->address_);
3460 return;
3461 }
3462
3463 if (leAudioDevice->HaveActiveAse()) {
3464 log::debug("{} is already configured, nothing to do", leAudioDevice->address_);
3465 return;
3466 }
3467
3468 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3469
3470 auto group_metadata_contexts = get_bidirectional(group->GetMetadataContexts());
3471 auto device_available_contexts = leAudioDevice->GetAvailableContexts();
3472 if (!group_metadata_contexts.test_any(device_available_contexts)) {
3473 log::info("{} does is not have required context type", leAudioDevice->address_);
3474 return;
3475 }
3476
3477 /* Restore configuration */
3478 auto* stream_conf = &group->stream_conf;
3479
3480 if (audio_sender_state_ == AudioState::IDLE && audio_receiver_state_ == AudioState::IDLE) {
3481 log::debug("Device not streaming but active - nothing to do");
3482 return;
3483 }
3484
3485 if (!stream_conf->conf) {
3486 log::info("Configuration not yet set. Nothing to do now");
3487 return;
3488 }
3489
3490 log::info("Attaching {} to group: {}", leAudioDevice->address_, leAudioDevice->group_id_);
3491
3492 for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink,
3493 bluetooth::le_audio::types::kLeAudioDirectionSource}) {
3494 log::info("Looking for requirements: {} - {}", stream_conf->conf->name,
3495 (direction == 1 ? "snk" : "src"));
3496 const auto& pacs = (direction == bluetooth::le_audio::types::kLeAudioDirectionSink)
3497 ? leAudioDevice->snk_pacs_
3498 : leAudioDevice->src_pacs_;
3499 for (const auto& ent : stream_conf->conf->confs.get(direction)) {
3500 if (!bluetooth::le_audio::utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
3501 log::info("Configuration is not supported by device {}", leAudioDevice->address_);
3502
3503 /* Reconfigure if newly connected member device cannot support
3504 * current codec configuration */
3505 initReconfiguration(group, configuration_context_type_);
3506 return;
3507 }
3508 }
3509 }
3510
3511 /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
3512 auto ccid_contexts = group->GetMetadataContexts();
3513 if (IsInVoipCall() && !IsInCall()) {
3514 ccid_contexts.sink.unset(LeAudioContextType::CONVERSATIONAL);
3515 ccid_contexts.source.unset(LeAudioContextType::CONVERSATIONAL);
3516 }
3517 BidirectionalPair<std::vector<uint8_t>> ccids = {
3518 .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.sink),
3519 .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.source)};
3520
3521 if (!groupStateMachine_->AttachToStream(group, leAudioDevice, std::move(ccids))) {
3522 log::warn("Could not add device {} to the group {} streaming.", leAudioDevice->address_,
3523 group->group_id_);
3524 scheduleAttachDeviceToTheStream(leAudioDevice->address_);
3525 } else {
3526 speed_start_setup(group->group_id_, configuration_context_type_, 1);
3527 }
3528 }
3529
restartAttachToTheStream(const RawAddress & addr)3530 void restartAttachToTheStream(const RawAddress& addr) {
3531 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
3532 if (leAudioDevice == nullptr || leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID) {
3533 log::info("Device {} not available anymore", addr);
3534 return;
3535 }
3536 AttachToStreamingGroupIfNeeded(leAudioDevice);
3537 }
3538
scheduleAttachDeviceToTheStream(const RawAddress & addr)3539 void scheduleAttachDeviceToTheStream(const RawAddress& addr) {
3540 log::info("Device {} is scheduled for streaming", addr);
3541 do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::restartAttachToTheStream,
3542 weak_factory_.GetWeakPtr(), addr),
3543 std::chrono::milliseconds(kDeviceAttachDelayMs));
3544 }
3545
SendAudioGroupSelectableCodecConfigChanged(LeAudioDeviceGroup * group)3546 void SendAudioGroupSelectableCodecConfigChanged(LeAudioDeviceGroup* group) {
3547 auto leAudioDevice = group->GetFirstDevice();
3548 callbacks_->OnAudioGroupSelectableCodecConf(
3549 group->group_id_,
3550 bluetooth::le_audio::utils::GetRemoteBtLeAudioCodecConfigFromPac(
3551 leAudioDevice->src_pacs_),
3552 bluetooth::le_audio::utils::GetRemoteBtLeAudioCodecConfigFromPac(
3553 leAudioDevice->snk_pacs_));
3554 }
3555
SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup * group)3556 void SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup* group) {
3557 // This shall be called when configuration changes
3558 log::debug("{}", group->group_id_);
3559
3560 auto audio_set_conf = group->GetConfiguration(configuration_context_type_);
3561 if (!audio_set_conf) {
3562 log::warn("Stream configuration is not valid for group id {}", group->group_id_);
3563 return;
3564 }
3565
3566 bluetooth::le_audio::btle_audio_codec_config_t input_config{};
3567 bluetooth::le_audio::utils::fillStreamParamsToBtLeAudioCodecConfig(audio_set_conf->confs.source,
3568 input_config);
3569
3570 bluetooth::le_audio::btle_audio_codec_config_t output_config{};
3571 bluetooth::le_audio::utils::fillStreamParamsToBtLeAudioCodecConfig(audio_set_conf->confs.sink,
3572 output_config);
3573
3574 callbacks_->OnAudioGroupCurrentCodecConf(group->group_id_, input_config, output_config);
3575 }
3576
connectionReady(LeAudioDevice * leAudioDevice)3577 void connectionReady(LeAudioDevice* leAudioDevice) {
3578 log::debug("{}, {}", leAudioDevice->address_,
3579 bluetooth::common::ToString(leAudioDevice->GetConnectionState()));
3580
3581 stack::l2cap::get_interface().L2CA_LockBleConnParamsForProfileConnection(
3582 leAudioDevice->address_, false);
3583
3584 if (leAudioDevice->GetConnectionState() ==
3585 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY &&
3586 (leAudioDevice->autoconnect_flag_ == false)) {
3587 btif_storage_set_leaudio_autoconnect(leAudioDevice->address_, true);
3588 leAudioDevice->autoconnect_flag_ = true;
3589 }
3590
3591 leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
3592 bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
3593 leAudioDevice->group_id_, leAudioDevice->address_, ConnectionState::CONNECTED,
3594 bluetooth::le_audio::ConnectionStatus::SUCCESS);
3595
3596 if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
3597 log::warn("LeAudio device {} connected with no group", leAudioDevice->address_);
3598 callbacks_->OnConnectionState(ConnectionState::CONNECTED, leAudioDevice->address_);
3599 return;
3600 }
3601
3602 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
3603 if (group) {
3604 UpdateLocationsAndContextsAvailability(group, true);
3605 }
3606
3607 /* Notify connected after contexts are notified */
3608 callbacks_->OnConnectionState(ConnectionState::CONNECTED, leAudioDevice->address_);
3609
3610 AttachToStreamingGroupIfNeeded(leAudioDevice);
3611
3612 if (reconnection_mode_ == BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS) {
3613 /* Add other devices to allow list if there are any not yet connected
3614 * from the group
3615 */
3616 group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
3617 }
3618 }
3619
IsAseAcceptingAudioData(struct ase * ase)3620 bool IsAseAcceptingAudioData(struct ase* ase) {
3621 if (ase == nullptr) {
3622 return false;
3623 }
3624 if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
3625 return false;
3626 }
3627 if (ase->data_path_state != DataPathState::CONFIGURED) {
3628 return false;
3629 }
3630
3631 return true;
3632 }
3633
3634 // mix stero signal into mono
mono_blend(const std::vector<uint8_t> & buf,int bytes_per_sample,size_t frames)3635 std::vector<uint8_t> mono_blend(const std::vector<uint8_t>& buf, int bytes_per_sample,
3636 size_t frames) {
3637 std::vector<uint8_t> mono_out;
3638 mono_out.resize(frames * bytes_per_sample);
3639
3640 if (bytes_per_sample == 2) {
3641 int16_t* out = (int16_t*)mono_out.data();
3642 const int16_t* in = (int16_t*)(buf.data());
3643 for (size_t i = 0; i < frames; ++i) {
3644 int accum = 0;
3645 accum += *in++;
3646 accum += *in++;
3647 accum /= 2; // round to 0
3648 *out++ = accum;
3649 }
3650 } else if (bytes_per_sample == 4) {
3651 int32_t* out = (int32_t*)mono_out.data();
3652 const int32_t* in = (int32_t*)(buf.data());
3653 for (size_t i = 0; i < frames; ++i) {
3654 int accum = 0;
3655 accum += *in++;
3656 accum += *in++;
3657 accum /= 2; // round to 0
3658 *out++ = accum;
3659 }
3660 } else {
3661 log::error("Don't know how to mono blend that {}!", bytes_per_sample);
3662 }
3663 return mono_out;
3664 }
3665
PrepareAndSendToTwoCises(const std::vector<uint8_t> & data,const struct bluetooth::le_audio::stream_parameters & stream_params)3666 void PrepareAndSendToTwoCises(
3667 const std::vector<uint8_t>& data,
3668 const struct bluetooth::le_audio::stream_parameters& stream_params) {
3669 uint16_t left_cis_handle = 0;
3670 uint16_t right_cis_handle = 0;
3671
3672 uint16_t number_of_required_samples_per_channel = sw_enc_left->GetNumOfSamplesPerChannel();
3673 uint8_t bytes_per_sample = sw_enc_left->GetNumOfBytesPerSample();
3674 if (data.size() <
3675 bytes_per_sample * 2 /* channels */ * number_of_required_samples_per_channel) {
3676 log::error("Missing samples. Data size: {} expected: {}", data.size(),
3677 bytes_per_sample * 2 * number_of_required_samples_per_channel);
3678 return;
3679 }
3680
3681 for (auto [cis_handle, audio_location] : stream_params.stream_locations) {
3682 if (audio_location & bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyLeft) {
3683 left_cis_handle = cis_handle;
3684 }
3685 if (audio_location & bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyRight) {
3686 right_cis_handle = cis_handle;
3687 }
3688 }
3689
3690 if (stream_params.codec_frames_blocks_per_sdu != 1) {
3691 log::error("Codec Frame Blocks of {} is not supported by the software encoding",
3692 +stream_params.codec_frames_blocks_per_sdu);
3693 }
3694
3695 uint16_t byte_count = stream_params.octets_per_codec_frame;
3696 bool mix_to_mono = (left_cis_handle == 0) || (right_cis_handle == 0);
3697 if (mix_to_mono) {
3698 std::vector<uint8_t> mono =
3699 mono_blend(data, bytes_per_sample, number_of_required_samples_per_channel);
3700 if (left_cis_handle) {
3701 sw_enc_left->Encode(mono.data(), 1, byte_count);
3702 }
3703
3704 if (right_cis_handle) {
3705 sw_enc_left->Encode(mono.data(), 1, byte_count);
3706 }
3707 } else {
3708 sw_enc_left->Encode(data.data(), 2, byte_count);
3709 sw_enc_right->Encode(data.data() + bytes_per_sample, 2, byte_count);
3710 }
3711
3712 log::debug("left_cis_handle: {} right_cis_handle: {}", left_cis_handle, right_cis_handle);
3713 /* Send data to the controller */
3714 if (left_cis_handle) {
3715 IsoManager::GetInstance()->SendIsoData(
3716 left_cis_handle, (const uint8_t*)sw_enc_left->GetDecodedSamples().data(),
3717 sw_enc_left->GetDecodedSamples().size() * 2);
3718 }
3719
3720 if (right_cis_handle) {
3721 IsoManager::GetInstance()->SendIsoData(
3722 right_cis_handle, (const uint8_t*)sw_enc_right->GetDecodedSamples().data(),
3723 sw_enc_right->GetDecodedSamples().size() * 2);
3724 }
3725 }
3726
PrepareAndSendToSingleCis(const std::vector<uint8_t> & data,const struct bluetooth::le_audio::stream_parameters & stream_params)3727 void PrepareAndSendToSingleCis(
3728 const std::vector<uint8_t>& data,
3729 const struct bluetooth::le_audio::stream_parameters& stream_params) {
3730 uint16_t num_channels = stream_params.num_of_channels;
3731 uint16_t cis_handle = stream_params.stream_locations.front().first;
3732
3733 uint16_t number_of_required_samples_per_channel = sw_enc_left->GetNumOfSamplesPerChannel();
3734 uint8_t bytes_per_sample = sw_enc_left->GetNumOfBytesPerSample();
3735 if ((int)data.size() <
3736 (bytes_per_sample * num_channels * number_of_required_samples_per_channel)) {
3737 log::error("Missing samples");
3738 return;
3739 }
3740
3741 if (stream_params.codec_frames_blocks_per_sdu != 1) {
3742 log::error("Codec Frame Blocks of {} is not supported by the software encoding",
3743 +stream_params.codec_frames_blocks_per_sdu);
3744 }
3745
3746 uint16_t byte_count = stream_params.octets_per_codec_frame;
3747 bool mix_to_mono = (num_channels == 1);
3748 if (mix_to_mono) {
3749 /* Since we always get two channels from framework, lets make it mono here
3750 */
3751 std::vector<uint8_t> mono =
3752 mono_blend(data, bytes_per_sample, number_of_required_samples_per_channel);
3753 sw_enc_left->Encode(mono.data(), 1, byte_count);
3754 } else {
3755 sw_enc_left->Encode((const uint8_t*)data.data(), 2, byte_count);
3756 // Output to the left channel buffer with `byte_count` offset
3757 sw_enc_right->Encode((const uint8_t*)data.data() + 2, 2, byte_count,
3758 &sw_enc_left->GetDecodedSamples(), byte_count);
3759 }
3760
3761 IsoManager::GetInstance()->SendIsoData(cis_handle,
3762 (const uint8_t*)sw_enc_left->GetDecodedSamples().data(),
3763 sw_enc_left->GetDecodedSamples().size() * 2);
3764 }
3765
GetStreamSinkConfiguration(LeAudioDeviceGroup * group)3766 const struct bluetooth::le_audio::stream_configuration* GetStreamSinkConfiguration(
3767 LeAudioDeviceGroup* group) {
3768 const struct bluetooth::le_audio::stream_configuration* stream_conf = &group->stream_conf;
3769 log::info("group_id: {}", group->group_id_);
3770 if (stream_conf->stream_params.sink.stream_locations.size() == 0) {
3771 return nullptr;
3772 }
3773
3774 log::info("configuration: {}", stream_conf->conf->name);
3775 return stream_conf;
3776 }
3777
OnAudioDataReady(const std::vector<uint8_t> & data)3778 void OnAudioDataReady(const std::vector<uint8_t>& data) {
3779 if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
3780 (audio_sender_state_ != AudioState::STARTED)) {
3781 return;
3782 }
3783
3784 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3785 if (!group) {
3786 log::error("There is no streaming group available");
3787 return;
3788 }
3789
3790 auto stream_conf = group->stream_conf;
3791 if ((stream_conf.stream_params.sink.num_of_devices > 2) ||
3792 (stream_conf.stream_params.sink.num_of_devices == 0) ||
3793 stream_conf.stream_params.sink.stream_locations.empty()) {
3794 log::error("Stream configufation is not valid.");
3795 return;
3796 }
3797
3798 if ((stream_conf.stream_params.sink.num_of_devices == 2) ||
3799 (stream_conf.stream_params.sink.stream_locations.size() == 2)) {
3800 /* Streaming to two devices or one device with 2 CISes */
3801 PrepareAndSendToTwoCises(data, stream_conf.stream_params.sink);
3802 } else {
3803 /* Streaming to one device and 1 CIS */
3804 PrepareAndSendToSingleCis(data, stream_conf.stream_params.sink);
3805 }
3806 }
3807
CleanCachedMicrophoneData()3808 void CleanCachedMicrophoneData() {
3809 cached_channel_timestamp_ = 0;
3810 cached_channel_ = nullptr;
3811 }
3812
3813 /* Handles audio data packets coming from the controller */
HandleIncomingCisData(uint8_t * data,uint16_t size,uint16_t cis_conn_hdl,uint32_t timestamp)3814 void HandleIncomingCisData(uint8_t* data, uint16_t size, uint16_t cis_conn_hdl,
3815 uint32_t timestamp) {
3816 /* Get only one channel for MONO microphone */
3817 /* Gather data for channel */
3818 if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
3819 (audio_receiver_state_ != AudioState::STARTED)) {
3820 return;
3821 }
3822
3823 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3824 if (!group) {
3825 log::error("There is no streaming group available");
3826 return;
3827 }
3828
3829 uint16_t left_cis_handle = 0;
3830 uint16_t right_cis_handle = 0;
3831 for (auto [cis_handle, audio_location] :
3832 group->stream_conf.stream_params.source.stream_locations) {
3833 if (audio_location & bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyLeft) {
3834 left_cis_handle = cis_handle;
3835 }
3836 if (audio_location & bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyRight) {
3837 right_cis_handle = cis_handle;
3838 }
3839 }
3840
3841 auto decoder = sw_dec_left.get();
3842 if (cis_conn_hdl == left_cis_handle) {
3843 decoder = sw_dec_left.get();
3844 } else if (cis_conn_hdl == right_cis_handle) {
3845 decoder = sw_dec_right.get();
3846 } else {
3847 log::error("Received data for unknown handle: {:04x}", cis_conn_hdl);
3848 return;
3849 }
3850
3851 if (!left_cis_handle || !right_cis_handle) {
3852 /* mono or just one device connected */
3853 decoder->Decode(data, size);
3854 SendAudioDataToAF(&decoder->GetDecodedSamples());
3855 return;
3856 }
3857 /* both devices are connected */
3858
3859 if (cached_channel_ == nullptr || cached_channel_->GetDecodedSamples().empty()) {
3860 /* First packet received, cache it. We need both channel data to send it
3861 * to AF. */
3862 decoder->Decode(data, size);
3863 cached_channel_timestamp_ = timestamp;
3864 cached_channel_ = decoder;
3865 return;
3866 }
3867
3868 /* We received either data for the other audio channel, or another
3869 * packet for same channel */
3870 if (cached_channel_ != decoder) {
3871 /* It's data for the 2nd channel */
3872 if (timestamp == cached_channel_timestamp_) {
3873 /* Ready to mix data and send out to AF */
3874 decoder->Decode(data, size);
3875 SendAudioDataToAF(&sw_dec_left->GetDecodedSamples(), &sw_dec_right->GetDecodedSamples());
3876
3877 CleanCachedMicrophoneData();
3878 return;
3879 }
3880
3881 /* 2nd Channel is in the future compared to the cached data.
3882 Send the cached data to AF, and keep the new channel data in cache.
3883 This should happen only during stream setup */
3884 SendAudioDataToAF(&decoder->GetDecodedSamples());
3885
3886 decoder->Decode(data, size);
3887 cached_channel_timestamp_ = timestamp;
3888 cached_channel_ = decoder;
3889 return;
3890 }
3891
3892 /* Data for same channel received. 2nd channel is down/not sending
3893 * data */
3894
3895 /* Send the cached data out */
3896 SendAudioDataToAF(&decoder->GetDecodedSamples());
3897
3898 /* Cache the data in case 2nd channel connects */
3899 decoder->Decode(data, size);
3900 cached_channel_timestamp_ = timestamp;
3901 cached_channel_ = decoder;
3902 }
3903
SendAudioDataToAF(std::vector<int16_t> * left,std::vector<int16_t> * right=nullptr)3904 void SendAudioDataToAF(std::vector<int16_t>* left, std::vector<int16_t>* right = nullptr) {
3905 uint16_t to_write = 0;
3906 uint16_t written = 0;
3907
3908 bool af_is_stereo = (audio_framework_sink_config.num_channels == 2);
3909 bool bt_got_stereo = (left != nullptr) & (right != nullptr);
3910
3911 if (!af_is_stereo) {
3912 if (!bt_got_stereo) {
3913 std::vector<int16_t>* mono = left ? left : right;
3914 /* mono audio over bluetooth, audio framework expects mono */
3915 to_write = sizeof(int16_t) * mono->size();
3916 written = le_audio_sink_hal_client_->SendData((uint8_t*)mono->data(), to_write);
3917 } else {
3918 /* stereo audio over bluetooth, audio framework expects mono */
3919 for (size_t i = 0; i < left->size(); i++) {
3920 (*left)[i] = ((*left)[i] + (*right)[i]) / 2;
3921 }
3922 to_write = sizeof(int16_t) * left->size();
3923 written = le_audio_sink_hal_client_->SendData((uint8_t*)left->data(), to_write);
3924 }
3925 } else {
3926 /* mono audio over bluetooth, audio framework expects stereo
3927 * Here we handle stream without checking bt_got_stereo flag.
3928 */
3929 const size_t mono_size = left ? left->size() : right->size();
3930 std::vector<uint16_t> mixed(mono_size * 2);
3931
3932 for (size_t i = 0; i < mono_size; i++) {
3933 mixed[2 * i] = left ? (*left)[i] : (*right)[i];
3934 mixed[2 * i + 1] = right ? (*right)[i] : (*left)[i];
3935 }
3936 to_write = sizeof(int16_t) * mixed.size();
3937 written = le_audio_sink_hal_client_->SendData((uint8_t*)mixed.data(), to_write);
3938 }
3939
3940 /* TODO: What to do if not all data sinked ? */
3941 if (written != to_write) {
3942 log::error("not all data sinked");
3943 }
3944 }
3945
ConfirmLocalAudioSourceStreamingRequest()3946 void ConfirmLocalAudioSourceStreamingRequest() {
3947 le_audio_source_hal_client_->ConfirmStreamingRequest();
3948
3949 LeAudioLogHistory::Get()->AddLogHistory(
3950 kLogBtCallAf, active_group_id_, RawAddress::kEmpty, kLogAfResumeConfirm + "LocalSource",
3951 "s_state: " + ToString(audio_sender_state_) + "-> STARTED");
3952
3953 audio_sender_state_ = AudioState::STARTED;
3954 }
3955
ConfirmLocalAudioSinkStreamingRequest()3956 void ConfirmLocalAudioSinkStreamingRequest() {
3957 le_audio_sink_hal_client_->ConfirmStreamingRequest();
3958
3959 LeAudioLogHistory::Get()->AddLogHistory(
3960 kLogBtCallAf, active_group_id_, RawAddress::kEmpty, kLogAfResumeConfirm + "LocalSink",
3961 "r_state: " + ToString(audio_receiver_state_) + "-> STARTED");
3962
3963 audio_receiver_state_ = AudioState::STARTED;
3964 }
3965
StartSendingAudio(int group_id)3966 void StartSendingAudio(int group_id) {
3967 log::info("");
3968
3969 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
3970 LeAudioDevice* device = group->GetFirstActiveDevice();
3971 log::assert_that(device, "Shouldn't be called without an active device.");
3972
3973 /* Assume 2 ases max just for now. */
3974 auto* stream_conf = GetStreamSinkConfiguration(group);
3975 if (stream_conf == nullptr) {
3976 log::error("could not get sink configuration");
3977 groupStateMachine_->StopStream(group);
3978 return;
3979 }
3980
3981 log::debug("Sink stream config (#{}):\n",
3982 static_cast<int>(stream_conf->stream_params.sink.stream_locations.size()));
3983 for (auto stream : stream_conf->stream_params.sink.stream_locations) {
3984 log::debug("Cis handle: 0x{:02x}, allocation 0x{:04x}\n", stream.first, stream.second);
3985 }
3986 log::debug("Source stream config (#{}):\n",
3987 static_cast<int>(stream_conf->stream_params.source.stream_locations.size()));
3988 for (auto stream : stream_conf->stream_params.source.stream_locations) {
3989 log::debug("Cis handle: 0x{:02x}, allocation 0x{:04x}\n", stream.first, stream.second);
3990 }
3991
3992 uint16_t remote_delay_ms =
3993 group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSink);
3994 if (CodecManager::GetInstance()->GetCodecLocation() ==
3995 bluetooth::le_audio::types::CodecLocation::HOST) {
3996 if (sw_enc_left || sw_enc_right) {
3997 log::warn("The encoder instance should have been already released.");
3998 }
3999 sw_enc_left = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4000 auto codec_status =
4001 sw_enc_left->InitEncoder(audio_framework_source_config, current_encoder_config_);
4002 if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4003 log::error("Left channel codec setup failed with err: {}", codec_status);
4004 groupStateMachine_->StopStream(group);
4005 return;
4006 }
4007
4008 sw_enc_right = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4009 codec_status =
4010 sw_enc_right->InitEncoder(audio_framework_source_config, current_encoder_config_);
4011 if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4012 log::error("Right channel codec setup failed with err: {}", codec_status);
4013 groupStateMachine_->StopStream(group);
4014 return;
4015 }
4016 }
4017
4018 le_audio_source_hal_client_->UpdateRemoteDelay(remote_delay_ms);
4019 ConfirmLocalAudioSourceStreamingRequest();
4020
4021 if (!LeAudioHalVerifier::SupportsStreamActiveApi()) {
4022 /* We update the target audio allocation before streamStarted so that the
4023 * CodecManager would know how to configure the encoder. */
4024 BidirectionalPair<uint16_t> delays_pair = {
4025 .sink = group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSink),
4026 .source = group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSource)};
4027 CodecManager::GetInstance()->UpdateActiveAudioConfig(
4028 group->stream_conf.stream_params, delays_pair,
4029 std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
4030 std::placeholders::_1, std::placeholders::_2));
4031 }
4032 }
4033
GetStreamSourceConfiguration(LeAudioDeviceGroup * group)4034 const struct bluetooth::le_audio::stream_configuration* GetStreamSourceConfiguration(
4035 LeAudioDeviceGroup* group) {
4036 const struct bluetooth::le_audio::stream_configuration* stream_conf = &group->stream_conf;
4037 if (stream_conf->stream_params.source.stream_locations.size() == 0) {
4038 return nullptr;
4039 }
4040 log::info("configuration: {}", stream_conf->conf->name);
4041 return stream_conf;
4042 }
4043
StartReceivingAudio(int group_id)4044 void StartReceivingAudio(int group_id) {
4045 log::info("");
4046
4047 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
4048
4049 auto* stream_conf = GetStreamSourceConfiguration(group);
4050 if (!stream_conf) {
4051 log::warn(
4052 "Could not get source configuration for group {} probably microphone not configured",
4053 active_group_id_);
4054 groupStateMachine_->StopStream(group);
4055 return;
4056 }
4057
4058 uint16_t remote_delay_ms =
4059 group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSource);
4060
4061 CleanCachedMicrophoneData();
4062
4063 if (CodecManager::GetInstance()->GetCodecLocation() ==
4064 bluetooth::le_audio::types::CodecLocation::HOST) {
4065 if (sw_dec_left.get() || sw_dec_right.get()) {
4066 log::warn("The decoder instance should have been already released.");
4067 }
4068 sw_dec_left = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4069 auto codec_status =
4070 sw_dec_left->InitDecoder(current_decoder_config_, audio_framework_sink_config);
4071 if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4072 log::error("Left channel codec setup failed with err: {}", codec_status);
4073 groupStateMachine_->StopStream(group);
4074 return;
4075 }
4076
4077 sw_dec_right = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4078 codec_status =
4079 sw_dec_right->InitDecoder(current_decoder_config_, audio_framework_sink_config);
4080 if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4081 log::error("Right channel codec setup failed with err: {}", codec_status);
4082 groupStateMachine_->StopStream(group);
4083 return;
4084 }
4085 }
4086 le_audio_sink_hal_client_->UpdateRemoteDelay(remote_delay_ms);
4087 ConfirmLocalAudioSinkStreamingRequest();
4088
4089 if (!LeAudioHalVerifier::SupportsStreamActiveApi()) {
4090 /* We update the target audio allocation before streamStarted so that the
4091 * CodecManager would know how to configure the encoder. */
4092 BidirectionalPair<uint16_t> delays_pair = {
4093 .sink = group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSink),
4094 .source = group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSource)};
4095 CodecManager::GetInstance()->UpdateActiveAudioConfig(
4096 group->stream_conf.stream_params, delays_pair,
4097 std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
4098 std::placeholders::_1, std::placeholders::_2));
4099 }
4100 }
4101
SuspendAudio(void)4102 void SuspendAudio(void) {
4103 CancelStreamingRequest();
4104
4105 if (sw_enc_left) {
4106 sw_enc_left.reset();
4107 }
4108 if (sw_enc_right) {
4109 sw_enc_right.reset();
4110 }
4111 if (sw_dec_left) {
4112 sw_dec_left.reset();
4113 }
4114 if (sw_dec_right) {
4115 sw_dec_right.reset();
4116 }
4117 CleanCachedMicrophoneData();
4118 }
4119
StopAudio(void)4120 void StopAudio(void) {
4121 SuspendAudio();
4122 stack::l2cap::get_interface().L2CA_SetEcosystemBaseInterval(0 /* clear recommendation */);
4123 }
4124
printCurrentStreamConfiguration(std::stringstream & stream)4125 void printCurrentStreamConfiguration(std::stringstream& stream) {
4126 auto config_printer = [&stream](LeAudioCodecConfiguration& conf) {
4127 stream << "\tsample rate: " << +conf.sample_rate << ", chan: " << +conf.num_channels
4128 << ", bits: " << +conf.bits_per_sample
4129 << ", data_interval_us: " << +conf.data_interval_us << "\n";
4130 };
4131
4132 stream << "\n";
4133 stream << " Speaker codec config (audio framework):\n";
4134 stream << "\taudio sender state: " << audio_sender_state_ << "\n";
4135 config_printer(audio_framework_source_config);
4136
4137 stream << " Microphone codec config (audio framework):\n";
4138 stream << "\taudio receiver state: " << audio_receiver_state_ << "\n";
4139 config_printer(audio_framework_sink_config);
4140
4141 stream << " Speaker codec config (SW encoder):\n";
4142 config_printer(current_encoder_config_);
4143
4144 stream << " Microphone codec config (SW decoder):\n";
4145 config_printer(current_decoder_config_);
4146 }
4147
Dump(int fd)4148 void Dump(int fd) {
4149 std::stringstream stream;
4150
4151 stream << " APP ID: " << +gatt_if_ << "\n";
4152 stream << " TBS state: " << (in_call_ ? " In call" : "No calls") << "\n";
4153 stream << " Active group: " << +active_group_id_ << "\n";
4154 stream << " Reconnection mode: "
4155 << (reconnection_mode_ == BTM_BLE_BKG_CONNECT_ALLOW_LIST ? "Allow List"
4156 : "Targeted Announcements")
4157 << "\n";
4158 stream << " Configuration: " << bluetooth::common::ToString(configuration_context_type_)
4159 << " (" << loghex(static_cast<uint16_t>(configuration_context_type_)) << ")\n";
4160 stream << " Local source metadata context type mask: "
4161 << local_metadata_context_types_.source.to_string() << "\n";
4162 stream << " Local sink metadata context type mask: "
4163 << local_metadata_context_types_.sink.to_string() << "\n";
4164 stream << " Sink listening mode: " << (sink_monitor_mode_ ? "true" : "false") << "\n";
4165 if (sink_monitor_notified_status_) {
4166 stream << " Local sink notified state: "
4167 << static_cast<int>(sink_monitor_notified_status_.value()) << "\n";
4168 }
4169 stream << " Source monitor mode: " << (source_monitor_mode_ ? "true" : "false") << "\n";
4170 if (source_monitor_notified_status_) {
4171 dprintf(fd, " Local source notified state: %d\n",
4172 static_cast<int>(source_monitor_notified_status_.value()));
4173 }
4174
4175 auto codec_loc = CodecManager::GetInstance()->GetCodecLocation();
4176 if (codec_loc == bluetooth::le_audio::types::CodecLocation::HOST) {
4177 stream << " Codec location: HOST\n";
4178 } else if (codec_loc == bluetooth::le_audio::types::CodecLocation::CONTROLLER) {
4179 stream << " Codec location: CONTROLLER\n";
4180 } else if (codec_loc == bluetooth::le_audio::types::CodecLocation::ADSP) {
4181 stream << " Codec location: ADSP"
4182 << (CodecManager::GetInstance()->IsUsingCodecExtensibility() ? " (codec extensibility)"
4183 : "")
4184 << "\n";
4185 } else {
4186 dprintf(fd, " Codec location: UNKNOWN\n");
4187 }
4188
4189 stream << " Stream creation speed: ";
4190 for (auto t : stream_speed_history_) {
4191 t.Dump(stream);
4192 stream << ",";
4193 }
4194 stream << "\n";
4195 printCurrentStreamConfiguration(stream);
4196 stream << "\n";
4197 aseGroups_.Dump(stream, active_group_id_);
4198 stream << "\n ";
4199 stream << " Not grouped devices:\n";
4200 leAudioDevices_.Dump(stream, bluetooth::groups::kGroupUnknown);
4201
4202 dprintf(fd, "%s", stream.str().c_str());
4203
4204 if (leAudioHealthStatus_) {
4205 leAudioHealthStatus_->DebugDump(fd);
4206 }
4207 }
4208
Cleanup()4209 void Cleanup() {
4210 StopVbcCloseTimeout();
4211 StopSuspendTimeout();
4212
4213 if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
4214 /* Bluetooth turned off while streaming */
4215 StopAudio();
4216 SetUnicastMonitorMode(bluetooth::le_audio::types::kLeAudioDirectionSink, false);
4217 ClientAudioInterfaceRelease();
4218 } else {
4219 /* There may be not stopped Sink HAL client due to set Listening mode */
4220 if (sink_monitor_mode_) {
4221 SetUnicastMonitorMode(bluetooth::le_audio::types::kLeAudioDirectionSink, false);
4222 }
4223 }
4224 groupStateMachine_->Cleanup();
4225 aseGroups_.Cleanup();
4226 lastNotifiedGroupStreamStatusMap_.clear();
4227 leAudioDevices_.Cleanup(gatt_if_);
4228 if (gatt_if_) {
4229 BTA_GATTC_AppDeregister(gatt_if_);
4230 }
4231
4232 if (leAudioHealthStatus_) {
4233 leAudioHealthStatus_->Cleanup();
4234 }
4235 }
4236
UpdateConfigAndCheckIfReconfigurationIsNeeded(LeAudioDeviceGroup * group,LeAudioContextType context_type)4237 AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded(
4238 LeAudioDeviceGroup* group, LeAudioContextType context_type) {
4239 log::debug("Checking whether to reconfigure from {} to {}",
4240 ToString(configuration_context_type_), ToString(context_type));
4241
4242 auto audio_set_conf = group->GetConfiguration(context_type);
4243 if (!audio_set_conf) {
4244 return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE;
4245 }
4246
4247 if (group->IsGroupConfiguredTo(*audio_set_conf) && !DsaReconfigureNeeded(group, context_type)) {
4248 // Assign the new configuration context as it represennts the current
4249 // use case even when it eventually ends up being the exact same
4250 // codec and qos configuration.
4251 if (configuration_context_type_ != context_type) {
4252 configuration_context_type_ = context_type;
4253 group->SetConfigurationContextType(context_type);
4254 }
4255 return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
4256 }
4257
4258 log::info("Session reconfiguration needed group: {} for context type: {}", group->group_id_,
4259 ToHexString(context_type));
4260
4261 configuration_context_type_ = context_type;
4262
4263 // Note: The local sink config is based on remote device's source config
4264 // and vice versa.
4265 current_decoder_config_ = group->GetAudioSessionCodecConfigForDirection(
4266 context_type, bluetooth::le_audio::types::kLeAudioDirectionSource);
4267 current_encoder_config_ = group->GetAudioSessionCodecConfigForDirection(
4268 context_type, bluetooth::le_audio::types::kLeAudioDirectionSink);
4269 return AudioReconfigurationResult::RECONFIGURATION_NEEDED;
4270 }
4271
4272 /* Returns true if stream is started */
OnAudioResume(LeAudioDeviceGroup * group,int local_direction)4273 bool OnAudioResume(LeAudioDeviceGroup* group, int local_direction) {
4274 auto remote_direction = (local_direction == bluetooth::le_audio::types::kLeAudioDirectionSink
4275 ? bluetooth::le_audio::types::kLeAudioDirectionSource
4276 : bluetooth::le_audio::types::kLeAudioDirectionSink);
4277
4278 auto remote_contexts = DirectionalRealignMetadataAudioContexts(group, remote_direction);
4279 ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts, remote_direction);
4280
4281 if (!remote_contexts.sink.any() && !remote_contexts.source.any()) {
4282 log::warn("Requested context type not available on the remote side");
4283
4284 if (com::android::bluetooth::flags::leaudio_no_context_validate_streaming_request() &&
4285 source_monitor_mode_) {
4286 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE);
4287
4288 return false;
4289 }
4290
4291 if (leAudioHealthStatus_) {
4292 leAudioHealthStatus_->AddStatisticForGroup(
4293 group, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE);
4294 }
4295 return false;
4296 }
4297
4298 return GroupStream(active_group_id_, configuration_context_type_, remote_contexts);
4299 }
4300
OnAudioSuspend()4301 void OnAudioSuspend() {
4302 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
4303 log::warn(", there is no longer active group");
4304 return;
4305 }
4306
4307 if (stack_config_get_interface()->get_pts_le_audio_disable_ases_before_stopping()) {
4308 log::info("Stream disable_timer_ started");
4309 if (alarm_is_scheduled(disable_timer_)) {
4310 alarm_cancel(disable_timer_);
4311 }
4312
4313 alarm_set_on_mloop(
4314 disable_timer_, kAudioDisableTimeoutMs,
4315 [](void* data) {
4316 if (instance) {
4317 auto const group_id = PTR_TO_INT(data);
4318 log::debug("No resume request received. Suspend the group ID: {}", group_id);
4319 instance->GroupSuspend(group_id);
4320 }
4321 },
4322 INT_TO_PTR(active_group_id_));
4323 }
4324
4325 StartSuspendTimeout();
4326 }
4327
OnLocalAudioSourceSuspend()4328 void OnLocalAudioSourceSuspend() {
4329 log::info("active group_id: {}, IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4330 active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4331 LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4332 kLogAfSuspend + "LocalSource",
4333 "r_state: " + ToString(audio_receiver_state_) +
4334 ", s_state: " + ToString(audio_sender_state_));
4335
4336 /* Note: This callback is from audio hal driver.
4337 * Bluetooth peer is a Sink for Audio Framework.
4338 * e.g. Peer is a speaker
4339 */
4340 switch (audio_sender_state_) {
4341 case AudioState::READY_TO_START:
4342 case AudioState::STARTED:
4343 audio_sender_state_ = AudioState::READY_TO_RELEASE;
4344 break;
4345 case AudioState::RELEASING:
4346 return;
4347 case AudioState::IDLE:
4348 if (audio_receiver_state_ == AudioState::READY_TO_RELEASE) {
4349 OnAudioSuspend();
4350 }
4351 return;
4352 case AudioState::READY_TO_RELEASE:
4353 break;
4354 }
4355
4356 /* Last suspends group - triggers group stop */
4357 if ((audio_receiver_state_ == AudioState::IDLE) ||
4358 (audio_receiver_state_ == AudioState::READY_TO_RELEASE)) {
4359 OnAudioSuspend();
4360 bluetooth::le_audio::MetricsCollector::Get()->OnStreamEnded(active_group_id_);
4361 }
4362
4363 log::info("OUT: audio_receiver_state_: {}, audio_sender_state_: {}",
4364 ToString(audio_receiver_state_), ToString(audio_sender_state_));
4365
4366 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
4367 kLogAfSuspendConfirm + "LocalSource",
4368 "r_state: " + ToString(audio_receiver_state_) +
4369 "s_state: " + ToString(audio_sender_state_));
4370 }
4371
OnLocalAudioSourceResume()4372 void OnLocalAudioSourceResume() {
4373 log::info("active group_id: {}, IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4374 active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4375 LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4376 kLogAfResume + "LocalSource",
4377 "r_state: " + ToString(audio_receiver_state_) +
4378 ", s_state: " + ToString(audio_sender_state_));
4379
4380 /* Note: This callback is from audio hal driver.
4381 * Bluetooth peer is a Sink for Audio Framework.
4382 * e.g. Peer is a speaker
4383 */
4384 auto group = aseGroups_.FindById(active_group_id_);
4385 if (!group) {
4386 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4387 return;
4388 }
4389
4390 /* Check if the device resume is allowed */
4391 if (!group->HasCodecConfigurationForDirection(
4392 configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4393 log::error("invalid resume request for context type: {}",
4394 ToHexString(configuration_context_type_));
4395 CancelLocalAudioSourceStreamingRequest();
4396 return;
4397 }
4398
4399 if (!group->GetAllowedContextMask(bluetooth::le_audio::types::kLeAudioDirectionSink)
4400 .test(configuration_context_type_)) {
4401 log::warn("Block source resume request context type: {}",
4402 ToHexString(configuration_context_type_));
4403 CancelLocalAudioSourceStreamingRequest();
4404 return;
4405 }
4406
4407 log::debug(
4408 "active_group_id: {}\n audio_receiver_state: {}\n audio_sender_state: "
4409 "{}\n configuration_context_type_: {}\n",
4410 active_group_id_, audio_receiver_state_, audio_sender_state_,
4411 ToHexString(configuration_context_type_));
4412
4413 switch (audio_sender_state_) {
4414 case AudioState::STARTED:
4415 /* Looks like previous Confirm did not get to the Audio Framework*/
4416 ConfirmLocalAudioSourceStreamingRequest();
4417 break;
4418 case AudioState::IDLE:
4419 switch (audio_receiver_state_) {
4420 case AudioState::IDLE:
4421 /* Stream is not started. Try to do it.*/
4422 if (OnAudioResume(group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4423 audio_sender_state_ = AudioState::READY_TO_START;
4424 if (IsReconfigurationTimeoutRunning(active_group_id_)) {
4425 StopReconfigurationTimeout(active_group_id_,
4426 bluetooth::le_audio::types::kLeAudioDirectionSource);
4427 }
4428 } else {
4429 CancelLocalAudioSourceStreamingRequest();
4430 }
4431 break;
4432 case AudioState::READY_TO_START:
4433 audio_sender_state_ = AudioState::READY_TO_START;
4434 if (!IsDirectionAvailableForCurrentConfiguration(
4435 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4436 log::warn(
4437 "sink is not configured. \n audio_receiver_state: {} "
4438 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4439 "Reconfiguring to {}",
4440 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4441 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4442 group->PrintDebugState();
4443 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4444 }
4445 break;
4446 case AudioState::STARTED:
4447 audio_sender_state_ = AudioState::READY_TO_START;
4448 /* If signalling part is completed trigger start sending audio
4449 * here, otherwise it'll be called on group streaming state callback
4450 */
4451 if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4452 if (IsDirectionAvailableForCurrentConfiguration(
4453 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4454 StartSendingAudio(active_group_id_);
4455 } else {
4456 log::warn(
4457 "sink is not configured. \n audio_receiver_state: {} "
4458 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4459 "Reconfiguring to {}",
4460 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4461 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4462 group->PrintDebugState();
4463 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4464 }
4465 } else {
4466 log::error(
4467 "called in wrong state. \n audio_receiver_state: {} "
4468 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4469 "Reconfiguring to {}",
4470 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4471 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4472 group->PrintDebugState();
4473 CancelStreamingRequest();
4474 }
4475 break;
4476 case AudioState::RELEASING:
4477 /* Group is reconfiguring, reassing state and wait for
4478 * the stream to be configured
4479 */
4480 audio_sender_state_ = audio_receiver_state_;
4481 break;
4482 case AudioState::READY_TO_RELEASE:
4483 /* If the other direction is streaming we can start sending audio */
4484 if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4485 if (IsDirectionAvailableForCurrentConfiguration(
4486 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4487 StopSuspendTimeout();
4488 StartSendingAudio(active_group_id_);
4489 } else {
4490 log::warn(
4491 "sink is not configured. \n audio_receiver_state: {} "
4492 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4493 "Reconfiguring to {}",
4494 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4495 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4496 group->PrintDebugState();
4497 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4498 }
4499 } else {
4500 log::error(
4501 "called in wrong state. \n audio_receiver_state: {} "
4502 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4503 "Reconfiguring to {}",
4504 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4505 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4506 group->PrintDebugState();
4507 CancelStreamingRequest();
4508 }
4509 break;
4510 }
4511 break;
4512 case AudioState::READY_TO_START:
4513 log::error(
4514 "called in wrong state, ignoring double start request. \n "
4515 "audio_receiver_state: {} \naudio_sender_state: {} \n "
4516 "isPendingConfiguration: {} \n Reconfiguring to {}",
4517 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4518 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4519 group->PrintDebugState();
4520 break;
4521 case AudioState::READY_TO_RELEASE:
4522 switch (audio_receiver_state_) {
4523 case AudioState::STARTED:
4524 case AudioState::READY_TO_START:
4525 case AudioState::IDLE:
4526 case AudioState::READY_TO_RELEASE:
4527 /* Stream is up just restore it */
4528 StopSuspendTimeout();
4529 ConfirmLocalAudioSourceStreamingRequest();
4530 bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted(
4531 active_group_id_, configuration_context_type_);
4532 break;
4533 case AudioState::RELEASING:
4534 /* Keep waiting. After release is done, Audio Hal will be notified
4535 */
4536 break;
4537 }
4538 break;
4539 case AudioState::RELEASING:
4540 /* Keep waiting. After release is done, Audio Hal will be notified */
4541 break;
4542 }
4543 }
4544
OnLocalAudioSinkSuspend()4545 void OnLocalAudioSinkSuspend() {
4546 log::info("active group_id: {}, IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4547 active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4548 LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4549 kLogAfSuspend + "LocalSink",
4550 "r_state: " + ToString(audio_receiver_state_) +
4551 ", s_state: " + ToString(audio_sender_state_));
4552
4553 /* If the local sink direction is used, we want to monitor
4554 * if back channel is actually needed.
4555 */
4556 StartVbcCloseTimeout();
4557
4558 /* Note: This callback is from audio hal driver.
4559 * Bluetooth peer is a Source for Audio Framework.
4560 * e.g. Peer is microphone.
4561 */
4562 switch (audio_receiver_state_) {
4563 case AudioState::READY_TO_START:
4564 case AudioState::STARTED:
4565 audio_receiver_state_ = AudioState::READY_TO_RELEASE;
4566 break;
4567 case AudioState::RELEASING:
4568 return;
4569 case AudioState::IDLE:
4570 if (audio_sender_state_ == AudioState::READY_TO_RELEASE) {
4571 OnAudioSuspend();
4572 }
4573 return;
4574 case AudioState::READY_TO_RELEASE:
4575 break;
4576 }
4577
4578 /* Last suspends group - triggers group stop */
4579 if ((audio_sender_state_ == AudioState::IDLE) ||
4580 (audio_sender_state_ == AudioState::READY_TO_RELEASE)) {
4581 OnAudioSuspend();
4582 }
4583
4584 log::info("OUT: audio_receiver_state_: {}, audio_sender_state_: {}",
4585 ToString(audio_receiver_state_), ToString(audio_sender_state_));
4586
4587 LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
4588 kLogAfSuspendConfirm + "LocalSink",
4589 "r_state: " + ToString(audio_receiver_state_) +
4590 "s_state: " + ToString(audio_sender_state_));
4591 }
4592
IsDirectionAvailableForCurrentConfiguration(const LeAudioDeviceGroup * group,uint8_t remote_direction) const4593 inline bool IsDirectionAvailableForCurrentConfiguration(const LeAudioDeviceGroup* group,
4594 uint8_t remote_direction) const {
4595 auto current_config =
4596 group->IsUsingPreferredAudioSetConfiguration(configuration_context_type_)
4597 ? group->GetCachedPreferredConfiguration(configuration_context_type_)
4598 : group->GetCachedConfiguration(configuration_context_type_);
4599 log::debug("configuration_context_type_ = {}, group_id: {}, remote_direction: {}",
4600 ToString(configuration_context_type_), group->group_id_,
4601 remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink ? "Sink"
4602 : "Source");
4603 if (current_config) {
4604 log::debug("name = {}, size {}", current_config->name,
4605 current_config->confs.get(remote_direction).size());
4606 return current_config->confs.get(remote_direction).size() != 0;
4607 }
4608 log::debug("no cached configuration");
4609 return false;
4610 }
4611
notifyAudioLocalSink(UnicastMonitorModeStatus status)4612 void notifyAudioLocalSink(UnicastMonitorModeStatus status) {
4613 if (sink_monitor_notified_status_ != status) {
4614 log::info("Stream monitoring status changed to: {}", static_cast<int>(status));
4615 sink_monitor_notified_status_ = status;
4616 callbacks_->OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
4617 status);
4618 }
4619 }
4620
notifyAudioLocalSource(UnicastMonitorModeStatus status)4621 void notifyAudioLocalSource(UnicastMonitorModeStatus status) {
4622 if (source_monitor_notified_status_ != status) {
4623 log::info("Source stream monitoring status changed to: {}", static_cast<int>(status));
4624 source_monitor_notified_status_ = status;
4625 callbacks_->OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
4626 status);
4627 }
4628 }
4629
OnLocalAudioSinkResume()4630 void OnLocalAudioSinkResume() {
4631 log::info("active group_id: {} IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4632 active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4633 LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4634 kLogAfResume + "LocalSink",
4635 "r_state: " + ToString(audio_receiver_state_) +
4636 ", s_state: " + ToString(audio_sender_state_));
4637
4638 if (sink_monitor_mode_ && active_group_id_ == bluetooth::groups::kGroupUnknown) {
4639 if (sink_monitor_notified_status_ != UnicastMonitorModeStatus::STREAMING_REQUESTED) {
4640 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_REQUESTED);
4641 }
4642 CancelLocalAudioSinkStreamingRequest();
4643 return;
4644 }
4645
4646 /* Stop the VBC close watchdog if needed */
4647 StopVbcCloseTimeout();
4648
4649 /* Note: This callback is from audio hal driver.
4650 * Bluetooth peer is a Source for Audio Framework.
4651 * e.g. Peer is microphone.
4652 */
4653 auto group = aseGroups_.FindById(active_group_id_);
4654 if (!group) {
4655 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4656 return;
4657 }
4658
4659 if (audio_receiver_state_ == AudioState::IDLE) {
4660 /* We need new configuration_context_type_ to be selected before we go any
4661 * further.
4662 */
4663 ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSource);
4664 log::info("new_configuration_context = {}", ToString(configuration_context_type_));
4665 }
4666
4667 /* Check if the device resume is allowed */
4668 if (!group->HasCodecConfigurationForDirection(
4669 configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4670 log::error("invalid resume request for context type: {}",
4671 ToHexString(configuration_context_type_));
4672 CancelLocalAudioSinkStreamingRequest();
4673 return;
4674 }
4675
4676 if (!group->GetAllowedContextMask(bluetooth::le_audio::types::kLeAudioDirectionSource)
4677 .test(configuration_context_type_)) {
4678 log::warn("Block sink resume request context type: {}",
4679 ToHexString(configuration_context_type_));
4680 CancelLocalAudioSourceStreamingRequest();
4681 return;
4682 }
4683
4684 log::debug(
4685 "active_group_id: {}\n audio_receiver_state: {}\n audio_sender_state: "
4686 "{}\n configuration_context_type_: {}\n group {}\n",
4687 active_group_id_, audio_receiver_state_, audio_sender_state_,
4688 ToHexString(configuration_context_type_), group ? " exist " : " does not exist ");
4689
4690 switch (audio_receiver_state_) {
4691 case AudioState::STARTED:
4692 ConfirmLocalAudioSinkStreamingRequest();
4693 break;
4694 case AudioState::IDLE:
4695 switch (audio_sender_state_) {
4696 case AudioState::IDLE:
4697 if (OnAudioResume(group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4698 audio_receiver_state_ = AudioState::READY_TO_START;
4699 if (IsReconfigurationTimeoutRunning(active_group_id_)) {
4700 StopReconfigurationTimeout(active_group_id_,
4701 bluetooth::le_audio::types::kLeAudioDirectionSink);
4702 }
4703 } else {
4704 CancelLocalAudioSinkStreamingRequest();
4705 }
4706 break;
4707 case AudioState::READY_TO_START:
4708 audio_receiver_state_ = AudioState::READY_TO_START;
4709 if (!IsDirectionAvailableForCurrentConfiguration(
4710 group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4711 log::warn(
4712 "source is not configured. \n audio_receiver_state: {} "
4713 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4714 "Reconfiguring to {}",
4715 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4716 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4717 group->PrintDebugState();
4718 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4719 }
4720 break;
4721 case AudioState::STARTED:
4722 audio_receiver_state_ = AudioState::READY_TO_START;
4723 /* If signalling part is completed trigger start receiving audio
4724 * here, otherwise it'll be called on group streaming state callback
4725 */
4726 if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4727 if (IsDirectionAvailableForCurrentConfiguration(
4728 group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4729 StartReceivingAudio(active_group_id_);
4730 } else {
4731 log::warn(
4732 "source is not configured. \n audio_receiver_state: {} "
4733 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4734 "Reconfiguring to {}",
4735 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4736 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4737 group->PrintDebugState();
4738 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4739 }
4740 } else {
4741 log::error(
4742 "called in wrong state. \n audio_receiver_state: {} "
4743 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4744 "Reconfiguring to {}",
4745 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4746 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4747 group->PrintDebugState();
4748 CancelStreamingRequest();
4749 }
4750 break;
4751 case AudioState::RELEASING:
4752 /* Group is reconfiguring, reassing state and wait for
4753 * the stream to be configured
4754 */
4755 audio_receiver_state_ = audio_sender_state_;
4756 break;
4757 case AudioState::READY_TO_RELEASE:
4758 /* If the other direction is streaming we can start receiving audio
4759 */
4760 if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4761 if (IsDirectionAvailableForCurrentConfiguration(
4762 group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4763 StopSuspendTimeout();
4764 StartReceivingAudio(active_group_id_);
4765 } else {
4766 log::warn(
4767 "source is not configured. \n audio_receiver_state: {} "
4768 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4769 "Reconfiguring to {}",
4770 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4771 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4772 group->PrintDebugState();
4773 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4774 }
4775 } else {
4776 log::error(
4777 "called in wrong state. \n audio_receiver_state: {} "
4778 "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4779 "Reconfiguring to {}",
4780 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4781 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4782 group->PrintDebugState();
4783 CancelStreamingRequest();
4784 }
4785 break;
4786 }
4787 break;
4788 case AudioState::READY_TO_START:
4789 log::error(
4790 "Double resume request, just ignore it.. \n audio_receiver_state: "
4791 "{} \naudio_sender_state: {} \n isPendingConfiguration: {} \n Reconfiguring to {}",
4792 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4793 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4794 group->PrintDebugState();
4795 break;
4796 case AudioState::READY_TO_RELEASE:
4797 switch (audio_sender_state_) {
4798 case AudioState::STARTED:
4799 case AudioState::IDLE:
4800 case AudioState::READY_TO_START:
4801 case AudioState::READY_TO_RELEASE:
4802 /* Stream is up just restore it */
4803 StopSuspendTimeout();
4804 ConfirmLocalAudioSinkStreamingRequest();
4805 break;
4806 case AudioState::RELEASING:
4807 /* Wait until releasing is completed */
4808 break;
4809 }
4810
4811 break;
4812 case AudioState::RELEASING:
4813 /* Wait until releasing is completed */
4814 break;
4815 }
4816 }
4817
4818 /* Chooses a single context type to use as a key for selecting a single
4819 * audio set configuration. Contexts used for the metadata can be different
4820 * than this, but it's reasonable to select a configuration context from
4821 * the metadata context types.
4822 */
ChooseConfigurationContextType(AudioContexts available_remote_contexts)4823 LeAudioContextType ChooseConfigurationContextType(AudioContexts available_remote_contexts) {
4824 log::debug("Got contexts={} in config_context={}",
4825 bluetooth::common::ToString(available_remote_contexts),
4826 bluetooth::common::ToString(configuration_context_type_));
4827
4828 if (IsInCall()) {
4829 log::debug("In Call preference used.");
4830 return LeAudioContextType::CONVERSATIONAL;
4831 }
4832
4833 /* Mini policy - always prioritize sink+source configurations so that we are
4834 * sure that for a mixed content we enable all the needed directions.
4835 */
4836 if (available_remote_contexts.any()) {
4837 LeAudioContextType context_priority_list[] = {
4838 /* Highest priority first */
4839 LeAudioContextType::CONVERSATIONAL,
4840 LeAudioContextType::RINGTONE,
4841 LeAudioContextType::LIVE,
4842 LeAudioContextType::VOICEASSISTANTS,
4843 LeAudioContextType::GAME,
4844 LeAudioContextType::MEDIA,
4845 LeAudioContextType::EMERGENCYALARM,
4846 LeAudioContextType::ALERTS,
4847 LeAudioContextType::INSTRUCTIONAL,
4848 LeAudioContextType::NOTIFICATIONS,
4849 LeAudioContextType::SOUNDEFFECTS,
4850 };
4851 for (auto ct : context_priority_list) {
4852 if (available_remote_contexts.test(ct)) {
4853 log::debug("Selecting configuration context type: {}", ToString(ct));
4854 return ct;
4855 }
4856 }
4857 }
4858
4859 /* Use BAP mandated UNSPECIFIED only if we don't have any other valid
4860 * configuration
4861 */
4862 auto fallback_config = LeAudioContextType::UNSPECIFIED;
4863 if (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) {
4864 fallback_config = configuration_context_type_;
4865 }
4866
4867 log::debug("Selecting configuration context type: {}", ToString(fallback_config));
4868 return fallback_config;
4869 }
4870
SetConfigurationAndStopStreamWhenNeeded(LeAudioDeviceGroup * group,LeAudioContextType new_context_type)4871 bool SetConfigurationAndStopStreamWhenNeeded(LeAudioDeviceGroup* group,
4872 LeAudioContextType new_context_type) {
4873 auto previous_context_type = configuration_context_type_;
4874
4875 auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded(group, new_context_type);
4876 /* Even though the reconfiguration may not be needed, this has
4877 * to be set here as it might be the initial configuration.
4878 */
4879
4880 configuration_context_type_ = new_context_type;
4881
4882 log::info("group_id {}, previous_context {} context type {} ({}), {}", group->group_id_,
4883 ToString(previous_context_type), ToString(new_context_type),
4884 ToHexString(new_context_type), ToString(reconfig_result));
4885 if (reconfig_result == AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED) {
4886 return false;
4887 }
4888
4889 if (reconfig_result == AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE) {
4890 return false;
4891 }
4892
4893 if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4894 log::debug("Group is not streaming");
4895 return false;
4896 }
4897
4898 StopSuspendTimeout();
4899 /* If group suspend is scheduled, cancel as we are stopping it anyway */
4900
4901 /* Need to reconfigure stream. At this point pre_configuration_context_type shall be set */
4902
4903 initReconfiguration(group, previous_context_type);
4904 SendAudioGroupCurrentCodecConfigChanged(group);
4905 return true;
4906 }
4907
OnLocalAudioSourceMetadataUpdate(const std::vector<struct playback_track_metadata_v7> & source_metadata,DsaMode dsa_mode)4908 void OnLocalAudioSourceMetadataUpdate(
4909 const std::vector<struct playback_track_metadata_v7>& source_metadata, DsaMode dsa_mode) {
4910 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
4911 log::warn(", cannot start streaming if no active group set");
4912 return;
4913 }
4914
4915 auto group = aseGroups_.FindById(active_group_id_);
4916 if (!group) {
4917 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4918 return;
4919 }
4920
4921 log::info(
4922 "group_id {} state={}, target_state={}, audio_receiver_state_: {}, "
4923 "audio_sender_state_: {}, dsa_mode: {}",
4924 group->group_id_, ToString(group->GetState()), ToString(group->GetTargetState()),
4925 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4926 static_cast<int>(dsa_mode));
4927
4928 if (IsReconfigurationTimeoutRunning(group->group_id_)) {
4929 log::info("Skip it as group is reconfiguring");
4930 return;
4931 }
4932
4933 /* Stop the VBC close timeout timer, since we will reconfigure anyway if the
4934 * VBC was suspended.
4935 */
4936 StopVbcCloseTimeout();
4937
4938 group->dsa_.mode = dsa_mode;
4939
4940 /* Set the remote sink metadata context from the playback tracks metadata */
4941 local_metadata_context_types_.source = GetAudioContextsFromSourceMetadata(source_metadata);
4942
4943 local_metadata_context_types_.source =
4944 ChooseMetadataContextType(local_metadata_context_types_.source);
4945
4946 ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSink);
4947 }
4948
4949 /* Applies some predefined policy on the audio context metadata, including
4950 * special handling of UNSPECIFIED context, which also involves checking
4951 * context support and availability.
4952 */
ApplyRemoteMetadataAudioContextPolicy(LeAudioDeviceGroup * group,BidirectionalPair<AudioContexts> & contexts_pair,int remote_dir)4953 void ApplyRemoteMetadataAudioContextPolicy(LeAudioDeviceGroup* group,
4954 BidirectionalPair<AudioContexts>& contexts_pair,
4955 int remote_dir) {
4956 // We expect at least some context when this direction gets enabled
4957 if (contexts_pair.get(remote_dir).none()) {
4958 log::warn("invalid/unknown {} context metadata, using 'UNSPECIFIED' instead",
4959 (remote_dir == bluetooth::le_audio::types::kLeAudioDirectionSink) ? "sink"
4960 : "source");
4961 contexts_pair.get(remote_dir) = AudioContexts(LeAudioContextType::UNSPECIFIED);
4962 }
4963
4964 std::tuple<int, int, AudioState*> remote_directions[] = {
4965 {bluetooth::le_audio::types::kLeAudioDirectionSink,
4966 bluetooth::le_audio::types::kLeAudioDirectionSource, &audio_sender_state_},
4967 {bluetooth::le_audio::types::kLeAudioDirectionSource,
4968 bluetooth::le_audio::types::kLeAudioDirectionSink, &audio_receiver_state_},
4969 };
4970
4971 /* Align with the context availability */
4972 for (auto entry : remote_directions) {
4973 int dir, other_dir;
4974 AudioState* local_hal_state;
4975 std::tie(dir, other_dir, local_hal_state) = entry;
4976
4977 /* When a certain context became unavailable while it was already in
4978 * an active stream, it means that it is unavailable to other clients
4979 * but we can keep using it.
4980 */
4981 auto group_available_contexts = group->GetAvailableContexts(dir);
4982 if ((*local_hal_state == AudioState::STARTED) ||
4983 (*local_hal_state == AudioState::READY_TO_START)) {
4984 group_available_contexts |= group->GetMetadataContexts().get(dir);
4985 }
4986
4987 log::debug("Checking contexts: {}, against the available contexts: {}",
4988 ToString(contexts_pair.get(dir)), ToString(group_available_contexts));
4989 auto unavail_contexts = contexts_pair.get(dir) & ~group_available_contexts;
4990 if (unavail_contexts.none()) {
4991 continue;
4992 }
4993
4994 // Use only available contexts
4995 contexts_pair.get(dir) &= group_available_contexts;
4996
4997 // Check we we should add UNSPECIFIED as well in case not available context is also not
4998 // supported
4999 auto unavail_but_supported = (unavail_contexts & group->GetSupportedContexts(dir));
5000 if (unavail_but_supported.none() &&
5001 group_available_contexts.test(LeAudioContextType::UNSPECIFIED)) {
5002 contexts_pair.get(dir).set(LeAudioContextType::UNSPECIFIED);
5003
5004 log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED -> {}",
5005 ToString(unavail_contexts), ToString(contexts_pair.get(dir)));
5006 } else {
5007 log::debug("Some contexts are supported but currently unavailable: {}!",
5008 ToString(unavail_but_supported));
5009 /* Some of the streamed contexts are support but not available and they
5010 * were erased from the metadata.
5011 * TODO: Either filter out these contexts from the stream or do not
5012 * stream at all if the unavail_but_supported contexts are the only
5013 * streamed contexts.
5014 */
5015 }
5016 }
5017
5018 /* Don't mix UNSPECIFIED with any other context
5019 * Note: This has to be in a separate loop - do not merge it with the above.
5020 */
5021 for (auto entry : remote_directions) {
5022 int dir, other_dir;
5023 AudioState* local_hal_state;
5024 std::tie(dir, other_dir, local_hal_state) = entry;
5025
5026 if (contexts_pair.get(dir).test(LeAudioContextType::UNSPECIFIED)) {
5027 /* If this directions is streaming just UNSPECIFIED and if other direction is streaming some
5028 * meaningfull context type, try to use the meaningful context type
5029 */
5030 if (contexts_pair.get(dir) == AudioContexts(LeAudioContextType::UNSPECIFIED)) {
5031 auto is_other_direction_streaming = (*local_hal_state == AudioState::STARTED) ||
5032 (*local_hal_state == AudioState::READY_TO_START);
5033 if (is_other_direction_streaming) {
5034 auto supported_contexts = group->GetAllSupportedSingleDirectionOnlyContextTypes(dir);
5035 auto common_part = supported_contexts & contexts_pair.get(other_dir);
5036
5037 log::info(
5038 "Other direction is streaming. Possible aligning other direction "
5039 "metadata to match the remote {} direction context: {}. Remote {} supported "
5040 "contexts: {} ",
5041 other_dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink"
5042 : " Source",
5043 ToString(contexts_pair.get(other_dir)),
5044 dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source",
5045 ToString(supported_contexts));
5046
5047 if (common_part.value() != 0) {
5048 contexts_pair.get(dir) = common_part;
5049 }
5050 }
5051 } else {
5052 log::debug("Removing UNSPECIFIED from the remote {} context: {}",
5053 dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source",
5054 ToString(contexts_pair.get(other_dir)));
5055 contexts_pair.get(dir).unset(LeAudioContextType::UNSPECIFIED);
5056 }
5057 }
5058 }
5059
5060 contexts_pair.sink = ChooseMetadataContextType(contexts_pair.sink);
5061 contexts_pair.source = ChooseMetadataContextType(contexts_pair.source);
5062
5063 log::debug("Aligned remote metadata audio context: sink={}, source={}",
5064 ToString(contexts_pair.sink), ToString(contexts_pair.source));
5065 }
5066
OnLocalAudioSinkMetadataUpdate(const std::vector<record_track_metadata_v7> & sink_metadata)5067 void OnLocalAudioSinkMetadataUpdate(const std::vector<record_track_metadata_v7>& sink_metadata) {
5068 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
5069 log::warn(", cannot start streaming if no active group set");
5070 return;
5071 }
5072
5073 auto group = aseGroups_.FindById(active_group_id_);
5074 if (!group) {
5075 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
5076 return;
5077 }
5078
5079 log::info(
5080 "group_id {} state={}, target_state={}, audio_receiver_state_: {}, "
5081 "audio_sender_state_: {}",
5082 group->group_id_, ToString(group->GetState()), ToString(group->GetTargetState()),
5083 ToString(audio_receiver_state_), ToString(audio_sender_state_));
5084
5085 if (IsReconfigurationTimeoutRunning(group->group_id_)) {
5086 log::info("Skip it as group is reconfiguring");
5087 return;
5088 }
5089
5090 /* Set remote source metadata context from the recording tracks metadata */
5091 local_metadata_context_types_.sink = GetAudioContextsFromSinkMetadata(sink_metadata);
5092
5093 local_metadata_context_types_.sink =
5094 ChooseMetadataContextType(local_metadata_context_types_.sink);
5095
5096 /* Reconfigure or update only if the stream is already started
5097 * otherwise wait for the local sink to resume.
5098 */
5099 if (audio_receiver_state_ == AudioState::STARTED) {
5100 ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSource);
5101 }
5102 }
5103
DirectionalRealignMetadataAudioContexts(LeAudioDeviceGroup * group,int remote_direction)5104 BidirectionalPair<AudioContexts> DirectionalRealignMetadataAudioContexts(
5105 LeAudioDeviceGroup* group, int remote_direction) {
5106 uint8_t remote_other_direction;
5107 std::string remote_direction_str;
5108 std::string remote_other_direction_str;
5109 AudioState other_direction_hal;
5110
5111 if (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink) {
5112 remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSource;
5113 remote_direction_str = "Sink";
5114 remote_other_direction_str = "Source";
5115 other_direction_hal = audio_receiver_state_;
5116 } else {
5117 remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSink;
5118 remote_direction_str = "Source";
5119 remote_other_direction_str = "Sink";
5120 other_direction_hal = audio_sender_state_;
5121 }
5122
5123 auto is_streaming_other_direction = (other_direction_hal == AudioState::STARTED) ||
5124 (other_direction_hal == AudioState::READY_TO_START);
5125
5126 auto local_direction = bluetooth::le_audio::types::kLeAudioDirectionBoth & ~remote_direction;
5127 auto local_other_direction =
5128 bluetooth::le_audio::types::kLeAudioDirectionBoth & ~remote_other_direction;
5129
5130 auto is_releasing_for_reconfiguration =
5131 (((audio_receiver_state_ == AudioState::RELEASING) ||
5132 (audio_sender_state_ == AudioState::RELEASING)) &&
5133 group->IsPendingConfiguration() &&
5134 IsDirectionAvailableForCurrentConfiguration(group, remote_other_direction)) ||
5135 IsReconfigurationTimeoutRunning(active_group_id_, local_direction);
5136
5137 auto is_releasing_for_reconfiguration_other_direction =
5138 is_releasing_for_reconfiguration &
5139 IsReconfigurationTimeoutRunning(active_group_id_, local_other_direction);
5140
5141 // Inject conversational when ringtone is played - this is required for all
5142 // the VoIP applications which are not using the telecom API.
5143 constexpr AudioContexts possible_voip_contexts =
5144 LeAudioContextType::RINGTONE | LeAudioContextType::CONVERSATIONAL;
5145 if (local_metadata_context_types_.source.test_any(possible_voip_contexts) &&
5146 ((remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink) ||
5147 (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource &&
5148 is_streaming_other_direction))) {
5149 /* Simulate, we are already in the call. Sending RINGTONE when there is
5150 * no incoming call to accept or reject on TBS could confuse the remote
5151 * device and interrupt the stream establish procedure.
5152 */
5153 if (!IsInCall()) {
5154 SetInVoipCall(true);
5155 }
5156 } else if (IsInVoipCall()) {
5157 SetInVoipCall(false);
5158 }
5159
5160 BidirectionalPair<AudioContexts> remote_metadata = {
5161 .sink = local_metadata_context_types_.source,
5162 .source = local_metadata_context_types_.sink};
5163
5164 auto all_bidirectional_contexts = group->GetAllSupportedBidirectionalContextTypes();
5165 log::debug("all_bidirectional_contexts {}", ToString(all_bidirectional_contexts));
5166
5167 /* Make sure we have CONVERSATIONAL when in a call and it is not mixed
5168 * with any other bidirectional context
5169 */
5170 if (IsInCall() || IsInVoipCall()) {
5171 log::debug("In Call preference used: {}, voip call: {}", IsInCall(), IsInVoipCall());
5172 remote_metadata.sink.unset_all(all_bidirectional_contexts);
5173 remote_metadata.source.unset_all(all_bidirectional_contexts);
5174 remote_metadata.sink.set(LeAudioContextType::CONVERSATIONAL);
5175 remote_metadata.source.set(LeAudioContextType::CONVERSATIONAL);
5176 }
5177
5178 if (!com::android::bluetooth::flags::leaudio_speed_up_reconfiguration_between_call()) {
5179 local_metadata_context_types_.sink = remote_metadata.source;
5180 local_metadata_context_types_.source = remote_metadata.sink;
5181 }
5182
5183 if (IsInVoipCall()) {
5184 log::debug("Unsetting RINGTONE from remote sink");
5185 remote_metadata.sink.unset(LeAudioContextType::RINGTONE);
5186 }
5187
5188 auto is_ongoing_call_on_other_direction =
5189 is_streaming_other_direction && (IsInVoipCall() || IsInCall());
5190
5191 log::debug("local_metadata_context_types_.source= {}",
5192 ToString(local_metadata_context_types_.source));
5193 log::debug("local_metadata_context_types_.sink= {}",
5194 ToString(local_metadata_context_types_.sink));
5195 log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
5196 log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
5197 log::debug("remote_direction= {}", remote_direction_str);
5198 log::debug("is_streaming_other_direction= {}", is_streaming_other_direction ? "True" : "False");
5199 log::debug("is_releasing_for_reconfiguration= {}",
5200 is_releasing_for_reconfiguration ? "True" : "False");
5201 log::debug("is_releasing_for_reconfiguration_other_direction= {}",
5202 is_releasing_for_reconfiguration_other_direction ? "True" : "False");
5203 log::debug("is_ongoing_call_on_other_direction={}",
5204 is_ongoing_call_on_other_direction ? "True" : "False");
5205
5206 if (remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts) &&
5207 !(is_streaming_other_direction || is_releasing_for_reconfiguration_other_direction)) {
5208 log::debug("The other direction is not streaming bidirectional, ignore that context.");
5209 remote_metadata.get(remote_other_direction).clear();
5210 }
5211
5212 auto single_direction_only_context_types =
5213 group->GetAllSupportedSingleDirectionOnlyContextTypes(remote_direction);
5214 auto single_other_direction_only_context_types =
5215 group->GetAllSupportedSingleDirectionOnlyContextTypes(remote_other_direction);
5216 log::debug(
5217 "single direction only contexts : {} for direction {}, single direction contexts {} "
5218 "for {}",
5219 ToString(single_direction_only_context_types), remote_direction_str,
5220 ToString(single_other_direction_only_context_types), remote_other_direction_str);
5221
5222 /* Mixed contexts in the voiceback channel scenarios can confuse the remote
5223 * on how to configure each channel. We should align the other direction
5224 * metadata for the remote device.
5225 */
5226 if (remote_metadata.get(remote_direction).test_any(all_bidirectional_contexts)) {
5227 log::debug("Aligning the other direction remote metadata to add this direction context");
5228
5229 if (is_ongoing_call_on_other_direction) {
5230 /* Other direction is streaming and is in call */
5231 remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts);
5232 remote_metadata.get(remote_direction).set(LeAudioContextType::CONVERSATIONAL);
5233 } else {
5234 if (!(is_streaming_other_direction || is_releasing_for_reconfiguration_other_direction)) {
5235 // Do not take the obsolete metadata
5236 remote_metadata.get(remote_other_direction).clear();
5237 } else {
5238 remote_metadata.get(remote_other_direction).unset_all(all_bidirectional_contexts);
5239 remote_metadata.get(remote_other_direction)
5240 .unset_all(single_direction_only_context_types);
5241 }
5242
5243 remote_metadata.get(remote_other_direction)
5244 .set_all(remote_metadata.get(remote_direction) &
5245 ~single_other_direction_only_context_types);
5246 }
5247 }
5248 log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
5249 log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
5250
5251 if (is_releasing_for_reconfiguration || is_streaming_other_direction) {
5252 log::debug("Other direction is streaming or there is reconfiguration. Taking its contexts {}",
5253 ToString(remote_metadata.get(remote_other_direction)));
5254 /* If current direction has no valid context or the other direction is
5255 * bidirectional scenario, take the other direction context as well
5256 */
5257 if ((remote_metadata.get(remote_direction).none() &&
5258 remote_metadata.get(remote_other_direction).any()) ||
5259 remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts)) {
5260 log::debug("Aligning this direction remote metadata to add the other direction context");
5261 /* Turn off bidirectional contexts on this direction to avoid mixing
5262 * with the other direction bidirectional context
5263 */
5264 remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts);
5265 remote_metadata.get(remote_direction).set_all(remote_metadata.get(remote_other_direction));
5266 }
5267 }
5268
5269 /* Make sure that after alignment no sink only context leaks into the other
5270 * direction. */
5271 remote_metadata.source.unset_all(group->GetAllSupportedSingleDirectionOnlyContextTypes(
5272 bluetooth::le_audio::types::kLeAudioDirectionSink));
5273
5274 log::debug("final remote_metadata.source= {}", ToString(remote_metadata.source));
5275 log::debug("final remote_metadata.sink= {}", ToString(remote_metadata.sink));
5276 return remote_metadata;
5277 }
5278
ReconfigureOrUpdateRemoteForPTS(LeAudioDeviceGroup * group,int)5279 bool ReconfigureOrUpdateRemoteForPTS(LeAudioDeviceGroup* group, int /*remote_direction*/) {
5280 log::info("{}", group->group_id_);
5281 // Use common audio stream contexts exposed by the PTS
5282 auto override_contexts = AudioContexts(0xFFFF);
5283 for (auto device = group->GetFirstDevice(); device != nullptr;
5284 device = group->GetNextDevice(device)) {
5285 override_contexts &= device->GetAvailableContexts();
5286 }
5287 if (override_contexts.value() == 0xFFFF) {
5288 override_contexts = AudioContexts(LeAudioContextType::UNSPECIFIED);
5289 }
5290 log::warn("Overriding local_metadata_context_types_: {} with: {}",
5291 local_metadata_context_types_.source.to_string(), override_contexts.to_string());
5292
5293 /* Choose the right configuration context */
5294 auto new_configuration_context = ChooseConfigurationContextType(override_contexts);
5295
5296 log::info("new_configuration_context= {}.", ToString(new_configuration_context));
5297 BidirectionalPair<AudioContexts> remote_contexts = {.sink = override_contexts,
5298 .source = override_contexts};
5299 return GroupStream(active_group_id_, new_configuration_context, remote_contexts);
5300 }
5301
5302 /* Return true if stream is started */
ReconfigureOrUpdateRemote(LeAudioDeviceGroup * group,int remote_direction)5303 bool ReconfigureOrUpdateRemote(LeAudioDeviceGroup* group, int remote_direction) {
5304 if (stack_config_get_interface()->get_pts_force_le_audio_multiple_contexts_metadata()) {
5305 return ReconfigureOrUpdateRemoteForPTS(group, remote_direction);
5306 }
5307
5308 /* When the local sink and source update their metadata, we need to come up
5309 * with a coherent set of contexts for either one or both directions,
5310 * especially when bidirectional scenarios can be triggered be either sink
5311 * or source metadata update event.
5312 */
5313 auto remote_metadata = DirectionalRealignMetadataAudioContexts(group, remote_direction);
5314
5315 /* Choose the right configuration context */
5316 auto config_context_candids = get_bidirectional(remote_metadata);
5317 auto new_config_context = ChooseConfigurationContextType(config_context_candids);
5318 log::debug("config_context_candids= {}, new_config_context= {}",
5319 ToString(config_context_candids), ToString(new_config_context));
5320
5321 /* For the following contexts we don't actually need HQ audio:
5322 * LeAudioContextType::NOTIFICATIONS
5323 * LeAudioContextType::SOUNDEFFECTS
5324 * LeAudioContextType::INSTRUCTIONAL
5325 * LeAudioContextType::ALERTS
5326 * LeAudioContextType::EMERGENCYALARM
5327 * LeAudioContextType::UNSPECIFIED
5328 * So do not reconfigure if the remote sink is already available at any
5329 * quality and these are the only contributors to the current audio stream.
5330 */
5331 auto no_reconfigure_contexts =
5332 LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
5333 LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
5334 LeAudioContextType::EMERGENCYALARM | LeAudioContextType::UNSPECIFIED;
5335 if (group->IsStreaming() && !group->IsReleasingOrIdle() && config_context_candids.any() &&
5336 (config_context_candids & ~no_reconfigure_contexts).none() &&
5337 (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) &&
5338 (configuration_context_type_ != LeAudioContextType::UNSPECIFIED) &&
5339 IsDirectionAvailableForCurrentConfiguration(
5340 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
5341 log::info(
5342 "There is no need to reconfigure for the sonification events, "
5343 "staying with the existing configuration context of {}",
5344 ToString(configuration_context_type_));
5345 new_config_context = configuration_context_type_;
5346 }
5347
5348 /* Do not configure the Voiceback channel if it is already configured.
5349 * WARNING: This eliminates additional reconfigurations but can
5350 * lead to unsatisfying audio quality when that direction was
5351 * already configured with a lower quality.
5352 */
5353 if (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
5354 const auto has_audio_source_configured =
5355 IsDirectionAvailableForCurrentConfiguration(
5356 group, bluetooth::le_audio::types::kLeAudioDirectionSource) &&
5357 (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5358 if (has_audio_source_configured) {
5359 log::info(
5360 "Audio source is already available in the current configuration "
5361 "context in {}. Not switching to {} right now.",
5362 ToString(configuration_context_type_), ToString(new_config_context));
5363 new_config_context = configuration_context_type_;
5364 }
5365 }
5366
5367 /* Note that the remote device metadata was so far unfiltered when it comes
5368 * to group context availability, or multiple contexts support flag, so that
5369 * we could choose the correct configuration for the use case. Now we can
5370 * align it to meet the metadata usage.
5371 */
5372 ApplyRemoteMetadataAudioContextPolicy(group, remote_metadata, remote_direction);
5373 return ReconfigureOrUpdateMetadata(group, new_config_context, remote_metadata);
5374 }
5375
DsaReconfigureNeeded(LeAudioDeviceGroup * group,LeAudioContextType context)5376 bool DsaReconfigureNeeded(LeAudioDeviceGroup* group, LeAudioContextType context) {
5377 if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
5378 return false;
5379 }
5380
5381 // Reconfigure if DSA mode changed for media streaming
5382 if (context != bluetooth::le_audio::types::LeAudioContextType::MEDIA) {
5383 return false;
5384 }
5385
5386 if (group->dsa_.mode != DsaMode::ISO_SW && group->dsa_.mode != DsaMode::ISO_HW) {
5387 return false;
5388 }
5389
5390 if (group->dsa_.active) {
5391 return false;
5392 }
5393
5394 log::info("DSA mode {} requested but not active", group->dsa_.mode);
5395 return true;
5396 }
5397
5398 /* Return true if stream is started */
ReconfigureOrUpdateMetadata(LeAudioDeviceGroup * group,LeAudioContextType new_configuration_context,BidirectionalPair<AudioContexts> remote_contexts)5399 bool ReconfigureOrUpdateMetadata(LeAudioDeviceGroup* group,
5400 LeAudioContextType new_configuration_context,
5401 BidirectionalPair<AudioContexts> remote_contexts) {
5402 if (new_configuration_context != configuration_context_type_ ||
5403 DsaReconfigureNeeded(group, new_configuration_context)) {
5404 log::info("Checking whether to change configuration context from {} to {}",
5405 ToString(configuration_context_type_), ToString(new_configuration_context));
5406
5407 LeAudioLogHistory::Get()->AddLogHistory(
5408 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
5409 kLogAfMetadataUpdate + "Reconfigure",
5410 ToString(configuration_context_type_) + "->" + ToString(new_configuration_context));
5411 auto is_stopping = SetConfigurationAndStopStreamWhenNeeded(group, new_configuration_context);
5412 if (is_stopping) {
5413 return false;
5414 }
5415 }
5416
5417 if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
5418 log::info("The {} configuration did not change. Updating the metadata to sink={}, source={}",
5419 ToString(configuration_context_type_), ToString(remote_contexts.sink),
5420 ToString(remote_contexts.source));
5421
5422 LeAudioLogHistory::Get()->AddLogHistory(
5423 kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
5424 kLogAfMetadataUpdate + "Updating...",
5425 "Sink: " + ToString(remote_contexts.sink) +
5426 "Source: " + ToString(remote_contexts.source));
5427
5428 return GroupStream(group->group_id_, configuration_context_type_, remote_contexts);
5429 }
5430 return false;
5431 }
5432
OnGattReadRspStatic(tCONN_ID conn_id,tGATT_STATUS status,uint16_t hdl,uint16_t len,uint8_t * value,void * data)5433 static void OnGattReadRspStatic(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, uint16_t len,
5434 uint8_t* value, void* data) {
5435 if (!instance) {
5436 return;
5437 }
5438
5439 LeAudioDevice* leAudioDevice = instance->leAudioDevices_.FindByConnId(conn_id);
5440
5441 if (status == GATT_SUCCESS) {
5442 instance->LeAudioCharValueHandle(conn_id, hdl, len, value);
5443 } else if (status == GATT_DATABASE_OUT_OF_SYNC) {
5444 instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
5445 return;
5446 } else {
5447 log::error("Failed to read attribute, hdl: 0x{:04x}, status: 0x{:02x}", hdl,
5448 static_cast<int>(status));
5449 return;
5450 }
5451
5452 /* We use data to keep notify connected flag. */
5453 if (data && !!PTR_TO_INT(data)) {
5454 leAudioDevice->notify_connected_after_read_ = false;
5455
5456 /* Update handles, PACs and ASEs when all is read.*/
5457 btif_storage_leaudio_update_handles_bin(leAudioDevice->address_);
5458 btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
5459 btif_storage_leaudio_update_ase_bin(leAudioDevice->address_);
5460
5461 btif_storage_set_leaudio_audio_location(leAudioDevice->address_,
5462 leAudioDevice->snk_audio_locations_.to_ulong(),
5463 leAudioDevice->src_audio_locations_.to_ulong());
5464
5465 instance->connectionReady(leAudioDevice);
5466 }
5467 }
5468
OnGattReadMultiRspStatic(tCONN_ID conn_id,tGATT_STATUS status,tBTA_GATTC_MULTI & handles,uint16_t total_len,uint8_t * value,void * data)5469 static void OnGattReadMultiRspStatic(tCONN_ID conn_id, tGATT_STATUS status,
5470 tBTA_GATTC_MULTI& handles, uint16_t total_len,
5471 uint8_t* value, void* data) {
5472 if (!instance) {
5473 return;
5474 }
5475
5476 if (status == GATT_DATABASE_OUT_OF_SYNC) {
5477 LeAudioDevice* leAudioDevice = instance->leAudioDevices_.FindByConnId(conn_id);
5478 instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
5479 return;
5480 }
5481 if (status != GATT_SUCCESS) {
5482 log::error("Failed to read multiple attributes, conn_id: 0x{:04x}, status: 0x{:02x}", conn_id,
5483 +status);
5484 return;
5485 }
5486
5487 size_t position = 0;
5488 int index = 0;
5489 while (position != total_len) {
5490 uint8_t* ptr = value + position;
5491 uint16_t len;
5492 STREAM_TO_UINT16(len, ptr);
5493 uint16_t hdl = handles.handles[index];
5494
5495 if (position + len >= total_len) {
5496 log::warn("Multi read was too long, value truncated conn_id: 0x{:04x} handle: 0x{:04x}",
5497 conn_id, hdl);
5498 break;
5499 }
5500
5501 OnGattReadRspStatic(conn_id, status, hdl, len, ptr,
5502 ((index == (handles.num_attr - 1)) ? data : nullptr));
5503
5504 position += len + 2; /* skip the length of data */
5505 index++;
5506 }
5507
5508 if (handles.num_attr - 1 != index) {
5509 log::warn("Attempted to read {} handles, but received just {} values", +handles.num_attr,
5510 index + 1);
5511 }
5512 }
5513
LeAudioHealthSendRecommendation(const RawAddress & address,int group_id,LeAudioHealthBasedAction action)5514 void LeAudioHealthSendRecommendation(const RawAddress& address, int group_id,
5515 LeAudioHealthBasedAction action) {
5516 log::debug("{}, {}, {}", address, group_id, ToString(action));
5517
5518 if (address != RawAddress::kEmpty && leAudioDevices_.FindByAddress(address)) {
5519 callbacks_->OnHealthBasedRecommendationAction(address, action);
5520 }
5521
5522 if (group_id != bluetooth::groups::kGroupUnknown && aseGroups_.FindById(group_id)) {
5523 callbacks_->OnHealthBasedGroupRecommendationAction(group_id, action);
5524 }
5525 }
5526
IsoCigEventsCb(uint16_t event_type,void * data)5527 void IsoCigEventsCb(uint16_t event_type, void* data) {
5528 switch (event_type) {
5529 case bluetooth::hci::iso_manager::kIsoEventCigOnCreateCmpl: {
5530 auto* evt = static_cast<cig_create_cmpl_evt*>(data);
5531 LeAudioDeviceGroup* group = aseGroups_.FindById(evt->cig_id);
5532 log::assert_that(group, "Group id: {} is null", evt->cig_id);
5533 groupStateMachine_->ProcessHciNotifOnCigCreate(group, evt->status, evt->cig_id,
5534 evt->conn_handles);
5535 } break;
5536 case bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl: {
5537 auto* evt = static_cast<cig_remove_cmpl_evt*>(data);
5538 LeAudioDeviceGroup* group = aseGroups_.FindById(evt->cig_id);
5539 log::assert_that(group, "Group id: {} is null", evt->cig_id);
5540 groupStateMachine_->ProcessHciNotifOnCigRemove(evt->status, group);
5541 remove_group_if_possible(group);
5542 } break;
5543 default:
5544 log::error("Invalid event {}", event_type);
5545 }
5546 }
5547
IsoCisEventsCb(uint16_t event_type,void * data)5548 void IsoCisEventsCb(uint16_t event_type, void* data) {
5549 switch (event_type) {
5550 case bluetooth::hci::iso_manager::kIsoEventCisDataAvailable: {
5551 auto* event = static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(data);
5552
5553 if (DsaDataConsume(event)) {
5554 return;
5555 }
5556
5557 if (audio_receiver_state_ != AudioState::STARTED) {
5558 log::error("receiver state not ready, current state={}", ToString(audio_receiver_state_));
5559 break;
5560 }
5561
5562 HandleIncomingCisData(event->p_msg->data + event->p_msg->offset,
5563 event->p_msg->len - event->p_msg->offset, event->cis_conn_hdl,
5564 event->ts);
5565 } break;
5566 case bluetooth::hci::iso_manager::kIsoEventCisEstablishCmpl: {
5567 auto* event = static_cast<bluetooth::hci::iso_manager::cis_establish_cmpl_evt*>(data);
5568
5569 LeAudioDevice* leAudioDevice =
5570 leAudioDevices_.FindByCisConnHdl(event->cig_id, event->cis_conn_hdl);
5571 if (!leAudioDevice) {
5572 log::error("no bonded Le Audio Device with CIS: {}", event->cis_conn_hdl);
5573 break;
5574 }
5575 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5576
5577 if (event->max_pdu_mtos > 0) {
5578 group->SetTransportLatency(bluetooth::le_audio::types::kLeAudioDirectionSink,
5579 event->trans_lat_mtos);
5580 }
5581 if (event->max_pdu_stom > 0) {
5582 group->SetTransportLatency(bluetooth::le_audio::types::kLeAudioDirectionSource,
5583 event->trans_lat_stom);
5584 }
5585
5586 if (leAudioHealthStatus_ && (event->status != HCI_SUCCESS)) {
5587 leAudioHealthStatus_->AddStatisticForGroup(
5588 group, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
5589 }
5590
5591 groupStateMachine_->ProcessHciNotifCisEstablished(group, leAudioDevice, event);
5592 } break;
5593 case bluetooth::hci::iso_manager::kIsoEventCisDisconnected: {
5594 auto* event = static_cast<bluetooth::hci::iso_manager::cis_disconnected_evt*>(data);
5595
5596 LeAudioDevice* leAudioDevice =
5597 leAudioDevices_.FindByCisConnHdl(event->cig_id, event->cis_conn_hdl);
5598 if (!leAudioDevice) {
5599 log::error("no bonded Le Audio Device with CIS: {}", event->cis_conn_hdl);
5600 break;
5601 }
5602 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5603
5604 groupStateMachine_->ProcessHciNotifCisDisconnected(group, leAudioDevice, event);
5605 } break;
5606 default:
5607 log::info(", Not handled ISO event");
5608 break;
5609 }
5610 }
5611
IsoSetupIsoDataPathCb(uint8_t status,uint16_t conn_handle,uint8_t cig_id)5612 void IsoSetupIsoDataPathCb(uint8_t status, uint16_t conn_handle, uint8_t cig_id) {
5613 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5614 /* In case device has been disconnected before data path was setup */
5615 if (!leAudioDevice) {
5616 log::warn("Device for CIG {} and using cis_handle 0x{:04x} is disconnected.", cig_id,
5617 conn_handle);
5618 return;
5619 }
5620 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5621
5622 instance->groupStateMachine_->ProcessHciNotifSetupIsoDataPath(group, leAudioDevice, status,
5623 conn_handle);
5624 }
5625
IsoRemoveIsoDataPathCb(uint8_t status,uint16_t conn_handle,uint8_t cig_id)5626 void IsoRemoveIsoDataPathCb(uint8_t status, uint16_t conn_handle, uint8_t cig_id) {
5627 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5628
5629 /* If CIS has been disconnected just before ACL being disconnected by the
5630 * remote device, leAudioDevice might be already cleared i.e. has no
5631 * information about conn_handle, when the data path remove compete arrives.
5632 */
5633 if (!leAudioDevice) {
5634 log::warn("Device for CIG {} and using cis_handle 0x{:04x} is disconnected.", cig_id,
5635 conn_handle);
5636 return;
5637 }
5638
5639 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5640
5641 instance->groupStateMachine_->ProcessHciNotifRemoveIsoDataPath(group, leAudioDevice, status,
5642 conn_handle);
5643 }
5644
IsoLinkQualityReadCb(uint8_t conn_handle,uint8_t cig_id,uint32_t txUnackedPackets,uint32_t txFlushedPackets,uint32_t txLastSubeventPackets,uint32_t retransmittedPackets,uint32_t crcErrorPackets,uint32_t rxUnreceivedPackets,uint32_t duplicatePackets)5645 void IsoLinkQualityReadCb(uint8_t conn_handle, uint8_t cig_id, uint32_t txUnackedPackets,
5646 uint32_t txFlushedPackets, uint32_t txLastSubeventPackets,
5647 uint32_t retransmittedPackets, uint32_t crcErrorPackets,
5648 uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) {
5649 LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5650 if (!leAudioDevice) {
5651 log::warn("device under connection handle: 0x{:x}, has been disconnecected in meantime",
5652 conn_handle);
5653 return;
5654 }
5655 LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5656
5657 instance->groupStateMachine_->ProcessHciNotifIsoLinkQualityRead(
5658 group, leAudioDevice, conn_handle, txUnackedPackets, txFlushedPackets,
5659 txLastSubeventPackets, retransmittedPackets, crcErrorPackets, rxUnreceivedPackets,
5660 duplicatePackets);
5661 }
5662
HandlePendingDeviceRemove(LeAudioDeviceGroup * group)5663 void HandlePendingDeviceRemove(LeAudioDeviceGroup* group) {
5664 for (auto device = group->GetFirstDevice(); device != nullptr;
5665 device = group->GetNextDevice(device)) {
5666 if (device->GetConnectionState() == DeviceConnectState::REMOVING) {
5667 if (device->closing_stream_for_disconnection_) {
5668 device->closing_stream_for_disconnection_ = false;
5669 log::info("Disconnecting group id: {}, address: {}", group->group_id_, device->address_);
5670 bool force_acl_disconnect = device->autoconnect_flag_ && group->IsEnabled();
5671 DisconnectDevice(device, force_acl_disconnect);
5672 }
5673 group_remove_node(group, device->address_, true);
5674 }
5675 }
5676 }
5677
HandlePendingDeviceDisconnection(LeAudioDeviceGroup * group)5678 void HandlePendingDeviceDisconnection(LeAudioDeviceGroup* group) {
5679 log::debug("");
5680
5681 auto leAudioDevice = group->GetFirstDevice();
5682 while (leAudioDevice) {
5683 if (leAudioDevice->closing_stream_for_disconnection_) {
5684 leAudioDevice->closing_stream_for_disconnection_ = false;
5685 log::debug("Disconnecting group id: {}, address: {}", group->group_id_,
5686 leAudioDevice->address_);
5687 bool force_acl_disconnect = leAudioDevice->autoconnect_flag_ && group->IsEnabled();
5688 DisconnectDevice(leAudioDevice, force_acl_disconnect);
5689 }
5690 leAudioDevice = group->GetNextDevice(leAudioDevice);
5691 }
5692 }
5693
UpdateAudioConfigToHal(const::bluetooth::le_audio::offload_config & config,uint8_t remote_direction)5694 void UpdateAudioConfigToHal(const ::bluetooth::le_audio::offload_config& config,
5695 uint8_t remote_direction) {
5696 if ((remote_direction & bluetooth::le_audio::types::kLeAudioDirectionSink) &&
5697 le_audio_source_hal_client_) {
5698 le_audio_source_hal_client_->UpdateAudioConfigToHal(config);
5699 }
5700 if ((remote_direction & bluetooth::le_audio::types::kLeAudioDirectionSource) &&
5701 le_audio_sink_hal_client_) {
5702 le_audio_sink_hal_client_->UpdateAudioConfigToHal(config);
5703 }
5704 }
5705
NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id)5706 void NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id) {
5707 if (!osi_property_get_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, false)) {
5708 return;
5709 }
5710
5711 /* If group is inactive, phone is in call and Group is not having CIS
5712 * connected, notify upper layer about it, so it can decide to create SCO if
5713 * it is in the handover case
5714 */
5715 if ((IsInCall() || IsInVoipCall()) && active_group_id_ == bluetooth::groups::kGroupUnknown) {
5716 callbacks_->OnGroupStatus(group_id, GroupStatus::TURNED_IDLE_DURING_CALL);
5717 }
5718 }
5719
speed_start_setup(int group_id,LeAudioContextType context_type,int num_of_connected,bool is_reconfig=false)5720 void speed_start_setup(int group_id, LeAudioContextType context_type, int num_of_connected,
5721 bool is_reconfig = false) {
5722 log::verbose("is_started {} is_reconfig {} num_of_connected {}", speed_tracker_.IsStarted(),
5723 is_reconfig, num_of_connected);
5724 if (!speed_tracker_.IsStarted()) {
5725 speed_tracker_.Init(group_id, context_type, num_of_connected);
5726 }
5727 if (is_reconfig) {
5728 speed_tracker_.ReconfigStarted();
5729 } else {
5730 speed_tracker_.StartStream();
5731 }
5732 }
5733
speed_stop_reconfig(void)5734 void speed_stop_reconfig(void) {
5735 log::verbose("");
5736 if (!speed_tracker_.IsStarted()) {
5737 return;
5738 }
5739 speed_tracker_.ReconfigurationComplete();
5740 }
5741
speed_stream_created()5742 void speed_stream_created() {
5743 log::verbose("");
5744 if (!speed_tracker_.IsStarted()) {
5745 return;
5746 }
5747
5748 speed_tracker_.StreamCreated();
5749 }
5750
speed_stop_setup()5751 void speed_stop_setup() {
5752 log::verbose("");
5753 if (!speed_tracker_.IsStarted()) {
5754 return;
5755 }
5756
5757 if (stream_speed_history_.size() == 10) {
5758 stream_speed_history_.pop_back();
5759 }
5760
5761 speed_tracker_.StopStreamSetup();
5762 stream_speed_history_.emplace_front(speed_tracker_);
5763 speed_tracker_.Reset();
5764 }
5765
notifyGroupStreamStatus(int group_id,GroupStreamStatus groupStreamStatus)5766 void notifyGroupStreamStatus(int group_id, GroupStreamStatus groupStreamStatus) {
5767 GroupStreamStatus newGroupStreamStatus = GroupStreamStatus::IDLE;
5768 if (groupStreamStatus == GroupStreamStatus::STREAMING) {
5769 newGroupStreamStatus = GroupStreamStatus::STREAMING;
5770 }
5771
5772 auto it = lastNotifiedGroupStreamStatusMap_.find(group_id);
5773
5774 if (it != lastNotifiedGroupStreamStatusMap_.end()) {
5775 if (it->second != newGroupStreamStatus) {
5776 callbacks_->OnGroupStreamStatus(group_id, newGroupStreamStatus);
5777 it->second = newGroupStreamStatus;
5778 }
5779 } else {
5780 callbacks_->OnGroupStreamStatus(group_id, newGroupStreamStatus);
5781 lastNotifiedGroupStreamStatusMap_.emplace(group_id, newGroupStreamStatus);
5782 }
5783 }
5784
handleAsymmetricPhyForUnicast(LeAudioDeviceGroup * group)5785 void handleAsymmetricPhyForUnicast(LeAudioDeviceGroup* group) {
5786 if (!group->asymmetric_phy_for_unidirectional_cis_supported) {
5787 return;
5788 }
5789
5790 auto it = lastNotifiedGroupStreamStatusMap_.find(group->group_id_);
5791
5792 if (it != lastNotifiedGroupStreamStatusMap_.end() &&
5793 it->second == GroupStreamStatus::STREAMING &&
5794 group->GetSduInterval(bluetooth::le_audio::types::kLeAudioDirectionSource) == 0) {
5795 SetAsymmetricBlePhy(group, true);
5796 return;
5797 }
5798
5799 SetAsymmetricBlePhy(group, false);
5800 }
5801
reconfigurationComplete(void)5802 void reconfigurationComplete(void) {
5803 // Check which directions were suspended
5804 uint8_t previously_active_directions = 0;
5805 if (audio_sender_state_ >= AudioState::READY_TO_START) {
5806 previously_active_directions |= bluetooth::le_audio::types::kLeAudioDirectionSink;
5807 }
5808 if (audio_receiver_state_ >= AudioState::READY_TO_START) {
5809 previously_active_directions |= bluetooth::le_audio::types::kLeAudioDirectionSource;
5810 }
5811
5812 /* We are done with reconfiguration.
5813 * Clean state and if Audio HAL is waiting, cancel the request
5814 * so Audio HAL can Resume again.
5815 */
5816 CancelStreamingRequest();
5817 ReconfigurationComplete(previously_active_directions);
5818 speed_stop_reconfig();
5819 }
5820
OnStateMachineStatusReportCb(int group_id,GroupStreamStatus status)5821 void OnStateMachineStatusReportCb(int group_id, GroupStreamStatus status) {
5822 log::info("status: {}, group_id: {}, audio_sender_state {}, audio_receiver_state {}",
5823 static_cast<int>(status), group_id, bluetooth::common::ToString(audio_sender_state_),
5824 bluetooth::common::ToString(audio_receiver_state_));
5825 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
5826
5827 notifyGroupStreamStatus(group_id, status);
5828
5829 switch (status) {
5830 case GroupStreamStatus::STREAMING: {
5831 if (group_id != active_group_id_) {
5832 log::error("Streaming group {} is no longer active. Stop the group.", group_id);
5833 GroupStop(group_id);
5834 return;
5835 }
5836
5837 speed_stream_created();
5838 bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted(active_group_id_,
5839 configuration_context_type_);
5840
5841 if (leAudioHealthStatus_) {
5842 leAudioHealthStatus_->AddStatisticForGroup(
5843 group, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
5844 }
5845
5846 if (!group) {
5847 log::error("Group {} does not exist anymore. This shall not happen", group_id);
5848 return;
5849 }
5850
5851 handleAsymmetricPhyForUnicast(group);
5852
5853 if ((audio_sender_state_ == AudioState::IDLE) &&
5854 (audio_receiver_state_ == AudioState::IDLE)) {
5855 /* Audio Framework is not interested in the stream anymore.
5856 * Just stop streaming
5857 */
5858 log::warn("Stopping stream for group {} as AF not interested.", group_id);
5859 speed_stop_setup();
5860 groupStateMachine_->StopStream(group);
5861 return;
5862 }
5863
5864 /* It might happen that the configuration has already changed, while
5865 * the group was in the ongoing reconfiguration. We should stop the
5866 * stream and reconfigure once again.
5867 */
5868 if (group->GetConfigurationContextType() != configuration_context_type_) {
5869 log::debug(
5870 "The configuration {} is no longer valid. Stopping the stream to "
5871 "reconfigure to {}",
5872 ToString(group->GetConfigurationContextType()),
5873 ToString(configuration_context_type_));
5874 speed_stop_setup();
5875 initReconfiguration(group, group->GetConfigurationContextType());
5876 return;
5877 }
5878
5879 BidirectionalPair<uint16_t> delays_pair = {
5880 .sink = group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSink),
5881 .source =
5882 group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSource)};
5883 CodecManager::GetInstance()->UpdateActiveAudioConfig(
5884 group->stream_conf.stream_params, delays_pair,
5885 std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
5886 std::placeholders::_1, std::placeholders::_2));
5887
5888 if (audio_sender_state_ == AudioState::READY_TO_START) {
5889 StartSendingAudio(group_id);
5890 }
5891
5892 if (audio_receiver_state_ == AudioState::READY_TO_START) {
5893 StartReceivingAudio(group_id);
5894 }
5895
5896 speed_stop_setup();
5897 break;
5898 }
5899 case GroupStreamStatus::SUSPENDED:
5900 speed_tracker_.Reset();
5901 /** Stop Audio but don't release all the Audio resources */
5902 SuspendAudio();
5903 break;
5904 case GroupStreamStatus::CONFIGURED_BY_USER:
5905 reconfigurationComplete();
5906 break;
5907 case GroupStreamStatus::CONFIGURED_AUTONOMOUS:
5908 /* This state is notified only when
5909 * groups stays into CONFIGURED state after
5910 * STREAMING. Peer device uses cache. For the moment
5911 * it is handled same as IDLE
5912 */
5913 case GroupStreamStatus::IDLE: {
5914 if (sw_enc_left) {
5915 sw_enc_left.reset();
5916 }
5917 if (sw_enc_right) {
5918 sw_enc_right.reset();
5919 }
5920 if (sw_dec_left) {
5921 sw_dec_left.reset();
5922 }
5923 if (sw_dec_right) {
5924 sw_dec_right.reset();
5925 }
5926 CleanCachedMicrophoneData();
5927
5928 if (group) {
5929 handleAsymmetricPhyForUnicast(group);
5930 UpdateLocationsAndContextsAvailability(group);
5931 if (group->IsPendingConfiguration()) {
5932 log::debug(
5933 "Pending configuration for group_id: {} pre_configuration_context_type_ : {} "
5934 "-> "
5935 "configuration_context_type_ {}",
5936 group->group_id_, ToString(pre_configuration_context_type_),
5937 ToString(configuration_context_type_));
5938 auto remote_direction = kLeAudioContextAllRemoteSource.test(configuration_context_type_)
5939 ? bluetooth::le_audio::types::kLeAudioDirectionSource
5940 : bluetooth::le_audio::types::kLeAudioDirectionSink;
5941
5942 /* Reconfiguration to non requiring source scenario */
5943 if (sink_monitor_mode_ &&
5944 (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink)) {
5945 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
5946 }
5947
5948 auto remote_contexts = DirectionalRealignMetadataAudioContexts(group, remote_direction);
5949 ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts, remote_direction);
5950 log::verbose(
5951 "Pending configuration 2 pre_configuration_context_type_ : {} -> "
5952 "configuration_context_type_ {}",
5953 ToString(pre_configuration_context_type_),
5954 ToString(configuration_context_type_));
5955 if ((configuration_context_type_ != pre_configuration_context_type_) &&
5956 GroupStream(group->group_id_, configuration_context_type_, remote_contexts)) {
5957 /* If configuration succeed wait for new status. */
5958 return;
5959 }
5960 log::info("Clear pending configuration flag for group {}", group->group_id_);
5961 group->ClearPendingConfiguration();
5962 reconfigurationComplete();
5963 } else {
5964 if (sink_monitor_mode_) {
5965 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
5966 }
5967
5968 if (source_monitor_mode_) {
5969 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
5970 }
5971 }
5972 }
5973
5974 speed_tracker_.Reset();
5975 CancelStreamingRequest();
5976
5977 if (group) {
5978 NotifyUpperLayerGroupTurnedIdleDuringCall(group->group_id_);
5979 HandlePendingDeviceRemove(group);
5980 HandlePendingDeviceDisconnection(group);
5981 }
5982 break;
5983 }
5984 case GroupStreamStatus::RELEASING:
5985 case GroupStreamStatus::SUSPENDING:
5986 if (active_group_id_ != bluetooth::groups::kGroupUnknown &&
5987 (active_group_id_ == group->group_id_) && !group->IsPendingConfiguration() &&
5988 (audio_sender_state_ == AudioState::STARTED ||
5989 audio_receiver_state_ == AudioState::STARTED) &&
5990 group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
5991 /* If releasing state is happening but it was not initiated either by
5992 * reconfiguration or Audio Framework actions either by the Active group change,
5993 * it means that it is some internal state machine error. This is very unlikely and
5994 * for now just Inactivate the group.
5995 */
5996 log::error("Internal state machine error");
5997 group->PrintDebugState();
5998 groupSetAndNotifyInactive();
5999 }
6000
6001 if (audio_sender_state_ != AudioState::IDLE) {
6002 audio_sender_state_ = AudioState::RELEASING;
6003 }
6004
6005 if (audio_receiver_state_ != AudioState::IDLE) {
6006 audio_receiver_state_ = AudioState::RELEASING;
6007 }
6008
6009 if (group && group->IsPendingConfiguration()) {
6010 log::info("Releasing for reconfiguration, don't send anything on CISes");
6011 SuspendedForReconfiguration();
6012 }
6013 break;
6014 default:
6015 break;
6016 }
6017 }
6018
OnUpdatedCisConfiguration(int group_id,uint8_t direction)6019 void OnUpdatedCisConfiguration(int group_id, uint8_t direction) {
6020 LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
6021 if (!group) {
6022 log::error("Invalid group_id: {}", group_id);
6023 return;
6024 }
6025 group->UpdateCisConfiguration(direction);
6026 }
6027
6028 private:
6029 tGATT_IF gatt_if_;
6030 bluetooth::le_audio::LeAudioClientCallbacks* callbacks_;
6031 LeAudioDevices leAudioDevices_;
6032 LeAudioDeviceGroups aseGroups_;
6033 LeAudioGroupStateMachine* groupStateMachine_;
6034 int active_group_id_;
6035 LeAudioContextType pre_configuration_context_type_;
6036 LeAudioContextType configuration_context_type_;
6037 static constexpr char kAllowMultipleContextsInMetadata[] =
6038 "persist.bluetooth.leaudio.allow.multiple.contexts";
6039 BidirectionalPair<AudioContexts> in_call_metadata_context_types_;
6040 BidirectionalPair<AudioContexts> local_metadata_context_types_;
6041 StreamSpeedTracker speed_tracker_;
6042 std::deque<StreamSpeedTracker> stream_speed_history_;
6043
6044 /* Microphone (s) */
6045 AudioState audio_receiver_state_;
6046 /* Speaker(s) */
6047 AudioState audio_sender_state_;
6048 /* Keep in call state. */
6049 bool in_call_;
6050 bool in_voip_call_;
6051 /* Listen for streaming status on Sink stream */
6052 bool sink_monitor_mode_;
6053 /* Sink stream status which has been notified to Service */
6054 std::optional<UnicastMonitorModeStatus> sink_monitor_notified_status_;
6055 /* Listen for streaming status on Source stream */
6056 bool source_monitor_mode_;
6057 /* Source stream status which has been notified to Service */
6058 std::optional<UnicastMonitorModeStatus> source_monitor_notified_status_;
6059
6060 /* Reconnection mode */
6061 tBTM_BLE_CONN_TYPE reconnection_mode_;
6062 static constexpr uint64_t kGroupConnectedWatchDelayMs = 3000;
6063 static constexpr uint64_t kRecoveryReconnectDelayMs = 2000;
6064 static constexpr uint64_t kAutoConnectAfterOwnDisconnectDelayMs = 1000;
6065 static constexpr uint64_t kCsisGroupMemberDelayMs = 5000;
6066
6067 /* LeAudioHealthStatus */
6068 LeAudioHealthStatus* leAudioHealthStatus_ = nullptr;
6069
6070 static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
6071 "persist.bluetooth.leaudio.notify.idle.during.call";
6072
6073 static constexpr uint16_t kBapMinimumAttMtu = 64;
6074
6075 /* Current stream configuration - used to set up the software codecs */
6076 LeAudioCodecConfiguration current_encoder_config_;
6077 LeAudioCodecConfiguration current_decoder_config_;
6078
6079 /* Static Audio Framework session configuration.
6080 * Resampling will be done inside the bt stack
6081 */
6082 LeAudioCodecConfiguration audio_framework_source_config = {
6083 .num_channels = 2,
6084 .sample_rate = bluetooth::audio::le_audio::kSampleRate48000,
6085 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
6086 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
6087 };
6088
6089 LeAudioCodecConfiguration audio_framework_sink_config = {
6090 .num_channels = 2,
6091 .sample_rate = bluetooth::audio::le_audio::kSampleRate16000,
6092 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
6093 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
6094 };
6095
6096 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_enc_left;
6097 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_enc_right;
6098
6099 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_dec_left;
6100 std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_dec_right;
6101
6102 std::vector<uint8_t> encoded_data;
6103 std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_;
6104 std::unique_ptr<LeAudioSinkAudioHalClient> le_audio_sink_hal_client_;
6105 static constexpr uint64_t kAudioSuspentKeepIsoAliveTimeoutMs = 500;
6106 static constexpr uint64_t kAudioDisableTimeoutMs = 3000;
6107 static constexpr char kAudioSuspentKeepIsoAliveTimeoutMsProp[] =
6108 "persist.bluetooth.leaudio.audio.suspend.timeoutms";
6109 static constexpr uint64_t kAudioReconfigurationTimeoutMs = 1500;
6110 alarm_t* close_vbc_timeout_;
6111 alarm_t* suspend_timeout_;
6112
6113 /* Reconfiguration guard to make sure reconfigration is not broken by unexpected Metadata change.
6114 * When Reconfiguration is scheduled then
6115 * 1. BT stack remembers local directions which should be resumed after reconfiguration
6116 * 2. Blocks another reconfiguration until:
6117 * a) all the reconfigured directions has been resumed
6118 * b) reconfiguration timeout fires
6119 */
6120 alarm_t* reconfiguration_timeout_;
6121 int reconfiguration_group_ = bluetooth::groups::kGroupUnknown;
6122 uint8_t reconfiguration_local_directions_ = 0;
6123
6124 alarm_t* disable_timer_;
6125 static constexpr uint64_t kDeviceAttachDelayMs = 500;
6126
6127 uint32_t cached_channel_timestamp_ = 0;
6128 bluetooth::le_audio::CodecInterface* cached_channel_ = nullptr;
6129
6130 base::WeakPtrFactory<LeAudioClientImpl> weak_factory_{this};
6131
6132 std::map<int, GroupStreamStatus> lastNotifiedGroupStreamStatusMap_;
6133
ClientAudioInterfaceRelease()6134 void ClientAudioInterfaceRelease() {
6135 auto group = aseGroups_.FindById(active_group_id_);
6136 if (!group) {
6137 log::error("Invalid group: {}", static_cast<int>(active_group_id_));
6138 } else {
6139 handleAsymmetricPhyForUnicast(group);
6140 log::info("ClientAudioInterfaceRelease - cleanup");
6141 }
6142
6143 auto result = CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
6144 le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(), false);
6145 log::assert_that(result, "Could not update session to codec manager");
6146
6147 if (le_audio_source_hal_client_) {
6148 le_audio_source_hal_client_->Stop();
6149 le_audio_source_hal_client_.reset();
6150 }
6151
6152 if (le_audio_sink_hal_client_) {
6153 /* Keep session set up to monitor streaming request. This is required if
6154 * there is another LE Audio device streaming (e.g. Broadcast) and via
6155 * the session callbacks special action from this Module would be
6156 * required e.g. to Unicast handover.
6157 */
6158 if (!sink_monitor_mode_) {
6159 local_metadata_context_types_.sink.clear();
6160 le_audio_sink_hal_client_->Stop();
6161 le_audio_sink_hal_client_.reset();
6162 }
6163 }
6164 local_metadata_context_types_.source.clear();
6165 configuration_context_type_ = LeAudioContextType::UNINITIALIZED;
6166
6167 bluetooth::le_audio::MetricsCollector::Get()->OnStreamEnded(active_group_id_);
6168 }
6169
DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt * event)6170 bool DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt* event) {
6171 if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
6172 return false;
6173 }
6174
6175 if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
6176 return false;
6177 }
6178 LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
6179 if (!group || !group->dsa_.active) {
6180 return false;
6181 }
6182
6183 if (group->dsa_.mode != DsaMode::ISO_SW) {
6184 log::warn("ISO packets received over HCI in DSA mode: {}", group->dsa_.mode);
6185 return false;
6186 }
6187
6188 if (iso_data_callback == nullptr) {
6189 log::warn("Dsa data consumer not registered");
6190 return false;
6191 }
6192
6193 uint16_t cis_conn_hdl = event->cis_conn_hdl;
6194 uint8_t* data = event->p_msg->data + event->p_msg->offset;
6195 uint16_t size = event->p_msg->len - event->p_msg->offset;
6196 uint32_t timestamp = event->ts;
6197
6198 // Find LE Audio device
6199 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
6200 while (leAudioDevice != nullptr) {
6201 if (leAudioDevice->GetDsaCisHandle() == cis_conn_hdl &&
6202 leAudioDevice->GetDsaDataPathState() == DataPathState::CONFIGURED) {
6203 break;
6204 }
6205 leAudioDevice = group->GetNextDevice(leAudioDevice);
6206 }
6207 if (leAudioDevice == nullptr) {
6208 log::warn("No LE Audio device found for CIS handle: {}", cis_conn_hdl);
6209 return false;
6210 }
6211
6212 bool consumed = iso_data_callback(leAudioDevice->address_, cis_conn_hdl, data, size, timestamp);
6213 if (consumed) {
6214 return true;
6215 } else {
6216 log::verbose("ISO data consumer not ready to accept data");
6217 return false;
6218 }
6219 }
6220
SetAsymmetricBlePhy(LeAudioDeviceGroup * group,bool asymmetric)6221 void SetAsymmetricBlePhy(LeAudioDeviceGroup* group, bool asymmetric) {
6222 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
6223 if (leAudioDevice == nullptr) {
6224 log::error("Shouldn't be called without a device.");
6225 return;
6226 }
6227
6228 for (auto tmpDevice = leAudioDevice; tmpDevice != nullptr;
6229 tmpDevice = group->GetNextDevice(tmpDevice)) {
6230 log::info("tmpDevice->acl_asymmetric_: {}, asymmetric: {}, address: {}, acl_connected: {}",
6231 tmpDevice->acl_asymmetric_ == asymmetric, asymmetric, tmpDevice->address_,
6232 get_btm_client_interface().peer.BTM_IsAclConnectionUp(tmpDevice->address_,
6233 BT_TRANSPORT_LE));
6234 if (tmpDevice->acl_asymmetric_ == asymmetric ||
6235 !get_btm_client_interface().peer.BTM_IsAclConnectionUp(tmpDevice->address_,
6236 BT_TRANSPORT_LE)) {
6237 continue;
6238 }
6239
6240 log::info("SetAsymmetricBlePhy: {} for {}", asymmetric, tmpDevice->address_);
6241 get_btm_client_interface().ble.BTM_BleSetPhy(tmpDevice->address_, PHY_LE_2M,
6242 asymmetric ? PHY_LE_1M : PHY_LE_2M, 0);
6243 tmpDevice->acl_asymmetric_ = asymmetric;
6244 }
6245 }
6246 };
6247
le_audio_health_status_callback(const RawAddress & addr,int group_id,LeAudioHealthBasedAction action)6248 static void le_audio_health_status_callback(const RawAddress& addr, int group_id,
6249 LeAudioHealthBasedAction action) {
6250 if (instance) {
6251 instance->LeAudioHealthSendRecommendation(addr, group_id, action);
6252 }
6253 }
6254
6255 /* This is a generic callback method for gatt client which handles every client
6256 * application events.
6257 */
le_audio_gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)6258 void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
6259 if (!p_data || !instance) {
6260 return;
6261 }
6262
6263 log::info("event = {}", static_cast<int>(event));
6264
6265 switch (event) {
6266 case BTA_GATTC_DEREG_EVT:
6267 break;
6268
6269 case BTA_GATTC_NOTIF_EVT:
6270 instance->LeAudioCharValueHandle(p_data->notify.conn_id, p_data->notify.handle,
6271 p_data->notify.len,
6272 static_cast<uint8_t*>(p_data->notify.value), true);
6273
6274 if (!p_data->notify.is_notify) {
6275 BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
6276 }
6277
6278 break;
6279
6280 case BTA_GATTC_OPEN_EVT:
6281 instance->OnGattConnected(p_data->open.status, p_data->open.conn_id, p_data->open.client_if,
6282 p_data->open.remote_bda, p_data->open.transport, p_data->open.mtu);
6283 break;
6284
6285 case BTA_GATTC_ENC_CMPL_CB_EVT: {
6286 tBTM_STATUS encryption_status;
6287 if (BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE)) {
6288 encryption_status = tBTM_STATUS::BTM_SUCCESS;
6289 } else {
6290 encryption_status = tBTM_STATUS::BTM_FAILED_ON_SECURITY;
6291 }
6292 instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, encryption_status);
6293 } break;
6294
6295 case BTA_GATTC_CLOSE_EVT:
6296 instance->OnGattDisconnected(p_data->close.conn_id, p_data->close.client_if,
6297 p_data->close.remote_bda, p_data->close.reason);
6298 break;
6299
6300 case BTA_GATTC_SEARCH_CMPL_EVT:
6301 instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
6302 break;
6303
6304 case BTA_GATTC_SRVC_DISC_DONE_EVT:
6305 instance->OnGattServiceDiscoveryDone(p_data->service_discovery_done.remote_bda);
6306 break;
6307
6308 case BTA_GATTC_SRVC_CHG_EVT:
6309 instance->OnServiceChangeEvent(p_data->service_changed.remote_bda);
6310 break;
6311 case BTA_GATTC_CFG_MTU_EVT:
6312 instance->OnMtuChanged(p_data->cfg_mtu.conn_id, p_data->cfg_mtu.mtu);
6313 break;
6314 case BTA_GATTC_PHY_UPDATE_EVT:
6315 instance->OnPhyUpdate(p_data->phy_update.conn_id, p_data->phy_update.tx_phy,
6316 p_data->phy_update.rx_phy, p_data->phy_update.status);
6317 break;
6318 default:
6319 break;
6320 }
6321 }
6322
6323 class LeAudioStateMachineHciCallbacksImpl : public CigCallbacks {
6324 public:
OnCigEvent(uint8_t event,void * data)6325 void OnCigEvent(uint8_t event, void* data) override {
6326 if (instance) {
6327 instance->IsoCigEventsCb(event, data);
6328 }
6329 }
6330
OnCisEvent(uint8_t event,void * data)6331 void OnCisEvent(uint8_t event, void* data) override {
6332 if (instance) {
6333 instance->IsoCisEventsCb(event, data);
6334 }
6335 }
6336
OnSetupIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t cig_id)6337 void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t cig_id) override {
6338 if (instance) {
6339 instance->IsoSetupIsoDataPathCb(status, conn_handle, cig_id);
6340 }
6341 }
6342
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t cig_id)6343 void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t cig_id) override {
6344 if (instance) {
6345 instance->IsoRemoveIsoDataPathCb(status, conn_handle, cig_id);
6346 }
6347 }
6348
OnIsoLinkQualityRead(uint8_t conn_handle,uint8_t cig_id,uint32_t txUnackedPackets,uint32_t txFlushedPackets,uint32_t txLastSubeventPackets,uint32_t retransmittedPackets,uint32_t crcErrorPackets,uint32_t rxUnreceivedPackets,uint32_t duplicatePackets)6349 void OnIsoLinkQualityRead(uint8_t conn_handle, uint8_t cig_id, uint32_t txUnackedPackets,
6350 uint32_t txFlushedPackets, uint32_t txLastSubeventPackets,
6351 uint32_t retransmittedPackets, uint32_t crcErrorPackets,
6352 uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) {
6353 if (instance) {
6354 instance->IsoLinkQualityReadCb(conn_handle, cig_id, txUnackedPackets, txFlushedPackets,
6355 txLastSubeventPackets, retransmittedPackets, crcErrorPackets,
6356 rxUnreceivedPackets, duplicatePackets);
6357 }
6358 }
6359 };
6360
6361 LeAudioStateMachineHciCallbacksImpl stateMachineHciCallbacksImpl;
6362
6363 class CallbacksImpl : public LeAudioGroupStateMachine::Callbacks {
6364 public:
StatusReportCb(int group_id,GroupStreamStatus status)6365 void StatusReportCb(int group_id, GroupStreamStatus status) override {
6366 if (instance) {
6367 instance->OnStateMachineStatusReportCb(group_id, status);
6368 }
6369 }
6370
OnStateTransitionTimeout(int group_id)6371 void OnStateTransitionTimeout(int group_id) override {
6372 if (instance) {
6373 instance->OnLeAudioDeviceSetStateTimeout(group_id);
6374 }
6375 }
6376
OnUpdatedCisConfiguration(int group_id,uint8_t direction)6377 void OnUpdatedCisConfiguration(int group_id, uint8_t direction) {
6378 if (instance) {
6379 instance->OnUpdatedCisConfiguration(group_id, direction);
6380 }
6381 }
6382 };
6383
6384 CallbacksImpl stateMachineCallbacksImpl;
6385
6386 class SourceCallbacksImpl : public LeAudioSourceAudioHalClient::Callbacks {
6387 public:
OnAudioDataReady(const std::vector<uint8_t> & data)6388 void OnAudioDataReady(const std::vector<uint8_t>& data) override {
6389 if (instance) {
6390 instance->OnAudioDataReady(data);
6391 }
6392 }
OnAudioSuspend(void)6393 void OnAudioSuspend(void) override {
6394 if (instance) {
6395 instance->OnLocalAudioSourceSuspend();
6396 }
6397 }
6398
OnAudioResume(void)6399 void OnAudioResume(void) override {
6400 if (instance) {
6401 instance->OnLocalAudioSourceResume();
6402 }
6403 }
6404
OnAudioMetadataUpdate(std::vector<struct playback_track_metadata_v7> source_metadata,DsaMode dsa_mode)6405 void OnAudioMetadataUpdate(std::vector<struct playback_track_metadata_v7> source_metadata,
6406 DsaMode dsa_mode) override {
6407 if (instance) {
6408 instance->OnLocalAudioSourceMetadataUpdate(source_metadata, dsa_mode);
6409 }
6410 }
6411 };
6412
6413 class SinkCallbacksImpl : public LeAudioSinkAudioHalClient::Callbacks {
6414 public:
OnAudioSuspend(void)6415 void OnAudioSuspend(void) override {
6416 if (instance) {
6417 instance->OnLocalAudioSinkSuspend();
6418 }
6419 }
OnAudioResume(void)6420 void OnAudioResume(void) override {
6421 if (instance) {
6422 instance->OnLocalAudioSinkResume();
6423 }
6424 }
6425
OnAudioMetadataUpdate(std::vector<record_track_metadata_v7> sink_metadata)6426 void OnAudioMetadataUpdate(std::vector<record_track_metadata_v7> sink_metadata) override {
6427 if (instance) {
6428 instance->OnLocalAudioSinkMetadataUpdate(sink_metadata);
6429 }
6430 }
6431 };
6432
6433 SourceCallbacksImpl audioSinkReceiverImpl;
6434 SinkCallbacksImpl audioSourceReceiverImpl;
6435
6436 class DeviceGroupsCallbacksImpl : public DeviceGroupsCallbacks {
6437 public:
OnGroupAdded(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)6438 void OnGroupAdded(const RawAddress& address, const bluetooth::Uuid& uuid, int group_id) override {
6439 if (instance) {
6440 instance->OnGroupAddedCb(address, uuid, group_id);
6441 }
6442 }
OnGroupMemberAdded(const RawAddress & address,int group_id)6443 void OnGroupMemberAdded(const RawAddress& address, int group_id) override {
6444 if (instance) {
6445 instance->OnGroupMemberAddedCb(address, group_id);
6446 }
6447 }
OnGroupMemberRemoved(const RawAddress & address,int group_id)6448 void OnGroupMemberRemoved(const RawAddress& address, int group_id) override {
6449 if (instance) {
6450 instance->OnGroupMemberRemovedCb(address, group_id);
6451 }
6452 }
OnGroupRemoved(const bluetooth::Uuid &,int)6453 void OnGroupRemoved(const bluetooth::Uuid& /*uuid*/,
6454 int /*group_id*/) { /* to implement if needed */ }
OnGroupAddFromStorage(const RawAddress &,const bluetooth::Uuid &,int)6455 void OnGroupAddFromStorage(const RawAddress& /*address*/, const bluetooth::Uuid& /*uuid*/,
6456 int /*group_id*/) {
6457 /* to implement if needed */
6458 }
6459 };
6460
6461 class DeviceGroupsCallbacksImpl;
6462 DeviceGroupsCallbacksImpl deviceGroupsCallbacksImpl;
6463
6464 } // namespace
6465
AddFromStorage(const RawAddress & addr,bool autoconnect,int sink_audio_location,int source_audio_location,int sink_supported_context_types,int source_supported_context_types,const std::vector<uint8_t> & handles,const std::vector<uint8_t> & sink_pacs,const std::vector<uint8_t> & source_pacs,const std::vector<uint8_t> & ases)6466 void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect,
6467 int sink_audio_location, int source_audio_location,
6468 int sink_supported_context_types,
6469 int source_supported_context_types,
6470 const std::vector<uint8_t>& handles,
6471 const std::vector<uint8_t>& sink_pacs,
6472 const std::vector<uint8_t>& source_pacs,
6473 const std::vector<uint8_t>& ases) {
6474 if (!instance) {
6475 log::error("Not initialized yet");
6476 return;
6477 }
6478
6479 instance->AddFromStorage(addr, autoconnect, sink_audio_location, source_audio_location,
6480 sink_supported_context_types, source_supported_context_types, handles,
6481 sink_pacs, source_pacs, ases);
6482 }
6483
GetHandlesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6484 bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6485 if (!instance) {
6486 log::error("Not initialized yet");
6487 return false;
6488 }
6489
6490 return instance->GetHandlesForStorage(addr, out);
6491 }
6492
GetSinkPacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6493 bool LeAudioClient::GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6494 if (!instance) {
6495 log::error("Not initialized yet");
6496 return false;
6497 }
6498
6499 return instance->GetSinkPacsForStorage(addr, out);
6500 }
6501
GetSourcePacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6502 bool LeAudioClient::GetSourcePacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6503 if (!instance) {
6504 log::error("Not initialized yet");
6505 return false;
6506 }
6507
6508 return instance->GetSourcePacsForStorage(addr, out);
6509 }
6510
GetAsesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6511 bool LeAudioClient::GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6512 if (!instance) {
6513 log::error("Not initialized yet");
6514 return false;
6515 }
6516
6517 return instance->GetAsesForStorage(addr, out);
6518 }
6519
IsLeAudioClientRunning(void)6520 bool LeAudioClient::IsLeAudioClientRunning(void) { return instance != nullptr; }
6521
IsLeAudioClientInStreaming(void)6522 bool LeAudioClient::IsLeAudioClientInStreaming(void) {
6523 if (!instance) {
6524 return false;
6525 }
6526 return instance->IsInStreaming();
6527 }
6528
Get()6529 LeAudioClient* LeAudioClient::Get() {
6530 log::assert_that(instance != nullptr, "assert failed: instance != nullptr");
6531 return instance;
6532 }
6533
6534 /* Initializer of main le audio implementation class and its instance */
Initialize(bluetooth::le_audio::LeAudioClientCallbacks * callbacks_,base::Closure initCb,base::Callback<bool ()> hal_2_1_verifier,const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> & offloading_preference)6535 void LeAudioClient::Initialize(
6536 bluetooth::le_audio::LeAudioClientCallbacks* callbacks_, base::Closure initCb,
6537 base::Callback<bool()> hal_2_1_verifier,
6538 const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& offloading_preference) {
6539 std::scoped_lock<std::mutex> lock(instance_mutex);
6540 if (instance) {
6541 log::error("Already initialized");
6542 return;
6543 }
6544
6545 if (!bluetooth::shim::GetController()->SupportsBleConnectedIsochronousStreamCentral() &&
6546 !bluetooth::shim::GetController()->SupportsBleConnectedIsochronousStreamPeripheral()) {
6547 log::error("Controller reports no ISO support. LeAudioClient Init aborted.");
6548 return;
6549 }
6550
6551 log::assert_that(std::move(hal_2_1_verifier).Run(),
6552 "LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
6553 "disable LE Audio Profile, or update your HAL");
6554
6555 IsoManager::GetInstance()->Start();
6556
6557 audioSinkReceiver = &audioSinkReceiverImpl;
6558 audioSourceReceiver = &audioSourceReceiverImpl;
6559 stateMachineHciCallbacks = &stateMachineHciCallbacksImpl;
6560 stateMachineCallbacks = &stateMachineCallbacksImpl;
6561 device_group_callbacks = &deviceGroupsCallbacksImpl;
6562 instance = new LeAudioClientImpl(callbacks_, stateMachineCallbacks, initCb);
6563
6564 IsoManager::GetInstance()->RegisterCigCallbacks(stateMachineHciCallbacks);
6565 CodecManager::GetInstance()->Start(offloading_preference);
6566 ContentControlIdKeeper::GetInstance()->Start();
6567
6568 callbacks_->OnInitialized();
6569
6570 auto cm = CodecManager::GetInstance();
6571 callbacks_->OnAudioLocalCodecCapabilities(cm->GetLocalAudioInputCodecCapa(),
6572 cm->GetLocalAudioOutputCodecCapa());
6573
6574 if (GmapServer::IsGmapServerEnabled()) {
6575 auto capabilities = cm->GetLocalAudioOutputCodecCapa();
6576 std::bitset<8> UGG_feature = GmapServer::GetUGGFeature();
6577 for (auto& capa : capabilities) {
6578 if (capa.sample_rate == bluetooth::le_audio::LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ) {
6579 UGG_feature |= static_cast<uint8_t>(
6580 bluetooth::gmap::UGGFeatureBitMask::NinetySixKbpsSourceFeatureSupport);
6581 break;
6582 }
6583 }
6584 GmapServer::Initialize(UGG_feature);
6585 }
6586 }
6587
DebugDump(int fd)6588 void LeAudioClient::DebugDump(int fd) {
6589 std::scoped_lock<std::mutex> lock(instance_mutex);
6590 DeviceGroups::DebugDump(fd);
6591
6592 dprintf(fd, "LeAudio Manager: \n");
6593 if (instance) {
6594 instance->Dump(fd);
6595 } else {
6596 dprintf(fd, " Not initialized \n");
6597 }
6598
6599 LeAudioSinkAudioHalClient::DebugDump(fd);
6600 LeAudioSourceAudioHalClient::DebugDump(fd);
6601 bluetooth::le_audio::AudioSetConfigurationProvider::DebugDump(fd);
6602 IsoManager::GetInstance()->Dump(fd);
6603 LeAudioLogHistory::DebugDump(fd);
6604 dprintf(fd, "\n");
6605 }
6606
Cleanup(void)6607 void LeAudioClient::Cleanup(void) {
6608 std::scoped_lock<std::mutex> lock(instance_mutex);
6609 if (!instance) {
6610 log::error("Not initialized");
6611 return;
6612 }
6613
6614 LeAudioClientImpl* ptr = instance;
6615 instance = nullptr;
6616 ptr->Cleanup();
6617 delete ptr;
6618 ptr = nullptr;
6619
6620 CodecManager::GetInstance()->Stop();
6621 ContentControlIdKeeper::GetInstance()->Stop();
6622 LeAudioGroupStateMachine::Cleanup();
6623
6624 if (!LeAudioBroadcaster::IsLeAudioBroadcasterRunning()) {
6625 IsoManager::GetInstance()->Stop();
6626 }
6627
6628 bluetooth::le_audio::MetricsCollector::Get()->Flush();
6629 }
6630
RegisterIsoDataConsumer(LeAudioIsoDataCallback callback)6631 bool LeAudioClient::RegisterIsoDataConsumer(LeAudioIsoDataCallback callback) {
6632 if (!com::android::bluetooth::flags::leaudio_dynamic_spatial_audio()) {
6633 return false;
6634 }
6635
6636 log::info("ISO data consumer changed");
6637 iso_data_callback = callback;
6638 return true;
6639 }
6640