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